s3-spoolss: use rpccli_spoolss_RouterReplyPrinterEx.
[ira/wip.git] / source3 / rpc_server / srv_spoolss_nt.c
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  *
11  *  This program is free software; you can redistribute it and/or modify
12  *  it under the terms of the GNU General Public License as published by
13  *  the Free Software Foundation; either version 3 of the License, or
14  *  (at your option) any later version.
15  *
16  *  This program is distributed in the hope that it will be useful,
17  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
18  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19  *  GNU General Public License for more details.
20  *
21  *  You should have received a copy of the GNU General Public License
22  *  along with this program; if not, see <http://www.gnu.org/licenses/>.
23  */
24
25 /* Since the SPOOLSS rpc routines are basically DOS 16-bit calls wrapped
26    up, all the errors returned are DOS errors, not NT status codes. */
27
28 #include "includes.h"
29
30 extern userdom_struct current_user_info;
31
32 #undef DBGC_CLASS
33 #define DBGC_CLASS DBGC_RPC_SRV
34
35 #ifndef MAX_OPEN_PRINTER_EXS
36 #define MAX_OPEN_PRINTER_EXS 50
37 #endif
38
39 #define MAGIC_DISPLAY_FREQUENCY 0xfade2bad
40 #define PHANTOM_DEVMODE_KEY "_p_f_a_n_t_0_m_"
41
42 struct table_node {
43         const char    *long_archi;
44         const char    *short_archi;
45         int     version;
46 };
47
48 static Printer_entry *printers_list;
49
50 typedef struct _counter_printer_0 {
51         struct _counter_printer_0 *next;
52         struct _counter_printer_0 *prev;
53
54         int snum;
55         uint32 counter;
56 } counter_printer_0;
57
58 static counter_printer_0 *counter_list;
59
60 static struct rpc_pipe_client *notify_cli_pipe; /* print notify back-channel pipe handle*/
61 static uint32 smb_connections=0;
62
63
64 /* in printing/nt_printing.c */
65
66 extern struct standard_mapping printer_std_mapping, printserver_std_mapping;
67
68 /* API table for Xcv Monitor functions */
69
70 struct xcv_api_table {
71         const char *name;
72         WERROR(*fn) (TALLOC_CTX *mem_ctx, NT_USER_TOKEN *token, DATA_BLOB *in, DATA_BLOB *out, uint32_t *needed);
73 };
74
75 /********************************************************************
76  * Canonicalize servername.
77  ********************************************************************/
78
79 static const char *canon_servername(const char *servername)
80 {
81         const char *pservername = servername;
82         while (*pservername == '\\') {
83                 pservername++;
84         }
85         return pservername;
86 }
87
88 /* translate between internal status numbers and NT status numbers */
89 static int nt_printj_status(int v)
90 {
91         switch (v) {
92         case LPQ_QUEUED:
93                 return 0;
94         case LPQ_PAUSED:
95                 return JOB_STATUS_PAUSED;
96         case LPQ_SPOOLING:
97                 return JOB_STATUS_SPOOLING;
98         case LPQ_PRINTING:
99                 return JOB_STATUS_PRINTING;
100         case LPQ_ERROR:
101                 return JOB_STATUS_ERROR;
102         case LPQ_DELETING:
103                 return JOB_STATUS_DELETING;
104         case LPQ_OFFLINE:
105                 return JOB_STATUS_OFFLINE;
106         case LPQ_PAPEROUT:
107                 return JOB_STATUS_PAPEROUT;
108         case LPQ_PRINTED:
109                 return JOB_STATUS_PRINTED;
110         case LPQ_DELETED:
111                 return JOB_STATUS_DELETED;
112         case LPQ_BLOCKED:
113                 return JOB_STATUS_BLOCKED;
114         case LPQ_USER_INTERVENTION:
115                 return JOB_STATUS_USER_INTERVENTION;
116         }
117         return 0;
118 }
119
120 static int nt_printq_status(int v)
121 {
122         switch (v) {
123         case LPQ_PAUSED:
124                 return PRINTER_STATUS_PAUSED;
125         case LPQ_QUEUED:
126         case LPQ_SPOOLING:
127         case LPQ_PRINTING:
128                 return 0;
129         }
130         return 0;
131 }
132
133 /****************************************************************************
134  Functions to handle SPOOL_NOTIFY_OPTION struct stored in Printer_entry.
135 ****************************************************************************/
136
137 static void free_spool_notify_option(SPOOL_NOTIFY_OPTION **pp)
138 {
139         if (*pp == NULL)
140                 return;
141
142         SAFE_FREE((*pp)->ctr.type);
143         SAFE_FREE(*pp);
144 }
145
146 /***************************************************************************
147  Disconnect from the client
148 ****************************************************************************/
149
150 static void srv_spoolss_replycloseprinter(int snum, POLICY_HND *handle)
151 {
152         WERROR result;
153         NTSTATUS status;
154
155         /*
156          * Tell the specific printing tdb we no longer want messages for this printer
157          * by deregistering our PID.
158          */
159
160         if (!print_notify_deregister_pid(snum))
161                 DEBUG(0,("print_notify_register_pid: Failed to register our pid for printer %s\n", lp_const_servicename(snum) ));
162
163         /* weird if the test succeds !!! */
164         if (smb_connections==0) {
165                 DEBUG(0,("srv_spoolss_replycloseprinter:Trying to close non-existant notify backchannel !\n"));
166                 return;
167         }
168
169         status = rpccli_spoolss_ReplyClosePrinter(notify_cli_pipe, talloc_tos(),
170                                                   handle,
171                                                   &result);
172         if (!NT_STATUS_IS_OK(status) || !W_ERROR_IS_OK(result))
173                 DEBUG(0,("srv_spoolss_replycloseprinter: reply_close_printer failed [%s].\n",
174                         win_errstr(result)));
175
176         /* if it's the last connection, deconnect the IPC$ share */
177         if (smb_connections==1) {
178
179                 cli_shutdown( rpc_pipe_np_smb_conn(notify_cli_pipe) );
180                 notify_cli_pipe = NULL; /* The above call shuts downn the pipe also. */
181
182                 messaging_deregister(smbd_messaging_context(),
183                                      MSG_PRINTER_NOTIFY2, NULL);
184
185                 /* Tell the connections db we're no longer interested in
186                  * printer notify messages. */
187
188                 register_message_flags( False, FLAG_MSG_PRINT_NOTIFY );
189         }
190
191         smb_connections--;
192 }
193
194 /****************************************************************************
195  Functions to free a printer entry datastruct.
196 ****************************************************************************/
197
198 static int printer_entry_destructor(Printer_entry *Printer)
199 {
200         if (Printer->notify.client_connected==True) {
201                 int snum = -1;
202
203                 if ( Printer->printer_type == SPLHND_SERVER) {
204                         snum = -1;
205                         srv_spoolss_replycloseprinter(snum, &Printer->notify.client_hnd);
206                 } else if (Printer->printer_type == SPLHND_PRINTER) {
207                         snum = print_queue_snum(Printer->sharename);
208                         if (snum != -1)
209                                 srv_spoolss_replycloseprinter(snum,
210                                                 &Printer->notify.client_hnd);
211                 }
212         }
213
214         Printer->notify.flags=0;
215         Printer->notify.options=0;
216         Printer->notify.localmachine[0]='\0';
217         Printer->notify.printerlocal=0;
218         free_spool_notify_option(&Printer->notify.option);
219         Printer->notify.option=NULL;
220         Printer->notify.client_connected=False;
221
222         free_nt_devicemode( &Printer->nt_devmode );
223         free_a_printer( &Printer->printer_info, 2 );
224
225         /* Remove from the internal list. */
226         DLIST_REMOVE(printers_list, Printer);
227         return 0;
228 }
229
230 /****************************************************************************
231  Functions to duplicate a SPOOL_NOTIFY_OPTION struct stored in Printer_entry.
232 ****************************************************************************/
233
234 static SPOOL_NOTIFY_OPTION *dup_spool_notify_option(SPOOL_NOTIFY_OPTION *sp)
235 {
236         SPOOL_NOTIFY_OPTION *new_sp = NULL;
237
238         if (!sp)
239                 return NULL;
240
241         new_sp = SMB_MALLOC_P(SPOOL_NOTIFY_OPTION);
242         if (!new_sp)
243                 return NULL;
244
245         *new_sp = *sp;
246
247         if (sp->ctr.count) {
248                 new_sp->ctr.type = (SPOOL_NOTIFY_OPTION_TYPE *)memdup(sp->ctr.type, sizeof(SPOOL_NOTIFY_OPTION_TYPE) * sp->ctr.count);
249
250                 if (!new_sp->ctr.type) {
251                         SAFE_FREE(new_sp);
252                         return NULL;
253                 }
254         }
255
256         return new_sp;
257 }
258
259 /****************************************************************************
260   find printer index by handle
261 ****************************************************************************/
262
263 static Printer_entry *find_printer_index_by_hnd(pipes_struct *p, POLICY_HND *hnd)
264 {
265         Printer_entry *find_printer = NULL;
266
267         if(!find_policy_by_hnd(p,hnd,(void **)(void *)&find_printer)) {
268                 DEBUG(2,("find_printer_index_by_hnd: Printer handle not found: "));
269                 return NULL;
270         }
271
272         return find_printer;
273 }
274
275 /****************************************************************************
276  Close printer index by handle.
277 ****************************************************************************/
278
279 static bool close_printer_handle(pipes_struct *p, POLICY_HND *hnd)
280 {
281         Printer_entry *Printer = find_printer_index_by_hnd(p, hnd);
282
283         if (!Printer) {
284                 DEBUG(2,("close_printer_handle: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(hnd)));
285                 return False;
286         }
287
288         close_policy_hnd(p, hnd);
289
290         return True;
291 }
292
293 /****************************************************************************
294  Delete a printer given a handle.
295 ****************************************************************************/
296
297 WERROR delete_printer_hook(TALLOC_CTX *ctx, NT_USER_TOKEN *token, const char *sharename )
298 {
299         char *cmd = lp_deleteprinter_cmd();
300         char *command = NULL;
301         int ret;
302         SE_PRIV se_printop = SE_PRINT_OPERATOR;
303         bool is_print_op = False;
304
305         /* can't fail if we don't try */
306
307         if ( !*cmd )
308                 return WERR_OK;
309
310         command = talloc_asprintf(ctx,
311                         "%s \"%s\"",
312                         cmd, sharename);
313         if (!command) {
314                 return WERR_NOMEM;
315         }
316         if ( token )
317                 is_print_op = user_has_privileges( token, &se_printop );
318
319         DEBUG(10,("Running [%s]\n", command));
320
321         /********** BEGIN SePrintOperatorPrivlege BLOCK **********/
322
323         if ( is_print_op )
324                 become_root();
325
326         if ( (ret = smbrun(command, NULL)) == 0 ) {
327                 /* Tell everyone we updated smb.conf. */
328                 message_send_all(smbd_messaging_context(),
329                                  MSG_SMB_CONF_UPDATED, NULL, 0, NULL);
330         }
331
332         if ( is_print_op )
333                 unbecome_root();
334
335         /********** END SePrintOperatorPrivlege BLOCK **********/
336
337         DEBUGADD(10,("returned [%d]\n", ret));
338
339         TALLOC_FREE(command);
340
341         if (ret != 0)
342                 return WERR_BADFID; /* What to return here? */
343
344         /* go ahead and re-read the services immediately */
345         reload_services( False );
346
347         if ( lp_servicenumber( sharename )  < 0 )
348                 return WERR_ACCESS_DENIED;
349
350         return WERR_OK;
351 }
352
353 /****************************************************************************
354  Delete a printer given a handle.
355 ****************************************************************************/
356
357 static WERROR delete_printer_handle(pipes_struct *p, POLICY_HND *hnd)
358 {
359         Printer_entry *Printer = find_printer_index_by_hnd(p, hnd);
360
361         if (!Printer) {
362                 DEBUG(2,("delete_printer_handle: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(hnd)));
363                 return WERR_BADFID;
364         }
365
366         /*
367          * It turns out that Windows allows delete printer on a handle
368          * opened by an admin user, then used on a pipe handle created
369          * by an anonymous user..... but they're working on security.... riiight !
370          * JRA.
371          */
372
373         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
374                 DEBUG(3, ("delete_printer_handle: denied by handle\n"));
375                 return WERR_ACCESS_DENIED;
376         }
377
378         /* this does not need a become root since the access check has been
379            done on the handle already */
380
381         if (del_a_printer( Printer->sharename ) != 0) {
382                 DEBUG(3,("Error deleting printer %s\n", Printer->sharename));
383                 return WERR_BADFID;
384         }
385
386         return delete_printer_hook(p->mem_ctx, p->server_info->ptok,
387                                    Printer->sharename );
388 }
389
390 /****************************************************************************
391  Return the snum of a printer corresponding to an handle.
392 ****************************************************************************/
393
394 static bool get_printer_snum(pipes_struct *p, POLICY_HND *hnd, int *number,
395                              struct share_params **params)
396 {
397         Printer_entry *Printer = find_printer_index_by_hnd(p, hnd);
398
399         if (!Printer) {
400                 DEBUG(2,("get_printer_snum: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(hnd)));
401                 return False;
402         }
403
404         switch (Printer->printer_type) {
405                 case SPLHND_PRINTER:
406                         DEBUG(4,("short name:%s\n", Printer->sharename));
407                         *number = print_queue_snum(Printer->sharename);
408                         return (*number != -1);
409                 case SPLHND_SERVER:
410                         return False;
411                 default:
412                         return False;
413         }
414 }
415
416 /****************************************************************************
417  Set printer handle type.
418  Check if it's \\server or \\server\printer
419 ****************************************************************************/
420
421 static bool set_printer_hnd_printertype(Printer_entry *Printer, char *handlename)
422 {
423         DEBUG(3,("Setting printer type=%s\n", handlename));
424
425         if ( strlen(handlename) < 3 ) {
426                 DEBUGADD(4,("A print server must have at least 1 char ! %s\n", handlename));
427                 return False;
428         }
429
430         /* it's a print server */
431         if (*handlename=='\\' && *(handlename+1)=='\\' && !strchr_m(handlename+2, '\\')) {
432                 DEBUGADD(4,("Printer is a print server\n"));
433                 Printer->printer_type = SPLHND_SERVER;
434         }
435         /* it's a printer (set_printer_hnd_name() will handle port monitors */
436         else {
437                 DEBUGADD(4,("Printer is a printer\n"));
438                 Printer->printer_type = SPLHND_PRINTER;
439         }
440
441         return True;
442 }
443
444 /****************************************************************************
445  Set printer handle name..  Accept names like \\server, \\server\printer,
446  \\server\SHARE, & "\\server\,XcvMonitor Standard TCP/IP Port"    See
447  the MSDN docs regarding OpenPrinter() for details on the XcvData() and
448  XcvDataPort() interface.
449 ****************************************************************************/
450
451 static bool set_printer_hnd_name(Printer_entry *Printer, char *handlename)
452 {
453         int snum;
454         int n_services=lp_numservices();
455         char *aprinter, *printername;
456         const char *servername;
457         fstring sname;
458         bool found=False;
459         NT_PRINTER_INFO_LEVEL *printer = NULL;
460         WERROR result;
461
462         DEBUG(4,("Setting printer name=%s (len=%lu)\n", handlename, (unsigned long)strlen(handlename)));
463
464         aprinter = handlename;
465         if ( *handlename == '\\' ) {
466                 servername = canon_servername(handlename);
467                 if ( (aprinter = strchr_m( servername, '\\' )) != NULL ) {
468                         *aprinter = '\0';
469                         aprinter++;
470                 }
471         } else {
472                 servername = "";
473         }
474
475         /* save the servername to fill in replies on this handle */
476
477         if ( !is_myname_or_ipaddr( servername ) )
478                 return False;
479
480         fstrcpy( Printer->servername, servername );
481
482         if ( Printer->printer_type == SPLHND_SERVER )
483                 return True;
484
485         if ( Printer->printer_type != SPLHND_PRINTER )
486                 return False;
487
488         DEBUGADD(5, ("searching for [%s]\n", aprinter ));
489
490         /* check for the Port Monitor Interface */
491
492         if ( strequal( aprinter, SPL_XCV_MONITOR_TCPMON ) ) {
493                 Printer->printer_type = SPLHND_PORTMON_TCP;
494                 fstrcpy(sname, SPL_XCV_MONITOR_TCPMON);
495                 found = True;
496         }
497         else if ( strequal( aprinter, SPL_XCV_MONITOR_LOCALMON ) ) {
498                 Printer->printer_type = SPLHND_PORTMON_LOCAL;
499                 fstrcpy(sname, SPL_XCV_MONITOR_LOCALMON);
500                 found = True;
501         }
502
503         /* Search all sharenames first as this is easier than pulling
504            the printer_info_2 off of disk. Don't use find_service() since
505            that calls out to map_username() */
506
507         /* do another loop to look for printernames */
508
509         for (snum=0; !found && snum<n_services; snum++) {
510
511                 /* no point going on if this is not a printer */
512
513                 if ( !(lp_snum_ok(snum) && lp_print_ok(snum)) )
514                         continue;
515
516                 fstrcpy(sname, lp_servicename(snum));
517                 if ( strequal( aprinter, sname ) ) {
518                         found = True;
519                         break;
520                 }
521
522                 /* no point looking up the printer object if
523                    we aren't allowing printername != sharename */
524
525                 if ( lp_force_printername(snum) )
526                         continue;
527
528                 fstrcpy(sname, lp_servicename(snum));
529
530                 printer = NULL;
531
532                 /* This call doesn't fill in the location or comment from
533                  * a CUPS server for efficiency with large numbers of printers.
534                  * JRA.
535                  */
536
537                 result = get_a_printer_search( NULL, &printer, 2, sname );
538                 if ( !W_ERROR_IS_OK(result) ) {
539                         DEBUG(0,("set_printer_hnd_name: failed to lookup printer [%s] -- result [%s]\n",
540                                 sname, win_errstr(result)));
541                         continue;
542                 }
543
544                 /* printername is always returned as \\server\printername */
545                 if ( !(printername = strchr_m(&printer->info_2->printername[2], '\\')) ) {
546                         DEBUG(0,("set_printer_hnd_name: info2->printername in wrong format! [%s]\n",
547                                 printer->info_2->printername));
548                         free_a_printer( &printer, 2);
549                         continue;
550                 }
551
552                 printername++;
553
554                 if ( strequal(printername, aprinter) ) {
555                         free_a_printer( &printer, 2);
556                         found = True;
557                         break;
558                 }
559
560                 DEBUGADD(10, ("printername: %s\n", printername));
561
562                 free_a_printer( &printer, 2);
563         }
564
565         free_a_printer( &printer, 2);
566
567         if ( !found ) {
568                 DEBUGADD(4,("Printer not found\n"));
569                 return False;
570         }
571
572         DEBUGADD(4,("set_printer_hnd_name: Printer found: %s -> %s\n", aprinter, sname));
573
574         fstrcpy(Printer->sharename, sname);
575
576         return True;
577 }
578
579 /****************************************************************************
580  Find first available printer slot. creates a printer handle for you.
581  ****************************************************************************/
582
583 static bool open_printer_hnd(pipes_struct *p, POLICY_HND *hnd, char *name, uint32 access_granted)
584 {
585         Printer_entry *new_printer;
586
587         DEBUG(10,("open_printer_hnd: name [%s]\n", name));
588
589         new_printer = TALLOC_ZERO_P(NULL, Printer_entry);
590         if (new_printer == NULL) {
591                 return false;
592         }
593         talloc_set_destructor(new_printer, printer_entry_destructor);
594
595         if (!create_policy_hnd(p, hnd, new_printer)) {
596                 TALLOC_FREE(new_printer);
597                 return False;
598         }
599
600         /* Add to the internal list. */
601         DLIST_ADD(printers_list, new_printer);
602
603         new_printer->notify.option=NULL;
604
605         if (!set_printer_hnd_printertype(new_printer, name)) {
606                 close_printer_handle(p, hnd);
607                 return False;
608         }
609
610         if (!set_printer_hnd_name(new_printer, name)) {
611                 close_printer_handle(p, hnd);
612                 return False;
613         }
614
615         new_printer->access_granted = access_granted;
616
617         DEBUG(5, ("%d printer handles active\n", (int)p->pipe_handles->count ));
618
619         return True;
620 }
621
622 /***************************************************************************
623  check to see if the client motify handle is monitoring the notification
624  given by (notify_type, notify_field).
625  **************************************************************************/
626
627 static bool is_monitoring_event_flags(uint32 flags, uint16 notify_type,
628                                       uint16 notify_field)
629 {
630         return True;
631 }
632
633 static bool is_monitoring_event(Printer_entry *p, uint16 notify_type,
634                                 uint16 notify_field)
635 {
636         SPOOL_NOTIFY_OPTION *option = p->notify.option;
637         uint32 i, j;
638
639         /*
640          * Flags should always be zero when the change notify
641          * is registered by the client's spooler.  A user Win32 app
642          * might use the flags though instead of the NOTIFY_OPTION_INFO
643          * --jerry
644          */
645
646         if (!option) {
647                 return False;
648         }
649
650         if (p->notify.flags)
651                 return is_monitoring_event_flags(
652                         p->notify.flags, notify_type, notify_field);
653
654         for (i = 0; i < option->count; i++) {
655
656                 /* Check match for notify_type */
657
658                 if (option->ctr.type[i].type != notify_type)
659                         continue;
660
661                 /* Check match for field */
662
663                 for (j = 0; j < option->ctr.type[i].count; j++) {
664                         if (option->ctr.type[i].fields[j] == notify_field) {
665                                 return True;
666                         }
667                 }
668         }
669
670         DEBUG(10, ("Open handle for \\\\%s\\%s is not monitoring 0x%02x/0x%02x\n",
671                    p->servername, p->sharename, notify_type, notify_field));
672
673         return False;
674 }
675
676 #define SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(_data, _integer) \
677         _data->data.integer[0] = _integer; \
678         _data->data.integer[1] = 0;
679
680
681 #define SETUP_SPOOLSS_NOTIFY_DATA_STRING(_data, _p) \
682         _data->data.string.string = talloc_strdup(mem_ctx, _p); \
683         if (!_data->data.string.string) {\
684                 _data->data.string.size = 0; \
685         } \
686         _data->data.string.size = strlen_m_term(_p) * 2;
687
688 #define SETUP_SPOOLSS_NOTIFY_DATA_DEVMODE(_data, _devmode) \
689         _data->data.devmode.devmode = _devmode;
690
691 #define SETUP_SPOOLSS_NOTIFY_DATA_SECDESC(_data, _size, _sd) \
692         _data->data.sd.sd = dup_sec_desc(mem_ctx, _sd); \
693         if (!_data->data.sd.sd) { \
694                 _data->data.sd.sd_size = 0; \
695         } \
696         _data->data.sd.sd_size = _size;
697
698 static void init_systemtime_buffer(TALLOC_CTX *mem_ctx,
699                                    struct tm *t,
700                                    const char **pp,
701                                    uint32_t *plen)
702 {
703         struct spoolss_Time st;
704         uint32_t len = 16;
705         char *p;
706
707         if (!init_systemtime(&st, t)) {
708                 return;
709         }
710
711         p = talloc_array(mem_ctx, char, len);
712         if (!p) {
713                 return;
714         }
715
716         /*
717          * Systemtime must be linearized as a set of UINT16's.
718          * Fix from Benjamin (Bj) Kuit bj@it.uts.edu.au
719          */
720
721         SSVAL(p, 0, st.year);
722         SSVAL(p, 2, st.month);
723         SSVAL(p, 4, st.day_of_week);
724         SSVAL(p, 6, st.day);
725         SSVAL(p, 8, st.hour);
726         SSVAL(p, 10, st.minute);
727         SSVAL(p, 12, st.second);
728         SSVAL(p, 14, st.millisecond);
729
730         *pp = p;
731         *plen = len;
732 }
733
734 /* Convert a notification message to a struct spoolss_Notify */
735
736 static void notify_one_value(struct spoolss_notify_msg *msg,
737                              struct spoolss_Notify *data,
738                              TALLOC_CTX *mem_ctx)
739 {
740         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, msg->notify.value[0]);
741 }
742
743 static void notify_string(struct spoolss_notify_msg *msg,
744                           struct spoolss_Notify *data,
745                           TALLOC_CTX *mem_ctx)
746 {
747         /* The length of the message includes the trailing \0 */
748
749         data->data.string.size = msg->len * 2;
750         data->data.string.string = talloc_strdup(mem_ctx, msg->notify.data);
751         if (!data->data.string.string) {
752                 data->data.string.size = 0;
753                 return;
754         }
755 }
756
757 static void notify_system_time(struct spoolss_notify_msg *msg,
758                                struct spoolss_Notify *data,
759                                TALLOC_CTX *mem_ctx)
760 {
761         data->data.string.string = NULL;
762         data->data.string.size = 0;
763
764         if (msg->len != sizeof(time_t)) {
765                 DEBUG(5, ("notify_system_time: received wrong sized message (%d)\n",
766                           msg->len));
767                 return;
768         }
769
770         init_systemtime_buffer(mem_ctx, gmtime((time_t *)msg->notify.data),
771                                &data->data.string.string,
772                                &data->data.string.size);
773 }
774
775 struct notify2_message_table {
776         const char *name;
777         void (*fn)(struct spoolss_notify_msg *msg,
778                    struct spoolss_Notify *data, TALLOC_CTX *mem_ctx);
779 };
780
781 static struct notify2_message_table printer_notify_table[] = {
782         /* 0x00 */ { "PRINTER_NOTIFY_SERVER_NAME", notify_string },
783         /* 0x01 */ { "PRINTER_NOTIFY_PRINTER_NAME", notify_string },
784         /* 0x02 */ { "PRINTER_NOTIFY_SHARE_NAME", notify_string },
785         /* 0x03 */ { "PRINTER_NOTIFY_PORT_NAME", notify_string },
786         /* 0x04 */ { "PRINTER_NOTIFY_DRIVER_NAME", notify_string },
787         /* 0x05 */ { "PRINTER_NOTIFY_COMMENT", notify_string },
788         /* 0x06 */ { "PRINTER_NOTIFY_LOCATION", notify_string },
789         /* 0x07 */ { "PRINTER_NOTIFY_DEVMODE", NULL },
790         /* 0x08 */ { "PRINTER_NOTIFY_SEPFILE", notify_string },
791         /* 0x09 */ { "PRINTER_NOTIFY_PRINT_PROCESSOR", notify_string },
792         /* 0x0a */ { "PRINTER_NOTIFY_PARAMETERS", NULL },
793         /* 0x0b */ { "PRINTER_NOTIFY_DATATYPE", notify_string },
794         /* 0x0c */ { "PRINTER_NOTIFY_SECURITY_DESCRIPTOR", NULL },
795         /* 0x0d */ { "PRINTER_NOTIFY_ATTRIBUTES", notify_one_value },
796         /* 0x0e */ { "PRINTER_NOTIFY_PRIORITY", notify_one_value },
797         /* 0x0f */ { "PRINTER_NOTIFY_DEFAULT_PRIORITY", NULL },
798         /* 0x10 */ { "PRINTER_NOTIFY_START_TIME", NULL },
799         /* 0x11 */ { "PRINTER_NOTIFY_UNTIL_TIME", NULL },
800         /* 0x12 */ { "PRINTER_NOTIFY_STATUS", notify_one_value },
801 };
802
803 static struct notify2_message_table job_notify_table[] = {
804         /* 0x00 */ { "JOB_NOTIFY_PRINTER_NAME", NULL },
805         /* 0x01 */ { "JOB_NOTIFY_MACHINE_NAME", NULL },
806         /* 0x02 */ { "JOB_NOTIFY_PORT_NAME", NULL },
807         /* 0x03 */ { "JOB_NOTIFY_USER_NAME", notify_string },
808         /* 0x04 */ { "JOB_NOTIFY_NOTIFY_NAME", NULL },
809         /* 0x05 */ { "JOB_NOTIFY_DATATYPE", NULL },
810         /* 0x06 */ { "JOB_NOTIFY_PRINT_PROCESSOR", NULL },
811         /* 0x07 */ { "JOB_NOTIFY_PARAMETERS", NULL },
812         /* 0x08 */ { "JOB_NOTIFY_DRIVER_NAME", NULL },
813         /* 0x09 */ { "JOB_NOTIFY_DEVMODE", NULL },
814         /* 0x0a */ { "JOB_NOTIFY_STATUS", notify_one_value },
815         /* 0x0b */ { "JOB_NOTIFY_STATUS_STRING", NULL },
816         /* 0x0c */ { "JOB_NOTIFY_SECURITY_DESCRIPTOR", NULL },
817         /* 0x0d */ { "JOB_NOTIFY_DOCUMENT", notify_string },
818         /* 0x0e */ { "JOB_NOTIFY_PRIORITY", NULL },
819         /* 0x0f */ { "JOB_NOTIFY_POSITION", NULL },
820         /* 0x10 */ { "JOB_NOTIFY_SUBMITTED", notify_system_time },
821         /* 0x11 */ { "JOB_NOTIFY_START_TIME", NULL },
822         /* 0x12 */ { "JOB_NOTIFY_UNTIL_TIME", NULL },
823         /* 0x13 */ { "JOB_NOTIFY_TIME", NULL },
824         /* 0x14 */ { "JOB_NOTIFY_TOTAL_PAGES", notify_one_value },
825         /* 0x15 */ { "JOB_NOTIFY_PAGES_PRINTED", NULL },
826         /* 0x16 */ { "JOB_NOTIFY_TOTAL_BYTES", notify_one_value },
827         /* 0x17 */ { "JOB_NOTIFY_BYTES_PRINTED", NULL },
828 };
829
830
831 /***********************************************************************
832  Allocate talloc context for container object
833  **********************************************************************/
834
835 static void notify_msg_ctr_init( SPOOLSS_NOTIFY_MSG_CTR *ctr )
836 {
837         if ( !ctr )
838                 return;
839
840         ctr->ctx = talloc_init("notify_msg_ctr_init %p", ctr);
841
842         return;
843 }
844
845 /***********************************************************************
846  release all allocated memory and zero out structure
847  **********************************************************************/
848
849 static void notify_msg_ctr_destroy( SPOOLSS_NOTIFY_MSG_CTR *ctr )
850 {
851         if ( !ctr )
852                 return;
853
854         if ( ctr->ctx )
855                 talloc_destroy(ctr->ctx);
856
857         ZERO_STRUCTP(ctr);
858
859         return;
860 }
861
862 /***********************************************************************
863  **********************************************************************/
864
865 static TALLOC_CTX* notify_ctr_getctx( SPOOLSS_NOTIFY_MSG_CTR *ctr )
866 {
867         if ( !ctr )
868                 return NULL;
869
870         return ctr->ctx;
871 }
872
873 /***********************************************************************
874  **********************************************************************/
875
876 static SPOOLSS_NOTIFY_MSG_GROUP* notify_ctr_getgroup( SPOOLSS_NOTIFY_MSG_CTR *ctr, uint32 idx )
877 {
878         if ( !ctr || !ctr->msg_groups )
879                 return NULL;
880
881         if ( idx >= ctr->num_groups )
882                 return NULL;
883
884         return &ctr->msg_groups[idx];
885
886 }
887
888 /***********************************************************************
889  How many groups of change messages do we have ?
890  **********************************************************************/
891
892 static int notify_msg_ctr_numgroups( SPOOLSS_NOTIFY_MSG_CTR *ctr )
893 {
894         if ( !ctr )
895                 return 0;
896
897         return ctr->num_groups;
898 }
899
900 /***********************************************************************
901  Add a SPOOLSS_NOTIFY_MSG_CTR to the correct group
902  **********************************************************************/
903
904 static int notify_msg_ctr_addmsg( SPOOLSS_NOTIFY_MSG_CTR *ctr, SPOOLSS_NOTIFY_MSG *msg )
905 {
906         SPOOLSS_NOTIFY_MSG_GROUP        *groups = NULL;
907         SPOOLSS_NOTIFY_MSG_GROUP        *msg_grp = NULL;
908         SPOOLSS_NOTIFY_MSG              *msg_list = NULL;
909         int                             i, new_slot;
910
911         if ( !ctr || !msg )
912                 return 0;
913
914         /* loop over all groups looking for a matching printer name */
915
916         for ( i=0; i<ctr->num_groups; i++ ) {
917                 if ( strcmp(ctr->msg_groups[i].printername, msg->printer) == 0 )
918                         break;
919         }
920
921         /* add a new group? */
922
923         if ( i == ctr->num_groups ) {
924                 ctr->num_groups++;
925
926                 if ( !(groups = TALLOC_REALLOC_ARRAY( ctr->ctx, ctr->msg_groups, SPOOLSS_NOTIFY_MSG_GROUP, ctr->num_groups)) ) {
927                         DEBUG(0,("notify_msg_ctr_addmsg: talloc_realloc() failed!\n"));
928                         return 0;
929                 }
930                 ctr->msg_groups = groups;
931
932                 /* clear the new entry and set the printer name */
933
934                 ZERO_STRUCT( ctr->msg_groups[ctr->num_groups-1] );
935                 fstrcpy( ctr->msg_groups[ctr->num_groups-1].printername, msg->printer );
936         }
937
938         /* add the change messages; 'i' is the correct index now regardless */
939
940         msg_grp = &ctr->msg_groups[i];
941
942         msg_grp->num_msgs++;
943
944         if ( !(msg_list = TALLOC_REALLOC_ARRAY( ctr->ctx, msg_grp->msgs, SPOOLSS_NOTIFY_MSG, msg_grp->num_msgs )) ) {
945                 DEBUG(0,("notify_msg_ctr_addmsg: talloc_realloc() failed for new message [%d]!\n", msg_grp->num_msgs));
946                 return 0;
947         }
948         msg_grp->msgs = msg_list;
949
950         new_slot = msg_grp->num_msgs-1;
951         memcpy( &msg_grp->msgs[new_slot], msg, sizeof(SPOOLSS_NOTIFY_MSG) );
952
953         /* need to allocate own copy of data */
954
955         if ( msg->len != 0 )
956                 msg_grp->msgs[new_slot].notify.data = (char *)
957                         TALLOC_MEMDUP( ctr->ctx, msg->notify.data, msg->len );
958
959         return ctr->num_groups;
960 }
961
962 /***********************************************************************
963  Send a change notication message on all handles which have a call
964  back registered
965  **********************************************************************/
966
967 static void send_notify2_changes( SPOOLSS_NOTIFY_MSG_CTR *ctr, uint32 idx )
968 {
969         Printer_entry            *p;
970         TALLOC_CTX               *mem_ctx = notify_ctr_getctx( ctr );
971         SPOOLSS_NOTIFY_MSG_GROUP *msg_group = notify_ctr_getgroup( ctr, idx );
972         SPOOLSS_NOTIFY_MSG       *messages;
973         int                      sending_msg_count;
974
975         if ( !msg_group ) {
976                 DEBUG(5,("send_notify2_changes() called with no msg group!\n"));
977                 return;
978         }
979
980         messages = msg_group->msgs;
981
982         if ( !messages ) {
983                 DEBUG(5,("send_notify2_changes() called with no messages!\n"));
984                 return;
985         }
986
987         DEBUG(8,("send_notify2_changes: Enter...[%s]\n", msg_group->printername));
988
989         /* loop over all printers */
990
991         for (p = printers_list; p; p = p->next) {
992                 struct spoolss_Notify *notifies;
993                 uint32_t count = 0;
994                 uint32_t id;
995                 int     i;
996
997                 /* Is there notification on this handle? */
998
999                 if ( !p->notify.client_connected )
1000                         continue;
1001
1002                 DEBUG(10,("Client connected! [\\\\%s\\%s]\n", p->servername, p->sharename));
1003
1004                 /* For this printer?  Print servers always receive
1005                    notifications. */
1006
1007                 if ( ( p->printer_type == SPLHND_PRINTER )  &&
1008                     ( !strequal(msg_group->printername, p->sharename) ) )
1009                         continue;
1010
1011                 DEBUG(10,("Our printer\n"));
1012
1013                 /* allocate the max entries possible */
1014
1015                 notifies = TALLOC_ZERO_ARRAY(mem_ctx, struct spoolss_Notify, msg_group->num_msgs);
1016                 if (!notifies) {
1017                         return;
1018                 }
1019
1020                 /* build the array of change notifications */
1021
1022                 sending_msg_count = 0;
1023
1024                 for ( i=0; i<msg_group->num_msgs; i++ ) {
1025                         SPOOLSS_NOTIFY_MSG      *msg = &messages[i];
1026
1027                         /* Are we monitoring this event? */
1028
1029                         if (!is_monitoring_event(p, msg->type, msg->field))
1030                                 continue;
1031
1032                         sending_msg_count++;
1033
1034
1035                         DEBUG(10,("process_notify2_message: Sending message type [0x%x] field [0x%2x] for printer [%s]\n",
1036                                 msg->type, msg->field, p->sharename));
1037
1038                         /*
1039                          * if the is a printer notification handle and not a job notification
1040                          * type, then set the id to 0.  Other wise just use what was specified
1041                          * in the message.
1042                          *
1043                          * When registering change notification on a print server handle
1044                          * we always need to send back the id (snum) matching the printer
1045                          * for which the change took place.  For change notify registered
1046                          * on a printer handle, this does not matter and the id should be 0.
1047                          *
1048                          * --jerry
1049                          */
1050
1051                         if ( ( p->printer_type == SPLHND_PRINTER ) && ( msg->type == PRINTER_NOTIFY_TYPE ) )
1052                                 id = 0;
1053                         else
1054                                 id = msg->id;
1055
1056
1057                         /* Convert unix jobid to smb jobid */
1058
1059                         if (msg->flags & SPOOLSS_NOTIFY_MSG_UNIX_JOBID) {
1060                                 id = sysjob_to_jobid(msg->id);
1061
1062                                 if (id == -1) {
1063                                         DEBUG(3, ("no such unix jobid %d\n", msg->id));
1064                                         goto done;
1065                                 }
1066                         }
1067
1068                         construct_info_data( &notifies[count], msg->type, msg->field, id );
1069
1070                         switch(msg->type) {
1071                         case PRINTER_NOTIFY_TYPE:
1072                                 if ( printer_notify_table[msg->field].fn )
1073                                         printer_notify_table[msg->field].fn(msg, &notifies[count], mem_ctx);
1074                                 break;
1075
1076                         case JOB_NOTIFY_TYPE:
1077                                 if ( job_notify_table[msg->field].fn )
1078                                         job_notify_table[msg->field].fn(msg, &notifies[count], mem_ctx);
1079                                 break;
1080
1081                         default:
1082                                 DEBUG(5, ("Unknown notification type %d\n", msg->type));
1083                                 goto done;
1084                         }
1085
1086                         count++;
1087                 }
1088
1089                 if ( sending_msg_count ) {
1090                         NTSTATUS status;
1091                         WERROR werr;
1092                         union spoolss_ReplyPrinterInfo info;
1093                         struct spoolss_NotifyInfo info0;
1094                         uint32_t reply_result;
1095
1096                         info0.version   = 0x2;
1097                         info0.flags     = count ? 0x00020000 /* ??? */ : PRINTER_NOTIFY_INFO_DISCARDED;
1098                         info0.count     = count;
1099                         info0.notifies  = notifies;
1100
1101                         info.info0 = &info0;
1102
1103                         status = rpccli_spoolss_RouterReplyPrinterEx(notify_cli_pipe, mem_ctx,
1104                                                                      &p->notify.client_hnd,
1105                                                                      p->notify.change, /* color */
1106                                                                      p->notify.flags,
1107                                                                      &reply_result,
1108                                                                      0, /* reply_type, must be 0 */
1109                                                                      info,
1110                                                                      &werr);
1111                         if (!NT_STATUS_IS_OK(status) || !W_ERROR_IS_OK(werr)) {
1112                                 DEBUG(1,("RouterReplyPrinterEx to client: %s failed: %s\n",
1113                                         notify_cli_pipe->srv_name_slash,
1114                                         win_errstr(werr)));
1115                         }
1116                         switch (reply_result) {
1117                                 case 0:
1118                                         break;
1119                                 case PRINTER_NOTIFY_INFO_DISCARDED:
1120                                 case PRINTER_NOTIFY_INFO_DISCARDNOTED:
1121                                 case PRINTER_NOTIFY_INFO_COLOR_MISMATCH:
1122                                         break;
1123                                 default:
1124                                         break;
1125                         }
1126                 }
1127         }
1128
1129 done:
1130         DEBUG(8,("send_notify2_changes: Exit...\n"));
1131         return;
1132 }
1133
1134 /***********************************************************************
1135  **********************************************************************/
1136
1137 static bool notify2_unpack_msg( SPOOLSS_NOTIFY_MSG *msg, struct timeval *tv, void *buf, size_t len )
1138 {
1139
1140         uint32 tv_sec, tv_usec;
1141         size_t offset = 0;
1142
1143         /* Unpack message */
1144
1145         offset += tdb_unpack((uint8 *)buf + offset, len - offset, "f",
1146                              msg->printer);
1147
1148         offset += tdb_unpack((uint8 *)buf + offset, len - offset, "ddddddd",
1149                                 &tv_sec, &tv_usec,
1150                                 &msg->type, &msg->field, &msg->id, &msg->len, &msg->flags);
1151
1152         if (msg->len == 0)
1153                 tdb_unpack((uint8 *)buf + offset, len - offset, "dd",
1154                            &msg->notify.value[0], &msg->notify.value[1]);
1155         else
1156                 tdb_unpack((uint8 *)buf + offset, len - offset, "B",
1157                            &msg->len, &msg->notify.data);
1158
1159         DEBUG(3, ("notify2_unpack_msg: got NOTIFY2 message for printer %s, jobid %u type %d, field 0x%02x, flags 0x%04x\n",
1160                   msg->printer, (unsigned int)msg->id, msg->type, msg->field, msg->flags));
1161
1162         tv->tv_sec = tv_sec;
1163         tv->tv_usec = tv_usec;
1164
1165         if (msg->len == 0)
1166                 DEBUG(3, ("notify2_unpack_msg: value1 = %d, value2 = %d\n", msg->notify.value[0],
1167                           msg->notify.value[1]));
1168         else
1169                 dump_data(3, (uint8 *)msg->notify.data, msg->len);
1170
1171         return True;
1172 }
1173
1174 /********************************************************************
1175  Receive a notify2 message list
1176  ********************************************************************/
1177
1178 static void receive_notify2_message_list(struct messaging_context *msg,
1179                                          void *private_data,
1180                                          uint32_t msg_type,
1181                                          struct server_id server_id,
1182                                          DATA_BLOB *data)
1183 {
1184         size_t                  msg_count, i;
1185         char                    *buf = (char *)data->data;
1186         char                    *msg_ptr;
1187         size_t                  msg_len;
1188         SPOOLSS_NOTIFY_MSG      notify;
1189         SPOOLSS_NOTIFY_MSG_CTR  messages;
1190         int                     num_groups;
1191
1192         if (data->length < 4) {
1193                 DEBUG(0,("receive_notify2_message_list: bad message format (len < 4)!\n"));
1194                 return;
1195         }
1196
1197         msg_count = IVAL(buf, 0);
1198         msg_ptr = buf + 4;
1199
1200         DEBUG(5, ("receive_notify2_message_list: got %lu messages in list\n", (unsigned long)msg_count));
1201
1202         if (msg_count == 0) {
1203                 DEBUG(0,("receive_notify2_message_list: bad message format (msg_count == 0) !\n"));
1204                 return;
1205         }
1206
1207         /* initialize the container */
1208
1209         ZERO_STRUCT( messages );
1210         notify_msg_ctr_init( &messages );
1211
1212         /*
1213          * build message groups for each printer identified
1214          * in a change_notify msg.  Remember that a PCN message
1215          * includes the handle returned for the srv_spoolss_replyopenprinter()
1216          * call.  Therefore messages are grouped according to printer handle.
1217          */
1218
1219         for ( i=0; i<msg_count; i++ ) {
1220                 struct timeval msg_tv;
1221
1222                 if (msg_ptr + 4 - buf > data->length) {
1223                         DEBUG(0,("receive_notify2_message_list: bad message format (len > buf_size) !\n"));
1224                         return;
1225                 }
1226
1227                 msg_len = IVAL(msg_ptr,0);
1228                 msg_ptr += 4;
1229
1230                 if (msg_ptr + msg_len - buf > data->length) {
1231                         DEBUG(0,("receive_notify2_message_list: bad message format (bad len) !\n"));
1232                         return;
1233                 }
1234
1235                 /* unpack messages */
1236
1237                 ZERO_STRUCT( notify );
1238                 notify2_unpack_msg( &notify, &msg_tv, msg_ptr, msg_len );
1239                 msg_ptr += msg_len;
1240
1241                 /* add to correct list in container */
1242
1243                 notify_msg_ctr_addmsg( &messages, &notify );
1244
1245                 /* free memory that might have been allocated by notify2_unpack_msg() */
1246
1247                 if ( notify.len != 0 )
1248                         SAFE_FREE( notify.notify.data );
1249         }
1250
1251         /* process each group of messages */
1252
1253         num_groups = notify_msg_ctr_numgroups( &messages );
1254         for ( i=0; i<num_groups; i++ )
1255                 send_notify2_changes( &messages, i );
1256
1257
1258         /* cleanup */
1259
1260         DEBUG(10,("receive_notify2_message_list: processed %u messages\n", (uint32)msg_count ));
1261
1262         notify_msg_ctr_destroy( &messages );
1263
1264         return;
1265 }
1266
1267 /********************************************************************
1268  Send a message to ourself about new driver being installed
1269  so we can upgrade the information for each printer bound to this
1270  driver
1271  ********************************************************************/
1272
1273 static bool srv_spoolss_drv_upgrade_printer(char* drivername)
1274 {
1275         int len = strlen(drivername);
1276
1277         if (!len)
1278                 return False;
1279
1280         DEBUG(10,("srv_spoolss_drv_upgrade_printer: Sending message about driver upgrade [%s]\n",
1281                 drivername));
1282
1283         messaging_send_buf(smbd_messaging_context(), procid_self(),
1284                            MSG_PRINTER_DRVUPGRADE,
1285                            (uint8 *)drivername, len+1);
1286
1287         return True;
1288 }
1289
1290 /**********************************************************************
1291  callback to receive a MSG_PRINTER_DRVUPGRADE message and interate
1292  over all printers, upgrading ones as necessary
1293  **********************************************************************/
1294
1295 void do_drv_upgrade_printer(struct messaging_context *msg,
1296                             void *private_data,
1297                             uint32_t msg_type,
1298                             struct server_id server_id,
1299                             DATA_BLOB *data)
1300 {
1301         fstring drivername;
1302         int snum;
1303         int n_services = lp_numservices();
1304         size_t len;
1305
1306         len = MIN(data->length,sizeof(drivername)-1);
1307         strncpy(drivername, (const char *)data->data, len);
1308
1309         DEBUG(10,("do_drv_upgrade_printer: Got message for new driver [%s]\n", drivername ));
1310
1311         /* Iterate the printer list */
1312
1313         for (snum=0; snum<n_services; snum++)
1314         {
1315                 if (lp_snum_ok(snum) && lp_print_ok(snum) )
1316                 {
1317                         WERROR result;
1318                         NT_PRINTER_INFO_LEVEL *printer = NULL;
1319
1320                         result = get_a_printer(NULL, &printer, 2, lp_const_servicename(snum));
1321                         if (!W_ERROR_IS_OK(result))
1322                                 continue;
1323
1324                         if (printer && printer->info_2 && !strcmp(drivername, printer->info_2->drivername))
1325                         {
1326                                 DEBUG(6,("Updating printer [%s]\n", printer->info_2->printername));
1327
1328                                 /* all we care about currently is the change_id */
1329
1330                                 result = mod_a_printer(printer, 2);
1331                                 if (!W_ERROR_IS_OK(result)) {
1332                                         DEBUG(3,("do_drv_upgrade_printer: mod_a_printer() failed with status [%s]\n",
1333                                                 win_errstr(result)));
1334                                 }
1335                         }
1336
1337                         free_a_printer(&printer, 2);
1338                 }
1339         }
1340
1341         /* all done */
1342 }
1343
1344 /********************************************************************
1345  Update the cache for all printq's with a registered client
1346  connection
1347  ********************************************************************/
1348
1349 void update_monitored_printq_cache( void )
1350 {
1351         Printer_entry *printer = printers_list;
1352         int snum;
1353
1354         /* loop through all printers and update the cache where
1355            client_connected == True */
1356         while ( printer )
1357         {
1358                 if ( (printer->printer_type == SPLHND_PRINTER)
1359                         && printer->notify.client_connected )
1360                 {
1361                         snum = print_queue_snum(printer->sharename);
1362                         print_queue_status( snum, NULL, NULL );
1363                 }
1364
1365                 printer = printer->next;
1366         }
1367
1368         return;
1369 }
1370 /********************************************************************
1371  Send a message to ourself about new driver being installed
1372  so we can upgrade the information for each printer bound to this
1373  driver
1374  ********************************************************************/
1375
1376 static bool srv_spoolss_reset_printerdata(char* drivername)
1377 {
1378         int len = strlen(drivername);
1379
1380         if (!len)
1381                 return False;
1382
1383         DEBUG(10,("srv_spoolss_reset_printerdata: Sending message about resetting printerdata [%s]\n",
1384                 drivername));
1385
1386         messaging_send_buf(smbd_messaging_context(), procid_self(),
1387                            MSG_PRINTERDATA_INIT_RESET,
1388                            (uint8 *)drivername, len+1);
1389
1390         return True;
1391 }
1392
1393 /**********************************************************************
1394  callback to receive a MSG_PRINTERDATA_INIT_RESET message and interate
1395  over all printers, resetting printer data as neessary
1396  **********************************************************************/
1397
1398 void reset_all_printerdata(struct messaging_context *msg,
1399                            void *private_data,
1400                            uint32_t msg_type,
1401                            struct server_id server_id,
1402                            DATA_BLOB *data)
1403 {
1404         fstring drivername;
1405         int snum;
1406         int n_services = lp_numservices();
1407         size_t len;
1408
1409         len = MIN( data->length, sizeof(drivername)-1 );
1410         strncpy( drivername, (const char *)data->data, len );
1411
1412         DEBUG(10,("reset_all_printerdata: Got message for new driver [%s]\n", drivername ));
1413
1414         /* Iterate the printer list */
1415
1416         for ( snum=0; snum<n_services; snum++ )
1417         {
1418                 if ( lp_snum_ok(snum) && lp_print_ok(snum) )
1419                 {
1420                         WERROR result;
1421                         NT_PRINTER_INFO_LEVEL *printer = NULL;
1422
1423                         result = get_a_printer( NULL, &printer, 2, lp_const_servicename(snum) );
1424                         if ( !W_ERROR_IS_OK(result) )
1425                                 continue;
1426
1427                         /*
1428                          * if the printer is bound to the driver,
1429                          * then reset to the new driver initdata
1430                          */
1431
1432                         if ( printer && printer->info_2 && !strcmp(drivername, printer->info_2->drivername) )
1433                         {
1434                                 DEBUG(6,("reset_all_printerdata: Updating printer [%s]\n", printer->info_2->printername));
1435
1436                                 if ( !set_driver_init(printer, 2) ) {
1437                                         DEBUG(5,("reset_all_printerdata: Error resetting printer data for printer [%s], driver [%s]!\n",
1438                                                 printer->info_2->printername, printer->info_2->drivername));
1439                                 }
1440
1441                                 result = mod_a_printer( printer, 2 );
1442                                 if ( !W_ERROR_IS_OK(result) ) {
1443                                         DEBUG(3,("reset_all_printerdata: mod_a_printer() failed!  (%s)\n",
1444                                                 get_dos_error_msg(result)));
1445                                 }
1446                         }
1447
1448                         free_a_printer( &printer, 2 );
1449                 }
1450         }
1451
1452         /* all done */
1453
1454         return;
1455 }
1456
1457 /****************************************************************
1458  _spoolss_OpenPrinter
1459 ****************************************************************/
1460
1461 WERROR _spoolss_OpenPrinter(pipes_struct *p,
1462                             struct spoolss_OpenPrinter *r)
1463 {
1464         struct spoolss_OpenPrinterEx e;
1465         WERROR werr;
1466
1467         ZERO_STRUCT(e.in.userlevel);
1468
1469         e.in.printername        = r->in.printername;
1470         e.in.datatype           = r->in.datatype;
1471         e.in.devmode_ctr        = r->in.devmode_ctr;
1472         e.in.access_mask        = r->in.access_mask;
1473         e.in.level              = 0;
1474
1475         e.out.handle            = r->out.handle;
1476
1477         werr = _spoolss_OpenPrinterEx(p, &e);
1478
1479         if (W_ERROR_EQUAL(werr, WERR_INVALID_PARAM)) {
1480                 /* OpenPrinterEx returns this for a bad
1481                  * printer name. We must return WERR_INVALID_PRINTER_NAME
1482                  * instead.
1483                  */
1484                 werr = WERR_INVALID_PRINTER_NAME;
1485         }
1486
1487         return werr;
1488 }
1489
1490 /********************************************************************
1491  FIXME: temporary convert_devicemode_new function
1492  ********************************************************************/
1493
1494 static bool convert_devicemode_new(const char *printername,
1495                                    struct spoolss_DeviceMode *devmode,
1496                                    NT_DEVICEMODE **pp_nt_devmode)
1497 {
1498         NT_DEVICEMODE *nt_devmode = *pp_nt_devmode;
1499
1500         /*
1501          * Ensure nt_devmode is a valid pointer
1502          * as we will be overwriting it.
1503          */
1504
1505         if (nt_devmode == NULL) {
1506                 DEBUG(5, ("convert_devicemode_new: allocating a generic devmode\n"));
1507                 if ((nt_devmode = construct_nt_devicemode(printername)) == NULL)
1508                         return false;
1509         }
1510
1511         rpcstr_push(nt_devmode->devicename, devmode->devicename, 31, 0);
1512         rpcstr_push(nt_devmode->formname, devmode->formname, 31, 0);
1513
1514         nt_devmode->specversion         = devmode->specversion;
1515         nt_devmode->driverversion       = devmode->driverversion;
1516         nt_devmode->size                = devmode->size;
1517         nt_devmode->fields              = devmode->fields;
1518         nt_devmode->orientation         = devmode->orientation;
1519         nt_devmode->papersize           = devmode->papersize;
1520         nt_devmode->paperlength         = devmode->paperlength;
1521         nt_devmode->paperwidth          = devmode->paperwidth;
1522         nt_devmode->scale               = devmode->scale;
1523         nt_devmode->copies              = devmode->copies;
1524         nt_devmode->defaultsource       = devmode->defaultsource;
1525         nt_devmode->printquality        = devmode->printquality;
1526         nt_devmode->color               = devmode->color;
1527         nt_devmode->duplex              = devmode->duplex;
1528         nt_devmode->yresolution         = devmode->yresolution;
1529         nt_devmode->ttoption            = devmode->ttoption;
1530         nt_devmode->collate             = devmode->collate;
1531
1532         nt_devmode->logpixels           = devmode->logpixels;
1533         nt_devmode->bitsperpel          = devmode->bitsperpel;
1534         nt_devmode->pelswidth           = devmode->pelswidth;
1535         nt_devmode->pelsheight          = devmode->pelsheight;
1536         nt_devmode->displayflags        = devmode->displayflags;
1537         nt_devmode->displayfrequency    = devmode->displayfrequency;
1538         nt_devmode->icmmethod           = devmode->icmmethod;
1539         nt_devmode->icmintent           = devmode->icmintent;
1540         nt_devmode->mediatype           = devmode->mediatype;
1541         nt_devmode->dithertype          = devmode->dithertype;
1542         nt_devmode->reserved1           = devmode->reserved1;
1543         nt_devmode->reserved2           = devmode->reserved2;
1544         nt_devmode->panningwidth        = devmode->panningwidth;
1545         nt_devmode->panningheight       = devmode->panningheight;
1546
1547         /*
1548          * Only change private and driverextra if the incoming devmode
1549          * has a new one. JRA.
1550          */
1551
1552         if ((devmode->__driverextra_length != 0) && (devmode->driverextra_data.data != NULL)) {
1553                 SAFE_FREE(nt_devmode->nt_dev_private);
1554                 nt_devmode->driverextra = devmode->__driverextra_length;
1555                 if((nt_devmode->nt_dev_private=SMB_MALLOC_ARRAY(uint8, nt_devmode->driverextra)) == NULL)
1556                         return false;
1557                 memcpy(nt_devmode->nt_dev_private, devmode->driverextra_data.data, nt_devmode->driverextra);
1558         }
1559
1560         *pp_nt_devmode = nt_devmode;
1561
1562         return true;
1563 }
1564
1565 /****************************************************************
1566  _spoolss_OpenPrinterEx
1567 ****************************************************************/
1568
1569 WERROR _spoolss_OpenPrinterEx(pipes_struct *p,
1570                               struct spoolss_OpenPrinterEx *r)
1571 {
1572         POLICY_HND              *handle = r->out.handle;
1573         char *name = CONST_DISCARD(char *, r->in.printername);
1574         int snum;
1575         Printer_entry *Printer=NULL;
1576
1577         if (!name) {
1578                 return WERR_INVALID_PARAM;
1579         }
1580
1581         /* some sanity check because you can open a printer or a print server */
1582         /* aka: \\server\printer or \\server */
1583
1584         DEBUGADD(3,("checking name: %s\n",name));
1585
1586         if (!open_printer_hnd(p, handle, name, 0)) {
1587                 ZERO_STRUCTP(r->out.handle);
1588                 return WERR_INVALID_PARAM;
1589         }
1590
1591         Printer=find_printer_index_by_hnd(p, handle);
1592         if ( !Printer ) {
1593                 DEBUG(0,("_spoolss_OpenPrinterEx: logic error.  Can't find printer "
1594                         "handle we created for printer %s\n", name ));
1595                 close_printer_handle(p,handle);
1596                 ZERO_STRUCTP(r->out.handle);
1597                 return WERR_INVALID_PARAM;
1598         }
1599
1600         /*
1601          * First case: the user is opening the print server:
1602          *
1603          * Disallow MS AddPrinterWizard if parameter disables it. A Win2k
1604          * client 1st tries an OpenPrinterEx with access==0, MUST be allowed.
1605          *
1606          * Then both Win2k and WinNT clients try an OpenPrinterEx with
1607          * SERVER_ALL_ACCESS, which we allow only if the user is root (uid=0)
1608          * or if the user is listed in the smb.conf printer admin parameter.
1609          *
1610          * Then they try OpenPrinterEx with SERVER_READ which we allow. This lets the
1611          * client view printer folder, but does not show the MSAPW.
1612          *
1613          * Note: this test needs code to check access rights here too. Jeremy
1614          * could you look at this?
1615          *
1616          * Second case: the user is opening a printer:
1617          * NT doesn't let us connect to a printer if the connecting user
1618          * doesn't have print permission.
1619          *
1620          * Third case: user is opening a Port Monitor
1621          * access checks same as opening a handle to the print server.
1622          */
1623
1624         switch (Printer->printer_type )
1625         {
1626         case SPLHND_SERVER:
1627         case SPLHND_PORTMON_TCP:
1628         case SPLHND_PORTMON_LOCAL:
1629                 /* Printserver handles use global struct... */
1630
1631                 snum = -1;
1632
1633                 /* Map standard access rights to object specific access rights */
1634
1635                 se_map_standard(&r->in.access_mask,
1636                                 &printserver_std_mapping);
1637
1638                 /* Deny any object specific bits that don't apply to print
1639                    servers (i.e printer and job specific bits) */
1640
1641                 r->in.access_mask &= SPECIFIC_RIGHTS_MASK;
1642
1643                 if (r->in.access_mask &
1644                     ~(SERVER_ACCESS_ADMINISTER | SERVER_ACCESS_ENUMERATE)) {
1645                         DEBUG(3, ("access DENIED for non-printserver bits\n"));
1646                         close_printer_handle(p, handle);
1647                         ZERO_STRUCTP(r->out.handle);
1648                         return WERR_ACCESS_DENIED;
1649                 }
1650
1651                 /* Allow admin access */
1652
1653                 if ( r->in.access_mask & SERVER_ACCESS_ADMINISTER )
1654                 {
1655                         SE_PRIV se_printop = SE_PRINT_OPERATOR;
1656
1657                         if (!lp_ms_add_printer_wizard()) {
1658                                 close_printer_handle(p, handle);
1659                                 ZERO_STRUCTP(r->out.handle);
1660                                 return WERR_ACCESS_DENIED;
1661                         }
1662
1663                         /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
1664                            and not a printer admin, then fail */
1665
1666                         if ((p->server_info->utok.uid != 0) &&
1667                             !user_has_privileges(p->server_info->ptok,
1668                                                  &se_printop ) &&
1669                             !token_contains_name_in_list(
1670                                     uidtoname(p->server_info->utok.uid),
1671                                     NULL, NULL,
1672                                     p->server_info->ptok,
1673                                     lp_printer_admin(snum))) {
1674                                 close_printer_handle(p, handle);
1675                                 ZERO_STRUCTP(r->out.handle);
1676                                 return WERR_ACCESS_DENIED;
1677                         }
1678
1679                         r->in.access_mask = SERVER_ACCESS_ADMINISTER;
1680                 }
1681                 else
1682                 {
1683                         r->in.access_mask = SERVER_ACCESS_ENUMERATE;
1684                 }
1685
1686                 DEBUG(4,("Setting print server access = %s\n", (r->in.access_mask == SERVER_ACCESS_ADMINISTER)
1687                         ? "SERVER_ACCESS_ADMINISTER" : "SERVER_ACCESS_ENUMERATE" ));
1688
1689                 /* We fall through to return WERR_OK */
1690                 break;
1691
1692         case SPLHND_PRINTER:
1693                 /* NT doesn't let us connect to a printer if the connecting user
1694                    doesn't have print permission.  */
1695
1696                 if (!get_printer_snum(p, handle, &snum, NULL)) {
1697                         close_printer_handle(p, handle);
1698                         ZERO_STRUCTP(r->out.handle);
1699                         return WERR_BADFID;
1700                 }
1701
1702                 se_map_standard(&r->in.access_mask, &printer_std_mapping);
1703
1704                 /* map an empty access mask to the minimum access mask */
1705                 if (r->in.access_mask == 0x0)
1706                         r->in.access_mask = PRINTER_ACCESS_USE;
1707
1708                 /*
1709                  * If we are not serving the printer driver for this printer,
1710                  * map PRINTER_ACCESS_ADMINISTER to PRINTER_ACCESS_USE.  This
1711                  * will keep NT clients happy  --jerry
1712                  */
1713
1714                 if (lp_use_client_driver(snum)
1715                         && (r->in.access_mask & PRINTER_ACCESS_ADMINISTER))
1716                 {
1717                         r->in.access_mask = PRINTER_ACCESS_USE;
1718                 }
1719
1720                 /* check smb.conf parameters and the the sec_desc */
1721
1722                 if ( !check_access(get_client_fd(), lp_hostsallow(snum), lp_hostsdeny(snum)) ) {
1723                         DEBUG(3, ("access DENIED (hosts allow/deny) for printer open\n"));
1724                         ZERO_STRUCTP(r->out.handle);
1725                         return WERR_ACCESS_DENIED;
1726                 }
1727
1728                 if (!user_ok_token(uidtoname(p->server_info->utok.uid), NULL,
1729                                    p->server_info->ptok, snum) ||
1730                     !print_access_check(p->server_info, snum,
1731                                         r->in.access_mask)) {
1732                         DEBUG(3, ("access DENIED for printer open\n"));
1733                         close_printer_handle(p, handle);
1734                         ZERO_STRUCTP(r->out.handle);
1735                         return WERR_ACCESS_DENIED;
1736                 }
1737
1738                 if ((r->in.access_mask & SPECIFIC_RIGHTS_MASK)& ~(PRINTER_ACCESS_ADMINISTER|PRINTER_ACCESS_USE)) {
1739                         DEBUG(3, ("access DENIED for printer open - unknown bits\n"));
1740                         close_printer_handle(p, handle);
1741                         ZERO_STRUCTP(r->out.handle);
1742                         return WERR_ACCESS_DENIED;
1743                 }
1744
1745                 if (r->in.access_mask & PRINTER_ACCESS_ADMINISTER)
1746                         r->in.access_mask = PRINTER_ACCESS_ADMINISTER;
1747                 else
1748                         r->in.access_mask = PRINTER_ACCESS_USE;
1749
1750                 DEBUG(4,("Setting printer access = %s\n", (r->in.access_mask == PRINTER_ACCESS_ADMINISTER)
1751                         ? "PRINTER_ACCESS_ADMINISTER" : "PRINTER_ACCESS_USE" ));
1752
1753                 break;
1754
1755         default:
1756                 /* sanity check to prevent programmer error */
1757                 ZERO_STRUCTP(r->out.handle);
1758                 return WERR_BADFID;
1759         }
1760
1761         Printer->access_granted = r->in.access_mask;
1762
1763         /*
1764          * If the client sent a devmode in the OpenPrinter() call, then
1765          * save it here in case we get a job submission on this handle
1766          */
1767
1768          if ( (Printer->printer_type != SPLHND_SERVER)
1769                 && r->in.devmode_ctr.devmode )
1770          {
1771                 convert_devicemode_new(Printer->sharename,
1772                                        r->in.devmode_ctr.devmode,
1773                                        &Printer->nt_devmode);
1774          }
1775
1776 #if 0   /* JERRY -- I'm doubtful this is really effective */
1777         /* HACK ALERT!!! Sleep for 1/3 of a second to try trigger a LAN/WAN
1778            optimization in Windows 2000 clients  --jerry */
1779
1780         if ( (r->in.access_mask == PRINTER_ACCESS_ADMINISTER)
1781                 && (RA_WIN2K == get_remote_arch()) )
1782         {
1783                 DEBUG(10,("_spoolss_OpenPrinterEx: Enabling LAN/WAN hack for Win2k clients.\n"));
1784                 sys_usleep( 500000 );
1785         }
1786 #endif
1787
1788         return WERR_OK;
1789 }
1790
1791 /****************************************************************************
1792 ****************************************************************************/
1793
1794 static bool printer_info2_to_nt_printer_info2(struct spoolss_SetPrinterInfo2 *r,
1795                                               NT_PRINTER_INFO_LEVEL_2 *d)
1796 {
1797         DEBUG(7,("printer_info2_to_nt_printer_info2\n"));
1798
1799         if (!r || !d) {
1800                 return false;
1801         }
1802
1803         d->attributes           = r->attributes;
1804         d->priority             = r->priority;
1805         d->default_priority     = r->defaultpriority;
1806         d->starttime            = r->starttime;
1807         d->untiltime            = r->untiltime;
1808         d->status               = r->status;
1809         d->cjobs                = r->cjobs;
1810
1811         fstrcpy(d->servername,  r->servername);
1812         fstrcpy(d->printername, r->printername);
1813         fstrcpy(d->sharename,   r->sharename);
1814         fstrcpy(d->portname,    r->portname);
1815         fstrcpy(d->drivername,  r->drivername);
1816         slprintf(d->comment, sizeof(d->comment)-1, "%s", r->comment);
1817         fstrcpy(d->location,    r->location);
1818         fstrcpy(d->sepfile,     r->sepfile);
1819         fstrcpy(d->printprocessor, r->printprocessor);
1820         fstrcpy(d->datatype,    r->datatype);
1821         fstrcpy(d->parameters,  r->parameters);
1822
1823         return true;
1824 }
1825
1826 /****************************************************************************
1827 ****************************************************************************/
1828
1829 static bool convert_printer_info_new(struct spoolss_SetPrinterInfoCtr *info_ctr,
1830                                      NT_PRINTER_INFO_LEVEL *printer)
1831 {
1832         bool ret;
1833
1834         switch (info_ctr->level) {
1835         case 2:
1836                 /* allocate memory if needed.  Messy because
1837                    convert_printer_info is used to update an existing
1838                    printer or build a new one */
1839
1840                 if (!printer->info_2) {
1841                         printer->info_2 = TALLOC_ZERO_P(printer, NT_PRINTER_INFO_LEVEL_2);
1842                         if (!printer->info_2) {
1843                                 DEBUG(0,("convert_printer_info_new: "
1844                                         "talloc() failed!\n"));
1845                                 return false;
1846                         }
1847                 }
1848
1849                 ret = printer_info2_to_nt_printer_info2(info_ctr->info.info2,
1850                                                         printer->info_2);
1851                 printer->info_2->setuptime = time(NULL);
1852                 return ret;
1853         }
1854
1855         return false;
1856 }
1857
1858 /*******************************************************************
1859 ********************************************************************/
1860
1861 static bool string_array_to_fstring_array(const char **sarray, fstring **farray)
1862 {
1863         int i;
1864
1865         if (!sarray) {
1866                 *farray = NULL;
1867                 return true;
1868         }
1869
1870         *farray = SMB_MALLOC_ARRAY(fstring, 1);
1871         if (!*farray) {
1872                 return false;
1873         }
1874
1875         for (i=0; sarray[i] != NULL; i++) {
1876                 *farray = SMB_REALLOC_ARRAY(*farray, fstring, i+2);
1877                 if (!*farray) {
1878                         return false;
1879                 }
1880                 fstrcpy((*farray)[i], sarray[i]);
1881         }
1882
1883         fstrcpy((*farray)[i], "");
1884
1885         return true;
1886 }
1887
1888 /*******************************************************************
1889 ********************************************************************/
1890
1891 static bool driver_info3_to_nt_driver_info3(struct spoolss_AddDriverInfo3 *r,
1892                                             NT_PRINTER_DRIVER_INFO_LEVEL_3 **p)
1893 {
1894         NT_PRINTER_DRIVER_INFO_LEVEL_3 *d;
1895
1896         DEBUG(7,("driver_info3_to_nt_driver_info3: Converting from UNICODE to ASCII\n"));
1897
1898         if (*p == NULL) {
1899                 *p = SMB_MALLOC_P(NT_PRINTER_DRIVER_INFO_LEVEL_3);
1900                 if (*p == NULL) {
1901                         return false;
1902                 }
1903                 ZERO_STRUCTP(*p);
1904         }
1905
1906         d = *p;
1907
1908         d->cversion =                   r->version;
1909
1910         fstrcpy(d->name,                r->driver_name);
1911         fstrcpy(d->environment,         r->architecture);
1912         fstrcpy(d->driverpath,          r->driver_path);
1913         fstrcpy(d->datafile,            r->data_file);
1914         fstrcpy(d->configfile,          r->config_file);
1915         fstrcpy(d->helpfile,            r->help_file);
1916         fstrcpy(d->monitorname,         r->monitor_name);
1917         fstrcpy(d->defaultdatatype,     r->default_datatype);
1918
1919         DEBUGADD(8,( "version:         %d\n", d->cversion));
1920         DEBUGADD(8,( "name:            %s\n", d->name));
1921         DEBUGADD(8,( "environment:     %s\n", d->environment));
1922         DEBUGADD(8,( "driverpath:      %s\n", d->driverpath));
1923         DEBUGADD(8,( "datafile:        %s\n", d->datafile));
1924         DEBUGADD(8,( "configfile:      %s\n", d->configfile));
1925         DEBUGADD(8,( "helpfile:        %s\n", d->helpfile));
1926         DEBUGADD(8,( "monitorname:     %s\n", d->monitorname));
1927         DEBUGADD(8,( "defaultdatatype: %s\n", d->defaultdatatype));
1928
1929         if (r->dependent_files) {
1930                 if (!string_array_to_fstring_array(r->dependent_files->string,
1931                                                    &d->dependentfiles)) {
1932                         SAFE_FREE(*p);
1933                         return false;
1934                 }
1935         }
1936
1937         return true;
1938 }
1939
1940 /*******************************************************************
1941 ********************************************************************/
1942
1943 static bool driver_info6_to_nt_driver_info6(struct spoolss_AddDriverInfo6 *r,
1944                                             NT_PRINTER_DRIVER_INFO_LEVEL_6 **p)
1945 {
1946         NT_PRINTER_DRIVER_INFO_LEVEL_6 *d;
1947
1948         DEBUG(7,("driver_info6_to_nt_driver_info6: Converting from UNICODE to ASCII\n"));
1949
1950         if (*p == NULL) {
1951                 *p = SMB_MALLOC_P(NT_PRINTER_DRIVER_INFO_LEVEL_6);
1952                 if (*p == NULL) {
1953                         return false;
1954                 }
1955                 ZERO_STRUCTP(*p);
1956         }
1957
1958         d = *p;
1959
1960         d->version =                    r->version;
1961
1962         fstrcpy(d->name,                r->driver_name);
1963         fstrcpy(d->environment,         r->architecture);
1964         fstrcpy(d->driverpath,          r->driver_path);
1965         fstrcpy(d->datafile,            r->data_file);
1966         fstrcpy(d->configfile,          r->config_file);
1967         fstrcpy(d->helpfile,            r->help_file);
1968         fstrcpy(d->monitorname,         r->monitor_name);
1969         fstrcpy(d->defaultdatatype,     r->default_datatype);
1970
1971         DEBUGADD(8,( "version:         %d\n", d->version));
1972         DEBUGADD(8,( "name:            %s\n", d->name));
1973         DEBUGADD(8,( "environment:     %s\n", d->environment));
1974         DEBUGADD(8,( "driverpath:      %s\n", d->driverpath));
1975         DEBUGADD(8,( "datafile:        %s\n", d->datafile));
1976         DEBUGADD(8,( "configfile:      %s\n", d->configfile));
1977         DEBUGADD(8,( "helpfile:        %s\n", d->helpfile));
1978         DEBUGADD(8,( "monitorname:     %s\n", d->monitorname));
1979         DEBUGADD(8,( "defaultdatatype: %s\n", d->defaultdatatype));
1980
1981         if (r->dependent_files) {
1982                 if (!string_array_to_fstring_array(r->dependent_files->string,
1983                                                    &d->dependentfiles)) {
1984                         goto error;
1985                 }
1986         }
1987
1988         if (r->previous_names) {
1989                 if (!string_array_to_fstring_array(r->previous_names->string,
1990                                                    &d->previousnames)) {
1991                         goto error;
1992                 }
1993         }
1994
1995         return true;
1996
1997  error:
1998         SAFE_FREE(*p);
1999         return false;
2000 }
2001
2002 /********************************************************************
2003  ********************************************************************/
2004
2005 static bool convert_printer_driver_info(const struct spoolss_AddDriverInfoCtr *r,
2006                                         NT_PRINTER_DRIVER_INFO_LEVEL *printer,
2007                                         uint32_t level)
2008 {
2009         switch (level) {
2010         case 3:
2011                 printer->info_3 = NULL;
2012                 if (!driver_info3_to_nt_driver_info3(r->info.info3, &printer->info_3)) {
2013                         return false;
2014                 }
2015                 break;
2016         case 6:
2017                 printer->info_6 = NULL;
2018                 if (!driver_info6_to_nt_driver_info6(r->info.info6, &printer->info_6)) {
2019                         return false;
2020                 }
2021                 break;
2022         default:
2023                 return false;
2024         }
2025
2026         return true;
2027 }
2028
2029 bool convert_devicemode(const char *printername, const DEVICEMODE *devmode,
2030                                 NT_DEVICEMODE **pp_nt_devmode)
2031 {
2032         NT_DEVICEMODE *nt_devmode = *pp_nt_devmode;
2033
2034         /*
2035          * Ensure nt_devmode is a valid pointer
2036          * as we will be overwriting it.
2037          */
2038
2039         if (nt_devmode == NULL) {
2040                 DEBUG(5, ("convert_devicemode: allocating a generic devmode\n"));
2041                 if ((nt_devmode = construct_nt_devicemode(printername)) == NULL)
2042                         return False;
2043         }
2044
2045         rpcstr_pull(nt_devmode->devicename,devmode->devicename.buffer, 31, -1, 0);
2046         rpcstr_pull(nt_devmode->formname,devmode->formname.buffer, 31, -1, 0);
2047
2048         nt_devmode->specversion=devmode->specversion;
2049         nt_devmode->driverversion=devmode->driverversion;
2050         nt_devmode->size=devmode->size;
2051         nt_devmode->fields=devmode->fields;
2052         nt_devmode->orientation=devmode->orientation;
2053         nt_devmode->papersize=devmode->papersize;
2054         nt_devmode->paperlength=devmode->paperlength;
2055         nt_devmode->paperwidth=devmode->paperwidth;
2056         nt_devmode->scale=devmode->scale;
2057         nt_devmode->copies=devmode->copies;
2058         nt_devmode->defaultsource=devmode->defaultsource;
2059         nt_devmode->printquality=devmode->printquality;
2060         nt_devmode->color=devmode->color;
2061         nt_devmode->duplex=devmode->duplex;
2062         nt_devmode->yresolution=devmode->yresolution;
2063         nt_devmode->ttoption=devmode->ttoption;
2064         nt_devmode->collate=devmode->collate;
2065
2066         nt_devmode->logpixels=devmode->logpixels;
2067         nt_devmode->bitsperpel=devmode->bitsperpel;
2068         nt_devmode->pelswidth=devmode->pelswidth;
2069         nt_devmode->pelsheight=devmode->pelsheight;
2070         nt_devmode->displayflags=devmode->displayflags;
2071         nt_devmode->displayfrequency=devmode->displayfrequency;
2072         nt_devmode->icmmethod=devmode->icmmethod;
2073         nt_devmode->icmintent=devmode->icmintent;
2074         nt_devmode->mediatype=devmode->mediatype;
2075         nt_devmode->dithertype=devmode->dithertype;
2076         nt_devmode->reserved1=devmode->reserved1;
2077         nt_devmode->reserved2=devmode->reserved2;
2078         nt_devmode->panningwidth=devmode->panningwidth;
2079         nt_devmode->panningheight=devmode->panningheight;
2080
2081         /*
2082          * Only change private and driverextra if the incoming devmode
2083          * has a new one. JRA.
2084          */
2085
2086         if ((devmode->driverextra != 0) && (devmode->dev_private != NULL)) {
2087                 SAFE_FREE(nt_devmode->nt_dev_private);
2088                 nt_devmode->driverextra=devmode->driverextra;
2089                 if((nt_devmode->nt_dev_private=SMB_MALLOC_ARRAY(uint8, nt_devmode->driverextra)) == NULL)
2090                         return False;
2091                 memcpy(nt_devmode->nt_dev_private, devmode->dev_private, nt_devmode->driverextra);
2092         }
2093
2094         *pp_nt_devmode = nt_devmode;
2095
2096         return True;
2097 }
2098
2099 /********************************************************************
2100  * _spoolss_enddocprinter_internal.
2101  ********************************************************************/
2102
2103 static WERROR _spoolss_enddocprinter_internal(pipes_struct *p, POLICY_HND *handle)
2104 {
2105         Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
2106         int snum;
2107
2108         if (!Printer) {
2109                 DEBUG(2,("_spoolss_enddocprinter_internal: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
2110                 return WERR_BADFID;
2111         }
2112
2113         if (!get_printer_snum(p, handle, &snum, NULL))
2114                 return WERR_BADFID;
2115
2116         Printer->document_started=False;
2117         print_job_end(snum, Printer->jobid,NORMAL_CLOSE);
2118         /* error codes unhandled so far ... */
2119
2120         return WERR_OK;
2121 }
2122
2123 /****************************************************************
2124  _spoolss_ClosePrinter
2125 ****************************************************************/
2126
2127 WERROR _spoolss_ClosePrinter(pipes_struct *p,
2128                              struct spoolss_ClosePrinter *r)
2129 {
2130         POLICY_HND *handle = r->in.handle;
2131
2132         Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
2133
2134         if (Printer && Printer->document_started)
2135                 _spoolss_enddocprinter_internal(p, handle);          /* print job was not closed */
2136
2137         if (!close_printer_handle(p, handle))
2138                 return WERR_BADFID;
2139
2140         /* clear the returned printer handle.  Observed behavior
2141            from Win2k server.  Don't think this really matters.
2142            Previous code just copied the value of the closed
2143            handle.    --jerry */
2144
2145         ZERO_STRUCTP(r->out.handle);
2146
2147         return WERR_OK;
2148 }
2149
2150 /****************************************************************
2151  _spoolss_DeletePrinter
2152 ****************************************************************/
2153
2154 WERROR _spoolss_DeletePrinter(pipes_struct *p,
2155                               struct spoolss_DeletePrinter *r)
2156 {
2157         POLICY_HND *handle = r->in.handle;
2158         Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
2159         WERROR result;
2160
2161         if (Printer && Printer->document_started)
2162                 _spoolss_enddocprinter_internal(p, handle);  /* print job was not closed */
2163
2164         result = delete_printer_handle(p, handle);
2165
2166         update_c_setprinter(False);
2167
2168         return result;
2169 }
2170
2171 /*******************************************************************
2172  * static function to lookup the version id corresponding to an
2173  * long architecture string
2174  ******************************************************************/
2175
2176 static int get_version_id (char * arch)
2177 {
2178         int i;
2179         struct table_node archi_table[]= {
2180
2181                 {"Windows 4.0",          "WIN40",       0 },
2182                 {"Windows NT x86",       "W32X86",      2 },
2183                 {"Windows NT R4000",     "W32MIPS",     2 },
2184                 {"Windows NT Alpha_AXP", "W32ALPHA",    2 },
2185                 {"Windows NT PowerPC",   "W32PPC",      2 },
2186                 {"Windows IA64",         "IA64",        3 },
2187                 {"Windows x64",          "x64",         3 },
2188                 {NULL,                   "",            -1 }
2189         };
2190
2191         for (i=0; archi_table[i].long_archi != NULL; i++)
2192         {
2193                 if (strcmp(arch, archi_table[i].long_archi) == 0)
2194                         return (archi_table[i].version);
2195         }
2196
2197         return -1;
2198 }
2199
2200 /****************************************************************
2201  _spoolss_DeletePrinterDriver
2202 ****************************************************************/
2203
2204 WERROR _spoolss_DeletePrinterDriver(pipes_struct *p,
2205                                     struct spoolss_DeletePrinterDriver *r)
2206 {
2207         char *driver;
2208         char *arch;
2209         NT_PRINTER_DRIVER_INFO_LEVEL    info;
2210         NT_PRINTER_DRIVER_INFO_LEVEL    info_win2k;
2211         int                             version;
2212         WERROR                          status;
2213         WERROR                          status_win2k = WERR_ACCESS_DENIED;
2214         SE_PRIV                         se_printop = SE_PRINT_OPERATOR;
2215
2216         /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
2217            and not a printer admin, then fail */
2218
2219         if ( (p->server_info->utok.uid != 0)
2220                 && !user_has_privileges(p->server_info->ptok, &se_printop )
2221                 && !token_contains_name_in_list(
2222                         uidtoname(p->server_info->utok.uid), NULL,
2223                         NULL, p->server_info->ptok,
2224                         lp_printer_admin(-1)) )
2225         {
2226                 return WERR_ACCESS_DENIED;
2227         }
2228
2229         driver = CONST_DISCARD(char *, r->in.driver);
2230         arch   = CONST_DISCARD(char *, r->in.architecture);
2231
2232         /* check that we have a valid driver name first */
2233
2234         if ((version=get_version_id(arch)) == -1)
2235                 return WERR_INVALID_ENVIRONMENT;
2236
2237         ZERO_STRUCT(info);
2238         ZERO_STRUCT(info_win2k);
2239
2240         if (!W_ERROR_IS_OK(get_a_printer_driver(&info, 3, driver, arch, version)))
2241         {
2242                 /* try for Win2k driver if "Windows NT x86" */
2243
2244                 if ( version == 2 ) {
2245                         version = 3;
2246                         if (!W_ERROR_IS_OK(get_a_printer_driver(&info, 3, driver, arch, version))) {
2247                                 status = WERR_UNKNOWN_PRINTER_DRIVER;
2248                                 goto done;
2249                         }
2250                 }
2251                 /* otherwise it was a failure */
2252                 else {
2253                         status = WERR_UNKNOWN_PRINTER_DRIVER;
2254                         goto done;
2255                 }
2256
2257         }
2258
2259         if (printer_driver_in_use(info.info_3)) {
2260                 status = WERR_PRINTER_DRIVER_IN_USE;
2261                 goto done;
2262         }
2263
2264         if ( version == 2 )
2265         {
2266                 if (W_ERROR_IS_OK(get_a_printer_driver(&info_win2k, 3, driver, arch, 3)))
2267                 {
2268                         /* if we get to here, we now have 2 driver info structures to remove */
2269                         /* remove the Win2k driver first*/
2270
2271                         status_win2k = delete_printer_driver(
2272                                 p, info_win2k.info_3, 3, False );
2273                         free_a_printer_driver( info_win2k, 3 );
2274
2275                         /* this should not have failed---if it did, report to client */
2276                         if ( !W_ERROR_IS_OK(status_win2k) )
2277                         {
2278                                 status = status_win2k;
2279                                 goto done;
2280                         }
2281                 }
2282         }
2283
2284         status = delete_printer_driver(p, info.info_3, version, False);
2285
2286         /* if at least one of the deletes succeeded return OK */
2287
2288         if ( W_ERROR_IS_OK(status) || W_ERROR_IS_OK(status_win2k) )
2289                 status = WERR_OK;
2290
2291 done:
2292         free_a_printer_driver( info, 3 );
2293
2294         return status;
2295 }
2296
2297 /****************************************************************
2298  _spoolss_DeletePrinterDriverEx
2299 ****************************************************************/
2300
2301 WERROR _spoolss_DeletePrinterDriverEx(pipes_struct *p,
2302                                       struct spoolss_DeletePrinterDriverEx *r)
2303 {
2304         char *driver;
2305         char *arch;
2306         NT_PRINTER_DRIVER_INFO_LEVEL    info;
2307         NT_PRINTER_DRIVER_INFO_LEVEL    info_win2k;
2308         int                             version;
2309         uint32_t                        flags = r->in.delete_flags;
2310         bool                            delete_files;
2311         WERROR                          status;
2312         WERROR                          status_win2k = WERR_ACCESS_DENIED;
2313         SE_PRIV                         se_printop = SE_PRINT_OPERATOR;
2314
2315         /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
2316            and not a printer admin, then fail */
2317
2318         if ( (p->server_info->utok.uid != 0)
2319                 && !user_has_privileges(p->server_info->ptok, &se_printop )
2320                 && !token_contains_name_in_list(
2321                         uidtoname(p->server_info->utok.uid), NULL, NULL,
2322                         p->server_info->ptok, lp_printer_admin(-1)) )
2323         {
2324                 return WERR_ACCESS_DENIED;
2325         }
2326
2327         driver = CONST_DISCARD(char *, r->in.driver);
2328         arch   = CONST_DISCARD(char *, r->in.architecture);
2329
2330         /* check that we have a valid driver name first */
2331         if ((version=get_version_id(arch)) == -1) {
2332                 /* this is what NT returns */
2333                 return WERR_INVALID_ENVIRONMENT;
2334         }
2335
2336         if ( flags & DPD_DELETE_SPECIFIC_VERSION )
2337                 version = r->in.version;
2338
2339         ZERO_STRUCT(info);
2340         ZERO_STRUCT(info_win2k);
2341
2342         status = get_a_printer_driver(&info, 3, driver, arch, version);
2343
2344         if ( !W_ERROR_IS_OK(status) )
2345         {
2346                 /*
2347                  * if the client asked for a specific version,
2348                  * or this is something other than Windows NT x86,
2349                  * then we've failed
2350                  */
2351
2352                 if ( (flags&DPD_DELETE_SPECIFIC_VERSION) || (version !=2) )
2353                         goto done;
2354
2355                 /* try for Win2k driver if "Windows NT x86" */
2356
2357                 version = 3;
2358                 if (!W_ERROR_IS_OK(get_a_printer_driver(&info, 3, driver, arch, version))) {
2359                         status = WERR_UNKNOWN_PRINTER_DRIVER;
2360                         goto done;
2361                 }
2362         }
2363
2364         if ( printer_driver_in_use(info.info_3) ) {
2365                 status = WERR_PRINTER_DRIVER_IN_USE;
2366                 goto done;
2367         }
2368
2369         /*
2370          * we have a couple of cases to consider.
2371          * (1) Are any files in use?  If so and DPD_DELTE_ALL_FILE is set,
2372          *     then the delete should fail if **any** files overlap with
2373          *     other drivers
2374          * (2) If DPD_DELTE_UNUSED_FILES is sert, then delete all
2375          *     non-overlapping files
2376          * (3) If neither DPD_DELTE_ALL_FILE nor DPD_DELTE_ALL_FILES
2377          *     is set, the do not delete any files
2378          * Refer to MSDN docs on DeletePrinterDriverEx() for details.
2379          */
2380
2381         delete_files = flags & (DPD_DELETE_ALL_FILES|DPD_DELETE_UNUSED_FILES);
2382
2383         /* fail if any files are in use and DPD_DELETE_ALL_FILES is set */
2384
2385         if ( delete_files && printer_driver_files_in_use(info.info_3) & (flags&DPD_DELETE_ALL_FILES) ) {
2386                 /* no idea of the correct error here */
2387                 status = WERR_ACCESS_DENIED;
2388                 goto done;
2389         }
2390
2391
2392         /* also check for W32X86/3 if necessary; maybe we already have? */
2393
2394         if ( (version == 2) && ((flags&DPD_DELETE_SPECIFIC_VERSION) != DPD_DELETE_SPECIFIC_VERSION)  ) {
2395                 if (W_ERROR_IS_OK(get_a_printer_driver(&info_win2k, 3, driver, arch, 3)))
2396                 {
2397
2398                         if ( delete_files && printer_driver_files_in_use(info_win2k.info_3) & (flags&DPD_DELETE_ALL_FILES) ) {
2399                                 /* no idea of the correct error here */
2400                                 free_a_printer_driver( info_win2k, 3 );
2401                                 status = WERR_ACCESS_DENIED;
2402                                 goto done;
2403                         }
2404
2405                         /* if we get to here, we now have 2 driver info structures to remove */
2406                         /* remove the Win2k driver first*/
2407
2408                         status_win2k = delete_printer_driver(
2409                                 p, info_win2k.info_3, 3, delete_files);
2410                         free_a_printer_driver( info_win2k, 3 );
2411
2412                         /* this should not have failed---if it did, report to client */
2413
2414                         if ( !W_ERROR_IS_OK(status_win2k) )
2415                                 goto done;
2416                 }
2417         }
2418
2419         status = delete_printer_driver(p, info.info_3, version, delete_files);
2420
2421         if ( W_ERROR_IS_OK(status) || W_ERROR_IS_OK(status_win2k) )
2422                 status = WERR_OK;
2423 done:
2424         free_a_printer_driver( info, 3 );
2425
2426         return status;
2427 }
2428
2429
2430 /****************************************************************************
2431  Internal routine for retreiving printerdata
2432  ***************************************************************************/
2433
2434 static WERROR get_printer_dataex( TALLOC_CTX *ctx, NT_PRINTER_INFO_LEVEL *printer,
2435                                   const char *key, const char *value, uint32 *type, uint8 **data,
2436                                   uint32 *needed, uint32 in_size  )
2437 {
2438         REGISTRY_VALUE          *val;
2439         uint32                  size;
2440         int                     data_len;
2441
2442         if ( !(val = get_printer_data( printer->info_2, key, value)) )
2443                 return WERR_BADFILE;
2444
2445         *type = regval_type( val );
2446
2447         DEBUG(5,("get_printer_dataex: allocating %d\n", in_size));
2448
2449         size = regval_size( val );
2450
2451         /* copy the min(in_size, len) */
2452
2453         if ( in_size ) {
2454                 data_len = (size > in_size) ? in_size : size*sizeof(uint8);
2455
2456                 /* special case for 0 length values */
2457                 if ( data_len ) {
2458                         if ( (*data  = (uint8 *)TALLOC_MEMDUP(ctx, regval_data_p(val), data_len)) == NULL )
2459                                 return WERR_NOMEM;
2460                 }
2461                 else {
2462                         if ( (*data  = (uint8 *)TALLOC_ZERO(ctx, in_size)) == NULL )
2463                                 return WERR_NOMEM;
2464                 }
2465         }
2466         else
2467                 *data = NULL;
2468
2469         *needed = size;
2470
2471         DEBUG(5,("get_printer_dataex: copy done\n"));
2472
2473         return WERR_OK;
2474 }
2475
2476 /****************************************************************************
2477  Internal routine for removing printerdata
2478  ***************************************************************************/
2479
2480 static WERROR delete_printer_dataex( NT_PRINTER_INFO_LEVEL *printer, const char *key, const char *value )
2481 {
2482         return delete_printer_data( printer->info_2, key, value );
2483 }
2484
2485 /****************************************************************************
2486  Internal routine for storing printerdata
2487  ***************************************************************************/
2488
2489 WERROR set_printer_dataex( NT_PRINTER_INFO_LEVEL *printer, const char *key, const char *value,
2490                                   uint32 type, uint8 *data, int real_len  )
2491 {
2492         /* the registry objects enforce uniqueness based on value name */
2493
2494         return add_printer_data( printer->info_2, key, value, type, data, real_len );
2495 }
2496
2497 /********************************************************************
2498  GetPrinterData on a printer server Handle.
2499 ********************************************************************/
2500
2501 static WERROR getprinterdata_printer_server(TALLOC_CTX *ctx, fstring value, uint32 *type, uint8 **data, uint32 *needed, uint32 in_size)
2502 {
2503         int i;
2504
2505         DEBUG(8,("getprinterdata_printer_server:%s\n", value));
2506
2507         if (!StrCaseCmp(value, "W3SvcInstalled")) {
2508                 *type = REG_DWORD;
2509                 if ( !(*data = TALLOC_ARRAY(ctx, uint8, sizeof(uint32) )) )
2510                         return WERR_NOMEM;
2511                 SIVAL(*data, 0, 0x00);
2512                 *needed = 0x4;
2513                 return WERR_OK;
2514         }
2515
2516         if (!StrCaseCmp(value, "BeepEnabled")) {
2517                 *type = REG_DWORD;
2518                 if ( !(*data = TALLOC_ARRAY(ctx, uint8, sizeof(uint32) )) )
2519                         return WERR_NOMEM;
2520                 SIVAL(*data, 0, 0x00);
2521                 *needed = 0x4;
2522                 return WERR_OK;
2523         }
2524
2525         if (!StrCaseCmp(value, "EventLog")) {
2526                 *type = REG_DWORD;
2527                 if ( !(*data = TALLOC_ARRAY(ctx, uint8, sizeof(uint32) )) )
2528                         return WERR_NOMEM;
2529                 /* formally was 0x1b */
2530                 SIVAL(*data, 0, 0x0);
2531                 *needed = 0x4;
2532                 return WERR_OK;
2533         }
2534
2535         if (!StrCaseCmp(value, "NetPopup")) {
2536                 *type = REG_DWORD;
2537                 if ( !(*data = TALLOC_ARRAY(ctx, uint8, sizeof(uint32) )) )
2538                         return WERR_NOMEM;
2539                 SIVAL(*data, 0, 0x00);
2540                 *needed = 0x4;
2541                 return WERR_OK;
2542         }
2543
2544         if (!StrCaseCmp(value, "MajorVersion")) {
2545                 *type = REG_DWORD;
2546                 if ( !(*data = TALLOC_ARRAY(ctx, uint8, sizeof(uint32) )) )
2547                         return WERR_NOMEM;
2548
2549                 /* Windows NT 4.0 seems to not allow uploading of drivers
2550                    to a server that reports 0x3 as the MajorVersion.
2551                    need to investigate more how Win2k gets around this .
2552                    -- jerry */
2553
2554                 if ( RA_WINNT == get_remote_arch() )
2555                         SIVAL(*data, 0, 2);
2556                 else
2557                         SIVAL(*data, 0, 3);
2558
2559                 *needed = 0x4;
2560                 return WERR_OK;
2561         }
2562
2563         if (!StrCaseCmp(value, "MinorVersion")) {
2564                 *type = REG_DWORD;
2565                 if ( !(*data = TALLOC_ARRAY(ctx, uint8, sizeof(uint32) )) )
2566                         return WERR_NOMEM;
2567                 SIVAL(*data, 0, 0);
2568                 *needed = 0x4;
2569                 return WERR_OK;
2570         }
2571
2572         /* REG_BINARY
2573          *  uint32 size          = 0x114
2574          *  uint32 major         = 5
2575          *  uint32 minor         = [0|1]
2576          *  uint32 build         = [2195|2600]
2577          *  extra unicode string = e.g. "Service Pack 3"
2578          */
2579         if (!StrCaseCmp(value, "OSVersion")) {
2580                 *type = REG_BINARY;
2581                 *needed = 0x114;
2582
2583                 if ( !(*data = TALLOC_ZERO_ARRAY(ctx, uint8, (*needed > in_size) ? *needed:in_size )) )
2584                         return WERR_NOMEM;
2585
2586                 SIVAL(*data, 0, *needed);       /* size */
2587                 SIVAL(*data, 4, 5);             /* Windows 2000 == 5.0 */
2588                 SIVAL(*data, 8, 0);
2589                 SIVAL(*data, 12, 2195);         /* build */
2590
2591                 /* leave extra string empty */
2592
2593                 return WERR_OK;
2594         }
2595
2596
2597         if (!StrCaseCmp(value, "DefaultSpoolDirectory")) {
2598                 const char *string="C:\\PRINTERS";
2599                 *type = REG_SZ;
2600                 *needed = 2*(strlen(string)+1);
2601                 if((*data  = (uint8 *)TALLOC(ctx, (*needed > in_size) ? *needed:in_size )) == NULL)
2602                         return WERR_NOMEM;
2603                 memset(*data, 0, (*needed > in_size) ? *needed:in_size);
2604
2605                 /* it's done by hand ready to go on the wire */
2606                 for (i=0; i<strlen(string); i++) {
2607                         (*data)[2*i]=string[i];
2608                         (*data)[2*i+1]='\0';
2609                 }
2610                 return WERR_OK;
2611         }
2612
2613         if (!StrCaseCmp(value, "Architecture")) {
2614                 const char *string="Windows NT x86";
2615                 *type = REG_SZ;
2616                 *needed = 2*(strlen(string)+1);
2617                 if((*data  = (uint8 *)TALLOC(ctx, (*needed > in_size) ? *needed:in_size )) == NULL)
2618                         return WERR_NOMEM;
2619                 memset(*data, 0, (*needed > in_size) ? *needed:in_size);
2620                 for (i=0; i<strlen(string); i++) {
2621                         (*data)[2*i]=string[i];
2622                         (*data)[2*i+1]='\0';
2623                 }
2624                 return WERR_OK;
2625         }
2626
2627         if (!StrCaseCmp(value, "DsPresent")) {
2628                 *type = REG_DWORD;
2629                 if ( !(*data = TALLOC_ARRAY(ctx, uint8, sizeof(uint32) )) )
2630                         return WERR_NOMEM;
2631
2632                 /* only show the publish check box if we are a
2633                    memeber of a AD domain */
2634
2635                 if ( lp_security() == SEC_ADS )
2636                         SIVAL(*data, 0, 0x01);
2637                 else
2638                         SIVAL(*data, 0, 0x00);
2639
2640                 *needed = 0x4;
2641                 return WERR_OK;
2642         }
2643
2644         if (!StrCaseCmp(value, "DNSMachineName")) {
2645                 const char *hostname = get_mydnsfullname();
2646
2647                 if (!hostname)
2648                         return WERR_BADFILE;
2649                 *type = REG_SZ;
2650                 *needed = 2*(strlen(hostname)+1);
2651                 if((*data  = (uint8 *)TALLOC(ctx, (*needed > in_size) ? *needed:in_size )) == NULL)
2652                         return WERR_NOMEM;
2653                 memset(*data, 0, (*needed > in_size) ? *needed:in_size);
2654                 for (i=0; i<strlen(hostname); i++) {
2655                         (*data)[2*i]=hostname[i];
2656                         (*data)[2*i+1]='\0';
2657                 }
2658                 return WERR_OK;
2659         }
2660
2661
2662         return WERR_BADFILE;
2663 }
2664
2665 /********************************************************************
2666  * spoolss_getprinterdata
2667  ********************************************************************/
2668
2669 WERROR _spoolss_getprinterdata(pipes_struct *p, SPOOL_Q_GETPRINTERDATA *q_u, SPOOL_R_GETPRINTERDATA *r_u)
2670 {
2671         POLICY_HND      *handle = &q_u->handle;
2672         UNISTR2         *valuename = &q_u->valuename;
2673         uint32          in_size = q_u->size;
2674         uint32          *type = &r_u->type;
2675         uint32          *out_size = &r_u->size;
2676         uint8           **data = &r_u->data;
2677         uint32          *needed = &r_u->needed;
2678         WERROR          status;
2679         fstring         value;
2680         Printer_entry   *Printer = find_printer_index_by_hnd(p, handle);
2681         NT_PRINTER_INFO_LEVEL   *printer = NULL;
2682         int             snum = 0;
2683
2684         /*
2685          * Reminder: when it's a string, the length is in BYTES
2686          * even if UNICODE is negociated.
2687          *
2688          * JFM, 4/19/1999
2689          */
2690
2691         *out_size = in_size;
2692
2693         /* in case of problem, return some default values */
2694
2695         *needed = 0;
2696         *type   = 0;
2697
2698         DEBUG(4,("_spoolss_getprinterdata\n"));
2699
2700         if ( !Printer ) {
2701                 DEBUG(2,("_spoolss_getprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
2702                 status = WERR_BADFID;
2703                 goto done;
2704         }
2705
2706         unistr2_to_ascii(value, valuename, sizeof(value));
2707
2708         if ( Printer->printer_type == SPLHND_SERVER )
2709                 status = getprinterdata_printer_server( p->mem_ctx, value, type, data, needed, *out_size );
2710         else
2711         {
2712                 if ( !get_printer_snum(p,handle, &snum, NULL) ) {
2713                         status = WERR_BADFID;
2714                         goto done;
2715                 }
2716
2717                 status = get_a_printer(Printer, &printer, 2, lp_servicename(snum));
2718                 if ( !W_ERROR_IS_OK(status) )
2719                         goto done;
2720
2721                 /* XP sends this and wants to change id value from the PRINTER_INFO_0 */
2722
2723                 if ( strequal(value, "ChangeId") ) {
2724                         *type = REG_DWORD;
2725                         *needed = sizeof(uint32);
2726                         if ( (*data = (uint8*)TALLOC(p->mem_ctx, sizeof(uint32))) == NULL) {
2727                                 status = WERR_NOMEM;
2728                                 goto done;
2729                         }
2730                         SIVAL( *data, 0, printer->info_2->changeid );
2731                         status = WERR_OK;
2732                 }
2733                 else
2734                         status = get_printer_dataex( p->mem_ctx, printer, SPOOL_PRINTERDATA_KEY, value, type, data, needed, *out_size );
2735         }
2736
2737         if (*needed > *out_size)
2738                 status = WERR_MORE_DATA;
2739
2740 done:
2741         if ( !W_ERROR_IS_OK(status) )
2742         {
2743                 DEBUG(5, ("error %d: allocating %d\n", W_ERROR_V(status),*out_size));
2744
2745                 /* reply this param doesn't exist */
2746
2747                 if ( *out_size ) {
2748                         if((*data=(uint8 *)TALLOC_ZERO_ARRAY(p->mem_ctx, uint8, *out_size)) == NULL) {
2749                                 if ( printer )
2750                                         free_a_printer( &printer, 2 );
2751                                 return WERR_NOMEM;
2752                         }
2753                 } else {
2754                         *data = NULL;
2755                 }
2756         }
2757
2758         /* cleanup & exit */
2759
2760         if ( printer )
2761                 free_a_printer( &printer, 2 );
2762
2763         return status;
2764 }
2765
2766 /*********************************************************
2767  Connect to the client machine.
2768 **********************************************************/
2769
2770 static bool spoolss_connect_to_client(struct rpc_pipe_client **pp_pipe,
2771                         struct sockaddr_storage *client_ss, const char *remote_machine)
2772 {
2773         NTSTATUS ret;
2774         struct cli_state *the_cli;
2775         struct sockaddr_storage rm_addr;
2776
2777         if ( is_zero_addr((struct sockaddr *)client_ss) ) {
2778                 if ( !resolve_name( remote_machine, &rm_addr, 0x20) ) {
2779                         DEBUG(2,("spoolss_connect_to_client: Can't resolve address for %s\n", remote_machine));
2780                         return False;
2781                 }
2782
2783                 if (ismyaddr((struct sockaddr *)&rm_addr)) {
2784                         DEBUG(0,("spoolss_connect_to_client: Machine %s is one of our addresses. Cannot add to ourselves.\n", remote_machine));
2785                         return False;
2786                 }
2787         } else {
2788                 char addr[INET6_ADDRSTRLEN];
2789                 rm_addr = *client_ss;
2790                 print_sockaddr(addr, sizeof(addr), &rm_addr);
2791                 DEBUG(5,("spoolss_connect_to_client: Using address %s (no name resolution necessary)\n",
2792                         addr));
2793         }
2794
2795         /* setup the connection */
2796
2797         ret = cli_full_connection( &the_cli, global_myname(), remote_machine,
2798                 &rm_addr, 0, "IPC$", "IPC",
2799                 "", /* username */
2800                 "", /* domain */
2801                 "", /* password */
2802                 0, lp_client_signing(), NULL );
2803
2804         if ( !NT_STATUS_IS_OK( ret ) ) {
2805                 DEBUG(2,("spoolss_connect_to_client: connection to [%s] failed!\n",
2806                         remote_machine ));
2807                 return False;
2808         }
2809
2810         if ( the_cli->protocol != PROTOCOL_NT1 ) {
2811                 DEBUG(0,("spoolss_connect_to_client: machine %s didn't negotiate NT protocol.\n", remote_machine));
2812                 cli_shutdown(the_cli);
2813                 return False;
2814         }
2815
2816         /*
2817          * Ok - we have an anonymous connection to the IPC$ share.
2818          * Now start the NT Domain stuff :-).
2819          */
2820
2821         ret = cli_rpc_pipe_open_noauth(the_cli, &syntax_spoolss, pp_pipe);
2822         if (!NT_STATUS_IS_OK(ret)) {
2823                 DEBUG(2,("spoolss_connect_to_client: unable to open the spoolss pipe on machine %s. Error was : %s.\n",
2824                         remote_machine, nt_errstr(ret)));
2825                 cli_shutdown(the_cli);
2826                 return False;
2827         }
2828
2829         return True;
2830 }
2831
2832 /***************************************************************************
2833  Connect to the client.
2834 ****************************************************************************/
2835
2836 static bool srv_spoolss_replyopenprinter(int snum, const char *printer,
2837                                         uint32 localprinter, uint32 type,
2838                                         POLICY_HND *handle, struct sockaddr_storage *client_ss)
2839 {
2840         WERROR result;
2841         NTSTATUS status;
2842
2843         /*
2844          * If it's the first connection, contact the client
2845          * and connect to the IPC$ share anonymously
2846          */
2847         if (smb_connections==0) {
2848                 fstring unix_printer;
2849
2850                 fstrcpy(unix_printer, printer+2); /* the +2 is to strip the leading 2 backslashs */
2851
2852                 if ( !spoolss_connect_to_client( &notify_cli_pipe, client_ss, unix_printer ))
2853                         return False;
2854
2855                 messaging_register(smbd_messaging_context(), NULL,
2856                                    MSG_PRINTER_NOTIFY2,
2857                                    receive_notify2_message_list);
2858                 /* Tell the connections db we're now interested in printer
2859                  * notify messages. */
2860                 register_message_flags( True, FLAG_MSG_PRINT_NOTIFY );
2861         }
2862
2863         /*
2864          * Tell the specific printing tdb we want messages for this printer
2865          * by registering our PID.
2866          */
2867
2868         if (!print_notify_register_pid(snum))
2869                 DEBUG(0,("print_notify_register_pid: Failed to register our pid for printer %s\n", printer ));
2870
2871         smb_connections++;
2872
2873         status = rpccli_spoolss_ReplyOpenPrinter(notify_cli_pipe, talloc_tos(),
2874                                                  printer,
2875                                                  localprinter,
2876                                                  type,
2877                                                  0,
2878                                                  NULL,
2879                                                  handle,
2880                                                  &result);
2881         if (!NT_STATUS_IS_OK(status) || !W_ERROR_IS_OK(result))
2882                 DEBUG(5,("srv_spoolss_reply_open_printer: Client RPC returned [%s]\n",
2883                         win_errstr(result)));
2884
2885         return (W_ERROR_IS_OK(result));
2886 }
2887
2888 /********************************************************************
2889  * _spoolss_rffpcnex
2890  * ReplyFindFirstPrinterChangeNotifyEx
2891  *
2892  * before replying OK: status=0 a rpc call is made to the workstation
2893  * asking ReplyOpenPrinter
2894  *
2895  * in fact ReplyOpenPrinter is the changenotify equivalent on the spoolss pipe
2896  * called from api_spoolss_rffpcnex
2897  ********************************************************************/
2898
2899 WERROR _spoolss_rffpcnex(pipes_struct *p, SPOOL_Q_RFFPCNEX *q_u, SPOOL_R_RFFPCNEX *r_u)
2900 {
2901         POLICY_HND *handle = &q_u->handle;
2902         uint32 flags = q_u->flags;
2903         uint32 options = q_u->options;
2904         UNISTR2 *localmachine = &q_u->localmachine;
2905         uint32 printerlocal = q_u->printerlocal;
2906         int snum = -1;
2907         SPOOL_NOTIFY_OPTION *option = q_u->option;
2908         struct sockaddr_storage client_ss;
2909
2910         /* store the notify value in the printer struct */
2911
2912         Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
2913
2914         if (!Printer) {
2915                 DEBUG(2,("_spoolss_rffpcnex: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
2916                 return WERR_BADFID;
2917         }
2918
2919         Printer->notify.flags=flags;
2920         Printer->notify.options=options;
2921         Printer->notify.printerlocal=printerlocal;
2922
2923         if (Printer->notify.option)
2924                 free_spool_notify_option(&Printer->notify.option);
2925
2926         Printer->notify.option=dup_spool_notify_option(option);
2927
2928         unistr2_to_ascii(Printer->notify.localmachine, localmachine,
2929                        sizeof(Printer->notify.localmachine));
2930
2931         /* Connect to the client machine and send a ReplyOpenPrinter */
2932
2933         if ( Printer->printer_type == SPLHND_SERVER)
2934                 snum = -1;
2935         else if ( (Printer->printer_type == SPLHND_PRINTER) &&
2936                         !get_printer_snum(p, handle, &snum, NULL) )
2937                 return WERR_BADFID;
2938
2939         if (!interpret_string_addr(&client_ss, p->client_address,
2940                                    AI_NUMERICHOST)) {
2941                 return WERR_SERVER_UNAVAILABLE;
2942         }
2943
2944         if(!srv_spoolss_replyopenprinter(snum, Printer->notify.localmachine,
2945                                         Printer->notify.printerlocal, 1,
2946                                         &Printer->notify.client_hnd, &client_ss))
2947                 return WERR_SERVER_UNAVAILABLE;
2948
2949         Printer->notify.client_connected=True;
2950
2951         return WERR_OK;
2952 }
2953
2954 /*******************************************************************
2955  * fill a notify_info_data with the servername
2956  ********************************************************************/
2957
2958 void spoolss_notify_server_name(int snum,
2959                                        struct spoolss_Notify *data,
2960                                        print_queue_struct *queue,
2961                                        NT_PRINTER_INFO_LEVEL *printer,
2962                                        TALLOC_CTX *mem_ctx)
2963 {
2964         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, printer->info_2->servername);
2965 }
2966
2967 /*******************************************************************
2968  * fill a notify_info_data with the printername (not including the servername).
2969  ********************************************************************/
2970
2971 void spoolss_notify_printer_name(int snum,
2972                                         struct spoolss_Notify *data,
2973                                         print_queue_struct *queue,
2974                                         NT_PRINTER_INFO_LEVEL *printer,
2975                                         TALLOC_CTX *mem_ctx)
2976 {
2977         /* the notify name should not contain the \\server\ part */
2978         char *p = strrchr(printer->info_2->printername, '\\');
2979
2980         if (!p) {
2981                 p = printer->info_2->printername;
2982         } else {
2983                 p++;
2984         }
2985
2986         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, p);
2987 }
2988
2989 /*******************************************************************
2990  * fill a notify_info_data with the servicename
2991  ********************************************************************/
2992
2993 void spoolss_notify_share_name(int snum,
2994                                       struct spoolss_Notify *data,
2995                                       print_queue_struct *queue,
2996                                       NT_PRINTER_INFO_LEVEL *printer,
2997                                       TALLOC_CTX *mem_ctx)
2998 {
2999         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, lp_servicename(snum));
3000 }
3001
3002 /*******************************************************************
3003  * fill a notify_info_data with the port name
3004  ********************************************************************/
3005
3006 void spoolss_notify_port_name(int snum,
3007                                      struct spoolss_Notify *data,
3008                                      print_queue_struct *queue,
3009                                      NT_PRINTER_INFO_LEVEL *printer,
3010                                      TALLOC_CTX *mem_ctx)
3011 {
3012         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, printer->info_2->portname);
3013 }
3014
3015 /*******************************************************************
3016  * fill a notify_info_data with the printername
3017  * but it doesn't exist, have to see what to do
3018  ********************************************************************/
3019
3020 void spoolss_notify_driver_name(int snum,
3021                                        struct spoolss_Notify *data,
3022                                        print_queue_struct *queue,
3023                                        NT_PRINTER_INFO_LEVEL *printer,
3024                                        TALLOC_CTX *mem_ctx)
3025 {
3026         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, printer->info_2->drivername);
3027 }
3028
3029 /*******************************************************************
3030  * fill a notify_info_data with the comment
3031  ********************************************************************/
3032
3033 void spoolss_notify_comment(int snum,
3034                                    struct spoolss_Notify *data,
3035                                    print_queue_struct *queue,
3036                                    NT_PRINTER_INFO_LEVEL *printer,
3037                                    TALLOC_CTX *mem_ctx)
3038 {
3039         char *p;
3040
3041         if (*printer->info_2->comment == '\0') {
3042                 p = lp_comment(snum);
3043         } else {
3044                 p = printer->info_2->comment;
3045         }
3046
3047         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, printer->info_2->comment);
3048 }
3049
3050 /*******************************************************************
3051  * fill a notify_info_data with the comment
3052  * location = "Room 1, floor 2, building 3"
3053  ********************************************************************/
3054
3055 void spoolss_notify_location(int snum,
3056                                     struct spoolss_Notify *data,
3057                                     print_queue_struct *queue,
3058                                     NT_PRINTER_INFO_LEVEL *printer,
3059                                     TALLOC_CTX *mem_ctx)
3060 {
3061         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, printer->info_2->location);
3062 }
3063
3064 /*******************************************************************
3065  * fill a notify_info_data with the device mode
3066  * jfm:xxxx don't to it for know but that's a real problem !!!
3067  ********************************************************************/
3068
3069 static void spoolss_notify_devmode(int snum,
3070                                    struct spoolss_Notify *data,
3071                                    print_queue_struct *queue,
3072                                    NT_PRINTER_INFO_LEVEL *printer,
3073                                    TALLOC_CTX *mem_ctx)
3074 {
3075         /* for a dummy implementation we have to zero the fields */
3076         SETUP_SPOOLSS_NOTIFY_DATA_DEVMODE(data, NULL);
3077 }
3078
3079 /*******************************************************************
3080  * fill a notify_info_data with the separator file name
3081  ********************************************************************/
3082
3083 void spoolss_notify_sepfile(int snum,
3084                                    struct spoolss_Notify *data,
3085                                    print_queue_struct *queue,
3086                                    NT_PRINTER_INFO_LEVEL *printer,
3087                                    TALLOC_CTX *mem_ctx)
3088 {
3089         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, printer->info_2->sepfile);
3090 }
3091
3092 /*******************************************************************
3093  * fill a notify_info_data with the print processor
3094  * jfm:xxxx return always winprint to indicate we don't do anything to it
3095  ********************************************************************/
3096
3097 void spoolss_notify_print_processor(int snum,
3098                                            struct spoolss_Notify *data,
3099                                            print_queue_struct *queue,
3100                                            NT_PRINTER_INFO_LEVEL *printer,
3101                                            TALLOC_CTX *mem_ctx)
3102 {
3103         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, printer->info_2->printprocessor);
3104 }
3105
3106 /*******************************************************************
3107  * fill a notify_info_data with the print processor options
3108  * jfm:xxxx send an empty string
3109  ********************************************************************/
3110
3111 void spoolss_notify_parameters(int snum,
3112                                       struct spoolss_Notify *data,
3113                                       print_queue_struct *queue,
3114                                       NT_PRINTER_INFO_LEVEL *printer,
3115                                       TALLOC_CTX *mem_ctx)
3116 {
3117         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, printer->info_2->parameters);
3118 }
3119
3120 /*******************************************************************
3121  * fill a notify_info_data with the data type
3122  * jfm:xxxx always send RAW as data type
3123  ********************************************************************/
3124
3125 void spoolss_notify_datatype(int snum,
3126                                     struct spoolss_Notify *data,
3127                                     print_queue_struct *queue,
3128                                     NT_PRINTER_INFO_LEVEL *printer,
3129                                     TALLOC_CTX *mem_ctx)
3130 {
3131         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, printer->info_2->datatype);
3132 }
3133
3134 /*******************************************************************
3135  * fill a notify_info_data with the security descriptor
3136  * jfm:xxxx send an null pointer to say no security desc
3137  * have to implement security before !
3138  ********************************************************************/
3139
3140 static void spoolss_notify_security_desc(int snum,
3141                                          struct spoolss_Notify *data,
3142                                          print_queue_struct *queue,
3143                                          NT_PRINTER_INFO_LEVEL *printer,
3144                                          TALLOC_CTX *mem_ctx)
3145 {
3146         SETUP_SPOOLSS_NOTIFY_DATA_SECDESC(data,
3147                                           printer->info_2->secdesc_buf->sd_size,
3148                                           printer->info_2->secdesc_buf->sd);
3149 }
3150
3151 /*******************************************************************
3152  * fill a notify_info_data with the attributes
3153  * jfm:xxxx a samba printer is always shared
3154  ********************************************************************/
3155
3156 void spoolss_notify_attributes(int snum,
3157                                       struct spoolss_Notify *data,
3158                                       print_queue_struct *queue,
3159                                       NT_PRINTER_INFO_LEVEL *printer,
3160                                       TALLOC_CTX *mem_ctx)
3161 {
3162         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, printer->info_2->attributes);
3163 }
3164
3165 /*******************************************************************
3166  * fill a notify_info_data with the priority
3167  ********************************************************************/
3168
3169 static void spoolss_notify_priority(int snum,
3170                                     struct spoolss_Notify *data,
3171                                     print_queue_struct *queue,
3172                                     NT_PRINTER_INFO_LEVEL *printer,
3173                                     TALLOC_CTX *mem_ctx)
3174 {
3175         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, printer->info_2->priority);
3176 }
3177
3178 /*******************************************************************
3179  * fill a notify_info_data with the default priority
3180  ********************************************************************/
3181
3182 static void spoolss_notify_default_priority(int snum,
3183                                             struct spoolss_Notify *data,
3184                                             print_queue_struct *queue,
3185                                             NT_PRINTER_INFO_LEVEL *printer,
3186                                             TALLOC_CTX *mem_ctx)
3187 {
3188         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, printer->info_2->default_priority);
3189 }
3190
3191 /*******************************************************************
3192  * fill a notify_info_data with the start time
3193  ********************************************************************/
3194
3195 static void spoolss_notify_start_time(int snum,
3196                                       struct spoolss_Notify *data,
3197                                       print_queue_struct *queue,
3198                                       NT_PRINTER_INFO_LEVEL *printer,
3199                                       TALLOC_CTX *mem_ctx)
3200 {
3201         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, printer->info_2->starttime);
3202 }
3203
3204 /*******************************************************************
3205  * fill a notify_info_data with the until time
3206  ********************************************************************/
3207
3208 static void spoolss_notify_until_time(int snum,
3209                                       struct spoolss_Notify *data,
3210                                       print_queue_struct *queue,
3211                                       NT_PRINTER_INFO_LEVEL *printer,
3212                                       TALLOC_CTX *mem_ctx)
3213 {
3214         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, printer->info_2->untiltime);
3215 }
3216
3217 /*******************************************************************
3218  * fill a notify_info_data with the status
3219  ********************************************************************/
3220
3221 static void spoolss_notify_status(int snum,
3222                                   struct spoolss_Notify *data,
3223                                   print_queue_struct *queue,
3224                                   NT_PRINTER_INFO_LEVEL *printer,
3225                                   TALLOC_CTX *mem_ctx)
3226 {
3227         print_status_struct status;
3228
3229         print_queue_length(snum, &status);
3230         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, status.status);
3231 }
3232
3233 /*******************************************************************
3234  * fill a notify_info_data with the number of jobs queued
3235  ********************************************************************/
3236
3237 void spoolss_notify_cjobs(int snum,
3238                                  struct spoolss_Notify *data,
3239                                  print_queue_struct *queue,
3240                                  NT_PRINTER_INFO_LEVEL *printer,
3241                                  TALLOC_CTX *mem_ctx)
3242 {
3243         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, print_queue_length(snum, NULL));
3244 }
3245
3246 /*******************************************************************
3247  * fill a notify_info_data with the average ppm
3248  ********************************************************************/
3249
3250 static void spoolss_notify_average_ppm(int snum,
3251                                        struct spoolss_Notify *data,
3252                                        print_queue_struct *queue,
3253                                        NT_PRINTER_INFO_LEVEL *printer,
3254                                        TALLOC_CTX *mem_ctx)
3255 {
3256         /* always respond 8 pages per minutes */
3257         /* a little hard ! */
3258         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, printer->info_2->averageppm);
3259 }
3260
3261 /*******************************************************************
3262  * fill a notify_info_data with username
3263  ********************************************************************/
3264
3265 static void spoolss_notify_username(int snum,
3266                                     struct spoolss_Notify *data,
3267                                     print_queue_struct *queue,
3268                                     NT_PRINTER_INFO_LEVEL *printer,
3269                                     TALLOC_CTX *mem_ctx)
3270 {
3271         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, queue->fs_user);
3272 }
3273
3274 /*******************************************************************
3275  * fill a notify_info_data with job status
3276  ********************************************************************/
3277
3278 static void spoolss_notify_job_status(int snum,
3279                                       struct spoolss_Notify *data,
3280                                       print_queue_struct *queue,
3281                                       NT_PRINTER_INFO_LEVEL *printer,
3282                                       TALLOC_CTX *mem_ctx)
3283 {
3284         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, nt_printj_status(queue->status));
3285 }
3286
3287 /*******************************************************************
3288  * fill a notify_info_data with job name
3289  ********************************************************************/
3290
3291 static void spoolss_notify_job_name(int snum,
3292                                     struct spoolss_Notify *data,
3293                                     print_queue_struct *queue,
3294                                     NT_PRINTER_INFO_LEVEL *printer,
3295                                     TALLOC_CTX *mem_ctx)
3296 {
3297         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, queue->fs_file);
3298 }
3299
3300 /*******************************************************************
3301  * fill a notify_info_data with job status
3302  ********************************************************************/
3303
3304 static void spoolss_notify_job_status_string(int snum,
3305                                              struct spoolss_Notify *data,
3306                                              print_queue_struct *queue,
3307                                              NT_PRINTER_INFO_LEVEL *printer,
3308                                              TALLOC_CTX *mem_ctx)
3309 {
3310         /*
3311          * Now we're returning job status codes we just return a "" here. JRA.
3312          */
3313
3314         const char *p = "";
3315
3316 #if 0 /* NO LONGER NEEDED - JRA. 02/22/2001 */
3317         p = "unknown";
3318
3319         switch (queue->status) {
3320         case LPQ_QUEUED:
3321                 p = "Queued";
3322                 break;
3323         case LPQ_PAUSED:
3324                 p = "";    /* NT provides the paused string */
3325                 break;
3326         case LPQ_SPOOLING:
3327                 p = "Spooling";
3328                 break;
3329         case LPQ_PRINTING:
3330                 p = "Printing";
3331                 break;
3332         }
3333 #endif /* NO LONGER NEEDED. */
3334
3335         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, p);
3336 }
3337
3338 /*******************************************************************
3339  * fill a notify_info_data with job time
3340  ********************************************************************/
3341
3342 static void spoolss_notify_job_time(int snum,
3343                                     struct spoolss_Notify *data,
3344                                     print_queue_struct *queue,
3345                                     NT_PRINTER_INFO_LEVEL *printer,
3346                                     TALLOC_CTX *mem_ctx)
3347 {
3348         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, 0);
3349 }
3350
3351 /*******************************************************************
3352  * fill a notify_info_data with job size
3353  ********************************************************************/
3354
3355 static void spoolss_notify_job_size(int snum,
3356                                     struct spoolss_Notify *data,
3357                                     print_queue_struct *queue,
3358                                     NT_PRINTER_INFO_LEVEL *printer,
3359                                     TALLOC_CTX *mem_ctx)
3360 {
3361         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, queue->size);
3362 }
3363
3364 /*******************************************************************
3365  * fill a notify_info_data with page info
3366  ********************************************************************/
3367 static void spoolss_notify_total_pages(int snum,
3368                                 struct spoolss_Notify *data,
3369                                 print_queue_struct *queue,
3370                                 NT_PRINTER_INFO_LEVEL *printer,
3371                                 TALLOC_CTX *mem_ctx)
3372 {
3373         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, queue->page_count);
3374 }
3375
3376 /*******************************************************************
3377  * fill a notify_info_data with pages printed info.
3378  ********************************************************************/
3379 static void spoolss_notify_pages_printed(int snum,
3380                                 struct spoolss_Notify *data,
3381                                 print_queue_struct *queue,
3382                                 NT_PRINTER_INFO_LEVEL *printer,
3383                                 TALLOC_CTX *mem_ctx)
3384 {
3385         /* Add code when back-end tracks this */
3386         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, 0);
3387 }
3388
3389 /*******************************************************************
3390  Fill a notify_info_data with job position.
3391  ********************************************************************/
3392
3393 static void spoolss_notify_job_position(int snum,
3394                                         struct spoolss_Notify *data,
3395                                         print_queue_struct *queue,
3396                                         NT_PRINTER_INFO_LEVEL *printer,
3397                                         TALLOC_CTX *mem_ctx)
3398 {
3399         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, queue->job);
3400 }
3401
3402 /*******************************************************************
3403  Fill a notify_info_data with submitted time.
3404  ********************************************************************/
3405
3406 static void spoolss_notify_submitted_time(int snum,
3407                                           struct spoolss_Notify *data,
3408                                           print_queue_struct *queue,
3409                                           NT_PRINTER_INFO_LEVEL *printer,
3410                                           TALLOC_CTX *mem_ctx)
3411 {
3412         data->data.string.string = NULL;
3413         data->data.string.size = 0;
3414
3415         init_systemtime_buffer(mem_ctx, gmtime(&queue->time),
3416                                &data->data.string.string,
3417                                &data->data.string.size);
3418
3419 }
3420
3421 struct s_notify_info_data_table
3422 {
3423         enum spoolss_NotifyType type;
3424         enum spoolss_Field field;
3425         const char *name;
3426         enum spoolss_NotifyTable variable_type;
3427         void (*fn) (int snum, struct spoolss_Notify *data,
3428                     print_queue_struct *queue,
3429                     NT_PRINTER_INFO_LEVEL *printer, TALLOC_CTX *mem_ctx);
3430 };
3431
3432 /* A table describing the various print notification constants and
3433    whether the notification data is a pointer to a variable sized
3434    buffer, a one value uint32 or a two value uint32. */
3435
3436 static const struct s_notify_info_data_table notify_info_data_table[] =
3437 {
3438 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SERVER_NAME,         "PRINTER_NOTIFY_SERVER_NAME",         NOTIFY_TABLE_STRING,   spoolss_notify_server_name },
3439 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PRINTER_NAME,        "PRINTER_NOTIFY_PRINTER_NAME",        NOTIFY_TABLE_STRING,   spoolss_notify_printer_name },
3440 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SHARE_NAME,          "PRINTER_NOTIFY_SHARE_NAME",          NOTIFY_TABLE_STRING,   spoolss_notify_share_name },
3441 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PORT_NAME,           "PRINTER_NOTIFY_PORT_NAME",           NOTIFY_TABLE_STRING,   spoolss_notify_port_name },
3442 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DRIVER_NAME,         "PRINTER_NOTIFY_DRIVER_NAME",         NOTIFY_TABLE_STRING,   spoolss_notify_driver_name },
3443 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_COMMENT,             "PRINTER_NOTIFY_COMMENT",             NOTIFY_TABLE_STRING,   spoolss_notify_comment },
3444 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_LOCATION,            "PRINTER_NOTIFY_LOCATION",            NOTIFY_TABLE_STRING,   spoolss_notify_location },
3445 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DEVMODE,             "PRINTER_NOTIFY_DEVMODE",             NOTIFY_TABLE_DEVMODE,  spoolss_notify_devmode },
3446 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SEPFILE,             "PRINTER_NOTIFY_SEPFILE",             NOTIFY_TABLE_STRING,   spoolss_notify_sepfile },
3447 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PRINT_PROCESSOR,     "PRINTER_NOTIFY_PRINT_PROCESSOR",     NOTIFY_TABLE_STRING,   spoolss_notify_print_processor },
3448 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PARAMETERS,          "PRINTER_NOTIFY_PARAMETERS",          NOTIFY_TABLE_STRING,   spoolss_notify_parameters },
3449 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DATATYPE,            "PRINTER_NOTIFY_DATATYPE",            NOTIFY_TABLE_STRING,   spoolss_notify_datatype },
3450 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SECURITY_DESCRIPTOR, "PRINTER_NOTIFY_SECURITY_DESCRIPTOR", NOTIFY_TABLE_SECURITYDESCRIPTOR,   spoolss_notify_security_desc },
3451 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_ATTRIBUTES,          "PRINTER_NOTIFY_ATTRIBUTES",          NOTIFY_TABLE_DWORD,    spoolss_notify_attributes },
3452 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PRIORITY,            "PRINTER_NOTIFY_PRIORITY",            NOTIFY_TABLE_DWORD,    spoolss_notify_priority },
3453 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DEFAULT_PRIORITY,    "PRINTER_NOTIFY_DEFAULT_PRIORITY",    NOTIFY_TABLE_DWORD,    spoolss_notify_default_priority },
3454 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_START_TIME,          "PRINTER_NOTIFY_START_TIME",          NOTIFY_TABLE_DWORD,    spoolss_notify_start_time },
3455 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_UNTIL_TIME,          "PRINTER_NOTIFY_UNTIL_TIME",          NOTIFY_TABLE_DWORD,    spoolss_notify_until_time },
3456 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_STATUS,              "PRINTER_NOTIFY_STATUS",              NOTIFY_TABLE_DWORD,    spoolss_notify_status },
3457 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_STATUS_STRING,       "PRINTER_NOTIFY_STATUS_STRING",       NOTIFY_TABLE_STRING,   NULL },
3458 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_CJOBS,               "PRINTER_NOTIFY_CJOBS",               NOTIFY_TABLE_DWORD,    spoolss_notify_cjobs },
3459 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_AVERAGE_PPM,         "PRINTER_NOTIFY_AVERAGE_PPM",         NOTIFY_TABLE_DWORD,    spoolss_notify_average_ppm },
3460 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_TOTAL_PAGES,         "PRINTER_NOTIFY_TOTAL_PAGES",         NOTIFY_TABLE_DWORD,    NULL },
3461 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PAGES_PRINTED,       "PRINTER_NOTIFY_PAGES_PRINTED",       NOTIFY_TABLE_DWORD,    NULL },
3462 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_TOTAL_BYTES,         "PRINTER_NOTIFY_TOTAL_BYTES",         NOTIFY_TABLE_DWORD,    NULL },
3463 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_BYTES_PRINTED,       "PRINTER_NOTIFY_BYTES_PRINTED",       NOTIFY_TABLE_DWORD,    NULL },
3464 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_PRINTER_NAME,            "JOB_NOTIFY_PRINTER_NAME",            NOTIFY_TABLE_STRING,   spoolss_notify_printer_name },
3465 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_MACHINE_NAME,            "JOB_NOTIFY_MACHINE_NAME",            NOTIFY_TABLE_STRING,   spoolss_notify_server_name },
3466 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_PORT_NAME,               "JOB_NOTIFY_PORT_NAME",               NOTIFY_TABLE_STRING,   spoolss_notify_port_name },
3467 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_USER_NAME,               "JOB_NOTIFY_USER_NAME",               NOTIFY_TABLE_STRING,   spoolss_notify_username },
3468 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_NOTIFY_NAME,             "JOB_NOTIFY_NOTIFY_NAME",             NOTIFY_TABLE_STRING,   spoolss_notify_username },
3469 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_DATATYPE,                "JOB_NOTIFY_DATATYPE",                NOTIFY_TABLE_STRING,   spoolss_notify_datatype },
3470 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_PRINT_PROCESSOR,         "JOB_NOTIFY_PRINT_PROCESSOR",         NOTIFY_TABLE_STRING,   spoolss_notify_print_processor },
3471 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_PARAMETERS,              "JOB_NOTIFY_PARAMETERS",              NOTIFY_TABLE_STRING,   spoolss_notify_parameters },
3472 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_DRIVER_NAME,             "JOB_NOTIFY_DRIVER_NAME",             NOTIFY_TABLE_STRING,   spoolss_notify_driver_name },
3473 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_DEVMODE,                 "JOB_NOTIFY_DEVMODE",                 NOTIFY_TABLE_DEVMODE,  spoolss_notify_devmode },
3474 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_STATUS,                  "JOB_NOTIFY_STATUS",                  NOTIFY_TABLE_DWORD,    spoolss_notify_job_status },
3475 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_STATUS_STRING,           "JOB_NOTIFY_STATUS_STRING",           NOTIFY_TABLE_STRING,   spoolss_notify_job_status_string },
3476 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_SECURITY_DESCRIPTOR,     "JOB_NOTIFY_SECURITY_DESCRIPTOR",     NOTIFY_TABLE_SECURITYDESCRIPTOR,   NULL },
3477 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_DOCUMENT,                "JOB_NOTIFY_DOCUMENT",                NOTIFY_TABLE_STRING,   spoolss_notify_job_name },
3478 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_PRIORITY,                "JOB_NOTIFY_PRIORITY",                NOTIFY_TABLE_DWORD,    spoolss_notify_priority },
3479 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_POSITION,                "JOB_NOTIFY_POSITION",                NOTIFY_TABLE_DWORD,    spoolss_notify_job_position },
3480 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_SUBMITTED,               "JOB_NOTIFY_SUBMITTED",               NOTIFY_TABLE_TIME,     spoolss_notify_submitted_time },
3481 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_START_TIME,              "JOB_NOTIFY_START_TIME",              NOTIFY_TABLE_DWORD,    spoolss_notify_start_time },
3482 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_UNTIL_TIME,              "JOB_NOTIFY_UNTIL_TIME",              NOTIFY_TABLE_DWORD,    spoolss_notify_until_time },
3483 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_TIME,                    "JOB_NOTIFY_TIME",                    NOTIFY_TABLE_DWORD,    spoolss_notify_job_time },
3484 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_TOTAL_PAGES,             "JOB_NOTIFY_TOTAL_PAGES",             NOTIFY_TABLE_DWORD,    spoolss_notify_total_pages },
3485 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_PAGES_PRINTED,           "JOB_NOTIFY_PAGES_PRINTED",           NOTIFY_TABLE_DWORD,    spoolss_notify_pages_printed },
3486 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_TOTAL_BYTES,             "JOB_NOTIFY_TOTAL_BYTES",             NOTIFY_TABLE_DWORD,    spoolss_notify_job_size },
3487 { PRINT_TABLE_END, 0x0, NULL, 0x0, NULL },
3488 };
3489
3490 /*******************************************************************
3491  Return the variable_type of info_data structure.
3492 ********************************************************************/
3493
3494 static uint32_t variable_type_of_notify_info_data(enum spoolss_NotifyType type,
3495                                                   enum spoolss_Field field)
3496 {
3497         int i=0;
3498
3499         for (i = 0; i < ARRAY_SIZE(notify_info_data_table); i++) {
3500                 if ( (notify_info_data_table[i].type == type) &&
3501                      (notify_info_data_table[i].field == field) ) {
3502                         return notify_info_data_table[i].variable_type;
3503                 }
3504         }
3505
3506         DEBUG(5, ("invalid notify data type %d/%d\n", type, field));
3507
3508         return 0;
3509 }
3510
3511 /****************************************************************************
3512 ****************************************************************************/
3513
3514 static bool search_notify(uint16 type, uint16 field, int *value)
3515 {
3516         int i;
3517
3518         for (i = 0; notify_info_data_table[i].type != PRINT_TABLE_END; i++) {
3519                 if (notify_info_data_table[i].type == type &&
3520                     notify_info_data_table[i].field == field &&
3521                     notify_info_data_table[i].fn != NULL) {
3522                         *value = i;
3523                         return True;
3524                 }
3525         }
3526
3527         return False;
3528 }
3529
3530 /****************************************************************************
3531 ****************************************************************************/
3532
3533 void construct_info_data(struct spoolss_Notify *info_data, uint16 type, uint16 field, int id)
3534 {
3535         info_data->type                 = type;
3536         info_data->field                = field;
3537         info_data->variable_type        = variable_type_of_notify_info_data(type, field);
3538         info_data->job_id               = id;
3539 }
3540
3541 /*******************************************************************
3542  *
3543  * fill a notify_info struct with info asked
3544  *
3545  ********************************************************************/
3546
3547 static bool construct_notify_printer_info(Printer_entry *print_hnd, struct spoolss_NotifyInfo *info, int
3548                                           snum, SPOOL_NOTIFY_OPTION_TYPE
3549                                           *option_type, uint32 id,
3550                                           TALLOC_CTX *mem_ctx)
3551 {
3552         int field_num,j;
3553         uint16 type;
3554         uint16 field;
3555
3556         struct spoolss_Notify *current_data;
3557         NT_PRINTER_INFO_LEVEL *printer = NULL;
3558         print_queue_struct *queue=NULL;
3559
3560         type=option_type->type;
3561
3562         DEBUG(4,("construct_notify_printer_info: Notify type: [%s], number of notify info: [%d] on printer: [%s]\n",
3563                 (option_type->type==PRINTER_NOTIFY_TYPE?"PRINTER_NOTIFY_TYPE":"JOB_NOTIFY_TYPE"),
3564                 option_type->count, lp_servicename(snum)));
3565
3566         if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &printer, 2, lp_const_servicename(snum))))
3567                 return False;
3568
3569         for(field_num=0; field_num<option_type->count; field_num++) {
3570                 field = option_type->fields[field_num];
3571
3572                 DEBUG(4,("construct_notify_printer_info: notify [%d]: type [%x], field [%x]\n", field_num, type, field));
3573
3574                 if (!search_notify(type, field, &j) )
3575                         continue;
3576
3577                 if((info->notifies = SMB_REALLOC_ARRAY(info->notifies, struct spoolss_Notify, info->count+1)) == NULL) {
3578                         DEBUG(2,("construct_notify_printer_info: failed to enlarge buffer info->data!\n"));
3579                         free_a_printer(&printer, 2);
3580                         return False;
3581                 }
3582
3583                 current_data = &info->notifies[info->count];
3584
3585                 construct_info_data(current_data, type, field, id);
3586
3587                 DEBUG(10,("construct_notify_printer_info: calling [%s]  snum=%d  printername=[%s])\n",
3588                                 notify_info_data_table[j].name, snum, printer->info_2->printername ));
3589
3590                 notify_info_data_table[j].fn(snum, current_data, queue,
3591                                              printer, mem_ctx);
3592
3593                 info->count++;
3594         }
3595
3596         free_a_printer(&printer, 2);
3597         return True;
3598 }
3599
3600 /*******************************************************************
3601  *
3602  * fill a notify_info struct with info asked
3603  *
3604  ********************************************************************/
3605
3606 static bool construct_notify_jobs_info(print_queue_struct *queue,
3607                                        struct spoolss_NotifyInfo *info,
3608                                        NT_PRINTER_INFO_LEVEL *printer,
3609                                        int snum, SPOOL_NOTIFY_OPTION_TYPE
3610                                        *option_type, uint32 id,
3611                                        TALLOC_CTX *mem_ctx)
3612 {
3613         int field_num,j;
3614         uint16 type;
3615         uint16 field;
3616
3617         struct spoolss_Notify *current_data;
3618
3619         DEBUG(4,("construct_notify_jobs_info\n"));
3620
3621         type = option_type->type;
3622
3623         DEBUGADD(4,("Notify type: [%s], number of notify info: [%d]\n",
3624                 (option_type->type==PRINTER_NOTIFY_TYPE?"PRINTER_NOTIFY_TYPE":"JOB_NOTIFY_TYPE"),
3625                 option_type->count));
3626
3627         for(field_num=0; field_num<option_type->count; field_num++) {
3628                 field = option_type->fields[field_num];
3629
3630                 if (!search_notify(type, field, &j) )
3631                         continue;
3632
3633                 if((info->notifies = SMB_REALLOC_ARRAY(info->notifies, struct spoolss_Notify, info->count+1)) == NULL) {
3634                         DEBUG(2,("construct_notify_jobs_info: failed to enlarg buffer info->data!\n"));
3635                         return False;
3636                 }
3637
3638                 current_data=&(info->notifies[info->count]);
3639
3640                 construct_info_data(current_data, type, field, id);
3641                 notify_info_data_table[j].fn(snum, current_data, queue,
3642                                              printer, mem_ctx);
3643                 info->count++;
3644         }
3645
3646         return True;
3647 }
3648
3649 /*
3650  * JFM: The enumeration is not that simple, it's even non obvious.
3651  *
3652  * let's take an example: I want to monitor the PRINTER SERVER for
3653  * the printer's name and the number of jobs currently queued.
3654  * So in the NOTIFY_OPTION, I have one NOTIFY_OPTION_TYPE structure.
3655  * Its type is PRINTER_NOTIFY_TYPE and it has 2 fields NAME and CJOBS.
3656  *
3657  * I have 3 printers on the back of my server.
3658  *
3659  * Now the response is a NOTIFY_INFO structure, with 6 NOTIFY_INFO_DATA
3660  * structures.
3661  *   Number     Data                    Id
3662  *      1       printer 1 name          1
3663  *      2       printer 1 cjob          1
3664  *      3       printer 2 name          2
3665  *      4       printer 2 cjob          2
3666  *      5       printer 3 name          3
3667  *      6       printer 3 name          3
3668  *
3669  * that's the print server case, the printer case is even worse.
3670  */
3671
3672 /*******************************************************************
3673  *
3674  * enumerate all printers on the printserver
3675  * fill a notify_info struct with info asked
3676  *
3677  ********************************************************************/
3678
3679 static WERROR printserver_notify_info(pipes_struct *p, POLICY_HND *hnd,
3680                                       struct spoolss_NotifyInfo *info,
3681                                       TALLOC_CTX *mem_ctx)
3682 {
3683         int snum;
3684         Printer_entry *Printer=find_printer_index_by_hnd(p, hnd);
3685         int n_services=lp_numservices();
3686         int i;
3687         SPOOL_NOTIFY_OPTION *option;
3688         SPOOL_NOTIFY_OPTION_TYPE *option_type;
3689
3690         DEBUG(4,("printserver_notify_info\n"));
3691
3692         if (!Printer)
3693                 return WERR_BADFID;
3694
3695         option=Printer->notify.option;
3696
3697         info->version   = 2;
3698         info->notifies  = NULL;
3699         info->count     = 0;
3700
3701         /* a bug in xp sp2 rc2 causes it to send a fnpcn request without
3702            sending a ffpcn() request first */
3703
3704         if ( !option )
3705                 return WERR_BADFID;
3706
3707         for (i=0; i<option->count; i++) {
3708                 option_type=&(option->ctr.type[i]);
3709
3710                 if (option_type->type!=PRINTER_NOTIFY_TYPE)
3711                         continue;
3712
3713                 for (snum=0; snum<n_services; snum++)
3714                 {
3715                         if ( lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) )
3716                                 construct_notify_printer_info ( Printer, info, snum, option_type, snum, mem_ctx );
3717                 }
3718         }
3719
3720 #if 0
3721         /*
3722          * Debugging information, don't delete.
3723          */
3724
3725         DEBUG(1,("dumping the NOTIFY_INFO\n"));
3726         DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
3727         DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3728
3729         for (i=0; i<info->count; i++) {
3730                 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3731                 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
3732                 info->data[i].id, info->data[i].size, info->data[i].enc_type));
3733         }
3734 #endif
3735
3736         return WERR_OK;
3737 }
3738
3739 /*******************************************************************
3740  *
3741  * fill a notify_info struct with info asked
3742  *
3743  ********************************************************************/
3744
3745 static WERROR printer_notify_info(pipes_struct *p, POLICY_HND *hnd, struct spoolss_NotifyInfo *info,
3746                                   TALLOC_CTX *mem_ctx)
3747 {
3748         int snum;
3749         Printer_entry *Printer=find_printer_index_by_hnd(p, hnd);
3750         int i;
3751         uint32 id;
3752         SPOOL_NOTIFY_OPTION *option;
3753         SPOOL_NOTIFY_OPTION_TYPE *option_type;
3754         int count,j;
3755         print_queue_struct *queue=NULL;
3756         print_status_struct status;
3757
3758         DEBUG(4,("printer_notify_info\n"));
3759
3760         if (!Printer)
3761                 return WERR_BADFID;
3762
3763         option=Printer->notify.option;
3764         id = 0x0;
3765
3766         info->version   = 2;
3767         info->notifies  = NULL;
3768         info->count     = 0;
3769
3770         /* a bug in xp sp2 rc2 causes it to send a fnpcn request without
3771            sending a ffpcn() request first */
3772
3773         if ( !option )
3774                 return WERR_BADFID;
3775
3776         get_printer_snum(p, hnd, &snum, NULL);
3777
3778         for (i=0; i<option->count; i++) {
3779                 option_type=&option->ctr.type[i];
3780
3781                 switch ( option_type->type ) {
3782                 case PRINTER_NOTIFY_TYPE:
3783                         if(construct_notify_printer_info(Printer, info, snum,
3784                                                          option_type, id,
3785                                                          mem_ctx))
3786                                 id--;
3787                         break;
3788
3789                 case JOB_NOTIFY_TYPE: {
3790                         NT_PRINTER_INFO_LEVEL *printer = NULL;
3791
3792                         count = print_queue_status(snum, &queue, &status);
3793
3794                         if (!W_ERROR_IS_OK(get_a_printer(Printer, &printer, 2, lp_const_servicename(snum))))
3795                                 goto done;
3796
3797                         for (j=0; j<count; j++) {
3798                                 construct_notify_jobs_info(&queue[j], info,
3799                                                            printer, snum,
3800                                                            option_type,
3801                                                            queue[j].job,
3802                                                            mem_ctx);
3803                         }
3804
3805                         free_a_printer(&printer, 2);
3806
3807                 done:
3808                         SAFE_FREE(queue);
3809                         break;
3810                 }
3811                 }
3812         }
3813
3814         /*
3815          * Debugging information, don't delete.
3816          */
3817         /*
3818         DEBUG(1,("dumping the NOTIFY_INFO\n"));
3819         DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
3820         DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3821
3822         for (i=0; i<info->count; i++) {
3823                 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3824                 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
3825                 info->data[i].id, info->data[i].size, info->data[i].enc_type));
3826         }
3827         */
3828         return WERR_OK;
3829 }
3830
3831 /****************************************************************
3832  _spoolss_RouterRefreshPrinterChangeNotify
3833 ****************************************************************/
3834
3835 WERROR _spoolss_RouterRefreshPrinterChangeNotify(pipes_struct *p,
3836                                                  struct spoolss_RouterRefreshPrinterChangeNotify *r)
3837 {
3838         POLICY_HND *handle = r->in.handle;
3839         struct spoolss_NotifyInfo *info;
3840
3841         Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
3842         WERROR result = WERR_BADFID;
3843
3844         /* we always have a spoolss_NotifyInfo struct */
3845         info = talloc_zero(p->mem_ctx, struct spoolss_NotifyInfo);
3846         if (!info) {
3847                 result = WERR_NOMEM;
3848                 goto done;
3849         }
3850
3851         *r->out.info = info;
3852
3853         if (!Printer) {
3854                 DEBUG(2,("_spoolss_RouterRefreshPrinterChangeNotify: "
3855                         "Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
3856                 goto done;
3857         }
3858
3859         DEBUG(4,("Printer type %x\n",Printer->printer_type));
3860
3861         /*
3862          *      We are now using the change value, and
3863          *      I should check for PRINTER_NOTIFY_OPTIONS_REFRESH but as
3864          *      I don't have a global notification system, I'm sending back all the
3865          *      informations even when _NOTHING_ has changed.
3866          */
3867
3868         /* We need to keep track of the change value to send back in
3869            RRPCN replies otherwise our updates are ignored. */
3870
3871         Printer->notify.fnpcn = True;
3872
3873         if (Printer->notify.client_connected) {
3874                 DEBUG(10,("_spoolss_RouterRefreshPrinterChangeNotify: "
3875                         "Saving change value in request [%x]\n",
3876                         r->in.change_low));
3877                 Printer->notify.change = r->in.change_low;
3878         }
3879
3880         /* just ignore the SPOOL_NOTIFY_OPTION */
3881
3882         switch (Printer->printer_type) {
3883                 case SPLHND_SERVER:
3884                         result = printserver_notify_info(p, handle, info, p->mem_ctx);
3885                         break;
3886
3887                 case SPLHND_PRINTER:
3888                         result = printer_notify_info(p, handle, info, p->mem_ctx);
3889                         break;
3890         }
3891
3892         Printer->notify.fnpcn = False;
3893
3894 done:
3895         return result;
3896 }
3897
3898 /********************************************************************
3899  * construct_printer_info_0
3900  * fill a printer_info_0 struct
3901  ********************************************************************/
3902
3903 static bool construct_printer_info_0(Printer_entry *print_hnd, PRINTER_INFO_0 *printer, int snum)
3904 {
3905         char *chaine = NULL;
3906         int count;
3907         NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
3908         counter_printer_0 *session_counter;
3909         uint32 global_counter;
3910         struct tm *t;
3911         time_t setuptime;
3912         print_status_struct status;
3913         TALLOC_CTX *ctx = talloc_tos();
3914
3915         if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
3916                 return False;
3917
3918         init_unistr(&printer->printername, ntprinter->info_2->printername);
3919
3920         chaine = talloc_asprintf(ctx, "\\\\%s", get_server_name(print_hnd));
3921         if (!chaine) {
3922                 free_a_printer(&ntprinter,2);
3923                 return false;
3924         }
3925
3926         count = print_queue_length(snum, &status);
3927
3928         /* check if we already have a counter for this printer */
3929         for(session_counter = counter_list; session_counter; session_counter = session_counter->next) {
3930                 if (session_counter->snum == snum)
3931                         break;
3932         }
3933
3934         init_unistr(&printer->servername, chaine);
3935
3936         /* it's the first time, add it to the list */
3937         if (session_counter==NULL) {
3938                 if((session_counter=SMB_MALLOC_P(counter_printer_0)) == NULL) {
3939                         free_a_printer(&ntprinter, 2);
3940                         return False;
3941                 }
3942                 ZERO_STRUCTP(session_counter);
3943                 session_counter->snum=snum;
3944                 session_counter->counter=0;
3945                 DLIST_ADD(counter_list, session_counter);
3946         }
3947
3948         /* increment it */
3949         session_counter->counter++;
3950
3951         /* JFM:
3952          * the global_counter should be stored in a TDB as it's common to all the clients
3953          * and should be zeroed on samba startup
3954          */
3955         global_counter=session_counter->counter;
3956         printer->cjobs = count;
3957         printer->total_jobs = 0;
3958         printer->total_bytes = 0;
3959
3960         setuptime = (time_t)ntprinter->info_2->setuptime;
3961         t=gmtime(&setuptime);
3962
3963         printer->year = t->tm_year+1900;
3964         printer->month = t->tm_mon+1;
3965         printer->dayofweek = t->tm_wday;
3966         printer->day = t->tm_mday;
3967         printer->hour = t->tm_hour;
3968         printer->minute = t->tm_min;
3969         printer->second = t->tm_sec;
3970         printer->milliseconds = 0;
3971
3972         printer->global_counter = global_counter;
3973         printer->total_pages = 0;
3974
3975         /* in 2.2 we reported ourselves as 0x0004 and 0x0565 */
3976         printer->major_version = 0x0005;        /* NT 5 */
3977         printer->build_version = 0x0893;        /* build 2195 */
3978
3979         printer->unknown7 = 0x1;
3980         printer->unknown8 = 0x0;
3981         printer->unknown9 = 0x0;
3982         printer->session_counter = session_counter->counter;
3983         printer->unknown11 = 0x0;
3984         printer->printer_errors = 0x0;          /* number of print failure */
3985         printer->unknown13 = 0x0;
3986         printer->unknown14 = 0x1;
3987         printer->unknown15 = 0x024a;            /* 586 Pentium ? */
3988         printer->unknown16 =  0x0;
3989         printer->change_id = ntprinter->info_2->changeid; /* ChangeID in milliseconds*/
3990         printer->unknown18 =  0x0;
3991         printer->status = nt_printq_status(status.status);
3992         printer->unknown20 =  0x0;
3993         printer->c_setprinter = get_c_setprinter(); /* monotonically increasing sum of delta printer counts */
3994         printer->unknown22 = 0x0;
3995         printer->unknown23 = 0x6;               /* 6  ???*/
3996         printer->unknown24 = 0;                 /* unknown 24 to 26 are always 0 */
3997         printer->unknown25 = 0;
3998         printer->unknown26 = 0;
3999         printer->unknown27 = 0;
4000         printer->unknown28 = 0;
4001         printer->unknown29 = 0;
4002
4003         free_a_printer(&ntprinter,2);
4004         return (True);
4005 }
4006
4007 /********************************************************************
4008  * construct_printer_info_1
4009  * fill a printer_info_1 struct
4010  ********************************************************************/
4011 static bool construct_printer_info_1(Printer_entry *print_hnd, uint32 flags, PRINTER_INFO_1 *printer, int snum)
4012 {
4013         char *chaine = NULL;
4014         NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4015         TALLOC_CTX *ctx = talloc_tos();
4016
4017         if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
4018                 return false;
4019
4020         printer->flags=flags;
4021
4022         if (*ntprinter->info_2->comment == '\0') {
4023                 init_unistr(&printer->comment, lp_comment(snum));
4024                 chaine = talloc_asprintf(ctx,
4025                                 "%s,%s,%s", ntprinter->info_2->printername,
4026                                 ntprinter->info_2->drivername, lp_comment(snum));
4027         }
4028         else {
4029                 init_unistr(&printer->comment, ntprinter->info_2->comment); /* saved comment. */
4030                 chaine = talloc_asprintf(ctx,
4031                                 "%s,%s,%s", ntprinter->info_2->printername,
4032                                 ntprinter->info_2->drivername, ntprinter->info_2->comment);
4033         }
4034
4035         if (!chaine) {
4036                 free_a_printer(&ntprinter,2);
4037                 return false;
4038         }
4039
4040         init_unistr(&printer->description, chaine);
4041         init_unistr(&printer->name, ntprinter->info_2->printername);
4042
4043         free_a_printer(&ntprinter,2);
4044
4045         return True;
4046 }
4047
4048 /****************************************************************************
4049  Free a DEVMODE struct.
4050 ****************************************************************************/
4051
4052 static void free_dev_mode(DEVICEMODE *dev)
4053 {
4054         if (dev == NULL)
4055                 return;
4056
4057         SAFE_FREE(dev->dev_private);
4058         SAFE_FREE(dev);
4059 }
4060
4061
4062 /****************************************************************************
4063  Convert an NT_DEVICEMODE to a DEVICEMODE structure.  Both pointers
4064  should be valid upon entry
4065 ****************************************************************************/
4066
4067 static bool convert_nt_devicemode( DEVICEMODE *devmode, NT_DEVICEMODE *ntdevmode )
4068 {
4069         if ( !devmode || !ntdevmode )
4070                 return False;
4071
4072         init_unistr(&devmode->devicename, ntdevmode->devicename);
4073
4074         init_unistr(&devmode->formname, ntdevmode->formname);
4075
4076         devmode->specversion      = ntdevmode->specversion;
4077         devmode->driverversion    = ntdevmode->driverversion;
4078         devmode->size             = ntdevmode->size;
4079         devmode->driverextra      = ntdevmode->driverextra;
4080         devmode->fields           = ntdevmode->fields;
4081
4082         devmode->orientation      = ntdevmode->orientation;
4083         devmode->papersize        = ntdevmode->papersize;
4084         devmode->paperlength      = ntdevmode->paperlength;
4085         devmode->paperwidth       = ntdevmode->paperwidth;
4086         devmode->scale            = ntdevmode->scale;
4087         devmode->copies           = ntdevmode->copies;
4088         devmode->defaultsource    = ntdevmode->defaultsource;
4089         devmode->printquality     = ntdevmode->printquality;
4090         devmode->color            = ntdevmode->color;
4091         devmode->duplex           = ntdevmode->duplex;
4092         devmode->yresolution      = ntdevmode->yresolution;
4093         devmode->ttoption         = ntdevmode->ttoption;
4094         devmode->collate          = ntdevmode->collate;
4095         devmode->icmmethod        = ntdevmode->icmmethod;
4096         devmode->icmintent        = ntdevmode->icmintent;
4097         devmode->mediatype        = ntdevmode->mediatype;
4098         devmode->dithertype       = ntdevmode->dithertype;
4099
4100         if (ntdevmode->nt_dev_private != NULL) {
4101                 if ((devmode->dev_private=(uint8 *)memdup(ntdevmode->nt_dev_private, ntdevmode->driverextra)) == NULL)
4102                         return False;
4103         }
4104
4105         return True;
4106 }
4107
4108 /****************************************************************************
4109  Create a DEVMODE struct. Returns malloced memory.
4110 ****************************************************************************/
4111
4112 DEVICEMODE *construct_dev_mode(const char *servicename)
4113 {
4114         NT_PRINTER_INFO_LEVEL   *printer = NULL;
4115         DEVICEMODE              *devmode = NULL;
4116
4117         DEBUG(7,("construct_dev_mode\n"));
4118
4119         DEBUGADD(8,("getting printer characteristics\n"));
4120
4121         if (!W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, servicename)))
4122                 return NULL;
4123
4124         if ( !printer->info_2->devmode ) {
4125                 DEBUG(5, ("BONG! There was no device mode!\n"));
4126                 goto done;
4127         }
4128
4129         if ((devmode = SMB_MALLOC_P(DEVICEMODE)) == NULL) {
4130                 DEBUG(2,("construct_dev_mode: malloc fail.\n"));
4131                 goto done;
4132         }
4133
4134         ZERO_STRUCTP(devmode);
4135
4136         DEBUGADD(8,("loading DEVICEMODE\n"));
4137
4138         if ( !convert_nt_devicemode( devmode, printer->info_2->devmode ) ) {
4139                 free_dev_mode( devmode );
4140                 devmode = NULL;
4141         }
4142
4143 done:
4144         free_a_printer(&printer,2);
4145
4146         return devmode;
4147 }
4148
4149 /********************************************************************
4150  * construct_printer_info_2
4151  * fill a printer_info_2 struct
4152  ********************************************************************/
4153
4154 static bool construct_printer_info_2(Printer_entry *print_hnd, PRINTER_INFO_2 *printer, int snum)
4155 {
4156         int count;
4157         NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4158
4159         print_status_struct status;
4160
4161         if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
4162                 return False;
4163
4164         count = print_queue_length(snum, &status);
4165
4166         init_unistr(&printer->servername, ntprinter->info_2->servername); /* servername*/
4167         init_unistr(&printer->printername, ntprinter->info_2->printername);                             /* printername*/
4168         init_unistr(&printer->sharename, lp_servicename(snum));                 /* sharename */
4169         init_unistr(&printer->portname, ntprinter->info_2->portname);                   /* port */
4170         init_unistr(&printer->drivername, ntprinter->info_2->drivername);       /* drivername */
4171
4172         if (*ntprinter->info_2->comment == '\0')
4173                 init_unistr(&printer->comment, lp_comment(snum));                       /* comment */
4174         else
4175                 init_unistr(&printer->comment, ntprinter->info_2->comment); /* saved comment. */
4176
4177         init_unistr(&printer->location, ntprinter->info_2->location);           /* location */
4178         init_unistr(&printer->sepfile, ntprinter->info_2->sepfile);             /* separator file */
4179         init_unistr(&printer->printprocessor, ntprinter->info_2->printprocessor);/* print processor */
4180         init_unistr(&printer->datatype, ntprinter->info_2->datatype);           /* datatype */
4181         init_unistr(&printer->parameters, ntprinter->info_2->parameters);       /* parameters (of print processor) */
4182
4183         printer->attributes = ntprinter->info_2->attributes;
4184
4185         printer->priority = ntprinter->info_2->priority;                                /* priority */
4186         printer->defaultpriority = ntprinter->info_2->default_priority;         /* default priority */
4187         printer->starttime = ntprinter->info_2->starttime;                      /* starttime */
4188         printer->untiltime = ntprinter->info_2->untiltime;                      /* untiltime */
4189         printer->status = nt_printq_status(status.status);                      /* status */
4190         printer->cjobs = count;                                                 /* jobs */
4191         printer->averageppm = ntprinter->info_2->averageppm;                    /* average pages per minute */
4192
4193         if ( !(printer->devmode = construct_dev_mode(
4194                        lp_const_servicename(snum))) )
4195                 DEBUG(8, ("Returning NULL Devicemode!\n"));
4196
4197         printer->secdesc = NULL;
4198
4199         if ( ntprinter->info_2->secdesc_buf
4200                 && ntprinter->info_2->secdesc_buf->sd_size != 0 )
4201         {
4202                 /* don't use talloc_steal() here unless you do a deep steal of all
4203                    the SEC_DESC members */
4204
4205                 printer->secdesc = dup_sec_desc( talloc_tos(),
4206                         ntprinter->info_2->secdesc_buf->sd );
4207         }
4208
4209         free_a_printer(&ntprinter, 2);
4210
4211         return True;
4212 }
4213
4214 /********************************************************************
4215  * construct_printer_info_3
4216  * fill a printer_info_3 struct
4217  ********************************************************************/
4218
4219 static bool construct_printer_info_3(Printer_entry *print_hnd, PRINTER_INFO_3 **pp_printer, int snum)
4220 {
4221         NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4222         PRINTER_INFO_3 *printer = NULL;
4223
4224         if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
4225                 return False;
4226
4227         *pp_printer = NULL;
4228         if ((printer = SMB_MALLOC_P(PRINTER_INFO_3)) == NULL) {
4229                 DEBUG(2,("construct_printer_info_3: malloc fail.\n"));
4230                 free_a_printer(&ntprinter, 2);
4231                 return False;
4232         }
4233
4234         ZERO_STRUCTP(printer);
4235
4236         /* These are the components of the SD we are returning. */
4237
4238         if (ntprinter->info_2->secdesc_buf && ntprinter->info_2->secdesc_buf->sd_size != 0) {
4239                 /* don't use talloc_steal() here unless you do a deep steal of all
4240                    the SEC_DESC members */
4241
4242                 printer->secdesc = dup_sec_desc( talloc_tos(),
4243                         ntprinter->info_2->secdesc_buf->sd );
4244         }
4245
4246         free_a_printer(&ntprinter, 2);
4247
4248         *pp_printer = printer;
4249         return True;
4250 }
4251
4252 /********************************************************************
4253  * construct_printer_info_4
4254  * fill a printer_info_4 struct
4255  ********************************************************************/
4256
4257 static bool construct_printer_info_4(Printer_entry *print_hnd, PRINTER_INFO_4 *printer, int snum)
4258 {
4259         NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4260
4261         if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
4262                 return False;
4263
4264         init_unistr(&printer->printername, ntprinter->info_2->printername);                             /* printername*/
4265         init_unistr(&printer->servername, ntprinter->info_2->servername); /* servername*/
4266         printer->attributes = ntprinter->info_2->attributes;
4267
4268         free_a_printer(&ntprinter, 2);
4269         return True;
4270 }
4271
4272 /********************************************************************
4273  * construct_printer_info_5
4274  * fill a printer_info_5 struct
4275  ********************************************************************/
4276
4277 static bool construct_printer_info_5(Printer_entry *print_hnd, PRINTER_INFO_5 *printer, int snum)
4278 {
4279         NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4280
4281         if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
4282                 return False;
4283
4284         init_unistr(&printer->printername, ntprinter->info_2->printername);
4285         init_unistr(&printer->portname, ntprinter->info_2->portname);
4286         printer->attributes = ntprinter->info_2->attributes;
4287
4288         /* these two are not used by NT+ according to MSDN */
4289
4290         printer->device_not_selected_timeout = 0x0;  /* have seen 0x3a98 */
4291         printer->transmission_retry_timeout  = 0x0;  /* have seen 0xafc8 */
4292
4293         free_a_printer(&ntprinter, 2);
4294
4295         return True;
4296 }
4297
4298 /********************************************************************
4299  * construct_printer_info_6
4300  * fill a printer_info_6 struct
4301  ********************************************************************/
4302
4303 static bool construct_printer_info_6(Printer_entry *print_hnd,
4304                                      PRINTER_INFO_6 *printer,
4305                                      int snum)
4306 {
4307         NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4308         int count;
4309         print_status_struct status;
4310
4311         if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2,
4312                                          lp_const_servicename(snum))))
4313                 return False;
4314
4315         count = print_queue_length(snum, &status);
4316
4317         printer->status = nt_printq_status(status.status);
4318
4319         free_a_printer(&ntprinter, 2);
4320
4321         return True;
4322 }
4323
4324 /********************************************************************
4325  * construct_printer_info_7
4326  * fill a printer_info_7 struct
4327  ********************************************************************/
4328
4329 static bool construct_printer_info_7(Printer_entry *print_hnd, PRINTER_INFO_7 *printer, int snum)
4330 {
4331         char *guid_str = NULL;
4332         struct GUID guid;
4333
4334         if (is_printer_published(print_hnd, snum, &guid)) {
4335                 if (asprintf(&guid_str, "{%s}",
4336                              GUID_string(talloc_tos(), &guid)) == -1) {
4337                         return false;
4338                 }
4339                 strupper_m(guid_str);
4340                 init_unistr(&printer->guid, guid_str);
4341                 SAFE_FREE(guid_str);
4342                 printer->action = SPOOL_DS_PUBLISH;
4343         } else {
4344                 init_unistr(&printer->guid, "");
4345                 printer->action = SPOOL_DS_UNPUBLISH;
4346         }
4347
4348         return True;
4349 }
4350
4351 /********************************************************************
4352  Spoolss_enumprinters.
4353 ********************************************************************/
4354
4355 static WERROR enum_all_printers_info_1(uint32 flags, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4356 {
4357         int snum;
4358         int i;
4359         int n_services=lp_numservices();
4360         PRINTER_INFO_1 *printers=NULL;
4361         PRINTER_INFO_1 current_prt;
4362         WERROR result = WERR_OK;
4363
4364         DEBUG(4,("enum_all_printers_info_1\n"));
4365
4366         for (snum=0; snum<n_services; snum++) {
4367                 if (lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) ) {
4368                         DEBUG(4,("Found a printer in smb.conf: %s[%x]\n", lp_servicename(snum), snum));
4369
4370                         if (construct_printer_info_1(NULL, flags, &current_prt, snum)) {
4371                                 if((printers=SMB_REALLOC_ARRAY(printers, PRINTER_INFO_1, *returned +1)) == NULL) {
4372                                         DEBUG(2,("enum_all_printers_info_1: failed to enlarge printers buffer!\n"));
4373                                         *returned=0;
4374                                         return WERR_NOMEM;
4375                                 }
4376                                 DEBUG(4,("ReAlloced memory for [%d] PRINTER_INFO_1\n", *returned));
4377
4378                                 memcpy(&printers[*returned], &current_prt, sizeof(PRINTER_INFO_1));
4379                                 (*returned)++;
4380                         }
4381                 }
4382         }
4383
4384         /* check the required size. */
4385         for (i=0; i<*returned; i++)
4386                 (*needed) += spoolss_size_printer_info_1(&printers[i]);
4387
4388         if (*needed > offered) {
4389                 result = WERR_INSUFFICIENT_BUFFER;
4390                 goto out;
4391         }
4392
4393         if (!rpcbuf_alloc_size(buffer, *needed)) {
4394                 result = WERR_NOMEM;
4395                 goto out;
4396         }
4397
4398         /* fill the buffer with the structures */
4399         for (i=0; i<*returned; i++)
4400                 smb_io_printer_info_1("", buffer, &printers[i], 0);
4401
4402 out:
4403         /* clear memory */
4404
4405         SAFE_FREE(printers);
4406
4407         if ( !W_ERROR_IS_OK(result) )
4408                 *returned = 0;
4409
4410         return result;
4411 }
4412
4413 /********************************************************************
4414  enum_all_printers_info_1_local.
4415 *********************************************************************/
4416
4417 static WERROR enum_all_printers_info_1_local(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4418 {
4419         DEBUG(4,("enum_all_printers_info_1_local\n"));
4420
4421         return enum_all_printers_info_1(PRINTER_ENUM_ICON8, buffer, offered, needed, returned);
4422 }
4423
4424 /********************************************************************
4425  enum_all_printers_info_1_name.
4426 *********************************************************************/
4427
4428 static WERROR enum_all_printers_info_1_name(fstring name, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4429 {
4430         char *s = name;
4431
4432         DEBUG(4,("enum_all_printers_info_1_name\n"));
4433
4434         if ((name[0] == '\\') && (name[1] == '\\'))
4435                 s = name + 2;
4436
4437         if (is_myname_or_ipaddr(s)) {
4438                 return enum_all_printers_info_1(PRINTER_ENUM_ICON8, buffer, offered, needed, returned);
4439         }
4440         else
4441                 return WERR_INVALID_NAME;
4442 }
4443
4444 #if 0   /* JERRY -- disabled for now.  Don't think this is used, tested, or correct */
4445 /********************************************************************
4446  enum_all_printers_info_1_remote.
4447 *********************************************************************/
4448
4449 static WERROR enum_all_printers_info_1_remote(fstring name, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4450 {
4451         PRINTER_INFO_1 *printer;
4452         fstring printername;
4453         fstring desc;
4454         fstring comment;
4455         DEBUG(4,("enum_all_printers_info_1_remote\n"));
4456         WERROR result = WERR_OK;
4457
4458         /* JFM: currently it's more a place holder than anything else.
4459          * In the spooler world there is a notion of server registration.
4460          * the print servers are registered on the PDC (in the same domain)
4461          *
4462          * We should have a TDB here. The registration is done thru an
4463          * undocumented RPC call.
4464          */
4465
4466         if((printer=SMB_MALLOC_P(PRINTER_INFO_1)) == NULL)
4467                 return WERR_NOMEM;
4468
4469         *returned=1;
4470
4471         slprintf(printername, sizeof(printername)-1,"Windows NT Remote Printers!!\\\\%s", name);
4472         slprintf(desc, sizeof(desc)-1,"%s", name);
4473         slprintf(comment, sizeof(comment)-1, "Logged on Domain");
4474
4475         init_unistr(&printer->description, desc);
4476         init_unistr(&printer->name, printername);
4477         init_unistr(&printer->comment, comment);
4478         printer->flags=PRINTER_ENUM_ICON3|PRINTER_ENUM_CONTAINER;
4479
4480         /* check the required size. */
4481         *needed += spoolss_size_printer_info_1(printer);
4482
4483         if (*needed > offered) {
4484                 result = WERR_INSUFFICIENT_BUFFER;
4485                 goto out;
4486         }
4487
4488         if (!rpcbuf_alloc_size(buffer, *needed)) {
4489                 result = WERR_NOMEM;
4490                 goto out;
4491         }
4492
4493         /* fill the buffer with the structures */
4494         smb_io_printer_info_1("", buffer, printer, 0);
4495
4496 out:
4497         /* clear memory */
4498         SAFE_FREE(printer);
4499
4500         if ( !W_ERROR_IS_OK(result) )
4501                 *returned = 0;
4502
4503         return result;
4504 }
4505
4506 #endif
4507
4508 /********************************************************************
4509  enum_all_printers_info_1_network.
4510 *********************************************************************/
4511
4512 static WERROR enum_all_printers_info_1_network(fstring name, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4513 {
4514         char *s = name;
4515
4516         DEBUG(4,("enum_all_printers_info_1_network\n"));
4517
4518         /* If we respond to a enum_printers level 1 on our name with flags
4519            set to PRINTER_ENUM_REMOTE with a list of printers then these
4520            printers incorrectly appear in the APW browse list.
4521            Specifically the printers for the server appear at the workgroup
4522            level where all the other servers in the domain are
4523            listed. Windows responds to this call with a
4524            WERR_CAN_NOT_COMPLETE so we should do the same. */
4525
4526         if (name[0] == '\\' && name[1] == '\\')
4527                  s = name + 2;
4528
4529         if (is_myname_or_ipaddr(s))
4530                  return WERR_CAN_NOT_COMPLETE;
4531
4532         return enum_all_printers_info_1(PRINTER_ENUM_NAME, buffer, offered, needed, returned);
4533 }
4534
4535 /********************************************************************
4536  * api_spoolss_enumprinters
4537  *
4538  * called from api_spoolss_enumprinters (see this to understand)
4539  ********************************************************************/
4540
4541 static WERROR enum_all_printers_info_2(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4542 {
4543         int snum;
4544         int i;
4545         int n_services=lp_numservices();
4546         PRINTER_INFO_2 *printers=NULL;
4547         PRINTER_INFO_2 current_prt;
4548         WERROR result = WERR_OK;
4549
4550         *returned = 0;
4551
4552         for (snum=0; snum<n_services; snum++) {
4553                 if (lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) ) {
4554                         DEBUG(4,("Found a printer in smb.conf: %s[%x]\n", lp_servicename(snum), snum));
4555
4556                         if (construct_printer_info_2(NULL, &current_prt, snum)) {
4557                                 if ( !(printers=SMB_REALLOC_ARRAY(printers, PRINTER_INFO_2, *returned +1)) ) {
4558                                         DEBUG(2,("enum_all_printers_info_2: failed to enlarge printers buffer!\n"));
4559                                         *returned = 0;
4560                                         return WERR_NOMEM;
4561                                 }
4562
4563                                 DEBUG(4,("ReAlloced memory for [%d] PRINTER_INFO_2\n", *returned + 1));
4564
4565                                 memcpy(&printers[*returned], &current_prt, sizeof(PRINTER_INFO_2));
4566
4567                                 (*returned)++;
4568                         }
4569                 }
4570         }
4571
4572         /* check the required size. */
4573         for (i=0; i<*returned; i++)
4574                 (*needed) += spoolss_size_printer_info_2(&printers[i]);
4575
4576         if (*needed > offered) {
4577                 result = WERR_INSUFFICIENT_BUFFER;
4578                 goto out;
4579         }
4580
4581         if (!rpcbuf_alloc_size(buffer, *needed)) {
4582                 result = WERR_NOMEM;
4583                 goto out;
4584         }
4585
4586         /* fill the buffer with the structures */
4587         for (i=0; i<*returned; i++)
4588                 smb_io_printer_info_2("", buffer, &(printers[i]), 0);
4589
4590 out:
4591         /* clear memory */
4592
4593         for (i=0; i<*returned; i++)
4594                 free_devmode(printers[i].devmode);
4595
4596         SAFE_FREE(printers);
4597
4598         if ( !W_ERROR_IS_OK(result) )
4599                 *returned = 0;
4600
4601         return result;
4602 }
4603
4604 /********************************************************************
4605  * handle enumeration of printers at level 1
4606  ********************************************************************/
4607
4608 static WERROR enumprinters_level1( uint32 flags, fstring name,
4609                                  RPC_BUFFER *buffer, uint32 offered,
4610                                  uint32 *needed, uint32 *returned)
4611 {
4612         /* Not all the flags are equals */
4613
4614         if (flags & PRINTER_ENUM_LOCAL)
4615                 return enum_all_printers_info_1_local(buffer, offered, needed, returned);
4616
4617         if (flags & PRINTER_ENUM_NAME)
4618                 return enum_all_printers_info_1_name(name, buffer, offered, needed, returned);
4619
4620 #if 0   /* JERRY - disabled for now */
4621         if (flags & PRINTER_ENUM_REMOTE)
4622                 return enum_all_printers_info_1_remote(name, buffer, offered, needed, returned);
4623 #endif
4624
4625         if (flags & PRINTER_ENUM_NETWORK)
4626                 return enum_all_printers_info_1_network(name, buffer, offered, needed, returned);
4627
4628         return WERR_OK; /* NT4sp5 does that */
4629 }
4630
4631 /********************************************************************
4632  * handle enumeration of printers at level 2
4633  ********************************************************************/
4634
4635 static WERROR enumprinters_level2( uint32 flags, const char *servername,
4636                                  RPC_BUFFER *buffer, uint32 offered,
4637                                  uint32 *needed, uint32 *returned)
4638 {
4639         if (flags & PRINTER_ENUM_LOCAL) {
4640                         return enum_all_printers_info_2(buffer, offered, needed, returned);
4641         }
4642
4643         if (flags & PRINTER_ENUM_NAME) {
4644                 if (is_myname_or_ipaddr(canon_servername(servername)))
4645                         return enum_all_printers_info_2(buffer, offered, needed, returned);
4646                 else
4647                         return WERR_INVALID_NAME;
4648         }
4649
4650         if (flags & PRINTER_ENUM_REMOTE)
4651                 return WERR_UNKNOWN_LEVEL;
4652
4653         return WERR_OK;
4654 }
4655
4656 /********************************************************************
4657  * handle enumeration of printers at level 5
4658  ********************************************************************/
4659
4660 static WERROR enumprinters_level5( uint32 flags, const char *servername,
4661                                  RPC_BUFFER *buffer, uint32 offered,
4662                                  uint32 *needed, uint32 *returned)
4663 {
4664 /*      return enum_all_printers_info_5(buffer, offered, needed, returned);*/
4665         return WERR_OK;
4666 }
4667
4668 /********************************************************************
4669  * api_spoolss_enumprinters
4670  *
4671  * called from api_spoolss_enumprinters (see this to understand)
4672  ********************************************************************/
4673
4674 WERROR _spoolss_enumprinters( pipes_struct *p, SPOOL_Q_ENUMPRINTERS *q_u, SPOOL_R_ENUMPRINTERS *r_u)
4675 {
4676         uint32 flags = q_u->flags;
4677         UNISTR2 *servername = &q_u->servername;
4678         uint32 level = q_u->level;
4679         RPC_BUFFER *buffer = NULL;
4680         uint32 offered = q_u->offered;
4681         uint32 *needed = &r_u->needed;
4682         uint32 *returned = &r_u->returned;
4683
4684         fstring name;
4685
4686         /* that's an [in out] buffer */
4687
4688         if (!q_u->buffer && (offered!=0)) {
4689                 return WERR_INVALID_PARAM;
4690         }
4691
4692         if (offered > MAX_RPC_DATA_SIZE) {
4693                 return WERR_INVALID_PARAM;
4694         }
4695
4696         rpcbuf_move(q_u->buffer, &r_u->buffer);
4697         buffer = r_u->buffer;
4698
4699         DEBUG(4,("_spoolss_enumprinters\n"));
4700
4701         *needed=0;
4702         *returned=0;
4703
4704         /*
4705          * Level 1:
4706          *          flags==PRINTER_ENUM_NAME
4707          *           if name=="" then enumerates all printers
4708          *           if name!="" then enumerate the printer
4709          *          flags==PRINTER_ENUM_REMOTE
4710          *          name is NULL, enumerate printers
4711          * Level 2: name!="" enumerates printers, name can't be NULL
4712          * Level 3: doesn't exist
4713          * Level 4: does a local registry lookup
4714          * Level 5: same as Level 2
4715          */
4716
4717         unistr2_to_ascii(name, servername, sizeof(name));
4718         strupper_m(name);
4719
4720         switch (level) {
4721         case 1:
4722                 return enumprinters_level1(flags, name, buffer, offered, needed, returned);
4723         case 2:
4724                 return enumprinters_level2(flags, name, buffer, offered, needed, returned);
4725         case 5:
4726                 return enumprinters_level5(flags, name, buffer, offered, needed, returned);
4727         case 3:
4728         case 4:
4729                 break;
4730         }
4731         return WERR_UNKNOWN_LEVEL;
4732 }
4733
4734 /****************************************************************************
4735 ****************************************************************************/
4736
4737 static WERROR getprinter_level_0(Printer_entry *print_hnd, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
4738 {
4739         PRINTER_INFO_0 *printer=NULL;
4740         WERROR result = WERR_OK;
4741
4742         if((printer=SMB_MALLOC_P(PRINTER_INFO_0)) == NULL)
4743                 return WERR_NOMEM;
4744
4745         construct_printer_info_0(print_hnd, printer, snum);
4746
4747         /* check the required size. */
4748         *needed += spoolss_size_printer_info_0(printer);
4749
4750         if (*needed > offered) {
4751                 result = WERR_INSUFFICIENT_BUFFER;
4752                 goto out;
4753         }
4754
4755         if (!rpcbuf_alloc_size(buffer, *needed)) {
4756                 result = WERR_NOMEM;
4757                 goto out;
4758         }
4759
4760         /* fill the buffer with the structures */
4761         smb_io_printer_info_0("", buffer, printer, 0);
4762
4763 out:
4764         /* clear memory */
4765
4766         SAFE_FREE(printer);
4767
4768         return result;
4769 }
4770
4771 /****************************************************************************
4772 ****************************************************************************/
4773
4774 static WERROR getprinter_level_1(Printer_entry *print_hnd, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
4775 {
4776         PRINTER_INFO_1 *printer=NULL;
4777         WERROR result = WERR_OK;
4778
4779         if((printer=SMB_MALLOC_P(PRINTER_INFO_1)) == NULL)
4780                 return WERR_NOMEM;
4781
4782         construct_printer_info_1(print_hnd, PRINTER_ENUM_ICON8, printer, snum);
4783
4784         /* check the required size. */
4785         *needed += spoolss_size_printer_info_1(printer);
4786
4787         if (*needed > offered) {
4788                 result = WERR_INSUFFICIENT_BUFFER;
4789                 goto out;
4790         }
4791
4792         if (!rpcbuf_alloc_size(buffer, *needed)) {
4793                 result = WERR_NOMEM;
4794                 goto out;
4795         }
4796
4797         /* fill the buffer with the structures */
4798         smb_io_printer_info_1("", buffer, printer, 0);
4799
4800 out:
4801         /* clear memory */
4802         SAFE_FREE(printer);
4803
4804         return result;
4805 }
4806
4807 /****************************************************************************
4808 ****************************************************************************/
4809
4810 static WERROR getprinter_level_2(Printer_entry *print_hnd, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
4811 {
4812         PRINTER_INFO_2 *printer=NULL;
4813         WERROR result = WERR_OK;
4814
4815         if((printer=SMB_MALLOC_P(PRINTER_INFO_2))==NULL)
4816                 return WERR_NOMEM;
4817
4818         construct_printer_info_2(print_hnd, printer, snum);
4819
4820         /* check the required size. */
4821         *needed += spoolss_size_printer_info_2(printer);
4822
4823         if (*needed > offered) {
4824                 result = WERR_INSUFFICIENT_BUFFER;
4825                 goto out;
4826         }
4827
4828         if (!rpcbuf_alloc_size(buffer, *needed)) {
4829                 result = WERR_NOMEM;
4830                 goto out;
4831         }
4832
4833         /* fill the buffer with the structures */
4834         if (!smb_io_printer_info_2("", buffer, printer, 0))
4835                 result = WERR_NOMEM;
4836
4837 out:
4838         /* clear memory */
4839         free_printer_info_2(printer);
4840
4841         return result;
4842 }
4843
4844 /****************************************************************************
4845 ****************************************************************************/
4846
4847 static WERROR getprinter_level_3(Printer_entry *print_hnd, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
4848 {
4849         PRINTER_INFO_3 *printer=NULL;
4850         WERROR result = WERR_OK;
4851
4852         if (!construct_printer_info_3(print_hnd, &printer, snum))
4853                 return WERR_NOMEM;
4854
4855         /* check the required size. */
4856         *needed += spoolss_size_printer_info_3(printer);
4857
4858         if (*needed > offered) {
4859                 result = WERR_INSUFFICIENT_BUFFER;
4860                 goto out;
4861         }
4862
4863         if (!rpcbuf_alloc_size(buffer, *needed)) {
4864                 result = WERR_NOMEM;
4865                 goto out;
4866         }
4867
4868         /* fill the buffer with the structures */
4869         smb_io_printer_info_3("", buffer, printer, 0);
4870
4871 out:
4872         /* clear memory */
4873         free_printer_info_3(printer);
4874
4875         return result;
4876 }
4877
4878 /****************************************************************************
4879 ****************************************************************************/
4880
4881 static WERROR getprinter_level_4(Printer_entry *print_hnd, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
4882 {
4883         PRINTER_INFO_4 *printer=NULL;
4884         WERROR result = WERR_OK;
4885
4886         if((printer=SMB_MALLOC_P(PRINTER_INFO_4))==NULL)
4887                 return WERR_NOMEM;
4888
4889         if (!construct_printer_info_4(print_hnd, printer, snum)) {
4890                 SAFE_FREE(printer);
4891                 return WERR_NOMEM;
4892         }
4893
4894         /* check the required size. */
4895         *needed += spoolss_size_printer_info_4(printer);
4896
4897         if (*needed > offered) {
4898                 result = WERR_INSUFFICIENT_BUFFER;
4899                 goto out;
4900         }
4901
4902         if (!rpcbuf_alloc_size(buffer, *needed)) {
4903                 result = WERR_NOMEM;
4904                 goto out;
4905         }
4906
4907         /* fill the buffer with the structures */
4908         smb_io_printer_info_4("", buffer, printer, 0);
4909
4910 out:
4911         /* clear memory */
4912         free_printer_info_4(printer);
4913
4914         return result;
4915 }
4916
4917 /****************************************************************************
4918 ****************************************************************************/
4919
4920 static WERROR getprinter_level_5(Printer_entry *print_hnd, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
4921 {
4922         PRINTER_INFO_5 *printer=NULL;
4923         WERROR result = WERR_OK;
4924
4925         if((printer=SMB_MALLOC_P(PRINTER_INFO_5))==NULL)
4926                 return WERR_NOMEM;
4927
4928         if (!construct_printer_info_5(print_hnd, printer, snum)) {
4929                 free_printer_info_5(printer);
4930                 return WERR_NOMEM;
4931         }
4932
4933         /* check the required size. */
4934         *needed += spoolss_size_printer_info_5(printer);
4935
4936         if (*needed > offered) {
4937                 result = WERR_INSUFFICIENT_BUFFER;
4938                 goto out;
4939         }
4940
4941         if (!rpcbuf_alloc_size(buffer, *needed)) {
4942                 result = WERR_NOMEM;
4943                 goto out;
4944         }
4945
4946         /* fill the buffer with the structures */
4947         smb_io_printer_info_5("", buffer, printer, 0);
4948
4949 out:
4950         /* clear memory */
4951         free_printer_info_5(printer);
4952
4953         return result;
4954 }
4955
4956 static WERROR getprinter_level_6(Printer_entry *print_hnd,
4957                                  int snum,
4958                                  RPC_BUFFER *buffer, uint32 offered,
4959                                  uint32 *needed)
4960 {
4961         PRINTER_INFO_6 *printer;
4962         WERROR result = WERR_OK;
4963
4964         if ((printer = SMB_MALLOC_P(PRINTER_INFO_6)) == NULL) {
4965                 return WERR_NOMEM;
4966         }
4967
4968         if (!construct_printer_info_6(print_hnd, printer, snum)) {
4969                 free_printer_info_6(printer);
4970                 return WERR_NOMEM;
4971         }
4972
4973         /* check the required size. */
4974         *needed += spoolss_size_printer_info_6(printer);
4975
4976         if (*needed > offered) {
4977                 result = WERR_INSUFFICIENT_BUFFER;
4978                 goto out;
4979         }
4980
4981         if (!rpcbuf_alloc_size(buffer, *needed)) {
4982                 result = WERR_NOMEM;
4983                 goto out;
4984         }
4985
4986         /* fill the buffer with the structures */
4987         smb_io_printer_info_6("", buffer, printer, 0);
4988
4989 out:
4990         /* clear memory */
4991         free_printer_info_6(printer);
4992
4993         return result;
4994 }
4995
4996 static WERROR getprinter_level_7(Printer_entry *print_hnd, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
4997 {
4998         PRINTER_INFO_7 *printer=NULL;
4999         WERROR result = WERR_OK;
5000
5001         if((printer=SMB_MALLOC_P(PRINTER_INFO_7))==NULL)
5002                 return WERR_NOMEM;
5003
5004         if (!construct_printer_info_7(print_hnd, printer, snum)) {
5005                 result = WERR_NOMEM;
5006                 goto out;
5007         }
5008
5009         /* check the required size. */
5010         *needed += spoolss_size_printer_info_7(printer);
5011
5012         if (*needed > offered) {
5013                 result = WERR_INSUFFICIENT_BUFFER;
5014                 goto out;
5015         }
5016
5017         if (!rpcbuf_alloc_size(buffer, *needed)) {
5018                 result = WERR_NOMEM;
5019                 goto out;
5020
5021         }
5022
5023         /* fill the buffer with the structures */
5024         smb_io_printer_info_7("", buffer, printer, 0);
5025
5026 out:
5027         /* clear memory */
5028         free_printer_info_7(printer);
5029
5030         return result;
5031 }
5032
5033 /****************************************************************************
5034 ****************************************************************************/
5035
5036 WERROR _spoolss_getprinter(pipes_struct *p, SPOOL_Q_GETPRINTER *q_u, SPOOL_R_GETPRINTER *r_u)
5037 {
5038         POLICY_HND *handle = &q_u->handle;
5039         uint32 level = q_u->level;
5040         RPC_BUFFER *buffer = NULL;
5041         uint32 offered = q_u->offered;
5042         uint32 *needed = &r_u->needed;
5043         Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
5044
5045         int snum;
5046
5047         /* that's an [in out] buffer */
5048
5049         if (!q_u->buffer && (offered!=0)) {
5050                 return WERR_INVALID_PARAM;
5051         }
5052
5053         if (offered > MAX_RPC_DATA_SIZE) {
5054                 return WERR_INVALID_PARAM;
5055         }
5056
5057         rpcbuf_move(q_u->buffer, &r_u->buffer);
5058         buffer = r_u->buffer;
5059
5060         *needed=0;
5061
5062         if (!get_printer_snum(p, handle, &snum, NULL))
5063                 return WERR_BADFID;
5064
5065         switch (level) {
5066         case 0:
5067                 return getprinter_level_0(Printer, snum, buffer, offered, needed);
5068         case 1:
5069                 return getprinter_level_1(Printer, snum, buffer, offered, needed);
5070         case 2:
5071                 return getprinter_level_2(Printer, snum, buffer, offered, needed);
5072         case 3:
5073                 return getprinter_level_3(Printer, snum, buffer, offered, needed);
5074         case 4:
5075                 return getprinter_level_4(Printer, snum, buffer, offered, needed);
5076         case 5:
5077                 return getprinter_level_5(Printer, snum, buffer, offered, needed);
5078         case 6:
5079                 return getprinter_level_6(Printer, snum, buffer, offered, needed);
5080         case 7:
5081                 return getprinter_level_7(Printer, snum, buffer, offered, needed);
5082         }
5083         return WERR_UNKNOWN_LEVEL;
5084 }
5085
5086 /********************************************************************
5087  * fill a DRIVER_INFO_1 struct
5088  ********************************************************************/
5089
5090 static void fill_printer_driver_info_1(DRIVER_INFO_1 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, const char *servername, fstring architecture)
5091 {
5092         init_unistr( &info->name, driver.info_3->name);
5093 }
5094
5095 /********************************************************************
5096  * construct_printer_driver_info_1
5097  ********************************************************************/
5098
5099 static WERROR construct_printer_driver_info_1(DRIVER_INFO_1 *info, int snum, const char *servername, fstring architecture, uint32 version)
5100 {
5101         NT_PRINTER_INFO_LEVEL *printer = NULL;
5102         NT_PRINTER_DRIVER_INFO_LEVEL driver;
5103
5104         ZERO_STRUCT(driver);
5105
5106         if (!W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, lp_const_servicename(snum))))
5107                 return WERR_INVALID_PRINTER_NAME;
5108
5109         if (!W_ERROR_IS_OK(get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version))) {
5110                 free_a_printer(&printer, 2);
5111                 return WERR_UNKNOWN_PRINTER_DRIVER;
5112         }
5113
5114         fill_printer_driver_info_1(info, driver, servername, architecture);
5115
5116         free_a_printer(&printer,2);
5117
5118         return WERR_OK;
5119 }
5120
5121 /********************************************************************
5122  * construct_printer_driver_info_2
5123  * fill a printer_info_2 struct
5124  ********************************************************************/
5125
5126 static void fill_printer_driver_info_2(DRIVER_INFO_2 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, const char *servername)
5127 {
5128         TALLOC_CTX *ctx = talloc_tos();
5129         char *temp = NULL;
5130         const char *cservername = canon_servername(servername);
5131
5132         info->version=driver.info_3->cversion;
5133
5134         init_unistr( &info->name, driver.info_3->name );
5135         init_unistr( &info->architecture, driver.info_3->environment );
5136
5137         if (strlen(driver.info_3->driverpath)) {
5138                 temp = talloc_asprintf(ctx,
5139                                 "\\\\%s%s",
5140                                 cservername,
5141                                 driver.info_3->driverpath);
5142                 init_unistr( &info->driverpath, temp );
5143         } else {
5144                 init_unistr( &info->driverpath, "" );
5145         }
5146
5147         TALLOC_FREE(temp);
5148         if (strlen(driver.info_3->datafile)) {
5149                 temp = talloc_asprintf(ctx,
5150                                 "\\\\%s%s",
5151                                 cservername,
5152                                 driver.info_3->datafile);
5153                 init_unistr( &info->datafile, temp );
5154         } else
5155                 init_unistr( &info->datafile, "" );
5156
5157         TALLOC_FREE(temp);
5158         if (strlen(driver.info_3->configfile)) {
5159                 temp = talloc_asprintf(ctx,
5160                                 "\\\\%s%s",
5161                                 cservername,
5162                                 driver.info_3->configfile);
5163                 init_unistr( &info->configfile, temp );
5164         } else
5165                 init_unistr( &info->configfile, "" );
5166 }
5167
5168 /********************************************************************
5169  * construct_printer_driver_info_2
5170  * fill a printer_info_2 struct
5171  ********************************************************************/
5172
5173 static WERROR construct_printer_driver_info_2(DRIVER_INFO_2 *info, int snum, const char *servername, fstring architecture, uint32 version)
5174 {
5175         NT_PRINTER_INFO_LEVEL *printer = NULL;
5176         NT_PRINTER_DRIVER_INFO_LEVEL driver;
5177
5178         ZERO_STRUCT(printer);
5179         ZERO_STRUCT(driver);
5180
5181         if (!W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, lp_const_servicename(snum))))
5182                 return WERR_INVALID_PRINTER_NAME;
5183
5184         if (!W_ERROR_IS_OK(get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version))) {
5185                 free_a_printer(&printer, 2);
5186                 return WERR_UNKNOWN_PRINTER_DRIVER;
5187         }
5188
5189         fill_printer_driver_info_2(info, driver, servername);
5190
5191         free_a_printer(&printer,2);
5192
5193         return WERR_OK;
5194 }
5195
5196 /********************************************************************
5197  * copy a strings array and convert to UNICODE
5198  *
5199  * convert an array of ascii string to a UNICODE string
5200  ********************************************************************/
5201
5202 static uint32 init_unistr_array(uint16 **uni_array, fstring *char_array, const char *servername)
5203 {
5204         int i=0;
5205         int j=0;
5206         const char *v;
5207         char *line = NULL;
5208         TALLOC_CTX *ctx = talloc_tos();
5209
5210         DEBUG(6,("init_unistr_array\n"));
5211         *uni_array=NULL;
5212
5213         while (true) {
5214                 if ( !char_array ) {
5215                         v = "";
5216                 } else {
5217                         v = char_array[i];
5218                         if (!v)
5219                                 v = ""; /* hack to handle null lists */
5220                 }
5221
5222                 /* hack to allow this to be used in places other than when generating
5223                    the list of dependent files */
5224
5225                 TALLOC_FREE(line);
5226                 if ( servername ) {
5227                         line = talloc_asprintf(ctx,
5228                                         "\\\\%s%s",
5229                                         canon_servername(servername),
5230                                         v);
5231                 } else {
5232                         line = talloc_strdup(ctx, v);
5233                 }
5234
5235                 if (!line) {
5236                         SAFE_FREE(*uni_array);
5237                         return 0;
5238                 }
5239                 DEBUGADD(6,("%d:%s:%lu\n", i, line, (unsigned long)strlen(line)));
5240
5241                 /* add one extra unit16 for the second terminating NULL */
5242
5243                 if ( (*uni_array=SMB_REALLOC_ARRAY(*uni_array, uint16, j+1+strlen(line)+2)) == NULL ) {
5244                         DEBUG(2,("init_unistr_array: Realloc error\n" ));
5245                         return 0;
5246                 }
5247
5248                 if ( !strlen(v) )
5249                         break;
5250
5251                 j += (rpcstr_push((*uni_array+j), line, sizeof(uint16)*strlen(line)+2, STR_TERMINATE) / sizeof(uint16));
5252                 i++;
5253         }
5254
5255         if (*uni_array) {
5256                 /* special case for ""; we need to add both NULL's here */
5257                 if (!j)
5258                         (*uni_array)[j++]=0x0000;
5259                 (*uni_array)[j]=0x0000;
5260         }
5261
5262         DEBUGADD(6,("last one:done\n"));
5263
5264         /* return size of array in uint16's */
5265
5266         return j+1;
5267 }
5268
5269 /********************************************************************
5270  * construct_printer_info_3
5271  * fill a printer_info_3 struct
5272  ********************************************************************/
5273
5274 static void fill_printer_driver_info_3(DRIVER_INFO_3 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, const char *servername)
5275 {
5276         char *temp = NULL;
5277         TALLOC_CTX *ctx = talloc_tos();
5278         const char *cservername = canon_servername(servername);
5279
5280         ZERO_STRUCTP(info);
5281
5282         info->version=driver.info_3->cversion;
5283
5284         init_unistr( &info->name, driver.info_3->name );
5285         init_unistr( &info->architecture, driver.info_3->environment );
5286
5287         if (strlen(driver.info_3->driverpath)) {
5288                 temp = talloc_asprintf(ctx,
5289                                 "\\\\%s%s",
5290                                 cservername,
5291                                 driver.info_3->driverpath);
5292                 init_unistr( &info->driverpath, temp );
5293         } else
5294                 init_unistr( &info->driverpath, "" );
5295
5296         TALLOC_FREE(temp);
5297         if (strlen(driver.info_3->datafile)) {
5298                 temp = talloc_asprintf(ctx,
5299                                 "\\\\%s%s",
5300                                 cservername,
5301                                 driver.info_3->datafile);
5302                 init_unistr( &info->datafile, temp );
5303         } else
5304                 init_unistr( &info->datafile, "" );
5305
5306         TALLOC_FREE(temp);
5307         if (strlen(driver.info_3->configfile)) {
5308                 temp = talloc_asprintf(ctx,
5309                                 "\\\\%s%s",
5310                                 cservername,
5311                                 driver.info_3->configfile);
5312                 init_unistr( &info->configfile, temp );
5313         } else
5314                 init_unistr( &info->configfile, "" );
5315
5316         TALLOC_FREE(temp);
5317         if (strlen(driver.info_3->helpfile)) {
5318                 temp = talloc_asprintf(ctx,
5319                                 "\\\\%s%s",
5320                                 cservername,
5321                                 driver.info_3->helpfile);
5322                 init_unistr( &info->helpfile, temp );
5323         } else
5324                 init_unistr( &info->helpfile, "" );
5325
5326         TALLOC_FREE(temp);
5327         init_unistr( &info->monitorname, driver.info_3->monitorname );
5328         init_unistr( &info->defaultdatatype, driver.info_3->defaultdatatype );
5329
5330         info->dependentfiles=NULL;
5331         init_unistr_array(&info->dependentfiles, driver.info_3->dependentfiles, cservername);
5332 }
5333
5334 /********************************************************************
5335  * construct_printer_info_3
5336  * fill a printer_info_3 struct
5337  ********************************************************************/
5338
5339 static WERROR construct_printer_driver_info_3(DRIVER_INFO_3 *info, int snum, const char *servername, fstring architecture, uint32 version)
5340 {
5341         NT_PRINTER_INFO_LEVEL *printer = NULL;
5342         NT_PRINTER_DRIVER_INFO_LEVEL driver;
5343         WERROR status;
5344         ZERO_STRUCT(driver);
5345
5346         status=get_a_printer(NULL, &printer, 2, lp_const_servicename(snum) );
5347         DEBUG(8,("construct_printer_driver_info_3: status: %s\n", win_errstr(status)));
5348         if (!W_ERROR_IS_OK(status))
5349                 return WERR_INVALID_PRINTER_NAME;
5350
5351         status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
5352         DEBUG(8,("construct_printer_driver_info_3: status: %s\n", win_errstr(status)));
5353
5354 #if 0   /* JERRY */
5355
5356         /*
5357          * I put this code in during testing.  Helpful when commenting out the
5358          * support for DRIVER_INFO_6 in regards to win2k.  Not needed in general
5359          * as win2k always queries the driver using an infor level of 6.
5360          * I've left it in (but ifdef'd out) because I'll probably
5361          * use it in experimentation again in the future.   --jerry 22/01/2002
5362          */
5363
5364         if (!W_ERROR_IS_OK(status)) {
5365                 /*
5366                  * Is this a W2k client ?
5367                  */
5368                 if (version == 3) {
5369                         /* Yes - try again with a WinNT driver. */
5370                         version = 2;
5371                         status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
5372                         DEBUG(8,("construct_printer_driver_info_3: status: %s\n", win_errstr(status)));
5373                 }
5374 #endif
5375
5376                 if (!W_ERROR_IS_OK(status)) {
5377                         free_a_printer(&printer,2);
5378                         return WERR_UNKNOWN_PRINTER_DRIVER;
5379                 }
5380
5381 #if 0   /* JERRY */
5382         }
5383 #endif
5384
5385
5386         fill_printer_driver_info_3(info, driver, servername);
5387
5388         free_a_printer(&printer,2);
5389
5390         return WERR_OK;
5391 }
5392
5393 /********************************************************************
5394  * construct_printer_info_6
5395  * fill a printer_info_6 struct - we know that driver is really level 3. This sucks. JRA.
5396  ********************************************************************/
5397
5398 static void fill_printer_driver_info_6(DRIVER_INFO_6 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, const char *servername)
5399 {
5400         char *temp = NULL;
5401         fstring nullstr;
5402         TALLOC_CTX *ctx = talloc_tos();
5403         const char *cservername = canon_servername(servername);
5404
5405         ZERO_STRUCTP(info);
5406         memset(&nullstr, '\0', sizeof(fstring));
5407
5408         info->version=driver.info_3->cversion;
5409
5410         init_unistr( &info->name, driver.info_3->name );
5411         init_unistr( &info->architecture, driver.info_3->environment );
5412
5413         if (strlen(driver.info_3->driverpath)) {
5414                 temp = talloc_asprintf(ctx,
5415                                 "\\\\%s%s",
5416                                 cservername,
5417                                 driver.info_3->driverpath);
5418                 init_unistr( &info->driverpath, temp );
5419         } else
5420                 init_unistr( &info->driverpath, "" );
5421
5422         TALLOC_FREE(temp);
5423         if (strlen(driver.info_3->datafile)) {
5424                 temp = talloc_asprintf(ctx,
5425                                 "\\\\%s%s",
5426                                 cservername,
5427                                 driver.info_3->datafile);
5428                 init_unistr( &info->datafile, temp );
5429         } else
5430                 init_unistr( &info->datafile, "" );
5431
5432         TALLOC_FREE(temp);
5433         if (strlen(driver.info_3->configfile)) {
5434                 temp = talloc_asprintf(ctx,
5435                                 "\\\\%s%s",
5436                                 cservername,
5437                                 driver.info_3->configfile);
5438                 init_unistr( &info->configfile, temp );
5439         } else
5440                 init_unistr( &info->configfile, "" );
5441
5442         TALLOC_FREE(temp);
5443         if (strlen(driver.info_3->helpfile)) {
5444                 temp = talloc_asprintf(ctx,
5445                                 "\\\\%s%s",
5446                                 cservername,
5447                                 driver.info_3->helpfile);
5448                 init_unistr( &info->helpfile, temp );
5449         } else
5450                 init_unistr( &info->helpfile, "" );
5451
5452         TALLOC_FREE(temp);
5453         init_unistr( &info->monitorname, driver.info_3->monitorname );
5454         init_unistr( &info->defaultdatatype, driver.info_3->defaultdatatype );
5455
5456         info->dependentfiles = NULL;
5457         init_unistr_array( &info->dependentfiles, driver.info_3->dependentfiles, servername );
5458
5459         info->previousdrivernames=NULL;
5460         init_unistr_array(&info->previousdrivernames, &nullstr, servername);
5461
5462         info->driver_date=0;
5463
5464         info->padding=0;
5465         info->driver_version_low=0;
5466         info->driver_version_high=0;
5467
5468         init_unistr( &info->mfgname, "");
5469         init_unistr( &info->oem_url, "");
5470         init_unistr( &info->hardware_id, "");
5471         init_unistr( &info->provider, "");
5472 }
5473
5474 /********************************************************************
5475  * construct_printer_info_6
5476  * fill a printer_info_6 struct
5477  ********************************************************************/
5478
5479 static WERROR construct_printer_driver_info_6(DRIVER_INFO_6 *info, int snum,
5480               const char *servername, fstring architecture, uint32 version)
5481 {
5482         NT_PRINTER_INFO_LEVEL           *printer = NULL;
5483         NT_PRINTER_DRIVER_INFO_LEVEL    driver;
5484         WERROR                          status;
5485
5486         ZERO_STRUCT(driver);
5487
5488         status=get_a_printer(NULL, &printer, 2, lp_const_servicename(snum) );
5489
5490         DEBUG(8,("construct_printer_driver_info_6: status: %s\n", win_errstr(status)));
5491
5492         if (!W_ERROR_IS_OK(status))
5493                 return WERR_INVALID_PRINTER_NAME;
5494
5495         status = get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
5496
5497         DEBUG(8,("construct_printer_driver_info_6: status: %s\n", win_errstr(status)));
5498
5499         if (!W_ERROR_IS_OK(status))
5500         {
5501                 /*
5502                  * Is this a W2k client ?
5503                  */
5504
5505                 if (version < 3) {
5506                         free_a_printer(&printer,2);
5507                         return WERR_UNKNOWN_PRINTER_DRIVER;
5508                 }
5509
5510                 /* Yes - try again with a WinNT driver. */
5511                 version = 2;
5512                 status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
5513                 DEBUG(8,("construct_printer_driver_info_6: status: %s\n", win_errstr(status)));
5514                 if (!W_ERROR_IS_OK(status)) {
5515                         free_a_printer(&printer,2);
5516                         return WERR_UNKNOWN_PRINTER_DRIVER;
5517                 }
5518         }
5519
5520         fill_printer_driver_info_6(info, driver, servername);
5521
5522         free_a_printer(&printer,2);
5523         free_a_printer_driver(driver, 3);
5524
5525         return WERR_OK;
5526 }
5527
5528 /****************************************************************************
5529 ****************************************************************************/
5530
5531 static void free_printer_driver_info_3(DRIVER_INFO_3 *info)
5532 {
5533         SAFE_FREE(info->dependentfiles);
5534 }
5535
5536 /****************************************************************************
5537 ****************************************************************************/
5538
5539 static void free_printer_driver_info_6(DRIVER_INFO_6 *info)
5540 {
5541         SAFE_FREE(info->dependentfiles);
5542 }
5543
5544 /****************************************************************************
5545 ****************************************************************************/
5546
5547 static WERROR getprinterdriver2_level1(const char *servername, fstring architecture, uint32 version, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
5548 {
5549         DRIVER_INFO_1 *info=NULL;
5550         WERROR result;
5551
5552         if((info=SMB_MALLOC_P(DRIVER_INFO_1)) == NULL)
5553                 return WERR_NOMEM;
5554
5555         result = construct_printer_driver_info_1(info, snum, servername, architecture, version);
5556         if (!W_ERROR_IS_OK(result))
5557                 goto out;
5558
5559         /* check the required size. */
5560         *needed += spoolss_size_printer_driver_info_1(info);
5561
5562         if (*needed > offered) {
5563                 result = WERR_INSUFFICIENT_BUFFER;
5564                 goto out;
5565         }
5566
5567         if (!rpcbuf_alloc_size(buffer, *needed)) {
5568                 result = WERR_NOMEM;
5569                 goto out;
5570         }
5571
5572         /* fill the buffer with the structures */
5573         smb_io_printer_driver_info_1("", buffer, info, 0);
5574
5575 out:
5576         /* clear memory */
5577         SAFE_FREE(info);
5578
5579         return result;
5580 }
5581
5582 /****************************************************************************
5583 ****************************************************************************/
5584
5585 static WERROR getprinterdriver2_level2(const char *servername, fstring architecture, uint32 version, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
5586 {
5587         DRIVER_INFO_2 *info=NULL;
5588         WERROR result;
5589
5590         if((info=SMB_MALLOC_P(DRIVER_INFO_2)) == NULL)
5591                 return WERR_NOMEM;
5592
5593         result = construct_printer_driver_info_2(info, snum, servername, architecture, version);
5594         if (!W_ERROR_IS_OK(result))
5595                 goto out;
5596
5597         /* check the required size. */
5598         *needed += spoolss_size_printer_driver_info_2(info);
5599
5600         if (*needed > offered) {
5601                 result = WERR_INSUFFICIENT_BUFFER;
5602                 goto out;
5603         }
5604
5605         if (!rpcbuf_alloc_size(buffer, *needed)) {
5606                 result = WERR_NOMEM;
5607                 goto out;
5608         }
5609
5610         /* fill the buffer with the structures */
5611         smb_io_printer_driver_info_2("", buffer, info, 0);
5612
5613 out:
5614         /* clear memory */
5615         SAFE_FREE(info);
5616
5617         return result;
5618 }
5619
5620 /****************************************************************************
5621 ****************************************************************************/
5622
5623 static WERROR getprinterdriver2_level3(const char *servername, fstring architecture, uint32 version, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
5624 {
5625         DRIVER_INFO_3 info;
5626         WERROR result;
5627
5628         ZERO_STRUCT(info);
5629
5630         result = construct_printer_driver_info_3(&info, snum, servername, architecture, version);
5631         if (!W_ERROR_IS_OK(result))
5632                 goto out;
5633
5634         /* check the required size. */
5635         *needed += spoolss_size_printer_driver_info_3(&info);
5636
5637         if (*needed > offered) {
5638                 result = WERR_INSUFFICIENT_BUFFER;
5639                 goto out;
5640         }
5641
5642         if (!rpcbuf_alloc_size(buffer, *needed)) {
5643                 result = WERR_NOMEM;
5644                 goto out;
5645         }
5646
5647         /* fill the buffer with the structures */
5648         smb_io_printer_driver_info_3("", buffer, &info, 0);
5649
5650 out:
5651         free_printer_driver_info_3(&info);
5652
5653         return result;
5654 }
5655
5656 /****************************************************************************
5657 ****************************************************************************/
5658
5659 static WERROR getprinterdriver2_level6(const char *servername, fstring architecture, uint32 version, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
5660 {
5661         DRIVER_INFO_6 info;
5662         WERROR result;
5663
5664         ZERO_STRUCT(info);
5665
5666         result = construct_printer_driver_info_6(&info, snum, servername, architecture, version);
5667         if (!W_ERROR_IS_OK(result))
5668                 goto out;
5669
5670         /* check the required size. */
5671         *needed += spoolss_size_printer_driver_info_6(&info);
5672
5673         if (*needed > offered) {
5674                 result = WERR_INSUFFICIENT_BUFFER;
5675                 goto out;
5676         }
5677
5678         if (!rpcbuf_alloc_size(buffer, *needed)) {
5679                 result = WERR_NOMEM;
5680                 goto out;
5681         }
5682
5683         /* fill the buffer with the structures */
5684         smb_io_printer_driver_info_6("", buffer, &info, 0);
5685
5686 out:
5687         free_printer_driver_info_6(&info);
5688
5689         return result;
5690 }
5691
5692 /****************************************************************************
5693 ****************************************************************************/
5694
5695 WERROR _spoolss_getprinterdriver2(pipes_struct *p, SPOOL_Q_GETPRINTERDRIVER2 *q_u, SPOOL_R_GETPRINTERDRIVER2 *r_u)
5696 {
5697         POLICY_HND *handle = &q_u->handle;
5698         UNISTR2 *uni_arch = &q_u->architecture;
5699         uint32 level = q_u->level;
5700         uint32 clientmajorversion = q_u->clientmajorversion;
5701         RPC_BUFFER *buffer = NULL;
5702         uint32 offered = q_u->offered;
5703         uint32 *needed = &r_u->needed;
5704         uint32 *servermajorversion = &r_u->servermajorversion;
5705         uint32 *serverminorversion = &r_u->serverminorversion;
5706         Printer_entry *printer;
5707
5708         fstring servername;
5709         fstring architecture;
5710         int snum;
5711
5712         /* that's an [in out] buffer */
5713
5714         if (!q_u->buffer && (offered!=0)) {
5715                 return WERR_INVALID_PARAM;
5716         }
5717
5718         if (offered > MAX_RPC_DATA_SIZE) {
5719                 return WERR_INVALID_PARAM;
5720         }
5721
5722         rpcbuf_move(q_u->buffer, &r_u->buffer);
5723         buffer = r_u->buffer;
5724
5725         DEBUG(4,("_spoolss_getprinterdriver2\n"));
5726
5727         if ( !(printer = find_printer_index_by_hnd( p, handle )) ) {
5728                 DEBUG(0,("_spoolss_getprinterdriver2: invalid printer handle!\n"));
5729                 return WERR_INVALID_PRINTER_NAME;
5730         }
5731
5732         *needed = 0;
5733         *servermajorversion = 0;
5734         *serverminorversion = 0;
5735
5736         fstrcpy(servername, get_server_name( printer ));
5737         unistr2_to_ascii(architecture, uni_arch, sizeof(architecture));
5738
5739         if (!get_printer_snum(p, handle, &snum, NULL))
5740                 return WERR_BADFID;
5741
5742         switch (level) {
5743         case 1:
5744                 return getprinterdriver2_level1(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
5745         case 2:
5746                 return getprinterdriver2_level2(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
5747         case 3:
5748                 return getprinterdriver2_level3(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
5749         case 6:
5750                 return getprinterdriver2_level6(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
5751 #if 0   /* JERRY */
5752         case 101:
5753                 /* apparently this call is the equivalent of
5754                    EnumPrinterDataEx() for the DsDriver key */
5755                 break;
5756 #endif
5757         }
5758
5759         return WERR_UNKNOWN_LEVEL;
5760 }
5761
5762
5763 /****************************************************************
5764  _spoolss_StartPagePrinter
5765 ****************************************************************/
5766
5767 WERROR _spoolss_StartPagePrinter(pipes_struct *p,
5768                                  struct spoolss_StartPagePrinter *r)
5769 {
5770         POLICY_HND *handle = r->in.handle;
5771
5772         Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5773
5774         if (!Printer) {
5775                 DEBUG(3,("_spoolss_StartPagePrinter: "
5776                         "Error in startpageprinter printer handle\n"));
5777                 return WERR_BADFID;
5778         }
5779
5780         Printer->page_started=True;
5781         return WERR_OK;
5782 }
5783
5784 /****************************************************************
5785  _spoolss_EndPagePrinter
5786 ****************************************************************/
5787
5788 WERROR _spoolss_EndPagePrinter(pipes_struct *p,
5789                                struct spoolss_EndPagePrinter *r)
5790 {
5791         POLICY_HND *handle = r->in.handle;
5792         int snum;
5793
5794         Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5795
5796         if (!Printer) {
5797                 DEBUG(2,("_spoolss_EndPagePrinter: Invalid handle (%s:%u:%u).\n",
5798                         OUR_HANDLE(handle)));
5799                 return WERR_BADFID;
5800         }
5801
5802         if (!get_printer_snum(p, handle, &snum, NULL))
5803                 return WERR_BADFID;
5804
5805         Printer->page_started=False;
5806         print_job_endpage(snum, Printer->jobid);
5807
5808         return WERR_OK;
5809 }
5810
5811 /****************************************************************
5812  _spoolss_StartDocPrinter
5813 ****************************************************************/
5814
5815 WERROR _spoolss_StartDocPrinter(pipes_struct *p,
5816                                 struct spoolss_StartDocPrinter *r)
5817 {
5818         POLICY_HND *handle = r->in.handle;
5819         uint32_t *jobid = r->out.job_id;
5820         struct spoolss_DocumentInfo1 *info_1;
5821         int snum;
5822         Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5823
5824         if (!Printer) {
5825                 DEBUG(2,("_spoolss_StartDocPrinter: "
5826                         "Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
5827                 return WERR_BADFID;
5828         }
5829
5830         if (r->in.level != 1) {
5831                 return WERR_UNKNOWN_LEVEL;
5832         }
5833
5834         info_1 = r->in.info.info1;
5835
5836         /*
5837          * a nice thing with NT is it doesn't listen to what you tell it.
5838          * when asked to send _only_ RAW datas, it tries to send datas
5839          * in EMF format.
5840          *
5841          * So I add checks like in NT Server ...
5842          */
5843
5844         if (info_1->datatype) {
5845                 if (strcmp(info_1->datatype, "RAW") != 0) {
5846                         (*jobid)=0;
5847                         return WERR_INVALID_DATATYPE;
5848                 }
5849         }
5850
5851         /* get the share number of the printer */
5852         if (!get_printer_snum(p, handle, &snum, NULL)) {
5853                 return WERR_BADFID;
5854         }
5855
5856         Printer->jobid = print_job_start(p->server_info, snum,
5857                                          CONST_DISCARD(char *,info_1->document_name),
5858                                          Printer->nt_devmode);
5859
5860         /* An error occured in print_job_start() so return an appropriate
5861            NT error code. */
5862
5863         if (Printer->jobid == -1) {
5864                 return map_werror_from_unix(errno);
5865         }
5866
5867         Printer->document_started=True;
5868         (*jobid) = Printer->jobid;
5869
5870         return WERR_OK;
5871 }
5872
5873 /****************************************************************
5874  _spoolss_EndDocPrinter
5875 ****************************************************************/
5876
5877 WERROR _spoolss_EndDocPrinter(pipes_struct *p,
5878                               struct spoolss_EndDocPrinter *r)
5879 {
5880         POLICY_HND *handle = r->in.handle;
5881
5882         return _spoolss_enddocprinter_internal(p, handle);
5883 }
5884
5885 /****************************************************************
5886  _spoolss_WritePrinter
5887 ****************************************************************/
5888
5889 WERROR _spoolss_WritePrinter(pipes_struct *p,
5890                              struct spoolss_WritePrinter *r)
5891 {
5892         POLICY_HND *handle = r->in.handle;
5893         uint32 buffer_size = r->in._data_size;
5894         uint8 *buffer = r->in.data.data;
5895         uint32 *buffer_written = &r->in._data_size;
5896         int snum;
5897         Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5898
5899         if (!Printer) {
5900                 DEBUG(2,("_spoolss_WritePrinter: Invalid handle (%s:%u:%u)\n",
5901                         OUR_HANDLE(handle)));
5902                 *r->out.num_written = r->in._data_size;
5903                 return WERR_BADFID;
5904         }
5905
5906         if (!get_printer_snum(p, handle, &snum, NULL))
5907                 return WERR_BADFID;
5908
5909         (*buffer_written) = (uint32)print_job_write(snum, Printer->jobid, (const char *)buffer,
5910                                         (SMB_OFF_T)-1, (size_t)buffer_size);
5911         if (*buffer_written == (uint32)-1) {
5912                 *r->out.num_written = 0;
5913                 if (errno == ENOSPC)
5914                         return WERR_NO_SPOOL_SPACE;
5915                 else
5916                         return WERR_ACCESS_DENIED;
5917         }
5918
5919         *r->out.num_written = r->in._data_size;
5920
5921         return WERR_OK;
5922 }
5923
5924 /********************************************************************
5925  * api_spoolss_getprinter
5926  * called from the spoolss dispatcher
5927  *
5928  ********************************************************************/
5929
5930 static WERROR control_printer(POLICY_HND *handle, uint32 command,
5931                               pipes_struct *p)
5932 {
5933         int snum;
5934         WERROR errcode = WERR_BADFUNC;
5935         Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5936
5937         if (!Printer) {
5938                 DEBUG(2,("control_printer: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
5939                 return WERR_BADFID;
5940         }
5941
5942         if (!get_printer_snum(p, handle, &snum, NULL))
5943                 return WERR_BADFID;
5944
5945         switch (command) {
5946         case SPOOLSS_PRINTER_CONTROL_PAUSE:
5947                 if (print_queue_pause(p->server_info, snum, &errcode)) {
5948                         errcode = WERR_OK;
5949                 }
5950                 break;
5951         case SPOOLSS_PRINTER_CONTROL_RESUME:
5952         case SPOOLSS_PRINTER_CONTROL_UNPAUSE:
5953                 if (print_queue_resume(p->server_info, snum, &errcode)) {
5954                         errcode = WERR_OK;
5955                 }
5956                 break;
5957         case SPOOLSS_PRINTER_CONTROL_PURGE:
5958                 if (print_queue_purge(p->server_info, snum, &errcode)) {
5959                         errcode = WERR_OK;
5960                 }
5961                 break;
5962         default:
5963                 return WERR_UNKNOWN_LEVEL;
5964         }
5965
5966         return errcode;
5967 }
5968
5969
5970 /****************************************************************
5971  _spoolss_AbortPrinter
5972  * From MSDN: "Deletes printer's spool file if printer is configured
5973  * for spooling"
5974 ****************************************************************/
5975
5976 WERROR _spoolss_AbortPrinter(pipes_struct *p,
5977                              struct spoolss_AbortPrinter *r)
5978 {
5979         POLICY_HND      *handle = r->in.handle;
5980         Printer_entry   *Printer = find_printer_index_by_hnd(p, handle);
5981         int             snum;
5982         WERROR          errcode = WERR_OK;
5983
5984         if (!Printer) {
5985                 DEBUG(2,("_spoolss_AbortPrinter: Invalid handle (%s:%u:%u)\n",
5986                         OUR_HANDLE(handle)));
5987                 return WERR_BADFID;
5988         }
5989
5990         if (!get_printer_snum(p, handle, &snum, NULL))
5991                 return WERR_BADFID;
5992
5993         print_job_delete(p->server_info, snum, Printer->jobid, &errcode );
5994
5995         return errcode;
5996 }
5997
5998 /********************************************************************
5999  * called by spoolss_api_setprinter
6000  * when updating a printer description
6001  ********************************************************************/
6002
6003 static WERROR update_printer_sec(POLICY_HND *handle,
6004                                  pipes_struct *p, SEC_DESC_BUF *secdesc_ctr)
6005 {
6006         SEC_DESC_BUF *new_secdesc_ctr = NULL, *old_secdesc_ctr = NULL;
6007         WERROR result;
6008         int snum;
6009
6010         Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
6011
6012         if (!Printer || !get_printer_snum(p, handle, &snum, NULL)) {
6013                 DEBUG(2,("update_printer_sec: Invalid handle (%s:%u:%u)\n",
6014                          OUR_HANDLE(handle)));
6015
6016                 result = WERR_BADFID;
6017                 goto done;
6018         }
6019
6020         if (!secdesc_ctr) {
6021                 DEBUG(10,("update_printer_sec: secdesc_ctr is NULL !\n"));
6022                 result = WERR_INVALID_PARAM;
6023                 goto done;
6024         }
6025
6026         /* Check the user has permissions to change the security
6027            descriptor.  By experimentation with two NT machines, the user
6028            requires Full Access to the printer to change security
6029            information. */
6030
6031         if ( Printer->access_granted != PRINTER_ACCESS_ADMINISTER ) {
6032                 DEBUG(4,("update_printer_sec: updated denied by printer permissions\n"));
6033                 result = WERR_ACCESS_DENIED;
6034                 goto done;
6035         }
6036
6037         /* NT seems to like setting the security descriptor even though
6038            nothing may have actually changed. */
6039
6040         if ( !nt_printing_getsec(p->mem_ctx, Printer->sharename, &old_secdesc_ctr)) {
6041                 DEBUG(2,("update_printer_sec: nt_printing_getsec() failed\n"));
6042                 result = WERR_BADFID;
6043                 goto done;
6044         }
6045
6046         if (DEBUGLEVEL >= 10) {
6047                 SEC_ACL *the_acl;
6048                 int i;
6049
6050                 the_acl = old_secdesc_ctr->sd->dacl;
6051                 DEBUG(10, ("old_secdesc_ctr for %s has %d aces:\n",
6052                            PRINTERNAME(snum), the_acl->num_aces));
6053
6054                 for (i = 0; i < the_acl->num_aces; i++) {
6055                         DEBUG(10, ("%s 0x%08x\n", sid_string_dbg(
6056                                            &the_acl->aces[i].trustee),
6057                                   the_acl->aces[i].access_mask));
6058                 }
6059
6060                 the_acl = secdesc_ctr->sd->dacl;
6061
6062                 if (the_acl) {
6063                         DEBUG(10, ("secdesc_ctr for %s has %d aces:\n",
6064                                    PRINTERNAME(snum), the_acl->num_aces));
6065
6066                         for (i = 0; i < the_acl->num_aces; i++) {
6067                                 DEBUG(10, ("%s 0x%08x\n", sid_string_dbg(
6068                                                    &the_acl->aces[i].trustee),
6069                                            the_acl->aces[i].access_mask));
6070                         }
6071                 } else {
6072                         DEBUG(10, ("dacl for secdesc_ctr is NULL\n"));
6073                 }
6074         }
6075
6076         new_secdesc_ctr = sec_desc_merge(p->mem_ctx, secdesc_ctr, old_secdesc_ctr);
6077         if (!new_secdesc_ctr) {
6078                 result = WERR_NOMEM;
6079                 goto done;
6080         }
6081
6082         if (sec_desc_equal(new_secdesc_ctr->sd, old_secdesc_ctr->sd)) {
6083                 result = WERR_OK;
6084                 goto done;
6085         }
6086
6087         result = nt_printing_setsec(Printer->sharename, new_secdesc_ctr);
6088
6089  done:
6090
6091         return result;
6092 }
6093
6094 /********************************************************************
6095  Canonicalize printer info from a client
6096
6097  ATTN: It does not matter what we set the servername to hear
6098  since we do the necessary work in get_a_printer() to set it to
6099  the correct value based on what the client sent in the
6100  _spoolss_open_printer_ex().
6101  ********************************************************************/
6102
6103 static bool check_printer_ok(NT_PRINTER_INFO_LEVEL_2 *info, int snum)
6104 {
6105         fstring printername;
6106         const char *p;
6107
6108         DEBUG(5,("check_printer_ok: servername=%s printername=%s sharename=%s "
6109                 "portname=%s drivername=%s comment=%s location=%s\n",
6110                 info->servername, info->printername, info->sharename,
6111                 info->portname, info->drivername, info->comment, info->location));
6112
6113         /* we force some elements to "correct" values */
6114         slprintf(info->servername, sizeof(info->servername)-1, "\\\\%s", global_myname());
6115         fstrcpy(info->sharename, lp_servicename(snum));
6116
6117         /* check to see if we allow printername != sharename */
6118
6119         if ( lp_force_printername(snum) ) {
6120                 slprintf(info->printername, sizeof(info->printername)-1, "\\\\%s\\%s",
6121                         global_myname(), info->sharename );
6122         } else {
6123
6124                 /* make sure printername is in \\server\printername format */
6125
6126                 fstrcpy( printername, info->printername );
6127                 p = printername;
6128                 if ( printername[0] == '\\' && printername[1] == '\\' ) {
6129                         if ( (p = strchr_m( &printername[2], '\\' )) != NULL )
6130                                 p++;
6131                 }
6132
6133                 slprintf(info->printername, sizeof(info->printername)-1, "\\\\%s\\%s",
6134                          global_myname(), p );
6135         }
6136
6137         info->attributes |= PRINTER_ATTRIBUTE_SAMBA;
6138         info->attributes &= ~PRINTER_ATTRIBUTE_NOT_SAMBA;
6139
6140
6141
6142         return True;
6143 }
6144
6145 /****************************************************************************
6146 ****************************************************************************/
6147
6148 WERROR add_port_hook(TALLOC_CTX *ctx, NT_USER_TOKEN *token, const char *portname, const char *uri )
6149 {
6150         char *cmd = lp_addport_cmd();
6151         char *command = NULL;
6152         int ret;
6153         SE_PRIV se_printop = SE_PRINT_OPERATOR;
6154         bool is_print_op = False;
6155
6156         if ( !*cmd ) {
6157                 return WERR_ACCESS_DENIED;
6158         }
6159
6160         command = talloc_asprintf(ctx,
6161                         "%s \"%s\" \"%s\"", cmd, portname, uri );
6162         if (!command) {
6163                 return WERR_NOMEM;
6164         }
6165
6166         if ( token )
6167                 is_print_op = user_has_privileges( token, &se_printop );
6168
6169         DEBUG(10,("Running [%s]\n", command));
6170
6171         /********* BEGIN SePrintOperatorPrivilege **********/
6172
6173         if ( is_print_op )
6174                 become_root();
6175
6176         ret = smbrun(command, NULL);
6177
6178         if ( is_print_op )
6179                 unbecome_root();
6180
6181         /********* END SePrintOperatorPrivilege **********/
6182
6183         DEBUGADD(10,("returned [%d]\n", ret));
6184
6185         TALLOC_FREE(command);
6186
6187         if ( ret != 0 ) {
6188                 return WERR_ACCESS_DENIED;
6189         }
6190
6191         return WERR_OK;
6192 }
6193
6194 /****************************************************************************
6195 ****************************************************************************/
6196
6197 bool add_printer_hook(TALLOC_CTX *ctx, NT_USER_TOKEN *token, NT_PRINTER_INFO_LEVEL *printer)
6198 {
6199         char *cmd = lp_addprinter_cmd();
6200         char **qlines;
6201         char *command = NULL;
6202         int numlines;
6203         int ret;
6204         int fd;
6205         SE_PRIV se_printop = SE_PRINT_OPERATOR;
6206         bool is_print_op = False;
6207         char *remote_machine = talloc_strdup(ctx, "%m");
6208
6209         if (!remote_machine) {
6210                 return false;
6211         }
6212         remote_machine = talloc_sub_basic(ctx,
6213                                 current_user_info.smb_name,
6214                                 current_user_info.domain,
6215                                 remote_machine);
6216         if (!remote_machine) {
6217                 return false;
6218         }
6219
6220         command = talloc_asprintf(ctx,
6221                         "%s \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\"",
6222                         cmd, printer->info_2->printername, printer->info_2->sharename,
6223                         printer->info_2->portname, printer->info_2->drivername,
6224                         printer->info_2->location, printer->info_2->comment, remote_machine);
6225         if (!command) {
6226                 return false;
6227         }
6228
6229         if ( token )
6230                 is_print_op = user_has_privileges( token, &se_printop );
6231
6232         DEBUG(10,("Running [%s]\n", command));
6233
6234         /********* BEGIN SePrintOperatorPrivilege **********/
6235
6236         if ( is_print_op )
6237                 become_root();
6238
6239         if ( (ret = smbrun(command, &fd)) == 0 ) {
6240                 /* Tell everyone we updated smb.conf. */
6241                 message_send_all(smbd_messaging_context(),
6242                                  MSG_SMB_CONF_UPDATED, NULL, 0, NULL);
6243         }
6244
6245         if ( is_print_op )
6246                 unbecome_root();
6247
6248         /********* END SePrintOperatorPrivilege **********/
6249
6250         DEBUGADD(10,("returned [%d]\n", ret));
6251
6252         TALLOC_FREE(command);
6253         TALLOC_FREE(remote_machine);
6254
6255         if ( ret != 0 ) {
6256                 if (fd != -1)
6257                         close(fd);
6258                 return False;
6259         }
6260
6261         /* reload our services immediately */
6262         reload_services( False );
6263
6264         numlines = 0;
6265         /* Get lines and convert them back to dos-codepage */
6266         qlines = fd_lines_load(fd, &numlines, 0, NULL);
6267         DEBUGADD(10,("Lines returned = [%d]\n", numlines));
6268         close(fd);
6269
6270         /* Set the portname to what the script says the portname should be. */
6271         /* but don't require anything to be return from the script exit a good error code */
6272
6273         if (numlines) {
6274                 /* Set the portname to what the script says the portname should be. */
6275                 strncpy(printer->info_2->portname, qlines[0], sizeof(printer->info_2->portname));
6276                 DEBUGADD(6,("Line[0] = [%s]\n", qlines[0]));
6277         }
6278
6279         TALLOC_FREE(qlines);
6280         return True;
6281 }
6282
6283
6284 /********************************************************************
6285  * Called by spoolss_api_setprinter
6286  * when updating a printer description.
6287  ********************************************************************/
6288
6289 static WERROR update_printer(pipes_struct *p, POLICY_HND *handle,
6290                              struct spoolss_SetPrinterInfoCtr *info_ctr,
6291                              struct spoolss_DeviceMode *devmode)
6292 {
6293         int snum;
6294         NT_PRINTER_INFO_LEVEL *printer = NULL, *old_printer = NULL;
6295         Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
6296         WERROR result;
6297         UNISTR2 buffer;
6298         fstring asc_buffer;
6299
6300         DEBUG(8,("update_printer\n"));
6301
6302         result = WERR_OK;
6303
6304         if (!Printer) {
6305                 result = WERR_BADFID;
6306                 goto done;
6307         }
6308
6309         if (!get_printer_snum(p, handle, &snum, NULL)) {
6310                 result = WERR_BADFID;
6311                 goto done;
6312         }
6313
6314         if (!W_ERROR_IS_OK(get_a_printer(Printer, &printer, 2, lp_const_servicename(snum))) ||
6315             (!W_ERROR_IS_OK(get_a_printer(Printer, &old_printer, 2, lp_const_servicename(snum))))) {
6316                 result = WERR_BADFID;
6317                 goto done;
6318         }
6319
6320         DEBUGADD(8,("Converting info_2 struct\n"));
6321
6322         /*
6323          * convert_printer_info converts the incoming
6324          * info from the client and overwrites the info
6325          * just read from the tdb in the pointer 'printer'.
6326          */
6327
6328         if (!convert_printer_info_new(info_ctr, printer)) {
6329                 result =  WERR_NOMEM;
6330                 goto done;
6331         }
6332
6333         if (devmode) {
6334                 /* we have a valid devmode
6335                    convert it and link it*/
6336
6337                 DEBUGADD(8,("update_printer: Converting the devicemode struct\n"));
6338                 if (!convert_devicemode_new(printer->info_2->printername,
6339                                             devmode,
6340                                             &printer->info_2->devmode)) {
6341                         result =  WERR_NOMEM;
6342                         goto done;
6343                 }
6344         }
6345
6346         /* Do sanity check on the requested changes for Samba */
6347
6348         if (!check_printer_ok(printer->info_2, snum)) {
6349                 result = WERR_INVALID_PARAM;
6350                 goto done;
6351         }
6352
6353         /* FIXME!!! If the driver has changed we really should verify that
6354            it is installed before doing much else   --jerry */
6355
6356         /* Check calling user has permission to update printer description */
6357
6358         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
6359                 DEBUG(3, ("update_printer: printer property change denied by handle\n"));
6360                 result = WERR_ACCESS_DENIED;
6361                 goto done;
6362         }
6363
6364         /* Call addprinter hook */
6365         /* Check changes to see if this is really needed */
6366
6367         if ( *lp_addprinter_cmd()
6368                 && (!strequal(printer->info_2->drivername, old_printer->info_2->drivername)
6369                         || !strequal(printer->info_2->comment, old_printer->info_2->comment)
6370                         || !strequal(printer->info_2->portname, old_printer->info_2->portname)
6371                         || !strequal(printer->info_2->location, old_printer->info_2->location)) )
6372         {
6373                 /* add_printer_hook() will call reload_services() */
6374
6375                 if ( !add_printer_hook(p->mem_ctx, p->server_info->ptok,
6376                                        printer) ) {
6377                         result = WERR_ACCESS_DENIED;
6378                         goto done;
6379                 }
6380         }
6381
6382         /*
6383          * When a *new* driver is bound to a printer, the drivername is used to
6384          * lookup previously saved driver initialization info, which is then
6385          * bound to the printer, simulating what happens in the Windows arch.
6386          */
6387         if (!strequal(printer->info_2->drivername, old_printer->info_2->drivername))
6388         {
6389                 if (!set_driver_init(printer, 2))
6390                 {
6391                         DEBUG(5,("update_printer: Error restoring driver initialization data for driver [%s]!\n",
6392                                 printer->info_2->drivername));
6393                 }
6394
6395                 DEBUG(10,("update_printer: changing driver [%s]!  Sending event!\n",
6396                         printer->info_2->drivername));
6397
6398                 notify_printer_driver(snum, printer->info_2->drivername);
6399         }
6400
6401         /*
6402          * flag which changes actually occured.  This is a small subset of
6403          * all the possible changes.  We also have to update things in the
6404          * DsSpooler key.
6405          */
6406
6407         if (!strequal(printer->info_2->comment, old_printer->info_2->comment)) {
6408                 init_unistr2( &buffer, printer->info_2->comment, UNI_STR_TERMINATE);
6409                 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "description",
6410                         REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6411
6412                 notify_printer_comment(snum, printer->info_2->comment);
6413         }
6414
6415         if (!strequal(printer->info_2->sharename, old_printer->info_2->sharename)) {
6416                 init_unistr2( &buffer, printer->info_2->sharename, UNI_STR_TERMINATE);
6417                 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "shareName",
6418                         REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6419
6420                 notify_printer_sharename(snum, printer->info_2->sharename);
6421         }
6422
6423         if (!strequal(printer->info_2->printername, old_printer->info_2->printername)) {
6424                 char *pname;
6425
6426                 if ( (pname = strchr_m( printer->info_2->printername+2, '\\' )) != NULL )
6427                         pname++;
6428                 else
6429                         pname = printer->info_2->printername;
6430
6431
6432                 init_unistr2( &buffer, pname, UNI_STR_TERMINATE);
6433                 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "printerName",
6434                         REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6435
6436                 notify_printer_printername( snum, pname );
6437         }
6438
6439         if (!strequal(printer->info_2->portname, old_printer->info_2->portname)) {
6440                 init_unistr2( &buffer, printer->info_2->portname, UNI_STR_TERMINATE);
6441                 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "portName",
6442                         REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6443
6444                 notify_printer_port(snum, printer->info_2->portname);
6445         }
6446
6447         if (!strequal(printer->info_2->location, old_printer->info_2->location)) {
6448                 init_unistr2( &buffer, printer->info_2->location, UNI_STR_TERMINATE);
6449                 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "location",
6450                         REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6451
6452                 notify_printer_location(snum, printer->info_2->location);
6453         }
6454
6455         /* here we need to update some more DsSpooler keys */
6456         /* uNCName, serverName, shortServerName */
6457
6458         init_unistr2( &buffer, global_myname(), UNI_STR_TERMINATE);
6459         set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "serverName",
6460                 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6461         set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "shortServerName",
6462                 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6463
6464         slprintf( asc_buffer, sizeof(asc_buffer)-1, "\\\\%s\\%s",
6465                  global_myname(), printer->info_2->sharename );
6466         init_unistr2( &buffer, asc_buffer, UNI_STR_TERMINATE);
6467         set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "uNCName",
6468                 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6469
6470         /* Update printer info */
6471         result = mod_a_printer(printer, 2);
6472
6473 done:
6474         free_a_printer(&printer, 2);
6475         free_a_printer(&old_printer, 2);
6476
6477
6478         return result;
6479 }
6480
6481 /****************************************************************************
6482 ****************************************************************************/
6483 static WERROR publish_or_unpublish_printer(pipes_struct *p, POLICY_HND *handle,
6484                                            struct spoolss_SetPrinterInfo7 *info7)
6485 {
6486 #ifdef HAVE_ADS
6487         int snum;
6488         Printer_entry *Printer;
6489
6490         if ( lp_security() != SEC_ADS ) {
6491                 return WERR_UNKNOWN_LEVEL;
6492         }
6493
6494         Printer = find_printer_index_by_hnd(p, handle);
6495
6496         DEBUG(5,("publish_or_unpublish_printer, action = %d\n",info7->action));
6497
6498         if (!Printer)
6499                 return WERR_BADFID;
6500
6501         if (!get_printer_snum(p, handle, &snum, NULL))
6502                 return WERR_BADFID;
6503
6504         nt_printer_publish(Printer, snum, info7->action);
6505
6506         return WERR_OK;
6507 #else
6508         return WERR_UNKNOWN_LEVEL;
6509 #endif
6510 }
6511
6512 /****************************************************************
6513  _spoolss_SetPrinter
6514 ****************************************************************/
6515
6516 WERROR _spoolss_SetPrinter(pipes_struct *p,
6517                            struct spoolss_SetPrinter *r)
6518 {
6519         POLICY_HND *handle = r->in.handle;
6520         WERROR result;
6521
6522         Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
6523
6524         if (!Printer) {
6525                 DEBUG(2,("_spoolss_SetPrinter: Invalid handle (%s:%u:%u)\n",
6526                         OUR_HANDLE(handle)));
6527                 return WERR_BADFID;
6528         }
6529
6530         /* check the level */
6531         switch (r->in.info_ctr->level) {
6532                 case 0:
6533                         return control_printer(handle, r->in.command, p);
6534                 case 2:
6535                         result = update_printer(p, handle,
6536                                                 r->in.info_ctr,
6537                                                 r->in.devmode_ctr->devmode);
6538                         if (!W_ERROR_IS_OK(result))
6539                                 return result;
6540                         if (r->in.secdesc_ctr->sd)
6541                                 result = update_printer_sec(handle, p,
6542                                                             r->in.secdesc_ctr);
6543                         return result;
6544                 case 3:
6545                         return update_printer_sec(handle, p,
6546                                                   r->in.secdesc_ctr);
6547                 case 7:
6548                         return publish_or_unpublish_printer(p, handle,
6549                                                             r->in.info_ctr->info.info7);
6550                 default:
6551                         return WERR_UNKNOWN_LEVEL;
6552         }
6553 }
6554
6555 /****************************************************************
6556  _spoolss_FindClosePrinterNotify
6557 ****************************************************************/
6558
6559 WERROR _spoolss_FindClosePrinterNotify(pipes_struct *p,
6560                                        struct spoolss_FindClosePrinterNotify *r)
6561 {
6562         POLICY_HND *handle = r->in.handle;
6563         Printer_entry *Printer= find_printer_index_by_hnd(p, handle);
6564
6565         if (!Printer) {
6566                 DEBUG(2,("_spoolss_FindClosePrinterNotify: "
6567                         "Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
6568                 return WERR_BADFID;
6569         }
6570
6571         if (Printer->notify.client_connected==True) {
6572                 int snum = -1;
6573
6574                 if ( Printer->printer_type == SPLHND_SERVER)
6575                         snum = -1;
6576                 else if ( (Printer->printer_type == SPLHND_PRINTER) &&
6577                                 !get_printer_snum(p, handle, &snum, NULL) )
6578                         return WERR_BADFID;
6579
6580                 srv_spoolss_replycloseprinter(snum, &Printer->notify.client_hnd);
6581         }
6582
6583         Printer->notify.flags=0;
6584         Printer->notify.options=0;
6585         Printer->notify.localmachine[0]='\0';
6586         Printer->notify.printerlocal=0;
6587         if (Printer->notify.option)
6588                 free_spool_notify_option(&Printer->notify.option);
6589         Printer->notify.client_connected=False;
6590
6591         return WERR_OK;
6592 }
6593
6594 /****************************************************************
6595  _spoolss_AddJob
6596 ****************************************************************/
6597
6598 WERROR _spoolss_AddJob(pipes_struct *p,
6599                        struct spoolss_AddJob *r)
6600 {
6601         if (!r->in.buffer && (r->in.offered != 0)) {
6602                 return WERR_INVALID_PARAM;
6603         }
6604
6605         /* this is what a NT server returns for AddJob. AddJob must fail on
6606          * non-local printers */
6607
6608         return WERR_INVALID_PARAM;
6609 }
6610
6611 /****************************************************************************
6612 ****************************************************************************/
6613
6614 static void fill_job_info_1(JOB_INFO_1 *job_info, const print_queue_struct *queue,
6615                             int position, int snum,
6616                             const NT_PRINTER_INFO_LEVEL *ntprinter)
6617 {
6618         struct tm *t;
6619
6620         t=gmtime(&queue->time);
6621
6622         job_info->jobid=queue->job;
6623         init_unistr(&job_info->printername, lp_servicename(snum));
6624         init_unistr(&job_info->machinename, ntprinter->info_2->servername);
6625         init_unistr(&job_info->username, queue->fs_user);
6626         init_unistr(&job_info->document, queue->fs_file);
6627         init_unistr(&job_info->datatype, "RAW");
6628         init_unistr(&job_info->text_status, "");
6629         job_info->status=nt_printj_status(queue->status);
6630         job_info->priority=queue->priority;
6631         job_info->position=position;
6632         job_info->totalpages=queue->page_count;
6633         job_info->pagesprinted=0;
6634
6635         make_systemtime(&job_info->submitted, t);
6636 }
6637
6638 /****************************************************************************
6639 ****************************************************************************/
6640
6641 static bool fill_job_info_2(JOB_INFO_2 *job_info, const print_queue_struct *queue,
6642                             int position, int snum,
6643                             const NT_PRINTER_INFO_LEVEL *ntprinter,
6644                             DEVICEMODE *devmode)
6645 {
6646         struct tm *t;
6647
6648         t=gmtime(&queue->time);
6649
6650         job_info->jobid=queue->job;
6651
6652         init_unistr(&job_info->printername, ntprinter->info_2->printername);
6653
6654         init_unistr(&job_info->machinename, ntprinter->info_2->servername);
6655         init_unistr(&job_info->username, queue->fs_user);
6656         init_unistr(&job_info->document, queue->fs_file);
6657         init_unistr(&job_info->notifyname, queue->fs_user);
6658         init_unistr(&job_info->datatype, "RAW");
6659         init_unistr(&job_info->printprocessor, "winprint");
6660         init_unistr(&job_info->parameters, "");
6661         init_unistr(&job_info->drivername, ntprinter->info_2->drivername);
6662         init_unistr(&job_info->text_status, "");
6663
6664 /* and here the security descriptor */
6665
6666         job_info->status=nt_printj_status(queue->status);
6667         job_info->priority=queue->priority;
6668         job_info->position=position;
6669         job_info->starttime=0;
6670         job_info->untiltime=0;
6671         job_info->totalpages=queue->page_count;
6672         job_info->size=queue->size;
6673         make_systemtime(&(job_info->submitted), t);
6674         job_info->timeelapsed=0;
6675         job_info->pagesprinted=0;
6676
6677         job_info->devmode = devmode;
6678
6679         return (True);
6680 }
6681
6682 /****************************************************************************
6683  Enumjobs at level 1.
6684 ****************************************************************************/
6685
6686 static WERROR enumjobs_level1(const print_queue_struct *queue, int snum,
6687                               const NT_PRINTER_INFO_LEVEL *ntprinter,
6688                               RPC_BUFFER *buffer, uint32 offered,
6689                               uint32 *needed, uint32 *returned)
6690 {
6691         JOB_INFO_1 *info;
6692         int i;
6693         WERROR result = WERR_OK;
6694
6695         info=SMB_MALLOC_ARRAY(JOB_INFO_1,*returned);
6696         if (info==NULL) {
6697                 *returned=0;
6698                 return WERR_NOMEM;
6699         }
6700
6701         for (i=0; i<*returned; i++)
6702                 fill_job_info_1( &info[i], &queue[i], i, snum, ntprinter );
6703
6704         /* check the required size. */
6705         for (i=0; i<*returned; i++)
6706                 (*needed) += spoolss_size_job_info_1(&info[i]);
6707
6708         if (*needed > offered) {
6709                 result = WERR_INSUFFICIENT_BUFFER;
6710                 goto out;
6711         }
6712
6713         if (!rpcbuf_alloc_size(buffer, *needed)) {
6714                 result = WERR_NOMEM;
6715                 goto out;
6716         }
6717
6718         /* fill the buffer with the structures */
6719         for (i=0; i<*returned; i++)
6720                 smb_io_job_info_1("", buffer, &info[i], 0);
6721
6722 out:
6723         /* clear memory */
6724         SAFE_FREE(info);
6725
6726         if ( !W_ERROR_IS_OK(result) )
6727                 *returned = 0;
6728
6729         return result;
6730 }
6731
6732 /****************************************************************************
6733  Enumjobs at level 2.
6734 ****************************************************************************/
6735
6736 static WERROR enumjobs_level2(const print_queue_struct *queue, int snum,
6737                               const NT_PRINTER_INFO_LEVEL *ntprinter,
6738                               RPC_BUFFER *buffer, uint32 offered,
6739                               uint32 *needed, uint32 *returned)
6740 {
6741         JOB_INFO_2 *info = NULL;
6742         int i;
6743         WERROR result = WERR_OK;
6744         DEVICEMODE *devmode = NULL;
6745
6746         if ( !(info = SMB_MALLOC_ARRAY(JOB_INFO_2,*returned)) ) {
6747                 *returned=0;
6748                 return WERR_NOMEM;
6749         }
6750
6751         /* this should not be a failure condition if the devmode is NULL */
6752
6753         devmode = construct_dev_mode(lp_const_servicename(snum));
6754
6755         for (i=0; i<*returned; i++)
6756                 fill_job_info_2(&(info[i]), &queue[i], i, snum, ntprinter, devmode);
6757
6758         /* check the required size. */
6759         for (i=0; i<*returned; i++)
6760                 (*needed) += spoolss_size_job_info_2(&info[i]);
6761
6762         if (*needed > offered) {
6763                 result = WERR_INSUFFICIENT_BUFFER;
6764                 goto out;
6765         }
6766
6767         if (!rpcbuf_alloc_size(buffer, *needed)) {
6768                 result = WERR_NOMEM;
6769                 goto out;
6770         }
6771
6772         /* fill the buffer with the structures */
6773         for (i=0; i<*returned; i++)
6774                 smb_io_job_info_2("", buffer, &info[i], 0);
6775
6776 out:
6777         free_devmode(devmode);
6778         SAFE_FREE(info);
6779
6780         if ( !W_ERROR_IS_OK(result) )
6781                 *returned = 0;
6782
6783         return result;
6784
6785 }
6786
6787 /****************************************************************************
6788  Enumjobs.
6789 ****************************************************************************/
6790
6791 WERROR _spoolss_enumjobs( pipes_struct *p, SPOOL_Q_ENUMJOBS *q_u, SPOOL_R_ENUMJOBS *r_u)
6792 {
6793         POLICY_HND *handle = &q_u->handle;
6794         uint32 level = q_u->level;
6795         RPC_BUFFER *buffer = NULL;
6796         uint32 offered = q_u->offered;
6797         uint32 *needed = &r_u->needed;
6798         uint32 *returned = &r_u->returned;
6799         WERROR wret;
6800         NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
6801         int snum;
6802         print_status_struct prt_status;
6803         print_queue_struct *queue=NULL;
6804
6805         /* that's an [in out] buffer */
6806
6807         if (!q_u->buffer && (offered!=0)) {
6808                 return WERR_INVALID_PARAM;
6809         }
6810
6811         if (offered > MAX_RPC_DATA_SIZE) {
6812                 return WERR_INVALID_PARAM;
6813         }
6814
6815         rpcbuf_move(q_u->buffer, &r_u->buffer);
6816         buffer = r_u->buffer;
6817
6818         DEBUG(4,("_spoolss_enumjobs\n"));
6819
6820         *needed=0;
6821         *returned=0;
6822
6823         /* lookup the printer snum and tdb entry */
6824
6825         if (!get_printer_snum(p, handle, &snum, NULL))
6826                 return WERR_BADFID;
6827
6828         wret = get_a_printer(NULL, &ntprinter, 2, lp_servicename(snum));
6829         if ( !W_ERROR_IS_OK(wret) )
6830                 return wret;
6831
6832         *returned = print_queue_status(snum, &queue, &prt_status);
6833         DEBUGADD(4,("count:[%d], status:[%d], [%s]\n", *returned, prt_status.status, prt_status.message));
6834
6835         if (*returned == 0) {
6836                 SAFE_FREE(queue);
6837                 free_a_printer(&ntprinter, 2);
6838                 return WERR_OK;
6839         }
6840
6841         switch (level) {
6842         case 1:
6843                 wret = enumjobs_level1(queue, snum, ntprinter, buffer, offered, needed, returned);
6844                 break;
6845         case 2:
6846                 wret = enumjobs_level2(queue, snum, ntprinter, buffer, offered, needed, returned);
6847                 break;
6848         default:
6849                 *returned=0;
6850                 wret = WERR_UNKNOWN_LEVEL;
6851                 break;
6852         }
6853
6854         SAFE_FREE(queue);
6855         free_a_printer( &ntprinter, 2 );
6856         return wret;
6857 }
6858
6859 /****************************************************************
6860  _spoolss_ScheduleJob
6861 ****************************************************************/
6862
6863 WERROR _spoolss_ScheduleJob(pipes_struct *p,
6864                             struct spoolss_ScheduleJob *r)
6865 {
6866         return WERR_OK;
6867 }
6868
6869 /****************************************************************
6870  _spoolss_SetJob
6871 ****************************************************************/
6872
6873 WERROR _spoolss_SetJob(pipes_struct *p,
6874                        struct spoolss_SetJob *r)
6875 {
6876         POLICY_HND *handle = r->in.handle;
6877         uint32 jobid = r->in.job_id;
6878         uint32 command = r->in.command;
6879
6880         int snum;
6881         WERROR errcode = WERR_BADFUNC;
6882
6883         if (!get_printer_snum(p, handle, &snum, NULL)) {
6884                 return WERR_BADFID;
6885         }
6886
6887         if (!print_job_exists(lp_const_servicename(snum), jobid)) {
6888                 return WERR_INVALID_PRINTER_NAME;
6889         }
6890
6891         switch (command) {
6892         case SPOOLSS_JOB_CONTROL_CANCEL:
6893         case SPOOLSS_JOB_CONTROL_DELETE:
6894                 if (print_job_delete(p->server_info, snum, jobid, &errcode)) {
6895                         errcode = WERR_OK;
6896                 }
6897                 break;
6898         case SPOOLSS_JOB_CONTROL_PAUSE:
6899                 if (print_job_pause(p->server_info, snum, jobid, &errcode)) {
6900                         errcode = WERR_OK;
6901                 }
6902                 break;
6903         case SPOOLSS_JOB_CONTROL_RESTART:
6904         case SPOOLSS_JOB_CONTROL_RESUME:
6905                 if (print_job_resume(p->server_info, snum, jobid, &errcode)) {
6906                         errcode = WERR_OK;
6907                 }
6908                 break;
6909         default:
6910                 return WERR_UNKNOWN_LEVEL;
6911         }
6912
6913         return errcode;
6914 }
6915
6916 /****************************************************************************
6917  Enumerates all printer drivers at level 1.
6918 ****************************************************************************/
6919
6920 static WERROR enumprinterdrivers_level1(const char *servername, fstring architecture, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
6921 {
6922         int i;
6923         int ndrivers;
6924         uint32 version;
6925         fstring *list = NULL;
6926         NT_PRINTER_DRIVER_INFO_LEVEL driver;
6927         DRIVER_INFO_1 *driver_info_1=NULL;
6928         WERROR result = WERR_OK;
6929
6930         *returned=0;
6931
6932         for (version=0; version<DRIVER_MAX_VERSION; version++) {
6933                 list=NULL;
6934                 ndrivers=get_ntdrivers(&list, architecture, version);
6935                 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
6936
6937                 if(ndrivers == -1) {
6938                         SAFE_FREE(driver_info_1);
6939                         return WERR_NOMEM;
6940                 }
6941
6942                 if(ndrivers != 0) {
6943                         if((driver_info_1=SMB_REALLOC_ARRAY(driver_info_1, DRIVER_INFO_1, *returned+ndrivers )) == NULL) {
6944                                 DEBUG(0,("enumprinterdrivers_level1: failed to enlarge driver info buffer!\n"));
6945                                 SAFE_FREE(list);
6946                                 return WERR_NOMEM;
6947                         }
6948                 }
6949
6950                 for (i=0; i<ndrivers; i++) {
6951                         WERROR status;
6952                         DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
6953                         ZERO_STRUCT(driver);
6954                         status = get_a_printer_driver(&driver, 3, list[i],
6955                                                       architecture, version);
6956                         if (!W_ERROR_IS_OK(status)) {
6957                                 SAFE_FREE(list);
6958                                 SAFE_FREE(driver_info_1);
6959                                 return status;
6960                         }
6961                         fill_printer_driver_info_1(&driver_info_1[*returned+i], driver, servername, architecture );
6962                         free_a_printer_driver(driver, 3);
6963                 }
6964
6965                 *returned+=ndrivers;
6966                 SAFE_FREE(list);
6967         }
6968
6969         /* check the required size. */
6970         for (i=0; i<*returned; i++) {
6971                 DEBUGADD(6,("adding driver [%d]'s size\n",i));
6972                 *needed += spoolss_size_printer_driver_info_1(&driver_info_1[i]);
6973         }
6974
6975         if (*needed > offered) {
6976                 result = WERR_INSUFFICIENT_BUFFER;
6977                 goto out;
6978         }
6979
6980         if (!rpcbuf_alloc_size(buffer, *needed)) {
6981                 result = WERR_NOMEM;
6982                 goto out;
6983         }
6984
6985         /* fill the buffer with the driver structures */
6986         for (i=0; i<*returned; i++) {
6987                 DEBUGADD(6,("adding driver [%d] to buffer\n",i));
6988                 smb_io_printer_driver_info_1("", buffer, &driver_info_1[i], 0);
6989         }
6990
6991 out:
6992         SAFE_FREE(driver_info_1);
6993
6994         if ( !W_ERROR_IS_OK(result) )
6995                 *returned = 0;
6996
6997         return result;
6998 }
6999
7000 /****************************************************************************
7001  Enumerates all printer drivers at level 2.
7002 ****************************************************************************/
7003
7004 static WERROR enumprinterdrivers_level2(const char *servername, fstring architecture, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
7005 {
7006         int i;
7007         int ndrivers;
7008         uint32 version;
7009         fstring *list = NULL;
7010         NT_PRINTER_DRIVER_INFO_LEVEL driver;
7011         DRIVER_INFO_2 *driver_info_2=NULL;
7012         WERROR result = WERR_OK;
7013
7014         *returned=0;
7015
7016         for (version=0; version<DRIVER_MAX_VERSION; version++) {
7017                 list=NULL;
7018                 ndrivers=get_ntdrivers(&list, architecture, version);
7019                 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
7020
7021                 if(ndrivers == -1) {
7022                         SAFE_FREE(driver_info_2);
7023                         return WERR_NOMEM;
7024                 }
7025
7026                 if(ndrivers != 0) {
7027                         if((driver_info_2=SMB_REALLOC_ARRAY(driver_info_2, DRIVER_INFO_2, *returned+ndrivers )) == NULL) {
7028                                 DEBUG(0,("enumprinterdrivers_level2: failed to enlarge driver info buffer!\n"));
7029                                 SAFE_FREE(list);
7030                                 return WERR_NOMEM;
7031                         }
7032                 }
7033
7034                 for (i=0; i<ndrivers; i++) {
7035                         WERROR status;
7036
7037                         DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
7038                         ZERO_STRUCT(driver);
7039                         status = get_a_printer_driver(&driver, 3, list[i],
7040                                                       architecture, version);
7041                         if (!W_ERROR_IS_OK(status)) {
7042                                 SAFE_FREE(list);
7043                                 SAFE_FREE(driver_info_2);
7044                                 return status;
7045                         }
7046                         fill_printer_driver_info_2(&driver_info_2[*returned+i], driver, servername);
7047                         free_a_printer_driver(driver, 3);
7048                 }
7049
7050                 *returned+=ndrivers;
7051                 SAFE_FREE(list);
7052         }
7053
7054         /* check the required size. */
7055         for (i=0; i<*returned; i++) {
7056                 DEBUGADD(6,("adding driver [%d]'s size\n",i));
7057                 *needed += spoolss_size_printer_driver_info_2(&(driver_info_2[i]));
7058         }
7059
7060         if (*needed > offered) {
7061                 result = WERR_INSUFFICIENT_BUFFER;
7062                 goto out;
7063         }
7064
7065         if (!rpcbuf_alloc_size(buffer, *needed)) {
7066                 result = WERR_NOMEM;
7067                 goto out;
7068         }
7069
7070         /* fill the buffer with the form structures */
7071         for (i=0; i<*returned; i++) {
7072                 DEBUGADD(6,("adding driver [%d] to buffer\n",i));
7073                 smb_io_printer_driver_info_2("", buffer, &(driver_info_2[i]), 0);
7074         }
7075
7076 out:
7077         SAFE_FREE(driver_info_2);
7078
7079         if ( !W_ERROR_IS_OK(result) )
7080                 *returned = 0;
7081
7082         return result;
7083 }
7084
7085 /****************************************************************************
7086  Enumerates all printer drivers at level 3.
7087 ****************************************************************************/
7088
7089 static WERROR enumprinterdrivers_level3(const char *servername, fstring architecture, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
7090 {
7091         int i;
7092         int ndrivers;
7093         uint32 version;
7094         fstring *list = NULL;
7095         DRIVER_INFO_3 *driver_info_3=NULL;
7096         NT_PRINTER_DRIVER_INFO_LEVEL driver;
7097         WERROR result = WERR_OK;
7098
7099         *returned=0;
7100
7101         for (version=0; version<DRIVER_MAX_VERSION; version++) {
7102                 list=NULL;
7103                 ndrivers=get_ntdrivers(&list, architecture, version);
7104                 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
7105
7106                 if(ndrivers == -1) {
7107                         SAFE_FREE(driver_info_3);
7108                         return WERR_NOMEM;
7109                 }
7110
7111                 if(ndrivers != 0) {
7112                         if((driver_info_3=SMB_REALLOC_ARRAY(driver_info_3, DRIVER_INFO_3, *returned+ndrivers )) == NULL) {
7113                                 DEBUG(0,("enumprinterdrivers_level3: failed to enlarge driver info buffer!\n"));
7114                                 SAFE_FREE(list);
7115                                 return WERR_NOMEM;
7116                         }
7117                 }
7118
7119                 for (i=0; i<ndrivers; i++) {
7120                         WERROR status;
7121
7122                         DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
7123                         ZERO_STRUCT(driver);
7124                         status = get_a_printer_driver(&driver, 3, list[i],
7125                                                       architecture, version);
7126                         if (!W_ERROR_IS_OK(status)) {
7127                                 SAFE_FREE(list);
7128                                 SAFE_FREE(driver_info_3);
7129                                 return status;
7130                         }
7131                         fill_printer_driver_info_3(&driver_info_3[*returned+i], driver, servername);
7132                         free_a_printer_driver(driver, 3);
7133                 }
7134
7135                 *returned+=ndrivers;
7136                 SAFE_FREE(list);
7137         }
7138
7139         /* check the required size. */
7140         for (i=0; i<*returned; i++) {
7141                 DEBUGADD(6,("adding driver [%d]'s size\n",i));
7142                 *needed += spoolss_size_printer_driver_info_3(&driver_info_3[i]);
7143         }
7144
7145         if (*needed > offered) {
7146                 result = WERR_INSUFFICIENT_BUFFER;
7147                 goto out;
7148         }
7149
7150         if (!rpcbuf_alloc_size(buffer, *needed)) {
7151                 result = WERR_NOMEM;
7152                 goto out;
7153         }
7154
7155         /* fill the buffer with the driver structures */
7156         for (i=0; i<*returned; i++) {
7157                 DEBUGADD(6,("adding driver [%d] to buffer\n",i));
7158                 smb_io_printer_driver_info_3("", buffer, &driver_info_3[i], 0);
7159         }
7160
7161 out:
7162         for (i=0; i<*returned; i++) {
7163                 SAFE_FREE(driver_info_3[i].dependentfiles);
7164         }
7165
7166         SAFE_FREE(driver_info_3);
7167
7168         if ( !W_ERROR_IS_OK(result) )
7169                 *returned = 0;
7170
7171         return result;
7172 }
7173
7174 /****************************************************************************
7175  Enumerates all printer drivers.
7176 ****************************************************************************/
7177
7178 WERROR _spoolss_enumprinterdrivers( pipes_struct *p, SPOOL_Q_ENUMPRINTERDRIVERS *q_u, SPOOL_R_ENUMPRINTERDRIVERS *r_u)
7179 {
7180         uint32 level = q_u->level;
7181         RPC_BUFFER *buffer = NULL;
7182         uint32 offered = q_u->offered;
7183         uint32 *needed = &r_u->needed;
7184         uint32 *returned = &r_u->returned;
7185         const char *cservername;
7186         fstring servername;
7187         fstring architecture;
7188
7189         /* that's an [in out] buffer */
7190
7191         if (!q_u->buffer && (offered!=0)) {
7192                 return WERR_INVALID_PARAM;
7193         }
7194
7195         if (offered > MAX_RPC_DATA_SIZE) {
7196                 return WERR_INVALID_PARAM;
7197         }
7198
7199         rpcbuf_move(q_u->buffer, &r_u->buffer);
7200         buffer = r_u->buffer;
7201
7202         DEBUG(4,("_spoolss_enumprinterdrivers\n"));
7203
7204         *needed   = 0;
7205         *returned = 0;
7206
7207         unistr2_to_ascii(architecture, &q_u->environment, sizeof(architecture));
7208         unistr2_to_ascii(servername, &q_u->name, sizeof(servername));
7209
7210         cservername = canon_servername(servername);
7211
7212         if (!is_myname_or_ipaddr(cservername))
7213                 return WERR_UNKNOWN_PRINTER_DRIVER;
7214
7215         switch (level) {
7216         case 1:
7217                 return enumprinterdrivers_level1(cservername, architecture, buffer, offered, needed, returned);
7218         case 2:
7219                 return enumprinterdrivers_level2(cservername, architecture, buffer, offered, needed, returned);
7220         case 3:
7221                 return enumprinterdrivers_level3(cservername, architecture, buffer, offered, needed, returned);
7222         default:
7223                 return WERR_UNKNOWN_LEVEL;
7224         }
7225 }
7226
7227 /****************************************************************************
7228 ****************************************************************************/
7229
7230 static void fill_form_1(FORM_1 *form, nt_forms_struct *list)
7231 {
7232         form->flag=list->flag;
7233         init_unistr(&form->name, list->name);
7234         form->width=list->width;
7235         form->length=list->length;
7236         form->left=list->left;
7237         form->top=list->top;
7238         form->right=list->right;
7239         form->bottom=list->bottom;
7240 }
7241
7242 /****************************************************************************
7243 ****************************************************************************/
7244
7245 static WERROR fill_form_info_1(TALLOC_CTX *mem_ctx,
7246                                struct spoolss_FormInfo1 *form,
7247                                nt_forms_struct *list)
7248 {
7249         form->form_name         = talloc_strdup(mem_ctx, list->name);
7250         W_ERROR_HAVE_NO_MEMORY(form->form_name);
7251
7252         form->flags             = list->flag;
7253         form->size.width        = list->width;
7254         form->size.height       = list->length;
7255         form->area.left         = list->left;
7256         form->area.top          = list->top;
7257         form->area.right        = list->right;
7258         form->area.bottom       = list->bottom;
7259
7260         return WERR_OK;
7261 }
7262
7263 /****************************************************************************
7264 ****************************************************************************/
7265
7266 WERROR _spoolss_enumforms(pipes_struct *p, SPOOL_Q_ENUMFORMS *q_u, SPOOL_R_ENUMFORMS *r_u)
7267 {
7268         uint32 level = q_u->level;
7269         RPC_BUFFER *buffer = NULL;
7270         uint32 offered = q_u->offered;
7271         uint32 *needed = &r_u->needed;
7272         uint32 *numofforms = &r_u->numofforms;
7273         uint32 numbuiltinforms;
7274
7275         nt_forms_struct *list=NULL;
7276         nt_forms_struct *builtinlist=NULL;
7277         FORM_1 *forms_1;
7278         int buffer_size=0;
7279         int i;
7280
7281         /* that's an [in out] buffer */
7282
7283         if (!q_u->buffer && (offered!=0) ) {
7284                 return WERR_INVALID_PARAM;
7285         }
7286
7287         if (offered > MAX_RPC_DATA_SIZE) {
7288                 return WERR_INVALID_PARAM;
7289         }
7290
7291         rpcbuf_move(q_u->buffer, &r_u->buffer);
7292         buffer = r_u->buffer;
7293
7294         DEBUG(4,("_spoolss_enumforms\n"));
7295         DEBUGADD(5,("Offered buffer size [%d]\n", offered));
7296         DEBUGADD(5,("Info level [%d]\n",          level));
7297
7298         numbuiltinforms = get_builtin_ntforms(&builtinlist);
7299         DEBUGADD(5,("Number of builtin forms [%d]\n",     numbuiltinforms));
7300         *numofforms = get_ntforms(&list);
7301         DEBUGADD(5,("Number of user forms [%d]\n",     *numofforms));
7302         *numofforms += numbuiltinforms;
7303
7304         if (*numofforms == 0) {
7305                 SAFE_FREE(builtinlist);
7306                 SAFE_FREE(list);
7307                 return WERR_NO_MORE_ITEMS;
7308         }
7309
7310         switch (level) {
7311         case 1:
7312                 if ((forms_1=SMB_MALLOC_ARRAY(FORM_1, *numofforms)) == NULL) {
7313                         SAFE_FREE(builtinlist);
7314                         SAFE_FREE(list);
7315                         *numofforms=0;
7316                         return WERR_NOMEM;
7317                 }
7318
7319                 /* construct the list of form structures */
7320                 for (i=0; i<numbuiltinforms; i++) {
7321                         DEBUGADD(6,("Filling form number [%d]\n",i));
7322                         fill_form_1(&forms_1[i], &builtinlist[i]);
7323                 }
7324
7325                 SAFE_FREE(builtinlist);
7326
7327                 for (; i<*numofforms; i++) {
7328                         DEBUGADD(6,("Filling form number [%d]\n",i));
7329                         fill_form_1(&forms_1[i], &list[i-numbuiltinforms]);
7330                 }
7331
7332                 SAFE_FREE(list);
7333
7334                 /* check the required size. */
7335                 for (i=0; i<numbuiltinforms; i++) {
7336                         DEBUGADD(6,("adding form [%d]'s size\n",i));
7337                         buffer_size += spoolss_size_form_1(&forms_1[i]);
7338                 }
7339                 for (; i<*numofforms; i++) {
7340                         DEBUGADD(6,("adding form [%d]'s size\n",i));
7341                         buffer_size += spoolss_size_form_1(&forms_1[i]);
7342                 }
7343
7344                 *needed=buffer_size;
7345
7346                 if (*needed > offered) {
7347                         SAFE_FREE(forms_1);
7348                         *numofforms=0;
7349                         return WERR_INSUFFICIENT_BUFFER;
7350                 }
7351
7352                 if (!rpcbuf_alloc_size(buffer, buffer_size)){
7353                         SAFE_FREE(forms_1);
7354                         *numofforms=0;
7355                         return WERR_NOMEM;
7356                 }
7357
7358                 /* fill the buffer with the form structures */
7359                 for (i=0; i<numbuiltinforms; i++) {
7360                         DEBUGADD(6,("adding form [%d] to buffer\n",i));
7361                         smb_io_form_1("", buffer, &forms_1[i], 0);
7362                 }
7363                 for (; i<*numofforms; i++) {
7364                         DEBUGADD(6,("adding form [%d] to buffer\n",i));
7365                         smb_io_form_1("", buffer, &forms_1[i], 0);
7366                 }
7367
7368                 SAFE_FREE(forms_1);
7369
7370                 return WERR_OK;
7371
7372         default:
7373                 SAFE_FREE(list);
7374                 SAFE_FREE(builtinlist);
7375                 return WERR_UNKNOWN_LEVEL;
7376         }
7377 }
7378
7379 /****************************************************************
7380  _spoolss_GetForm
7381 ****************************************************************/
7382
7383 WERROR _spoolss_GetForm(pipes_struct *p,
7384                         struct spoolss_GetForm *r)
7385 {
7386         uint32 level = r->in.level;
7387         uint32 offered = r->in.offered;
7388         uint32 *needed = r->out.needed;
7389
7390         nt_forms_struct *list=NULL;
7391         nt_forms_struct builtin_form;
7392         bool foundBuiltin;
7393         union spoolss_FormInfo info;
7394         struct spoolss_FormInfo1 form_1;
7395         int numofforms=0, i=0;
7396
7397         /* that's an [in out] buffer */
7398
7399         if (!r->in.buffer && (offered!=0)) {
7400                 return WERR_INVALID_PARAM;
7401         }
7402
7403         DEBUG(4,("_spoolss_GetForm\n"));
7404         DEBUGADD(5,("Offered buffer size [%d]\n", offered));
7405         DEBUGADD(5,("Info level [%d]\n",          level));
7406
7407         foundBuiltin = get_a_builtin_ntform_by_string(r->in.form_name, &builtin_form);
7408         if (!foundBuiltin) {
7409                 numofforms = get_ntforms(&list);
7410                 DEBUGADD(5,("Number of forms [%d]\n",     numofforms));
7411
7412                 if (numofforms == 0)
7413                         return WERR_BADFID;
7414         }
7415
7416         ZERO_STRUCT(form_1);
7417
7418         switch (level) {
7419         case 1:
7420                 if (foundBuiltin) {
7421                         fill_form_info_1(p->mem_ctx, &form_1, &builtin_form);
7422                 } else {
7423
7424                         /* Check if the requested name is in the list of form structures */
7425                         for (i=0; i<numofforms; i++) {
7426
7427                                 DEBUG(4,("_spoolss_GetForm: checking form %s (want %s)\n",
7428                                         list[i].name, r->in.form_name));
7429
7430                                 if (strequal(r->in.form_name, list[i].name)) {
7431                                         DEBUGADD(6,("Found form %s number [%d]\n",
7432                                                 r->in.form_name, i));
7433                                         fill_form_info_1(p->mem_ctx, &form_1, &list[i]);
7434                                         break;
7435                                 }
7436                         }
7437
7438                         SAFE_FREE(list);
7439                         if (i == numofforms) {
7440                                 return WERR_BADFID;
7441                         }
7442                 }
7443                 /* check the required size. */
7444
7445                 info.info1 = form_1;
7446
7447                 *needed = ndr_size_spoolss_FormInfo(&info, 1, NULL, 0);
7448
7449                 if (*needed > offered) {
7450                         r->out.info = NULL;
7451                         return WERR_INSUFFICIENT_BUFFER;
7452                 }
7453
7454                 r->out.info->info1 = form_1;
7455
7456                 /* fill the buffer with the form structures */
7457                 DEBUGADD(6,("adding form %s [%d] to buffer\n",
7458                         r->in.form_name, i));
7459
7460                 return WERR_OK;
7461
7462         default:
7463                 SAFE_FREE(list);
7464                 return WERR_UNKNOWN_LEVEL;
7465         }
7466 }
7467
7468 /****************************************************************************
7469 ****************************************************************************/
7470
7471 static void fill_port_1(PORT_INFO_1 *port, const char *name)
7472 {
7473         init_unistr(&port->port_name, name);
7474 }
7475
7476 /****************************************************************************
7477  TODO: This probably needs distinguish between TCP/IP and Local ports
7478  somehow.
7479 ****************************************************************************/
7480
7481 static void fill_port_2(PORT_INFO_2 *port, const char *name)
7482 {
7483         init_unistr(&port->port_name, name);
7484         init_unistr(&port->monitor_name, "Local Monitor");
7485         init_unistr(&port->description, SPL_LOCAL_PORT );
7486         port->port_type=PORT_TYPE_WRITE;
7487         port->reserved=0x0;
7488 }
7489
7490
7491 /****************************************************************************
7492  wrapper around the enumer ports command
7493 ****************************************************************************/
7494
7495 WERROR enumports_hook(TALLOC_CTX *ctx, int *count, char ***lines )
7496 {
7497         char *cmd = lp_enumports_cmd();
7498         char **qlines = NULL;
7499         char *command = NULL;
7500         int numlines;
7501         int ret;
7502         int fd;
7503
7504         *count = 0;
7505         *lines = NULL;
7506
7507         /* if no hook then just fill in the default port */
7508
7509         if ( !*cmd ) {
7510                 if (!(qlines = TALLOC_ARRAY( NULL, char*, 2 ))) {
7511                         return WERR_NOMEM;
7512                 }
7513                 if (!(qlines[0] = talloc_strdup(qlines, SAMBA_PRINTER_PORT_NAME ))) {
7514                         TALLOC_FREE(qlines);
7515                         return WERR_NOMEM;
7516                 }
7517                 qlines[1] = NULL;
7518                 numlines = 1;
7519         }
7520         else {
7521                 /* we have a valid enumport command */
7522
7523                 command = talloc_asprintf(ctx, "%s \"%d\"", cmd, 1);
7524                 if (!command) {
7525                         return WERR_NOMEM;
7526                 }
7527
7528                 DEBUG(10,("Running [%s]\n", command));
7529                 ret = smbrun(command, &fd);
7530                 DEBUG(10,("Returned [%d]\n", ret));
7531                 TALLOC_FREE(command);
7532                 if (ret != 0) {
7533                         if (fd != -1) {
7534                                 close(fd);
7535                         }
7536                         return WERR_ACCESS_DENIED;
7537                 }
7538
7539                 numlines = 0;
7540                 qlines = fd_lines_load(fd, &numlines, 0, NULL);
7541                 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
7542                 close(fd);
7543         }
7544
7545         *count = numlines;
7546         *lines = qlines;
7547
7548         return WERR_OK;
7549 }
7550
7551 /****************************************************************************
7552  enumports level 1.
7553 ****************************************************************************/
7554
7555 static WERROR enumports_level_1(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
7556 {
7557         PORT_INFO_1 *ports=NULL;
7558         int i=0;
7559         WERROR result = WERR_OK;
7560         char **qlines = NULL;
7561         int numlines = 0;
7562
7563         result = enumports_hook(talloc_tos(), &numlines, &qlines );
7564         if (!W_ERROR_IS_OK(result)) {
7565                 TALLOC_FREE(qlines);
7566                 return result;
7567         }
7568
7569         if(numlines) {
7570                 if((ports=SMB_MALLOC_ARRAY( PORT_INFO_1, numlines )) == NULL) {
7571                         DEBUG(10,("Returning WERR_NOMEM [%s]\n",
7572                                   win_errstr(WERR_NOMEM)));
7573                         TALLOC_FREE(qlines);
7574                         return WERR_NOMEM;
7575                 }
7576
7577                 for (i=0; i<numlines; i++) {
7578                         DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
7579                         fill_port_1(&ports[i], qlines[i]);
7580                 }
7581         }
7582         TALLOC_FREE(qlines);
7583
7584         *returned = numlines;
7585
7586         /* check the required size. */
7587         for (i=0; i<*returned; i++) {
7588                 DEBUGADD(6,("adding port [%d]'s size\n", i));
7589                 *needed += spoolss_size_port_info_1(&ports[i]);
7590         }
7591
7592         if (*needed > offered) {
7593                 result = WERR_INSUFFICIENT_BUFFER;
7594                 goto out;
7595         }
7596
7597         if (!rpcbuf_alloc_size(buffer, *needed)) {
7598                 result = WERR_NOMEM;
7599                 goto out;
7600         }
7601
7602         /* fill the buffer with the ports structures */
7603         for (i=0; i<*returned; i++) {
7604                 DEBUGADD(6,("adding port [%d] to buffer\n", i));
7605                 smb_io_port_1("", buffer, &ports[i], 0);
7606         }
7607
7608 out:
7609         SAFE_FREE(ports);
7610
7611         if ( !W_ERROR_IS_OK(result) )
7612                 *returned = 0;
7613
7614         return result;
7615 }
7616
7617 /****************************************************************************
7618  enumports level 2.
7619 ****************************************************************************/
7620
7621 static WERROR enumports_level_2(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
7622 {
7623         PORT_INFO_2 *ports=NULL;
7624         int i=0;
7625         WERROR result = WERR_OK;
7626         char **qlines = NULL;
7627         int numlines = 0;
7628
7629         result = enumports_hook(talloc_tos(), &numlines, &qlines );
7630         if ( !W_ERROR_IS_OK(result)) {
7631                 TALLOC_FREE(qlines);
7632                 return result;
7633         }
7634
7635         if(numlines) {
7636                 if((ports=SMB_MALLOC_ARRAY( PORT_INFO_2, numlines)) == NULL) {
7637                         TALLOC_FREE(qlines);
7638                         return WERR_NOMEM;
7639                 }
7640
7641                 for (i=0; i<numlines; i++) {
7642                         DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
7643                         fill_port_2(&(ports[i]), qlines[i]);
7644                 }
7645         }
7646
7647         TALLOC_FREE(qlines);
7648
7649         *returned = numlines;
7650
7651         /* check the required size. */
7652         for (i=0; i<*returned; i++) {
7653                 DEBUGADD(6,("adding port [%d]'s size\n", i));
7654                 *needed += spoolss_size_port_info_2(&ports[i]);
7655         }
7656
7657         if (*needed > offered) {
7658                 result = WERR_INSUFFICIENT_BUFFER;
7659                 goto out;
7660         }
7661
7662         if (!rpcbuf_alloc_size(buffer, *needed)) {
7663                 result = WERR_NOMEM;
7664                 goto out;
7665         }
7666
7667         /* fill the buffer with the ports structures */
7668         for (i=0; i<*returned; i++) {
7669                 DEBUGADD(6,("adding port [%d] to buffer\n", i));
7670                 smb_io_port_2("", buffer, &ports[i], 0);
7671         }
7672
7673 out:
7674         SAFE_FREE(ports);
7675
7676         if ( !W_ERROR_IS_OK(result) )
7677                 *returned = 0;
7678
7679         return result;
7680 }
7681
7682 /****************************************************************************
7683  enumports.
7684 ****************************************************************************/
7685
7686 WERROR _spoolss_enumports( pipes_struct *p, SPOOL_Q_ENUMPORTS *q_u, SPOOL_R_ENUMPORTS *r_u)
7687 {
7688         uint32 level = q_u->level;
7689         RPC_BUFFER *buffer = NULL;
7690         uint32 offered = q_u->offered;
7691         uint32 *needed = &r_u->needed;
7692         uint32 *returned = &r_u->returned;
7693
7694         /* that's an [in out] buffer */
7695
7696         if (!q_u->buffer && (offered!=0)) {
7697                 return WERR_INVALID_PARAM;
7698         }
7699
7700         if (offered > MAX_RPC_DATA_SIZE) {
7701                 return WERR_INVALID_PARAM;
7702         }
7703
7704         rpcbuf_move(q_u->buffer, &r_u->buffer);
7705         buffer = r_u->buffer;
7706
7707         DEBUG(4,("_spoolss_enumports\n"));
7708
7709         *returned=0;
7710         *needed=0;
7711
7712         switch (level) {
7713         case 1:
7714                 return enumports_level_1(buffer, offered, needed, returned);
7715         case 2:
7716                 return enumports_level_2(buffer, offered, needed, returned);
7717         default:
7718                 return WERR_UNKNOWN_LEVEL;
7719         }
7720 }
7721
7722 /****************************************************************************
7723 ****************************************************************************/
7724
7725 static WERROR spoolss_addprinterex_level_2(pipes_struct *p,
7726                                            const char *server,
7727                                            struct spoolss_SetPrinterInfoCtr *info_ctr,
7728                                            struct spoolss_DeviceMode *devmode,
7729                                            struct security_descriptor *sec_desc,
7730                                            struct spoolss_UserLevelCtr *user_ctr,
7731                                            POLICY_HND *handle)
7732 {
7733         NT_PRINTER_INFO_LEVEL *printer = NULL;
7734         fstring name;
7735         int     snum;
7736         WERROR err = WERR_OK;
7737
7738         if ( !(printer = TALLOC_ZERO_P(NULL, NT_PRINTER_INFO_LEVEL)) ) {
7739                 DEBUG(0,("spoolss_addprinterex_level_2: malloc fail.\n"));
7740                 return WERR_NOMEM;
7741         }
7742
7743         /* convert from UNICODE to ASCII - this allocates the info_2 struct inside *printer.*/
7744         if (!convert_printer_info_new(info_ctr, printer)) {
7745                 free_a_printer(&printer, 2);
7746                 return WERR_NOMEM;
7747         }
7748
7749         /* check to see if the printer already exists */
7750
7751         if ((snum = print_queue_snum(printer->info_2->sharename)) != -1) {
7752                 DEBUG(5, ("spoolss_addprinterex_level_2: Attempted to add a printer named [%s] when one already existed!\n",
7753                         printer->info_2->sharename));
7754                 free_a_printer(&printer, 2);
7755                 return WERR_PRINTER_ALREADY_EXISTS;
7756         }
7757
7758         /* FIXME!!!  smbd should check to see if the driver is installed before
7759            trying to add a printer like this  --jerry */
7760
7761         if (*lp_addprinter_cmd() ) {
7762                 if ( !add_printer_hook(p->mem_ctx, p->server_info->ptok,
7763                                        printer) ) {
7764                         free_a_printer(&printer,2);
7765                         return WERR_ACCESS_DENIED;
7766                 }
7767         } else {
7768                 DEBUG(0,("spoolss_addprinterex_level_2: add printer for printer %s called and no"
7769                         "smb.conf parameter \"addprinter command\" is defined. This"
7770                         "parameter must exist for this call to succeed\n",
7771                         printer->info_2->sharename ));
7772         }
7773
7774         /* use our primary netbios name since get_a_printer() will convert
7775            it to what the client expects on a case by case basis */
7776
7777         slprintf(name, sizeof(name)-1, "\\\\%s\\%s", global_myname(),
7778              printer->info_2->sharename);
7779
7780
7781         if ((snum = print_queue_snum(printer->info_2->sharename)) == -1) {
7782                 free_a_printer(&printer,2);
7783                 return WERR_ACCESS_DENIED;
7784         }
7785
7786         /* you must be a printer admin to add a new printer */
7787         if (!print_access_check(NULL, snum, PRINTER_ACCESS_ADMINISTER)) {
7788                 free_a_printer(&printer,2);
7789                 return WERR_ACCESS_DENIED;
7790         }
7791
7792         /*
7793          * Do sanity check on the requested changes for Samba.
7794          */
7795
7796         if (!check_printer_ok(printer->info_2, snum)) {
7797                 free_a_printer(&printer,2);
7798                 return WERR_INVALID_PARAM;
7799         }
7800
7801         /*
7802          * When a printer is created, the drivername bound to the printer is used
7803          * to lookup previously saved driver initialization info, which is then
7804          * bound to the new printer, simulating what happens in the Windows arch.
7805          */
7806
7807         if (!devmode)
7808         {
7809                 set_driver_init(printer, 2);
7810         }
7811         else
7812         {
7813                 /* A valid devmode was included, convert and link it
7814                 */
7815                 DEBUGADD(10, ("spoolss_addprinterex_level_2: devmode included, converting\n"));
7816
7817                 if (!convert_devicemode_new(printer->info_2->printername,
7818                                             devmode,
7819                                             &printer->info_2->devmode))
7820                         return  WERR_NOMEM;
7821         }
7822
7823         /* write the ASCII on disk */
7824         err = mod_a_printer(printer, 2);
7825         if (!W_ERROR_IS_OK(err)) {
7826                 free_a_printer(&printer,2);
7827                 return err;
7828         }
7829
7830         if (!open_printer_hnd(p, handle, name, PRINTER_ACCESS_ADMINISTER)) {
7831                 /* Handle open failed - remove addition. */
7832                 del_a_printer(printer->info_2->sharename);
7833                 free_a_printer(&printer,2);
7834                 ZERO_STRUCTP(handle);
7835                 return WERR_ACCESS_DENIED;
7836         }
7837
7838         update_c_setprinter(False);
7839         free_a_printer(&printer,2);
7840
7841         return WERR_OK;
7842 }
7843
7844 /****************************************************************
7845  _spoolss_AddPrinterEx
7846 ****************************************************************/
7847
7848 WERROR _spoolss_AddPrinterEx(pipes_struct *p,
7849                              struct spoolss_AddPrinterEx *r)
7850 {
7851         switch (r->in.info_ctr->level) {
7852         case 1:
7853                 /* we don't handle yet */
7854                 /* but I know what to do ... */
7855                 return WERR_UNKNOWN_LEVEL;
7856         case 2:
7857                 return spoolss_addprinterex_level_2(p, r->in.server,
7858                                                     r->in.info_ctr,
7859                                                     r->in.devmode_ctr->devmode,
7860                                                     r->in.secdesc_ctr->sd,
7861                                                     r->in.userlevel_ctr,
7862                                                     r->out.handle);
7863         default:
7864                 return WERR_UNKNOWN_LEVEL;
7865         }
7866 }
7867
7868 /****************************************************************
7869  _spoolss_AddPrinterDriver
7870 ****************************************************************/
7871
7872 WERROR _spoolss_AddPrinterDriver(pipes_struct *p,
7873                                  struct spoolss_AddPrinterDriver *r)
7874 {
7875         uint32_t level = r->in.info_ctr->level;
7876         struct spoolss_AddDriverInfoCtr *info = r->in.info_ctr;
7877         WERROR err = WERR_OK;
7878         NT_PRINTER_DRIVER_INFO_LEVEL driver;
7879         fstring driver_name;
7880         uint32 version;
7881         const char *fn;
7882
7883         switch (p->hdr_req.opnum) {
7884                 case NDR_SPOOLSS_ADDPRINTERDRIVER:
7885                         fn = "_spoolss_AddPrinterDriver";
7886                         break;
7887                 case NDR_SPOOLSS_ADDPRINTERDRIVEREX:
7888                         fn = "_spoolss_AddPrinterDriverEx";
7889                         break;
7890                 default:
7891                         return WERR_INVALID_PARAM;
7892         }
7893
7894
7895         /* FIXME */
7896         if (level != 3 && level != 6) {
7897                 /* Clever hack from Martin Zielinski <mz@seh.de>
7898                  * to allow downgrade from level 8 (Vista).
7899                  */
7900                 DEBUG(0,("%s: level %d not yet implemented\n", fn, level));
7901                 return WERR_UNKNOWN_LEVEL;
7902         }
7903
7904         ZERO_STRUCT(driver);
7905
7906         if (!convert_printer_driver_info(info, &driver, level)) {
7907                 err = WERR_NOMEM;
7908                 goto done;
7909         }
7910
7911         DEBUG(5,("Cleaning driver's information\n"));
7912         err = clean_up_driver_struct(p, driver, level);
7913         if (!W_ERROR_IS_OK(err))
7914                 goto done;
7915
7916         DEBUG(5,("Moving driver to final destination\n"));
7917         if( !W_ERROR_IS_OK(err = move_driver_to_download_area(p, driver, level,
7918                                                               &err)) ) {
7919                 goto done;
7920         }
7921
7922         if (add_a_printer_driver(driver, level)!=0) {
7923                 err = WERR_ACCESS_DENIED;
7924                 goto done;
7925         }
7926
7927         switch(level) {
7928         case 3:
7929                 fstrcpy(driver_name,
7930                         driver.info_3->name ? driver.info_3->name : "");
7931                 break;
7932         case 6:
7933                 fstrcpy(driver_name,
7934                         driver.info_6->name ?  driver.info_6->name : "");
7935                 break;
7936         }
7937
7938         /*
7939          * I think this is where he DrvUpgradePrinter() hook would be
7940          * be called in a driver's interface DLL on a Windows NT 4.0/2k
7941          * server.  Right now, we just need to send ourselves a message
7942          * to update each printer bound to this driver.   --jerry
7943          */
7944
7945         if (!srv_spoolss_drv_upgrade_printer(driver_name)) {
7946                 DEBUG(0,("%s: Failed to send message about upgrading driver [%s]!\n",
7947                         fn, driver_name));
7948         }
7949
7950         /*
7951          * Based on the version (e.g. driver destination dir: 0=9x,2=Nt/2k,3=2k/Xp),
7952          * decide if the driver init data should be deleted. The rules are:
7953          *  1) never delete init data if it is a 9x driver, they don't use it anyway
7954          *  2) delete init data only if there is no 2k/Xp driver
7955          *  3) always delete init data
7956          * The generalized rule is always use init data from the highest order driver.
7957          * It is necessary to follow the driver install by an initialization step to
7958          * finish off this process.
7959         */
7960         if (level == 3)
7961                 version = driver.info_3->cversion;
7962         else if (level == 6)
7963                 version = driver.info_6->version;
7964         else
7965                 version = -1;
7966         switch (version) {
7967                 /*
7968                  * 9x printer driver - never delete init data
7969                 */
7970                 case 0:
7971                         DEBUG(10,("%s: init data not deleted for 9x driver [%s]\n",
7972                                 fn, driver_name));
7973                         break;
7974
7975                 /*
7976                  * Nt or 2k (compatiblity mode) printer driver - only delete init data if
7977                  * there is no 2k/Xp driver init data for this driver name.
7978                 */
7979                 case 2:
7980                 {
7981                         NT_PRINTER_DRIVER_INFO_LEVEL driver1;
7982
7983                         if (!W_ERROR_IS_OK(get_a_printer_driver(&driver1, 3, driver_name, "Windows NT x86", 3))) {
7984                                 /*
7985                                  * No 2k/Xp driver found, delete init data (if any) for the new Nt driver.
7986                                 */
7987                                 if (!del_driver_init(driver_name))
7988                                         DEBUG(6,("%s: del_driver_init(%s) Nt failed!\n",
7989                                                 fn, driver_name));
7990                         } else {
7991                                 /*
7992                                  * a 2k/Xp driver was found, don't delete init data because Nt driver will use it.
7993                                 */
7994                                 free_a_printer_driver(driver1,3);
7995                                 DEBUG(10,("%s: init data not deleted for Nt driver [%s]\n",
7996                                         fn, driver_name));
7997                         }
7998                 }
7999                 break;
8000
8001                 /*
8002                  * 2k or Xp printer driver - always delete init data
8003                 */
8004                 case 3:
8005                         if (!del_driver_init(driver_name))
8006                                 DEBUG(6,("%s: del_driver_init(%s) 2k/Xp failed!\n",
8007                                         fn, driver_name));
8008                         break;
8009
8010                 default:
8011                         DEBUG(0,("%s: invalid level=%d\n", fn, level));
8012                         break;
8013         }
8014
8015
8016 done:
8017         free_a_printer_driver(driver, level);
8018         return err;
8019 }
8020
8021 /****************************************************************
8022  _spoolss_AddPrinterDriverEx
8023 ****************************************************************/
8024
8025 WERROR _spoolss_AddPrinterDriverEx(pipes_struct *p,
8026                                    struct spoolss_AddPrinterDriverEx *r)
8027 {
8028         struct spoolss_AddPrinterDriver a;
8029
8030         /*
8031          * we only support the semantics of AddPrinterDriver()
8032          * i.e. only copy files that are newer than existing ones
8033          */
8034
8035         if (r->in.flags != APD_COPY_NEW_FILES) {
8036                 return WERR_ACCESS_DENIED;
8037         }
8038
8039         a.in.servername         = r->in.servername;
8040         a.in.info_ctr           = r->in.info_ctr;
8041
8042         return _spoolss_AddPrinterDriver(p, &a);
8043 }
8044
8045 /****************************************************************************
8046 ****************************************************************************/
8047
8048 static WERROR getprinterdriverdir_level_1(TALLOC_CTX *mem_ctx,
8049                                           const char *servername,
8050                                           const char *environment,
8051                                           struct spoolss_DriverDirectoryInfo1 *info1,
8052                                           uint32_t offered,
8053                                           uint32_t *needed)
8054 {
8055         char *path = NULL;
8056         const char *pservername = NULL;
8057         const char *long_archi = SPOOLSS_ARCHITECTURE_NT_X86;
8058         const char *short_archi;
8059
8060         if (environment) {
8061                 long_archi = environment;
8062         }
8063
8064         pservername = canon_servername(servername);
8065
8066         if ( !is_myname_or_ipaddr(pservername))
8067                 return WERR_INVALID_PARAM;
8068
8069         if (!(short_archi = get_short_archi(long_archi)))
8070                 return WERR_INVALID_ENVIRONMENT;
8071
8072         path = talloc_asprintf(mem_ctx,
8073                         "\\\\%s\\print$\\%s", pservername, short_archi);
8074         if (!path) {
8075                 return WERR_NOMEM;
8076         }
8077
8078         DEBUG(4,("printer driver directory: [%s]\n", path));
8079
8080         info1->directory_name = path;
8081
8082         *needed += ndr_size_spoolss_DriverDirectoryInfo1(info1, NULL, 0);
8083
8084         if (*needed > offered) {
8085                 talloc_free(path);
8086                 ZERO_STRUCTP(info1);
8087                 return WERR_INSUFFICIENT_BUFFER;
8088         }
8089
8090         return WERR_OK;
8091 }
8092
8093 /****************************************************************
8094  _spoolss_GetPrinterDriverDirectory
8095 ****************************************************************/
8096
8097 WERROR _spoolss_GetPrinterDriverDirectory(pipes_struct *p,
8098                                           struct spoolss_GetPrinterDriverDirectory *r)
8099 {
8100         WERROR werror;
8101
8102         /* that's an [in out] buffer */
8103
8104         if (!r->in.buffer && (r->in.offered != 0)) {
8105                 return WERR_INVALID_PARAM;
8106         }
8107
8108         if (r->in.offered > MAX_RPC_DATA_SIZE) {
8109                 return WERR_INVALID_PARAM;
8110         }
8111
8112         DEBUG(4,("_spoolss_GetPrinterDriverDirectory\n"));
8113
8114         *r->out.needed = 0;
8115
8116         switch (r->in.level) {
8117         case 1:
8118                 werror = getprinterdriverdir_level_1(p->mem_ctx,
8119                                                      r->in.server,
8120                                                      r->in.environment,
8121                                                      &r->out.info->info1,
8122                                                      r->in.offered,
8123                                                      r->out.needed);
8124                 if (!W_ERROR_IS_OK(werror)) {
8125                         TALLOC_FREE(r->out.info);
8126                 }
8127                 break;
8128         default:
8129                 return WERR_UNKNOWN_LEVEL;
8130         }
8131
8132         return werror;
8133 }
8134
8135 /****************************************************************************
8136 ****************************************************************************/
8137
8138 WERROR _spoolss_enumprinterdata(pipes_struct *p, SPOOL_Q_ENUMPRINTERDATA *q_u, SPOOL_R_ENUMPRINTERDATA *r_u)
8139 {
8140         POLICY_HND *handle = &q_u->handle;
8141         uint32 idx               = q_u->index;
8142         uint32 in_value_len      = q_u->valuesize;
8143         uint32 in_data_len       = q_u->datasize;
8144         uint32 *out_max_value_len = &r_u->valuesize;
8145         uint16 **out_value       = &r_u->value;
8146         uint32 *out_value_len    = &r_u->realvaluesize;
8147         uint32 *out_type         = &r_u->type;
8148         uint32 *out_max_data_len = &r_u->datasize;
8149         uint8  **data_out        = &r_u->data;
8150         uint32 *out_data_len     = &r_u->realdatasize;
8151
8152         NT_PRINTER_INFO_LEVEL *printer = NULL;
8153
8154         uint32          biggest_valuesize;
8155         uint32          biggest_datasize;
8156         uint32          data_len;
8157         Printer_entry   *Printer = find_printer_index_by_hnd(p, handle);
8158         int             snum;
8159         WERROR          result;
8160         REGISTRY_VALUE  *val = NULL;
8161         NT_PRINTER_DATA *p_data;
8162         int             i, key_index, num_values;
8163         int             name_length;
8164
8165         *out_type = 0;
8166
8167         *out_max_data_len = 0;
8168         *data_out         = NULL;
8169         *out_data_len     = 0;
8170
8171         DEBUG(5,("spoolss_enumprinterdata\n"));
8172
8173         if (!Printer) {
8174                 DEBUG(2,("_spoolss_enumprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8175                 return WERR_BADFID;
8176         }
8177
8178         if (!get_printer_snum(p,handle, &snum, NULL))
8179                 return WERR_BADFID;
8180
8181         result = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8182         if (!W_ERROR_IS_OK(result))
8183                 return result;
8184
8185         p_data = printer->info_2->data;
8186         key_index = lookup_printerkey( p_data, SPOOL_PRINTERDATA_KEY );
8187
8188         result = WERR_OK;
8189
8190         /*
8191          * The NT machine wants to know the biggest size of value and data
8192          *
8193          * cf: MSDN EnumPrinterData remark section
8194          */
8195
8196         if ( !in_value_len && !in_data_len && (key_index != -1) )
8197         {
8198                 DEBUGADD(6,("Activating NT mega-hack to find sizes\n"));
8199
8200                 biggest_valuesize = 0;
8201                 biggest_datasize  = 0;
8202
8203                 num_values = regval_ctr_numvals( p_data->keys[key_index].values );
8204
8205                 for ( i=0; i<num_values; i++ )
8206                 {
8207                         val = regval_ctr_specific_value( p_data->keys[key_index].values, i );
8208
8209                         name_length = strlen(val->valuename);
8210                         if ( strlen(val->valuename) > biggest_valuesize )
8211                                 biggest_valuesize = name_length;
8212
8213                         if ( val->size > biggest_datasize )
8214                                 biggest_datasize = val->size;
8215
8216                         DEBUG(6,("current values: [%d], [%d]\n", biggest_valuesize,
8217                                 biggest_datasize));
8218                 }
8219
8220                 /* the value is an UNICODE string but real_value_size is the length
8221                    in bytes including the trailing 0 */
8222
8223                 *out_value_len = 2 * (1+biggest_valuesize);
8224                 *out_data_len  = biggest_datasize;
8225
8226                 DEBUG(6,("final values: [%d], [%d]\n", *out_value_len, *out_data_len));
8227
8228                 goto done;
8229         }
8230
8231         /*
8232          * the value len is wrong in NT sp3
8233          * that's the number of bytes not the number of unicode chars
8234          */
8235
8236         if ( key_index != -1 )
8237                 val = regval_ctr_specific_value( p_data->keys[key_index].values, idx );
8238
8239         if ( !val )
8240         {
8241
8242                 /* out_value should default to "" or else NT4 has
8243                    problems unmarshalling the response */
8244
8245                 *out_max_value_len=(in_value_len/sizeof(uint16));
8246
8247                 if (in_value_len) {
8248                         if((*out_value=(uint16 *)TALLOC_ZERO(p->mem_ctx, in_value_len*sizeof(uint8))) == NULL)
8249                         {
8250                                 result = WERR_NOMEM;
8251                                 goto done;
8252                         }
8253                         *out_value_len = (uint32)rpcstr_push((char *)*out_value, "", in_value_len, 0);
8254                 } else {
8255                         *out_value=NULL;
8256                         *out_value_len = 0;
8257                 }
8258
8259                 /* the data is counted in bytes */
8260
8261                 *out_max_data_len = in_data_len;
8262                 *out_data_len     = in_data_len;
8263
8264                 /* only allocate when given a non-zero data_len */
8265
8266                 if ( in_data_len && ((*data_out=(uint8 *)TALLOC_ZERO(p->mem_ctx, in_data_len*sizeof(uint8))) == NULL) )
8267                 {
8268                         result = WERR_NOMEM;
8269                         goto done;
8270                 }
8271
8272                 result = WERR_NO_MORE_ITEMS;
8273         }
8274         else
8275         {
8276                 /*
8277                  * the value is:
8278                  * - counted in bytes in the request
8279                  * - counted in UNICODE chars in the max reply
8280                  * - counted in bytes in the real size
8281                  *
8282                  * take a pause *before* coding not *during* coding
8283                  */
8284
8285                 /* name */
8286                 *out_max_value_len=(in_value_len/sizeof(uint16));
8287                 if (in_value_len) {
8288                         if ( (*out_value = (uint16 *)TALLOC_ZERO(p->mem_ctx, in_value_len*sizeof(uint8))) == NULL )
8289                         {
8290                                 result = WERR_NOMEM;
8291                                 goto done;
8292                         }
8293
8294                         *out_value_len = (uint32)rpcstr_push((char *)*out_value, regval_name(val), (size_t)in_value_len, 0);
8295                 } else {
8296                         *out_value = NULL;
8297                         *out_value_len = 0;
8298                 }
8299
8300                 /* type */
8301
8302                 *out_type = regval_type( val );
8303
8304                 /* data - counted in bytes */
8305
8306                 *out_max_data_len = in_data_len;
8307                 if ( in_data_len && (*data_out = (uint8 *)TALLOC_ZERO(p->mem_ctx, in_data_len*sizeof(uint8))) == NULL)
8308                 {
8309                         result = WERR_NOMEM;
8310                         goto done;
8311                 }
8312                 data_len = regval_size(val);
8313                 if ( *data_out && data_len )
8314                         memcpy( *data_out, regval_data_p(val), data_len );
8315                 *out_data_len = data_len;
8316         }
8317
8318 done:
8319         free_a_printer(&printer, 2);
8320         return result;
8321 }
8322
8323 /****************************************************************************
8324 ****************************************************************************/
8325
8326 WERROR _spoolss_setprinterdata( pipes_struct *p, SPOOL_Q_SETPRINTERDATA *q_u, SPOOL_R_SETPRINTERDATA *r_u)
8327 {
8328         POLICY_HND              *handle = &q_u->handle;
8329         UNISTR2                 *value = &q_u->value;
8330         uint32                  type = q_u->type;
8331         uint8                   *data = q_u->data;
8332         uint32                  real_len = q_u->real_len;
8333
8334         NT_PRINTER_INFO_LEVEL   *printer = NULL;
8335         int                     snum=0;
8336         WERROR                  status = WERR_OK;
8337         Printer_entry           *Printer=find_printer_index_by_hnd(p, handle);
8338         fstring                 valuename;
8339
8340         DEBUG(5,("spoolss_setprinterdata\n"));
8341
8342         if (!Printer) {
8343                 DEBUG(2,("_spoolss_setprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8344                 return WERR_BADFID;
8345         }
8346
8347         if ( Printer->printer_type == SPLHND_SERVER ) {
8348                 DEBUG(10,("_spoolss_setprinterdata: Not implemented for server handles yet\n"));
8349                 return WERR_INVALID_PARAM;
8350         }
8351
8352         if (!get_printer_snum(p,handle, &snum, NULL))
8353                 return WERR_BADFID;
8354
8355         /*
8356          * Access check : NT returns "access denied" if you make a
8357          * SetPrinterData call without the necessary privildge.
8358          * we were originally returning OK if nothing changed
8359          * which made Win2k issue **a lot** of SetPrinterData
8360          * when connecting to a printer  --jerry
8361          */
8362
8363         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER)
8364         {
8365                 DEBUG(3, ("_spoolss_setprinterdata: change denied by handle access permissions\n"));
8366                 status = WERR_ACCESS_DENIED;
8367                 goto done;
8368         }
8369
8370         status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8371         if (!W_ERROR_IS_OK(status))
8372                 return status;
8373
8374         unistr2_to_ascii(valuename, value, sizeof(valuename));
8375
8376         /*
8377          * When client side code sets a magic printer data key, detect it and save
8378          * the current printer data and the magic key's data (its the DEVMODE) for
8379          * future printer/driver initializations.
8380          */
8381         if ( (type == REG_BINARY) && strequal( valuename, PHANTOM_DEVMODE_KEY))
8382         {
8383                 /* Set devmode and printer initialization info */
8384                 status = save_driver_init( printer, 2, data, real_len );
8385
8386                 srv_spoolss_reset_printerdata( printer->info_2->drivername );
8387         }
8388         else
8389         {
8390         status = set_printer_dataex( printer, SPOOL_PRINTERDATA_KEY, valuename,
8391                                         type, data, real_len );
8392                 if ( W_ERROR_IS_OK(status) )
8393                         status = mod_a_printer(printer, 2);
8394         }
8395
8396 done:
8397         free_a_printer(&printer, 2);
8398
8399         return status;
8400 }
8401
8402 /****************************************************************
8403  _spoolss_ResetPrinter
8404 ****************************************************************/
8405
8406 WERROR _spoolss_ResetPrinter(pipes_struct *p,
8407                              struct spoolss_ResetPrinter *r)
8408 {
8409         POLICY_HND      *handle = r->in.handle;
8410         Printer_entry   *Printer=find_printer_index_by_hnd(p, handle);
8411         int             snum;
8412
8413         DEBUG(5,("_spoolss_ResetPrinter\n"));
8414
8415         /*
8416          * All we do is to check to see if the handle and queue is valid.
8417          * This call really doesn't mean anything to us because we only
8418          * support RAW printing.   --jerry
8419          */
8420
8421         if (!Printer) {
8422                 DEBUG(2,("_spoolss_ResetPrinter: Invalid handle (%s:%u:%u).\n",
8423                         OUR_HANDLE(handle)));
8424                 return WERR_BADFID;
8425         }
8426
8427         if (!get_printer_snum(p,handle, &snum, NULL))
8428                 return WERR_BADFID;
8429
8430
8431         /* blindly return success */
8432         return WERR_OK;
8433 }
8434
8435 /****************************************************************
8436  _spoolss_DeletePrinterData
8437 ****************************************************************/
8438
8439 WERROR _spoolss_DeletePrinterData(pipes_struct *p,
8440                                   struct spoolss_DeletePrinterData *r)
8441 {
8442         POLICY_HND      *handle = r->in.handle;
8443         NT_PRINTER_INFO_LEVEL   *printer = NULL;
8444         int             snum=0;
8445         WERROR          status = WERR_OK;
8446         Printer_entry   *Printer=find_printer_index_by_hnd(p, handle);
8447
8448         DEBUG(5,("_spoolss_DeletePrinterData\n"));
8449
8450         if (!Printer) {
8451                 DEBUG(2,("_spoolss_DeletePrinterData: Invalid handle (%s:%u:%u).\n",
8452                         OUR_HANDLE(handle)));
8453                 return WERR_BADFID;
8454         }
8455
8456         if (!get_printer_snum(p, handle, &snum, NULL))
8457                 return WERR_BADFID;
8458
8459         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
8460                 DEBUG(3, ("_spoolss_DeletePrinterData: "
8461                         "printer properties change denied by handle\n"));
8462                 return WERR_ACCESS_DENIED;
8463         }
8464
8465         status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8466         if (!W_ERROR_IS_OK(status))
8467                 return status;
8468
8469         if (!r->in.value_name) {
8470                 free_a_printer(&printer, 2);
8471                 return WERR_NOMEM;
8472         }
8473
8474         status = delete_printer_dataex( printer, SPOOL_PRINTERDATA_KEY,
8475                                         r->in.value_name );
8476
8477         if ( W_ERROR_IS_OK(status) )
8478                 mod_a_printer( printer, 2 );
8479
8480         free_a_printer(&printer, 2);
8481
8482         return status;
8483 }
8484
8485 /****************************************************************
8486  _spoolss_AddForm
8487 ****************************************************************/
8488
8489 WERROR _spoolss_AddForm(pipes_struct *p,
8490                         struct spoolss_AddForm *r)
8491 {
8492         POLICY_HND *handle = r->in.handle;
8493         struct spoolss_AddFormInfo1 *form = r->in.info.info1;
8494         nt_forms_struct tmpForm;
8495         int snum;
8496         WERROR status = WERR_OK;
8497         NT_PRINTER_INFO_LEVEL *printer = NULL;
8498
8499         int count=0;
8500         nt_forms_struct *list=NULL;
8501         Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8502
8503         DEBUG(5,("_spoolss_AddForm\n"));
8504
8505         if (!Printer) {
8506                 DEBUG(2,("_spoolss_AddForm: Invalid handle (%s:%u:%u).\n",
8507                         OUR_HANDLE(handle)));
8508                 return WERR_BADFID;
8509         }
8510
8511
8512         /* forms can be added on printer of on the print server handle */
8513
8514         if ( Printer->printer_type == SPLHND_PRINTER )
8515         {
8516                 if (!get_printer_snum(p,handle, &snum, NULL))
8517                         return WERR_BADFID;
8518
8519                 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8520                 if (!W_ERROR_IS_OK(status))
8521                         goto done;
8522         }
8523
8524         if ( !(Printer->access_granted & (PRINTER_ACCESS_ADMINISTER|SERVER_ACCESS_ADMINISTER)) ) {
8525                 DEBUG(2,("_spoolss_addform: denied by handle permissions.\n"));
8526                 status = WERR_ACCESS_DENIED;
8527                 goto done;
8528         }
8529
8530         /* can't add if builtin */
8531
8532         if (get_a_builtin_ntform_by_string(form->form_name, &tmpForm)) {
8533                 status = WERR_FILE_EXISTS;
8534                 goto done;
8535         }
8536
8537         count = get_ntforms(&list);
8538
8539         if(!add_a_form(&list, form, &count)) {
8540                 status =  WERR_NOMEM;
8541                 goto done;
8542         }
8543
8544         write_ntforms(&list, count);
8545
8546         /*
8547          * ChangeID must always be set if this is a printer
8548          */
8549
8550         if ( Printer->printer_type == SPLHND_PRINTER )
8551                 status = mod_a_printer(printer, 2);
8552
8553 done:
8554         if ( printer )
8555                 free_a_printer(&printer, 2);
8556         SAFE_FREE(list);
8557
8558         return status;
8559 }
8560
8561 /****************************************************************
8562  _spoolss_DeleteForm
8563 ****************************************************************/
8564
8565 WERROR _spoolss_DeleteForm(pipes_struct *p,
8566                            struct spoolss_DeleteForm *r)
8567 {
8568         POLICY_HND *handle = r->in.handle;
8569         const char *form_name = r->in.form_name;
8570         nt_forms_struct tmpForm;
8571         int count=0;
8572         nt_forms_struct *list=NULL;
8573         Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8574         int snum;
8575         WERROR status = WERR_OK;
8576         NT_PRINTER_INFO_LEVEL *printer = NULL;
8577
8578         DEBUG(5,("_spoolss_DeleteForm\n"));
8579
8580         if (!Printer) {
8581                 DEBUG(2,("_spoolss_DeleteForm: Invalid handle (%s:%u:%u).\n",
8582                         OUR_HANDLE(handle)));
8583                 return WERR_BADFID;
8584         }
8585
8586         /* forms can be deleted on printer of on the print server handle */
8587
8588         if ( Printer->printer_type == SPLHND_PRINTER )
8589         {
8590                 if (!get_printer_snum(p,handle, &snum, NULL))
8591                         return WERR_BADFID;
8592
8593                 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8594                 if (!W_ERROR_IS_OK(status))
8595                         goto done;
8596         }
8597
8598         if ( !(Printer->access_granted & (PRINTER_ACCESS_ADMINISTER|SERVER_ACCESS_ADMINISTER)) ) {
8599                 DEBUG(2,("_spoolss_DeleteForm: denied by handle permissions.\n"));
8600                 status = WERR_ACCESS_DENIED;
8601                 goto done;
8602         }
8603
8604         /* can't delete if builtin */
8605
8606         if (get_a_builtin_ntform_by_string(form_name,&tmpForm)) {
8607                 status = WERR_INVALID_PARAM;
8608                 goto done;
8609         }
8610
8611         count = get_ntforms(&list);
8612
8613         if ( !delete_a_form(&list, form_name, &count, &status ))
8614                 goto done;
8615
8616         /*
8617          * ChangeID must always be set if this is a printer
8618          */
8619
8620         if ( Printer->printer_type == SPLHND_PRINTER )
8621                 status = mod_a_printer(printer, 2);
8622
8623 done:
8624         if ( printer )
8625                 free_a_printer(&printer, 2);
8626         SAFE_FREE(list);
8627
8628         return status;
8629 }
8630
8631 /****************************************************************
8632  _spoolss_SetForm
8633 ****************************************************************/
8634
8635 WERROR _spoolss_SetForm(pipes_struct *p,
8636                         struct spoolss_SetForm *r)
8637 {
8638         POLICY_HND *handle = r->in.handle;
8639         struct spoolss_AddFormInfo1 *form = r->in.info.info1;
8640         nt_forms_struct tmpForm;
8641         int snum;
8642         WERROR status = WERR_OK;
8643         NT_PRINTER_INFO_LEVEL *printer = NULL;
8644
8645         int count=0;
8646         nt_forms_struct *list=NULL;
8647         Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8648
8649         DEBUG(5,("_spoolss_SetForm\n"));
8650
8651         if (!Printer) {
8652                 DEBUG(2,("_spoolss_SetForm: Invalid handle (%s:%u:%u).\n",
8653                         OUR_HANDLE(handle)));
8654                 return WERR_BADFID;
8655         }
8656
8657         /* forms can be modified on printer of on the print server handle */
8658
8659         if ( Printer->printer_type == SPLHND_PRINTER )
8660         {
8661                 if (!get_printer_snum(p,handle, &snum, NULL))
8662                         return WERR_BADFID;
8663
8664                 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8665                 if (!W_ERROR_IS_OK(status))
8666                         goto done;
8667         }
8668
8669         if ( !(Printer->access_granted & (PRINTER_ACCESS_ADMINISTER|SERVER_ACCESS_ADMINISTER)) ) {
8670                 DEBUG(2,("_spoolss_SetForm: denied by handle permissions\n"));
8671                 status = WERR_ACCESS_DENIED;
8672                 goto done;
8673         }
8674
8675         /* can't set if builtin */
8676         if (get_a_builtin_ntform_by_string(form->form_name, &tmpForm)) {
8677                 status = WERR_INVALID_PARAM;
8678                 goto done;
8679         }
8680
8681         count = get_ntforms(&list);
8682         update_a_form(&list, form, count);
8683         write_ntforms(&list, count);
8684
8685         /*
8686          * ChangeID must always be set if this is a printer
8687          */
8688
8689         if ( Printer->printer_type == SPLHND_PRINTER )
8690                 status = mod_a_printer(printer, 2);
8691
8692
8693 done:
8694         if ( printer )
8695                 free_a_printer(&printer, 2);
8696         SAFE_FREE(list);
8697
8698         return status;
8699 }
8700
8701 /****************************************************************************
8702  enumprintprocessors level 1.
8703 ****************************************************************************/
8704
8705 static WERROR enumprintprocessors_level_1(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
8706 {
8707         PRINTPROCESSOR_1 *info_1=NULL;
8708         WERROR result = WERR_OK;
8709
8710         if((info_1 = SMB_MALLOC_P(PRINTPROCESSOR_1)) == NULL)
8711                 return WERR_NOMEM;
8712
8713         (*returned) = 0x1;
8714
8715         init_unistr(&info_1->name, "winprint");
8716
8717         *needed += spoolss_size_printprocessor_info_1(info_1);
8718
8719         if (*needed > offered) {
8720                 result = WERR_INSUFFICIENT_BUFFER;
8721                 goto out;
8722         }
8723
8724         if (!rpcbuf_alloc_size(buffer, *needed)) {
8725                 result = WERR_NOMEM;
8726                 goto out;
8727         }
8728
8729         smb_io_printprocessor_info_1("", buffer, info_1, 0);
8730
8731 out:
8732         SAFE_FREE(info_1);
8733
8734         if ( !W_ERROR_IS_OK(result) )
8735                 *returned = 0;
8736
8737         return result;
8738 }
8739
8740 /****************************************************************************
8741 ****************************************************************************/
8742
8743 WERROR _spoolss_enumprintprocessors(pipes_struct *p, SPOOL_Q_ENUMPRINTPROCESSORS *q_u, SPOOL_R_ENUMPRINTPROCESSORS *r_u)
8744 {
8745         uint32 level = q_u->level;
8746         RPC_BUFFER *buffer = NULL;
8747         uint32 offered = q_u->offered;
8748         uint32 *needed = &r_u->needed;
8749         uint32 *returned = &r_u->returned;
8750
8751         /* that's an [in out] buffer */
8752
8753         if (!q_u->buffer && (offered!=0)) {
8754                 return WERR_INVALID_PARAM;
8755         }
8756
8757         if (offered > MAX_RPC_DATA_SIZE) {
8758                 return WERR_INVALID_PARAM;
8759         }
8760
8761         rpcbuf_move(q_u->buffer, &r_u->buffer);
8762         buffer = r_u->buffer;
8763
8764         DEBUG(5,("spoolss_enumprintprocessors\n"));
8765
8766         /*
8767          * Enumerate the print processors ...
8768          *
8769          * Just reply with "winprint", to keep NT happy
8770          * and I can use my nice printer checker.
8771          */
8772
8773         *returned=0;
8774         *needed=0;
8775
8776         switch (level) {
8777         case 1:
8778                 return enumprintprocessors_level_1(buffer, offered, needed, returned);
8779         default:
8780                 return WERR_UNKNOWN_LEVEL;
8781         }
8782 }
8783
8784 /****************************************************************************
8785  enumprintprocdatatypes level 1.
8786 ****************************************************************************/
8787
8788 static WERROR enumprintprocdatatypes_level_1(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
8789 {
8790         PRINTPROCDATATYPE_1 *info_1=NULL;
8791         WERROR result = WERR_OK;
8792
8793         if((info_1 = SMB_MALLOC_P(PRINTPROCDATATYPE_1)) == NULL)
8794                 return WERR_NOMEM;
8795
8796         (*returned) = 0x1;
8797
8798         init_unistr(&info_1->name, "RAW");
8799
8800         *needed += spoolss_size_printprocdatatype_info_1(info_1);
8801
8802         if (*needed > offered) {
8803                 result = WERR_INSUFFICIENT_BUFFER;
8804                 goto out;
8805         }
8806
8807         if (!rpcbuf_alloc_size(buffer, *needed)) {
8808                 result = WERR_NOMEM;
8809                 goto out;
8810         }
8811
8812         smb_io_printprocdatatype_info_1("", buffer, info_1, 0);
8813
8814 out:
8815         SAFE_FREE(info_1);
8816
8817         if ( !W_ERROR_IS_OK(result) )
8818                 *returned = 0;
8819
8820         return result;
8821 }
8822
8823 /****************************************************************************
8824 ****************************************************************************/
8825
8826 WERROR _spoolss_enumprintprocdatatypes(pipes_struct *p, SPOOL_Q_ENUMPRINTPROCDATATYPES *q_u, SPOOL_R_ENUMPRINTPROCDATATYPES *r_u)
8827 {
8828         uint32 level = q_u->level;
8829         RPC_BUFFER *buffer = NULL;
8830         uint32 offered = q_u->offered;
8831         uint32 *needed = &r_u->needed;
8832         uint32 *returned = &r_u->returned;
8833
8834         /* that's an [in out] buffer */
8835
8836         if (!q_u->buffer && (offered!=0)) {
8837                 return WERR_INVALID_PARAM;
8838         }
8839
8840         if (offered > MAX_RPC_DATA_SIZE) {
8841                 return WERR_INVALID_PARAM;
8842         }
8843
8844         rpcbuf_move(q_u->buffer, &r_u->buffer);
8845         buffer = r_u->buffer;
8846
8847         DEBUG(5,("_spoolss_enumprintprocdatatypes\n"));
8848
8849         *returned=0;
8850         *needed=0;
8851
8852         switch (level) {
8853         case 1:
8854                 return enumprintprocdatatypes_level_1(buffer, offered, needed, returned);
8855         default:
8856                 return WERR_UNKNOWN_LEVEL;
8857         }
8858 }
8859
8860 /****************************************************************************
8861  enumprintmonitors level 1.
8862 ****************************************************************************/
8863
8864 static WERROR enumprintmonitors_level_1(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
8865 {
8866         PRINTMONITOR_1 *info_1;
8867         WERROR result = WERR_OK;
8868         int i;
8869
8870         if((info_1 = SMB_MALLOC_ARRAY(PRINTMONITOR_1, 2)) == NULL)
8871                 return WERR_NOMEM;
8872
8873         *returned = 2;
8874
8875         init_unistr(&(info_1[0].name), SPL_LOCAL_PORT );
8876         init_unistr(&(info_1[1].name), SPL_TCPIP_PORT );
8877
8878         for ( i=0; i<*returned; i++ ) {
8879                 *needed += spoolss_size_printmonitor_info_1(&info_1[i]);
8880         }
8881
8882         if (*needed > offered) {
8883                 result = WERR_INSUFFICIENT_BUFFER;
8884                 goto out;
8885         }
8886
8887         if (!rpcbuf_alloc_size(buffer, *needed)) {
8888                 result = WERR_NOMEM;
8889                 goto out;
8890         }
8891
8892         for ( i=0; i<*returned; i++ ) {
8893                 smb_io_printmonitor_info_1("", buffer, &info_1[i], 0);
8894         }
8895
8896 out:
8897         SAFE_FREE(info_1);
8898
8899         if ( !W_ERROR_IS_OK(result) )
8900                 *returned = 0;
8901
8902         return result;
8903 }
8904
8905 /****************************************************************************
8906  enumprintmonitors level 2.
8907 ****************************************************************************/
8908
8909 static WERROR enumprintmonitors_level_2(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
8910 {
8911         PRINTMONITOR_2 *info_2;
8912         WERROR result = WERR_OK;
8913         int i;
8914
8915         if((info_2 = SMB_MALLOC_ARRAY(PRINTMONITOR_2, 2)) == NULL)
8916                 return WERR_NOMEM;
8917
8918         *returned = 2;
8919
8920         init_unistr( &(info_2[0].name), SPL_LOCAL_PORT );
8921         init_unistr( &(info_2[0].environment), "Windows NT X86" );
8922         init_unistr( &(info_2[0].dll_name), "localmon.dll" );
8923
8924         init_unistr( &(info_2[1].name), SPL_TCPIP_PORT );
8925         init_unistr( &(info_2[1].environment), "Windows NT X86" );
8926         init_unistr( &(info_2[1].dll_name), "tcpmon.dll" );
8927
8928         for ( i=0; i<*returned; i++ ) {
8929                 *needed += spoolss_size_printmonitor_info_2(&info_2[i]);
8930         }
8931
8932         if (*needed > offered) {
8933                 result = WERR_INSUFFICIENT_BUFFER;
8934                 goto out;
8935         }
8936
8937         if (!rpcbuf_alloc_size(buffer, *needed)) {
8938                 result = WERR_NOMEM;
8939                 goto out;
8940         }
8941
8942         for ( i=0; i<*returned; i++ ) {
8943                 smb_io_printmonitor_info_2("", buffer, &info_2[i], 0);
8944         }
8945
8946 out:
8947         SAFE_FREE(info_2);
8948
8949         if ( !W_ERROR_IS_OK(result) )
8950                 *returned = 0;
8951
8952         return result;
8953 }
8954
8955 /****************************************************************************
8956 ****************************************************************************/
8957
8958 WERROR _spoolss_enumprintmonitors(pipes_struct *p, SPOOL_Q_ENUMPRINTMONITORS *q_u, SPOOL_R_ENUMPRINTMONITORS *r_u)
8959 {
8960         uint32 level = q_u->level;
8961         RPC_BUFFER *buffer = NULL;
8962         uint32 offered = q_u->offered;
8963         uint32 *needed = &r_u->needed;
8964         uint32 *returned = &r_u->returned;
8965
8966         /* that's an [in out] buffer */
8967
8968         if (!q_u->buffer && (offered!=0)) {
8969                 return WERR_INVALID_PARAM;
8970         }
8971
8972         if (offered > MAX_RPC_DATA_SIZE) {
8973                 return WERR_INVALID_PARAM;
8974         }
8975
8976         rpcbuf_move(q_u->buffer, &r_u->buffer);
8977         buffer = r_u->buffer;
8978
8979         DEBUG(5,("spoolss_enumprintmonitors\n"));
8980
8981         /*
8982          * Enumerate the print monitors ...
8983          *
8984          * Just reply with "Local Port", to keep NT happy
8985          * and I can use my nice printer checker.
8986          */
8987
8988         *returned=0;
8989         *needed=0;
8990
8991         switch (level) {
8992         case 1:
8993                 return enumprintmonitors_level_1(buffer, offered, needed, returned);
8994         case 2:
8995                 return enumprintmonitors_level_2(buffer, offered, needed, returned);
8996         default:
8997                 return WERR_UNKNOWN_LEVEL;
8998         }
8999 }
9000
9001 /****************************************************************************
9002 ****************************************************************************/
9003
9004 static WERROR getjob_level_1(print_queue_struct **queue, int count, int snum,
9005                              NT_PRINTER_INFO_LEVEL *ntprinter,
9006                              uint32 jobid, RPC_BUFFER *buffer, uint32 offered,
9007                              uint32 *needed)
9008 {
9009         int i=0;
9010         bool found=False;
9011         JOB_INFO_1 *info_1=NULL;
9012         WERROR result = WERR_OK;
9013
9014         info_1=SMB_MALLOC_P(JOB_INFO_1);
9015
9016         if (info_1 == NULL) {
9017                 return WERR_NOMEM;
9018         }
9019
9020         for (i=0; i<count && found==False; i++) {
9021                 if ((*queue)[i].job==(int)jobid)
9022                         found=True;
9023         }
9024
9025         if (found==False) {
9026                 SAFE_FREE(info_1);
9027                 /* NT treats not found as bad param... yet another bad choice */
9028                 return WERR_INVALID_PARAM;
9029         }
9030
9031         fill_job_info_1( info_1, &((*queue)[i-1]), i, snum, ntprinter );
9032
9033         *needed += spoolss_size_job_info_1(info_1);
9034
9035         if (*needed > offered) {
9036                 result = WERR_INSUFFICIENT_BUFFER;
9037                 goto out;
9038         }
9039
9040         if (!rpcbuf_alloc_size(buffer, *needed)) {
9041                 result = WERR_NOMEM;
9042                 goto out;
9043         }
9044
9045         smb_io_job_info_1("", buffer, info_1, 0);
9046
9047 out:
9048         SAFE_FREE(info_1);
9049
9050         return result;
9051 }
9052
9053 /****************************************************************************
9054 ****************************************************************************/
9055
9056 static WERROR getjob_level_2(print_queue_struct **queue, int count, int snum,
9057                              NT_PRINTER_INFO_LEVEL *ntprinter,
9058                              uint32 jobid, RPC_BUFFER *buffer, uint32 offered,
9059                              uint32 *needed)
9060 {
9061         int             i = 0;
9062         bool            found = False;
9063         JOB_INFO_2      *info_2;
9064         WERROR          result;
9065         DEVICEMODE      *devmode = NULL;
9066         NT_DEVICEMODE   *nt_devmode = NULL;
9067
9068         if ( !(info_2=SMB_MALLOC_P(JOB_INFO_2)) )
9069                 return WERR_NOMEM;
9070
9071         ZERO_STRUCTP(info_2);
9072
9073         for ( i=0; i<count && found==False; i++ )
9074         {
9075                 if ((*queue)[i].job == (int)jobid)
9076                         found = True;
9077         }
9078
9079         if ( !found ) {
9080                 /* NT treats not found as bad param... yet another bad
9081                    choice */
9082                 result = WERR_INVALID_PARAM;
9083                 goto done;
9084         }
9085
9086         /*
9087          * if the print job does not have a DEVMODE associated with it,
9088          * just use the one for the printer. A NULL devicemode is not
9089          *  a failure condition
9090          */
9091
9092         if ( !(nt_devmode=print_job_devmode( lp_const_servicename(snum), jobid )) )
9093                 devmode = construct_dev_mode(lp_const_servicename(snum));
9094         else {
9095                 if ((devmode = SMB_MALLOC_P(DEVICEMODE)) != NULL) {
9096                         ZERO_STRUCTP( devmode );
9097                         convert_nt_devicemode( devmode, nt_devmode );
9098                 }
9099         }
9100
9101         fill_job_info_2(info_2, &((*queue)[i-1]), i, snum, ntprinter, devmode);
9102
9103         *needed += spoolss_size_job_info_2(info_2);
9104
9105         if (*needed > offered) {
9106                 result = WERR_INSUFFICIENT_BUFFER;
9107                 goto done;
9108         }
9109
9110         if (!rpcbuf_alloc_size(buffer, *needed)) {
9111                 result = WERR_NOMEM;
9112                 goto done;
9113         }
9114
9115         smb_io_job_info_2("", buffer, info_2, 0);
9116
9117         result = WERR_OK;
9118
9119  done:
9120         /* Cleanup allocated memory */
9121
9122         free_job_info_2(info_2);        /* Also frees devmode */
9123         SAFE_FREE(info_2);
9124
9125         return result;
9126 }
9127
9128 /****************************************************************************
9129 ****************************************************************************/
9130
9131 WERROR _spoolss_getjob( pipes_struct *p, SPOOL_Q_GETJOB *q_u, SPOOL_R_GETJOB *r_u)
9132 {
9133         POLICY_HND *handle = &q_u->handle;
9134         uint32 jobid = q_u->jobid;
9135         uint32 level = q_u->level;
9136         RPC_BUFFER *buffer = NULL;
9137         uint32 offered = q_u->offered;
9138         uint32 *needed = &r_u->needed;
9139         WERROR          wstatus = WERR_OK;
9140         NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
9141         int snum;
9142         int count;
9143         print_queue_struct      *queue = NULL;
9144         print_status_struct prt_status;
9145
9146         /* that's an [in out] buffer */
9147
9148         if (!q_u->buffer && (offered!=0)) {
9149                 return WERR_INVALID_PARAM;
9150         }
9151
9152         if (offered > MAX_RPC_DATA_SIZE) {
9153                 return WERR_INVALID_PARAM;
9154         }
9155
9156         rpcbuf_move(q_u->buffer, &r_u->buffer);
9157         buffer = r_u->buffer;
9158
9159         DEBUG(5,("spoolss_getjob\n"));
9160
9161         *needed = 0;
9162
9163         if (!get_printer_snum(p, handle, &snum, NULL))
9164                 return WERR_BADFID;
9165
9166         wstatus = get_a_printer(NULL, &ntprinter, 2, lp_servicename(snum));
9167         if ( !W_ERROR_IS_OK(wstatus) )
9168                 return wstatus;
9169
9170         count = print_queue_status(snum, &queue, &prt_status);
9171
9172         DEBUGADD(4,("count:[%d], prt_status:[%d], [%s]\n",
9173                      count, prt_status.status, prt_status.message));
9174
9175         switch ( level ) {
9176         case 1:
9177                         wstatus = getjob_level_1(&queue, count, snum, ntprinter, jobid,
9178                                 buffer, offered, needed);
9179                         break;
9180         case 2:
9181                         wstatus = getjob_level_2(&queue, count, snum, ntprinter, jobid,
9182                                 buffer, offered, needed);
9183                         break;
9184         default:
9185                         wstatus = WERR_UNKNOWN_LEVEL;
9186                         break;
9187         }
9188
9189         SAFE_FREE(queue);
9190         free_a_printer( &ntprinter, 2 );
9191
9192         return wstatus;
9193 }
9194
9195 /****************************************************************
9196  _spoolss_GetPrinterDataEx
9197
9198  From MSDN documentation of GetPrinterDataEx: pass request
9199  to GetPrinterData if key is "PrinterDriverData".
9200 ****************************************************************/
9201
9202 WERROR _spoolss_GetPrinterDataEx(pipes_struct *p,
9203                                  struct spoolss_GetPrinterDataEx *r)
9204 {
9205         POLICY_HND      *handle = r->in.handle;
9206         uint8           *data = NULL;
9207         const char      *keyname = r->in.key_name;
9208         const char      *valuename = r->in.value_name;
9209
9210         Printer_entry   *Printer = find_printer_index_by_hnd(p, handle);
9211
9212         NT_PRINTER_INFO_LEVEL   *printer = NULL;
9213         int                     snum = 0;
9214         WERROR                  status = WERR_OK;
9215
9216         DEBUG(4,("_spoolss_GetPrinterDataEx\n"));
9217
9218         DEBUG(10, ("_spoolss_GetPrinterDataEx: key => [%s], value => [%s]\n",
9219                 keyname, valuename));
9220
9221         /* in case of problem, return some default values */
9222
9223         *r->out.needed  = 0;
9224         *r->out.type    = 0;
9225
9226         if (!Printer) {
9227                 DEBUG(2,("_spoolss_GetPrinterDataEx: "
9228                         "Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
9229                 status = WERR_BADFID;
9230                 goto done;
9231         }
9232
9233         /* Is the handle to a printer or to the server? */
9234
9235         if (Printer->printer_type == SPLHND_SERVER) {
9236                 DEBUG(10,("_spoolss_GetPrinterDataEx: "
9237                         "Not implemented for server handles yet\n"));
9238                 status = WERR_INVALID_PARAM;
9239                 goto done;
9240         }
9241
9242         if ( !get_printer_snum(p,handle, &snum, NULL) )
9243                 return WERR_BADFID;
9244
9245         status = get_a_printer(Printer, &printer, 2, lp_servicename(snum));
9246         if ( !W_ERROR_IS_OK(status) )
9247                 goto done;
9248
9249         /* check to see if the keyname is valid */
9250         if ( !strlen(keyname) ) {
9251                 status = WERR_INVALID_PARAM;
9252                 goto done;
9253         }
9254
9255         if ( lookup_printerkey( printer->info_2->data, keyname ) == -1 ) {
9256                 DEBUG(4,("_spoolss_GetPrinterDataEx: "
9257                         "Invalid keyname [%s]\n", keyname ));
9258                 free_a_printer( &printer, 2 );
9259                 status = WERR_BADFILE;
9260                 goto done;
9261         }
9262
9263         /* When given a new keyname, we should just create it */
9264
9265         status = get_printer_dataex( p->mem_ctx, printer, keyname, valuename,
9266                                      r->out.type, &data, r->out.needed,
9267                                      r->in.offered );
9268
9269         if (*r->out.needed > r->in.offered) {
9270                 status = WERR_MORE_DATA;
9271         }
9272
9273         if (W_ERROR_IS_OK(status)) {
9274                 memcpy(r->out.buffer, data, r->in.offered);
9275         }
9276
9277 done:
9278         if ( printer )
9279         free_a_printer( &printer, 2 );
9280
9281         return status;
9282 }
9283
9284 /****************************************************************
9285  _spoolss_SetPrinterDataEx
9286 ****************************************************************/
9287
9288 WERROR _spoolss_SetPrinterDataEx(pipes_struct *p,
9289                                  struct spoolss_SetPrinterDataEx *r)
9290 {
9291         POLICY_HND              *handle = r->in.handle;
9292         NT_PRINTER_INFO_LEVEL   *printer = NULL;
9293         int                     snum = 0;
9294         WERROR                  status = WERR_OK;
9295         Printer_entry           *Printer = find_printer_index_by_hnd(p, handle);
9296         char                    *oid_string;
9297
9298         DEBUG(4,("_spoolss_SetPrinterDataEx\n"));
9299
9300         /* From MSDN documentation of SetPrinterDataEx: pass request to
9301            SetPrinterData if key is "PrinterDriverData" */
9302
9303         if (!Printer) {
9304                 DEBUG(2,("_spoolss_SetPrinterDataEx: "
9305                         "Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
9306                 return WERR_BADFID;
9307         }
9308
9309         if ( Printer->printer_type == SPLHND_SERVER ) {
9310                 DEBUG(10,("_spoolss_SetPrinterDataEx: "
9311                         "Not implemented for server handles yet\n"));
9312                 return WERR_INVALID_PARAM;
9313         }
9314
9315         if ( !get_printer_snum(p,handle, &snum, NULL) )
9316                 return WERR_BADFID;
9317
9318         /*
9319          * Access check : NT returns "access denied" if you make a
9320          * SetPrinterData call without the necessary privildge.
9321          * we were originally returning OK if nothing changed
9322          * which made Win2k issue **a lot** of SetPrinterData
9323          * when connecting to a printer  --jerry
9324          */
9325
9326         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER)
9327         {
9328                 DEBUG(3, ("_spoolss_SetPrinterDataEx: "
9329                         "change denied by handle access permissions\n"));
9330                 return WERR_ACCESS_DENIED;
9331         }
9332
9333         status = get_a_printer(Printer, &printer, 2, lp_servicename(snum));
9334         if (!W_ERROR_IS_OK(status))
9335                 return status;
9336
9337         /* check for OID in valuename */
9338
9339         if ( (oid_string = strchr( r->in.value_name, ',' )) != NULL )
9340         {
9341                 *oid_string = '\0';
9342                 oid_string++;
9343         }
9344
9345         /* save the registry data */
9346
9347         status = set_printer_dataex( printer, r->in.key_name, r->in.value_name,
9348                                      r->in.type, r->in.buffer, r->in.offered );
9349
9350         if ( W_ERROR_IS_OK(status) )
9351         {
9352                 /* save the OID if one was specified */
9353                 if ( oid_string ) {
9354                         char *str = talloc_asprintf(p->mem_ctx, "%s\\%s",
9355                                 r->in.key_name, SPOOL_OID_KEY);
9356                         if (!str) {
9357                                 return WERR_NOMEM;
9358                         }
9359
9360                         /*
9361                          * I'm not checking the status here on purpose.  Don't know
9362                          * if this is right, but I'm returning the status from the
9363                          * previous set_printer_dataex() call.  I have no idea if
9364                          * this is right.    --jerry
9365                          */
9366
9367                         set_printer_dataex( printer, str, r->in.value_name,
9368                                             REG_SZ, (uint8 *)oid_string,
9369                                             strlen(oid_string)+1 );
9370                 }
9371
9372                 status = mod_a_printer(printer, 2);
9373         }
9374
9375         free_a_printer(&printer, 2);
9376
9377         return status;
9378 }
9379
9380 /****************************************************************
9381  _spoolss_DeletePrinterDataEx
9382 ****************************************************************/
9383
9384 WERROR _spoolss_DeletePrinterDataEx(pipes_struct *p,
9385                                     struct spoolss_DeletePrinterDataEx *r)
9386 {
9387         POLICY_HND      *handle = r->in.handle;
9388         NT_PRINTER_INFO_LEVEL   *printer = NULL;
9389         int             snum=0;
9390         WERROR          status = WERR_OK;
9391         Printer_entry   *Printer=find_printer_index_by_hnd(p, handle);
9392
9393         DEBUG(5,("_spoolss_DeletePrinterDataEx\n"));
9394
9395         if (!Printer) {
9396                 DEBUG(2,("_spoolss_DeletePrinterDataEx: "
9397                         "Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
9398                 return WERR_BADFID;
9399         }
9400
9401         if (!get_printer_snum(p, handle, &snum, NULL))
9402                 return WERR_BADFID;
9403
9404         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
9405                 DEBUG(3, ("_spoolss_DeletePrinterDataEx: "
9406                         "printer properties change denied by handle\n"));
9407                 return WERR_ACCESS_DENIED;
9408         }
9409
9410         if (!r->in.value_name || !r->in.key_name) {
9411                 return WERR_NOMEM;
9412         }
9413
9414         status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
9415         if (!W_ERROR_IS_OK(status))
9416                 return status;
9417
9418         status = delete_printer_dataex( printer, r->in.key_name, r->in.value_name );
9419
9420         if ( W_ERROR_IS_OK(status) )
9421                 mod_a_printer( printer, 2 );
9422
9423         free_a_printer(&printer, 2);
9424
9425         return status;
9426 }
9427
9428 /********************************************************************
9429  * spoolss_enumprinterkey
9430  ********************************************************************/
9431
9432
9433 WERROR _spoolss_enumprinterkey(pipes_struct *p, SPOOL_Q_ENUMPRINTERKEY *q_u, SPOOL_R_ENUMPRINTERKEY *r_u)
9434 {
9435         fstring         key;
9436         fstring         *keynames = NULL;
9437         uint16          *enumkeys = NULL;
9438         int             num_keys;
9439         int             printerkey_len;
9440         POLICY_HND      *handle = &q_u->handle;
9441         Printer_entry   *Printer = find_printer_index_by_hnd(p, handle);
9442         NT_PRINTER_DATA *data;
9443         NT_PRINTER_INFO_LEVEL   *printer = NULL;
9444         int             snum = 0;
9445         WERROR          status = WERR_BADFILE;
9446
9447
9448         DEBUG(4,("_spoolss_enumprinterkey\n"));
9449
9450         if (!Printer) {
9451                 DEBUG(2,("_spoolss_enumprinterkey: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
9452                 return WERR_BADFID;
9453         }
9454
9455         if ( !get_printer_snum(p,handle, &snum, NULL) )
9456                 return WERR_BADFID;
9457
9458         status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
9459         if (!W_ERROR_IS_OK(status))
9460                 return status;
9461
9462         /* get the list of subkey names */
9463
9464         unistr2_to_ascii(key, &q_u->key, sizeof(key));
9465         data = printer->info_2->data;
9466
9467         num_keys = get_printer_subkeys( data, key, &keynames );
9468
9469         if ( num_keys == -1 ) {
9470                 status = WERR_BADFILE;
9471                 goto done;
9472         }
9473
9474         printerkey_len = init_unistr_array( &enumkeys,  keynames, NULL );
9475
9476         r_u->needed = printerkey_len*2;
9477
9478         if ( q_u->size < r_u->needed ) {
9479                 status = WERR_MORE_DATA;
9480                 goto done;
9481         }
9482
9483         if (!make_spoolss_buffer5(p->mem_ctx, &r_u->keys, printerkey_len, enumkeys)) {
9484                 status = WERR_NOMEM;
9485                 goto done;
9486         }
9487
9488         status = WERR_OK;
9489
9490         if ( q_u->size < r_u->needed )
9491                 status = WERR_MORE_DATA;
9492
9493 done:
9494         free_a_printer( &printer, 2 );
9495         SAFE_FREE( keynames );
9496
9497         return status;
9498 }
9499
9500 /****************************************************************
9501  _spoolss_DeletePrinterKey
9502 ****************************************************************/
9503
9504 WERROR _spoolss_DeletePrinterKey(pipes_struct *p,
9505                                  struct spoolss_DeletePrinterKey *r)
9506 {
9507         POLICY_HND              *handle = r->in.handle;
9508         Printer_entry           *Printer = find_printer_index_by_hnd(p, handle);
9509         NT_PRINTER_INFO_LEVEL   *printer = NULL;
9510         int                     snum=0;
9511         WERROR                  status;
9512
9513         DEBUG(5,("_spoolss_DeletePrinterKey\n"));
9514
9515         if (!Printer) {
9516                 DEBUG(2,("_spoolss_DeletePrinterKey: Invalid handle (%s:%u:%u).\n",
9517                         OUR_HANDLE(handle)));
9518                 return WERR_BADFID;
9519         }
9520
9521         /* if keyname == NULL, return error */
9522
9523         if ( !r->in.key_name )
9524                 return WERR_INVALID_PARAM;
9525
9526         if (!get_printer_snum(p, handle, &snum, NULL))
9527                 return WERR_BADFID;
9528
9529         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
9530                 DEBUG(3, ("_spoolss_DeletePrinterKey: "
9531                         "printer properties change denied by handle\n"));
9532                 return WERR_ACCESS_DENIED;
9533         }
9534
9535         status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
9536         if (!W_ERROR_IS_OK(status))
9537                 return status;
9538
9539         /* delete the key and all subneys */
9540
9541         status = delete_all_printer_data( printer->info_2, r->in.key_name );
9542
9543         if ( W_ERROR_IS_OK(status) )
9544                 status = mod_a_printer(printer, 2);
9545
9546         free_a_printer( &printer, 2 );
9547
9548         return status;
9549 }
9550
9551
9552 /********************************************************************
9553  * spoolss_enumprinterdataex
9554  ********************************************************************/
9555
9556 WERROR _spoolss_enumprinterdataex(pipes_struct *p, SPOOL_Q_ENUMPRINTERDATAEX *q_u, SPOOL_R_ENUMPRINTERDATAEX *r_u)
9557 {
9558         POLICY_HND      *handle = &q_u->handle;
9559         uint32          in_size = q_u->size;
9560         uint32          num_entries,
9561                         needed;
9562         NT_PRINTER_INFO_LEVEL   *printer = NULL;
9563         PRINTER_ENUM_VALUES     *enum_values = NULL;
9564         NT_PRINTER_DATA         *p_data;
9565         fstring         key;
9566         Printer_entry   *Printer = find_printer_index_by_hnd(p, handle);
9567         int             snum;
9568         WERROR          result;
9569         int             key_index;
9570         int             i;
9571         REGISTRY_VALUE  *val;
9572         char            *value_name;
9573         uint32          data_len;
9574
9575
9576         DEBUG(4,("_spoolss_enumprinterdataex\n"));
9577
9578         if (!Printer) {
9579                 DEBUG(2,("_spoolss_enumprinterdataex: Invalid handle (%s:%u:%u1<).\n", OUR_HANDLE(handle)));
9580                 return WERR_BADFID;
9581         }
9582
9583         /*
9584          * first check for a keyname of NULL or "".  Win2k seems to send
9585          * this a lot and we should send back WERR_INVALID_PARAM
9586          * no need to spend time looking up the printer in this case.
9587          * --jerry
9588          */
9589
9590         unistr2_to_ascii(key, &q_u->key, sizeof(key));
9591         if ( !strlen(key) ) {
9592                 result = WERR_INVALID_PARAM;
9593                 goto done;
9594         }
9595
9596         /* get the printer off of disk */
9597
9598         if (!get_printer_snum(p,handle, &snum, NULL))
9599                 return WERR_BADFID;
9600
9601         ZERO_STRUCT(printer);
9602         result = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
9603         if (!W_ERROR_IS_OK(result))
9604                 return result;
9605
9606         /* now look for a match on the key name */
9607
9608         p_data = printer->info_2->data;
9609
9610         unistr2_to_ascii(key, &q_u->key, sizeof(key));
9611         if ( (key_index = lookup_printerkey( p_data, key)) == -1  )
9612         {
9613                 DEBUG(10,("_spoolss_enumprinterdataex: Unknown keyname [%s]\n", key));
9614                 result = WERR_INVALID_PARAM;
9615                 goto done;
9616         }
9617
9618         result = WERR_OK;
9619         needed = 0;
9620
9621         /* allocate the memory for the array of pointers -- if necessary */
9622
9623         num_entries = regval_ctr_numvals( p_data->keys[key_index].values );
9624         if ( num_entries )
9625         {
9626                 if ( (enum_values=TALLOC_ARRAY(p->mem_ctx, PRINTER_ENUM_VALUES, num_entries)) == NULL )
9627                 {
9628                         DEBUG(0,("_spoolss_enumprinterdataex: talloc() failed to allocate memory for [%lu] bytes!\n",
9629                                 (unsigned long)num_entries*sizeof(PRINTER_ENUM_VALUES)));
9630                         result = WERR_NOMEM;
9631                         goto done;
9632                 }
9633
9634                 memset( enum_values, 0x0, num_entries*sizeof(PRINTER_ENUM_VALUES) );
9635         }
9636
9637         /*
9638          * loop through all params and build the array to pass
9639          * back to the  client
9640          */
9641
9642         for ( i=0; i<num_entries; i++ )
9643         {
9644                 /* lookup the registry value */
9645
9646                 val = regval_ctr_specific_value( p_data->keys[key_index].values, i );
9647                 DEBUG(10,("retrieved value number [%d] [%s]\n", i, regval_name(val) ));
9648
9649                 /* copy the data */
9650
9651                 value_name = regval_name( val );
9652                 init_unistr( &enum_values[i].valuename, value_name );
9653                 enum_values[i].value_len = (strlen(value_name)+1) * 2;
9654                 enum_values[i].type      = regval_type( val );
9655
9656                 data_len = regval_size( val );
9657                 if ( data_len ) {
9658                         if ( !(enum_values[i].data = (uint8 *)TALLOC_MEMDUP(p->mem_ctx, regval_data_p(val), data_len)) )
9659                         {
9660                                 DEBUG(0,("TALLOC_MEMDUP failed to allocate memory [data_len=%d] for data!\n",
9661                                         data_len ));
9662                                 result = WERR_NOMEM;
9663                                 goto done;
9664                         }
9665                 }
9666                 enum_values[i].data_len = data_len;
9667
9668                 /* keep track of the size of the array in bytes */
9669
9670                 needed += spoolss_size_printer_enum_values(&enum_values[i]);
9671         }
9672
9673         /* housekeeping information in the reply */
9674
9675         /* Fix from Martin Zielinski <mz@seh.de> - ensure
9676          * the hand marshalled container size is a multiple
9677          * of 4 bytes for RPC alignment.
9678          */
9679
9680         if (needed % 4) {
9681                 needed += 4-(needed % 4);
9682         }
9683
9684         r_u->needed     = needed;
9685         r_u->returned   = num_entries;
9686
9687         if (needed > in_size) {
9688                 result = WERR_MORE_DATA;
9689                 goto done;
9690         }
9691
9692         /* copy data into the reply */
9693
9694         /* mz: Vista x64 returns 0x6f7 (The stub received bad data), if the
9695            response buffer size is != the offered buffer size
9696
9697                 r_u->ctr.size           = r_u->needed;
9698         */
9699         r_u->ctr.size           = in_size;
9700
9701         r_u->ctr.size_of_array  = r_u->returned;
9702         r_u->ctr.values         = enum_values;
9703
9704 done:
9705         if ( printer )
9706         free_a_printer(&printer, 2);
9707
9708         return result;
9709 }
9710
9711 /****************************************************************************
9712 ****************************************************************************/
9713
9714 static WERROR getprintprocessordirectory_level_1(TALLOC_CTX *mem_ctx,
9715                                                  const char *servername,
9716                                                  const char *environment,
9717                                                  struct spoolss_PrintProcessorDirectoryInfo1 *info1,
9718                                                  uint32_t offered,
9719                                                  uint32_t *needed)
9720 {
9721         const char *long_archi = SPOOLSS_ARCHITECTURE_NT_X86;
9722         const char *short_archi;
9723
9724         if (environment) {
9725                 long_archi = environment;
9726         }
9727
9728         short_archi = get_short_archi(long_archi);
9729         if (!short_archi) {
9730                 return WERR_INVALID_ENVIRONMENT;
9731         }
9732
9733         /* I think this should look like this - gd
9734         info1->directory_name = talloc_asprintf(mem_ctx,
9735                 "C:\\WINNT\\System32\\spool\\PRTPROCS\\%s", short_archi);
9736         */
9737         info1->directory_name = talloc_strdup(mem_ctx,
9738                 "C:\\WINNT\\System32\\spool\\PRTPROCS\\W32X86");
9739
9740         if (!info1->directory_name) {
9741                 return WERR_NOMEM;
9742         }
9743
9744         *needed += ndr_size_spoolss_PrintProcessorDirectoryInfo1(info1, NULL, 0);
9745
9746         if (*needed > offered) {
9747                 return WERR_INSUFFICIENT_BUFFER;
9748         }
9749
9750         return WERR_OK;
9751 }
9752
9753 /****************************************************************
9754  _spoolss_GetPrintProcessorDirectory
9755 ****************************************************************/
9756
9757 WERROR _spoolss_GetPrintProcessorDirectory(pipes_struct *p,
9758                                            struct spoolss_GetPrintProcessorDirectory *r)
9759 {
9760         WERROR result;
9761
9762         /* that's an [in out] buffer */
9763
9764         if (!r->in.buffer && (r->in.offered != 0)) {
9765                 return WERR_INVALID_PARAM;
9766         }
9767
9768         if (r->in.offered > MAX_RPC_DATA_SIZE) {
9769                 return WERR_INVALID_PARAM;
9770         }
9771
9772         DEBUG(5,("_spoolss_GetPrintProcessorDirectory\n"));
9773
9774         *r->out.needed = 0;
9775
9776         switch (r->in.level) {
9777         case 1:
9778                 result = getprintprocessordirectory_level_1(p->mem_ctx,
9779                                                             r->in.server,
9780                                                             r->in.environment,
9781                                                             &r->out.info->info1,
9782                                                             r->in.offered,
9783                                                             r->out.needed);
9784                 if (!W_ERROR_IS_OK(result)) {
9785                         TALLOC_FREE(r->out.info);
9786                 }
9787                 break;
9788         default:
9789                 result = WERR_UNKNOWN_LEVEL;
9790         }
9791
9792         return result;
9793 }
9794
9795 /*******************************************************************
9796  ********************************************************************/
9797
9798 static bool push_monitorui_buf(TALLOC_CTX *mem_ctx, DATA_BLOB *buf,
9799                                const char *dllname)
9800 {
9801         enum ndr_err_code ndr_err;
9802         struct spoolss_MonitorUi ui;
9803
9804         ui.dll_name = dllname;
9805
9806         ndr_err = ndr_push_struct_blob(buf, mem_ctx, NULL, &ui,
9807                        (ndr_push_flags_fn_t)ndr_push_spoolss_MonitorUi);
9808         if (NDR_ERR_CODE_IS_SUCCESS(ndr_err) && (DEBUGLEVEL >= 10)) {
9809                 NDR_PRINT_DEBUG(spoolss_MonitorUi, &ui);
9810         }
9811         return NDR_ERR_CODE_IS_SUCCESS(ndr_err);
9812 }
9813
9814 /*******************************************************************
9815  Streams the monitor UI DLL name in UNICODE
9816 *******************************************************************/
9817
9818 static WERROR xcvtcp_monitorui(TALLOC_CTX *mem_ctx,
9819                                NT_USER_TOKEN *token, DATA_BLOB *in,
9820                                DATA_BLOB *out, uint32_t *needed)
9821 {
9822         const char *dllname = "tcpmonui.dll";
9823
9824         *needed = (strlen(dllname)+1) * 2;
9825
9826         if (out->length < *needed) {
9827                 return WERR_INSUFFICIENT_BUFFER;
9828         }
9829
9830         if (!push_monitorui_buf(mem_ctx, out, dllname)) {
9831                 return WERR_NOMEM;
9832         }
9833
9834         return WERR_OK;
9835 }
9836
9837 /*******************************************************************
9838  ********************************************************************/
9839
9840 static bool pull_port_data_1(TALLOC_CTX *mem_ctx,
9841                              struct spoolss_PortData1 *port1,
9842                              const DATA_BLOB *buf)
9843 {
9844         enum ndr_err_code ndr_err;
9845         ndr_err = ndr_pull_struct_blob(buf, mem_ctx, NULL, port1,
9846                        (ndr_pull_flags_fn_t)ndr_pull_spoolss_PortData1);
9847         if (NDR_ERR_CODE_IS_SUCCESS(ndr_err) && (DEBUGLEVEL >= 10)) {
9848                 NDR_PRINT_DEBUG(spoolss_PortData1, port1);
9849         }
9850         return NDR_ERR_CODE_IS_SUCCESS(ndr_err);
9851 }
9852
9853 /*******************************************************************
9854  ********************************************************************/
9855
9856 static bool pull_port_data_2(TALLOC_CTX *mem_ctx,
9857                              struct spoolss_PortData2 *port2,
9858                              const DATA_BLOB *buf)
9859 {
9860         enum ndr_err_code ndr_err;
9861         ndr_err = ndr_pull_struct_blob(buf, mem_ctx, NULL, port2,
9862                        (ndr_pull_flags_fn_t)ndr_pull_spoolss_PortData2);
9863         if (NDR_ERR_CODE_IS_SUCCESS(ndr_err) && (DEBUGLEVEL >= 10)) {
9864                 NDR_PRINT_DEBUG(spoolss_PortData2, port2);
9865         }
9866         return NDR_ERR_CODE_IS_SUCCESS(ndr_err);
9867 }
9868
9869 /*******************************************************************
9870  Create a new TCP/IP port
9871 *******************************************************************/
9872
9873 static WERROR xcvtcp_addport(TALLOC_CTX *mem_ctx,
9874                              NT_USER_TOKEN *token, DATA_BLOB *in,
9875                              DATA_BLOB *out, uint32_t *needed)
9876 {
9877         struct spoolss_PortData1 port1;
9878         struct spoolss_PortData2 port2;
9879         char *device_uri = NULL;
9880         uint32_t version;
9881
9882         const char *portname;
9883         const char *hostaddress;
9884         const char *queue;
9885         uint32_t port_number;
9886         uint32_t protocol;
9887
9888         /* peek for spoolss_PortData version */
9889
9890         if (!in || (in->length < (128 + 4))) {
9891                 return WERR_GENERAL_FAILURE;
9892         }
9893
9894         version = IVAL(in->data, 128);
9895
9896         switch (version) {
9897                 case 1:
9898                         ZERO_STRUCT(port1);
9899
9900                         if (!pull_port_data_1(mem_ctx, &port1, in)) {
9901                                 return WERR_NOMEM;
9902                         }
9903
9904                         portname        = port1.portname;
9905                         hostaddress     = port1.hostaddress;
9906                         queue           = port1.queue;
9907                         protocol        = port1.protocol;
9908                         port_number     = port1.port_number;
9909
9910                         break;
9911                 case 2:
9912                         ZERO_STRUCT(port2);
9913
9914                         if (!pull_port_data_2(mem_ctx, &port2, in)) {
9915                                 return WERR_NOMEM;
9916                         }
9917
9918                         portname        = port2.portname;
9919                         hostaddress     = port2.hostaddress;
9920                         queue           = port2.queue;
9921                         protocol        = port2.protocol;
9922                         port_number     = port2.port_number;
9923
9924                         break;
9925                 default:
9926                         DEBUG(1,("xcvtcp_addport: "
9927                                 "unknown version of port_data: %d\n", version));
9928                         return WERR_UNKNOWN_PORT;
9929         }
9930
9931         /* create the device URI and call the add_port_hook() */
9932
9933         switch (protocol) {
9934         case PROTOCOL_RAWTCP_TYPE:
9935                 device_uri = talloc_asprintf(mem_ctx,
9936                                 "socket://%s:%d/", hostaddress,
9937                                 port_number);
9938                 break;
9939
9940         case PROTOCOL_LPR_TYPE:
9941                 device_uri = talloc_asprintf(mem_ctx,
9942                         "lpr://%s/%s", hostaddress, queue );
9943                 break;
9944
9945         default:
9946                 return WERR_UNKNOWN_PORT;
9947         }
9948
9949         if (!device_uri) {
9950                 return WERR_NOMEM;
9951         }
9952
9953         return add_port_hook(mem_ctx, token, portname, device_uri);
9954 }
9955
9956 /*******************************************************************
9957 *******************************************************************/
9958
9959 struct xcv_api_table xcvtcp_cmds[] = {
9960         { "MonitorUI",  xcvtcp_monitorui },
9961         { "AddPort",    xcvtcp_addport},
9962         { NULL,         NULL }
9963 };
9964
9965 static WERROR process_xcvtcp_command(TALLOC_CTX *mem_ctx,
9966                                      NT_USER_TOKEN *token, const char *command,
9967                                      DATA_BLOB *inbuf,
9968                                      DATA_BLOB *outbuf,
9969                                      uint32_t *needed )
9970 {
9971         int i;
9972
9973         DEBUG(10,("process_xcvtcp_command: Received command \"%s\"\n", command));
9974
9975         for ( i=0; xcvtcp_cmds[i].name; i++ ) {
9976                 if ( strcmp( command, xcvtcp_cmds[i].name ) == 0 )
9977                         return xcvtcp_cmds[i].fn(mem_ctx, token, inbuf, outbuf, needed);
9978         }
9979
9980         return WERR_BADFUNC;
9981 }
9982
9983 /*******************************************************************
9984 *******************************************************************/
9985 #if 0   /* don't support management using the "Local Port" monitor */
9986
9987 static WERROR xcvlocal_monitorui(TALLOC_CTX *mem_ctx,
9988                                  NT_USER_TOKEN *token, DATA_BLOB *in,
9989                                  DATA_BLOB *out, uint32_t *needed)
9990 {
9991         const char *dllname = "localui.dll";
9992
9993         *needed = (strlen(dllname)+1) * 2;
9994
9995         if (out->length < *needed) {
9996                 return WERR_INSUFFICIENT_BUFFER;
9997         }
9998
9999         if (!push_monitorui_buf(mem_ctx, out, dllname)) {
10000                 return WERR_NOMEM;
10001         }
10002
10003         return WERR_OK;
10004 }
10005
10006 /*******************************************************************
10007 *******************************************************************/
10008
10009 struct xcv_api_table xcvlocal_cmds[] = {
10010         { "MonitorUI",  xcvlocal_monitorui },
10011         { NULL,         NULL }
10012 };
10013 #else
10014 struct xcv_api_table xcvlocal_cmds[] = {
10015         { NULL,         NULL }
10016 };
10017 #endif
10018
10019
10020
10021 /*******************************************************************
10022 *******************************************************************/
10023
10024 static WERROR process_xcvlocal_command(TALLOC_CTX *mem_ctx,
10025                                        NT_USER_TOKEN *token, const char *command,
10026                                        DATA_BLOB *inbuf, DATA_BLOB *outbuf,
10027                                        uint32_t *needed)
10028 {
10029         int i;
10030
10031         DEBUG(10,("process_xcvlocal_command: Received command \"%s\"\n", command));
10032
10033         for ( i=0; xcvlocal_cmds[i].name; i++ ) {
10034                 if ( strcmp( command, xcvlocal_cmds[i].name ) == 0 )
10035                         return xcvlocal_cmds[i].fn(mem_ctx, token, inbuf, outbuf, needed);
10036         }
10037         return WERR_BADFUNC;
10038 }
10039
10040 /****************************************************************
10041  _spoolss_XcvData
10042 ****************************************************************/
10043
10044 WERROR _spoolss_XcvData(pipes_struct *p,
10045                         struct spoolss_XcvData *r)
10046 {
10047         Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
10048         DATA_BLOB out_data;
10049         WERROR werror;
10050
10051         if (!Printer) {
10052                 DEBUG(2,("_spoolss_XcvData: Invalid handle (%s:%u:%u).\n",
10053                         OUR_HANDLE(r->in.handle)));
10054                 return WERR_BADFID;
10055         }
10056
10057         /* Has to be a handle to the TCP/IP port monitor */
10058
10059         if ( !(Printer->printer_type & (SPLHND_PORTMON_LOCAL|SPLHND_PORTMON_TCP)) ) {
10060                 DEBUG(2,("_spoolss_XcvData: Call only valid for Port Monitors\n"));
10061                 return WERR_BADFID;
10062         }
10063
10064         /* requires administrative access to the server */
10065
10066         if ( !(Printer->access_granted & SERVER_ACCESS_ADMINISTER) ) {
10067                 DEBUG(2,("_spoolss_XcvData: denied by handle permissions.\n"));
10068                 return WERR_ACCESS_DENIED;
10069         }
10070
10071         /* Allocate the outgoing buffer */
10072
10073         if (r->in.out_data_size) {
10074                 out_data = data_blob_talloc_zero(p->mem_ctx, r->in.out_data_size);
10075                 if (out_data.data == NULL) {
10076                         return WERR_NOMEM;
10077                 }
10078         }
10079
10080         switch ( Printer->printer_type ) {
10081         case SPLHND_PORTMON_TCP:
10082                 werror = process_xcvtcp_command(p->mem_ctx,
10083                                                 p->server_info->ptok,
10084                                                 r->in.function_name,
10085                                                 &r->in.in_data, &out_data,
10086                                                 r->out.needed);
10087                 break;
10088         case SPLHND_PORTMON_LOCAL:
10089                 werror = process_xcvlocal_command(p->mem_ctx,
10090                                                   p->server_info->ptok,
10091                                                   r->in.function_name,
10092                                                   &r->in.in_data, &out_data,
10093                                                   r->out.needed);
10094                 break;
10095         default:
10096                 werror = WERR_INVALID_PRINT_MONITOR;
10097         }
10098
10099         if (!W_ERROR_IS_OK(werror)) {
10100                 return werror;
10101         }
10102
10103         *r->out.status_code = 0;
10104
10105         memcpy(r->out.out_data, out_data.data, out_data.length);
10106
10107         return WERR_OK;
10108 }
10109
10110 /****************************************************************
10111  _spoolss_AddPrintProcessor
10112 ****************************************************************/
10113
10114 WERROR _spoolss_AddPrintProcessor(pipes_struct *p,
10115                                   struct spoolss_AddPrintProcessor *r)
10116 {
10117         /* for now, just indicate success and ignore the add.  We'll
10118            automatically set the winprint processor for printer
10119            entries later.  Used to debug the LexMark Optra S 1855 PCL
10120            driver --jerry */
10121
10122         return WERR_OK;
10123 }
10124
10125 /****************************************************************
10126  _spoolss_EnumPrinters
10127 ****************************************************************/
10128
10129 WERROR _spoolss_EnumPrinters(pipes_struct *p,
10130                              struct spoolss_EnumPrinters *r)
10131 {
10132         p->rng_fault_state = true;
10133         return WERR_NOT_SUPPORTED;
10134 }
10135
10136 /****************************************************************
10137  _spoolss_GetJob
10138 ****************************************************************/
10139
10140 WERROR _spoolss_GetJob(pipes_struct *p,
10141                        struct spoolss_GetJob *r)
10142 {
10143         p->rng_fault_state = true;
10144         return WERR_NOT_SUPPORTED;
10145 }
10146
10147 /****************************************************************
10148  _spoolss_EnumJobs
10149 ****************************************************************/
10150
10151 WERROR _spoolss_EnumJobs(pipes_struct *p,
10152                          struct spoolss_EnumJobs *r)
10153 {
10154         p->rng_fault_state = true;
10155         return WERR_NOT_SUPPORTED;
10156 }
10157
10158 /****************************************************************
10159  _spoolss_AddPrinter
10160 ****************************************************************/
10161
10162 WERROR _spoolss_AddPrinter(pipes_struct *p,
10163                            struct spoolss_AddPrinter *r)
10164 {
10165         p->rng_fault_state = true;
10166         return WERR_NOT_SUPPORTED;
10167 }
10168
10169 /****************************************************************
10170  _spoolss_GetPrinter
10171 ****************************************************************/
10172
10173 WERROR _spoolss_GetPrinter(pipes_struct *p,
10174                            struct spoolss_GetPrinter *r)
10175 {
10176         p->rng_fault_state = true;
10177         return WERR_NOT_SUPPORTED;
10178 }
10179
10180 /****************************************************************
10181  _spoolss_EnumPrinterDrivers
10182 ****************************************************************/
10183
10184 WERROR _spoolss_EnumPrinterDrivers(pipes_struct *p,
10185                                    struct spoolss_EnumPrinterDrivers *r)
10186 {
10187         p->rng_fault_state = true;
10188         return WERR_NOT_SUPPORTED;
10189 }
10190
10191 /****************************************************************
10192  _spoolss_GetPrinterDriver
10193 ****************************************************************/
10194
10195 WERROR _spoolss_GetPrinterDriver(pipes_struct *p,
10196                                  struct spoolss_GetPrinterDriver *r)
10197 {
10198         p->rng_fault_state = true;
10199         return WERR_NOT_SUPPORTED;
10200 }
10201
10202 /****************************************************************
10203  _spoolss_EnumPrintProcessors
10204 ****************************************************************/
10205
10206 WERROR _spoolss_EnumPrintProcessors(pipes_struct *p,
10207                                     struct spoolss_EnumPrintProcessors *r)
10208 {
10209         p->rng_fault_state = true;
10210         return WERR_NOT_SUPPORTED;
10211 }
10212
10213 /****************************************************************
10214  _spoolss_ReadPrinter
10215 ****************************************************************/
10216
10217 WERROR _spoolss_ReadPrinter(pipes_struct *p,
10218                             struct spoolss_ReadPrinter *r)
10219 {
10220         p->rng_fault_state = true;
10221         return WERR_NOT_SUPPORTED;
10222 }
10223
10224 /****************************************************************
10225  _spoolss_GetPrinterData
10226 ****************************************************************/
10227
10228 WERROR _spoolss_GetPrinterData(pipes_struct *p,
10229                                struct spoolss_GetPrinterData *r)
10230 {
10231         p->rng_fault_state = true;
10232         return WERR_NOT_SUPPORTED;
10233 }
10234
10235 /****************************************************************
10236  _spoolss_SetPrinterData
10237 ****************************************************************/
10238
10239 WERROR _spoolss_SetPrinterData(pipes_struct *p,
10240                                struct spoolss_SetPrinterData *r)
10241 {
10242         p->rng_fault_state = true;
10243         return WERR_NOT_SUPPORTED;
10244 }
10245
10246 /****************************************************************
10247  _spoolss_WaitForPrinterChange
10248 ****************************************************************/
10249
10250 WERROR _spoolss_WaitForPrinterChange(pipes_struct *p,
10251                                      struct spoolss_WaitForPrinterChange *r)
10252 {
10253         p->rng_fault_state = true;
10254         return WERR_NOT_SUPPORTED;
10255 }
10256
10257 /****************************************************************
10258  _spoolss_EnumForms
10259 ****************************************************************/
10260
10261 WERROR _spoolss_EnumForms(pipes_struct *p,
10262                           struct spoolss_EnumForms *r)
10263 {
10264         p->rng_fault_state = true;
10265         return WERR_NOT_SUPPORTED;
10266 }
10267
10268 /****************************************************************
10269  _spoolss_EnumPorts
10270 ****************************************************************/
10271
10272 WERROR _spoolss_EnumPorts(pipes_struct *p,
10273                           struct spoolss_EnumPorts *r)
10274 {
10275         p->rng_fault_state = true;
10276         return WERR_NOT_SUPPORTED;
10277 }
10278
10279 /****************************************************************
10280  _spoolss_EnumMonitors
10281 ****************************************************************/
10282
10283 WERROR _spoolss_EnumMonitors(pipes_struct *p,
10284                              struct spoolss_EnumMonitors *r)
10285 {
10286         p->rng_fault_state = true;
10287         return WERR_NOT_SUPPORTED;
10288 }
10289
10290 /****************************************************************
10291  _spoolss_AddPort
10292 ****************************************************************/
10293
10294 WERROR _spoolss_AddPort(pipes_struct *p,
10295                         struct spoolss_AddPort *r)
10296 {
10297         p->rng_fault_state = true;
10298         return WERR_NOT_SUPPORTED;
10299 }
10300
10301 /****************************************************************
10302  _spoolss_ConfigurePort
10303 ****************************************************************/
10304
10305 WERROR _spoolss_ConfigurePort(pipes_struct *p,
10306                               struct spoolss_ConfigurePort *r)
10307 {
10308         p->rng_fault_state = true;
10309         return WERR_NOT_SUPPORTED;
10310 }
10311
10312 /****************************************************************
10313  _spoolss_DeletePort
10314 ****************************************************************/
10315
10316 WERROR _spoolss_DeletePort(pipes_struct *p,
10317                            struct spoolss_DeletePort *r)
10318 {
10319         p->rng_fault_state = true;
10320         return WERR_NOT_SUPPORTED;
10321 }
10322
10323 /****************************************************************
10324  _spoolss_CreatePrinterIC
10325 ****************************************************************/
10326
10327 WERROR _spoolss_CreatePrinterIC(pipes_struct *p,
10328                                 struct spoolss_CreatePrinterIC *r)
10329 {
10330         p->rng_fault_state = true;
10331         return WERR_NOT_SUPPORTED;
10332 }
10333
10334 /****************************************************************
10335  _spoolss_PlayGDIScriptOnPrinterIC
10336 ****************************************************************/
10337
10338 WERROR _spoolss_PlayGDIScriptOnPrinterIC(pipes_struct *p,
10339                                          struct spoolss_PlayGDIScriptOnPrinterIC *r)
10340 {
10341         p->rng_fault_state = true;
10342         return WERR_NOT_SUPPORTED;
10343 }
10344
10345 /****************************************************************
10346  _spoolss_DeletePrinterIC
10347 ****************************************************************/
10348
10349 WERROR _spoolss_DeletePrinterIC(pipes_struct *p,
10350                                 struct spoolss_DeletePrinterIC *r)
10351 {
10352         p->rng_fault_state = true;
10353         return WERR_NOT_SUPPORTED;
10354 }
10355
10356 /****************************************************************
10357  _spoolss_AddPrinterConnection
10358 ****************************************************************/
10359
10360 WERROR _spoolss_AddPrinterConnection(pipes_struct *p,
10361                                      struct spoolss_AddPrinterConnection *r)
10362 {
10363         p->rng_fault_state = true;
10364         return WERR_NOT_SUPPORTED;
10365 }
10366
10367 /****************************************************************
10368  _spoolss_DeletePrinterConnection
10369 ****************************************************************/
10370
10371 WERROR _spoolss_DeletePrinterConnection(pipes_struct *p,
10372                                         struct spoolss_DeletePrinterConnection *r)
10373 {
10374         p->rng_fault_state = true;
10375         return WERR_NOT_SUPPORTED;
10376 }
10377
10378 /****************************************************************
10379  _spoolss_PrinterMessageBox
10380 ****************************************************************/
10381
10382 WERROR _spoolss_PrinterMessageBox(pipes_struct *p,
10383                                   struct spoolss_PrinterMessageBox *r)
10384 {
10385         p->rng_fault_state = true;
10386         return WERR_NOT_SUPPORTED;
10387 }
10388
10389 /****************************************************************
10390  _spoolss_AddMonitor
10391 ****************************************************************/
10392
10393 WERROR _spoolss_AddMonitor(pipes_struct *p,
10394                            struct spoolss_AddMonitor *r)
10395 {
10396         p->rng_fault_state = true;
10397         return WERR_NOT_SUPPORTED;
10398 }
10399
10400 /****************************************************************
10401  _spoolss_DeleteMonitor
10402 ****************************************************************/
10403
10404 WERROR _spoolss_DeleteMonitor(pipes_struct *p,
10405                               struct spoolss_DeleteMonitor *r)
10406 {
10407         p->rng_fault_state = true;
10408         return WERR_NOT_SUPPORTED;
10409 }
10410
10411 /****************************************************************
10412  _spoolss_DeletePrintProcessor
10413 ****************************************************************/
10414
10415 WERROR _spoolss_DeletePrintProcessor(pipes_struct *p,
10416                                      struct spoolss_DeletePrintProcessor *r)
10417 {
10418         p->rng_fault_state = true;
10419         return WERR_NOT_SUPPORTED;
10420 }
10421
10422 /****************************************************************
10423  _spoolss_AddPrintProvidor
10424 ****************************************************************/
10425
10426 WERROR _spoolss_AddPrintProvidor(pipes_struct *p,
10427                                  struct spoolss_AddPrintProvidor *r)
10428 {
10429         p->rng_fault_state = true;
10430         return WERR_NOT_SUPPORTED;
10431 }
10432
10433 /****************************************************************
10434  _spoolss_DeletePrintProvidor
10435 ****************************************************************/
10436
10437 WERROR _spoolss_DeletePrintProvidor(pipes_struct *p,
10438                                     struct spoolss_DeletePrintProvidor *r)
10439 {
10440         p->rng_fault_state = true;
10441         return WERR_NOT_SUPPORTED;
10442 }
10443
10444 /****************************************************************
10445  _spoolss_EnumPrintProcDataTypes
10446 ****************************************************************/
10447
10448 WERROR _spoolss_EnumPrintProcDataTypes(pipes_struct *p,
10449                                        struct spoolss_EnumPrintProcDataTypes *r)
10450 {
10451         p->rng_fault_state = true;
10452         return WERR_NOT_SUPPORTED;
10453 }
10454
10455 /****************************************************************
10456  _spoolss_GetPrinterDriver2
10457 ****************************************************************/
10458
10459 WERROR _spoolss_GetPrinterDriver2(pipes_struct *p,
10460                                   struct spoolss_GetPrinterDriver2 *r)
10461 {
10462         p->rng_fault_state = true;
10463         return WERR_NOT_SUPPORTED;
10464 }
10465
10466 /****************************************************************
10467  _spoolss_FindFirstPrinterChangeNotification
10468 ****************************************************************/
10469
10470 WERROR _spoolss_FindFirstPrinterChangeNotification(pipes_struct *p,
10471                                                    struct spoolss_FindFirstPrinterChangeNotification *r)
10472 {
10473         p->rng_fault_state = true;
10474         return WERR_NOT_SUPPORTED;
10475 }
10476
10477 /****************************************************************
10478  _spoolss_FindNextPrinterChangeNotification
10479 ****************************************************************/
10480
10481 WERROR _spoolss_FindNextPrinterChangeNotification(pipes_struct *p,
10482                                                   struct spoolss_FindNextPrinterChangeNotification *r)
10483 {
10484         p->rng_fault_state = true;
10485         return WERR_NOT_SUPPORTED;
10486 }
10487
10488 /****************************************************************
10489  _spoolss_RouterFindFirstPrinterChangeNotificationOld
10490 ****************************************************************/
10491
10492 WERROR _spoolss_RouterFindFirstPrinterChangeNotificationOld(pipes_struct *p,
10493                                                             struct spoolss_RouterFindFirstPrinterChangeNotificationOld *r)
10494 {
10495         p->rng_fault_state = true;
10496         return WERR_NOT_SUPPORTED;
10497 }
10498
10499 /****************************************************************
10500  _spoolss_ReplyOpenPrinter
10501 ****************************************************************/
10502
10503 WERROR _spoolss_ReplyOpenPrinter(pipes_struct *p,
10504                                  struct spoolss_ReplyOpenPrinter *r)
10505 {
10506         p->rng_fault_state = true;
10507         return WERR_NOT_SUPPORTED;
10508 }
10509
10510 /****************************************************************
10511  _spoolss_RouterReplyPrinter
10512 ****************************************************************/
10513
10514 WERROR _spoolss_RouterReplyPrinter(pipes_struct *p,
10515                                    struct spoolss_RouterReplyPrinter *r)
10516 {
10517         p->rng_fault_state = true;
10518         return WERR_NOT_SUPPORTED;
10519 }
10520
10521 /****************************************************************
10522  _spoolss_ReplyClosePrinter
10523 ****************************************************************/
10524
10525 WERROR _spoolss_ReplyClosePrinter(pipes_struct *p,
10526                                   struct spoolss_ReplyClosePrinter *r)
10527 {
10528         p->rng_fault_state = true;
10529         return WERR_NOT_SUPPORTED;
10530 }
10531
10532 /****************************************************************
10533  _spoolss_AddPortEx
10534 ****************************************************************/
10535
10536 WERROR _spoolss_AddPortEx(pipes_struct *p,
10537                           struct spoolss_AddPortEx *r)
10538 {
10539         p->rng_fault_state = true;
10540         return WERR_NOT_SUPPORTED;
10541 }
10542
10543 /****************************************************************
10544  _spoolss_RouterFindFirstPrinterChangeNotification
10545 ****************************************************************/
10546
10547 WERROR _spoolss_RouterFindFirstPrinterChangeNotification(pipes_struct *p,
10548                                                          struct spoolss_RouterFindFirstPrinterChangeNotification *r)
10549 {
10550         p->rng_fault_state = true;
10551         return WERR_NOT_SUPPORTED;
10552 }
10553
10554 /****************************************************************
10555  _spoolss_SpoolerInit
10556 ****************************************************************/
10557
10558 WERROR _spoolss_SpoolerInit(pipes_struct *p,
10559                             struct spoolss_SpoolerInit *r)
10560 {
10561         p->rng_fault_state = true;
10562         return WERR_NOT_SUPPORTED;
10563 }
10564
10565 /****************************************************************
10566  _spoolss_ResetPrinterEx
10567 ****************************************************************/
10568
10569 WERROR _spoolss_ResetPrinterEx(pipes_struct *p,
10570                                struct spoolss_ResetPrinterEx *r)
10571 {
10572         p->rng_fault_state = true;
10573         return WERR_NOT_SUPPORTED;
10574 }
10575
10576 /****************************************************************
10577  _spoolss_RemoteFindFirstPrinterChangeNotifyEx
10578 ****************************************************************/
10579
10580 WERROR _spoolss_RemoteFindFirstPrinterChangeNotifyEx(pipes_struct *p,
10581                                                      struct spoolss_RemoteFindFirstPrinterChangeNotifyEx *r)
10582 {
10583         p->rng_fault_state = true;
10584         return WERR_NOT_SUPPORTED;
10585 }
10586
10587 /****************************************************************
10588  _spoolss_RouterReplyPrinterEx
10589 ****************************************************************/
10590
10591 WERROR _spoolss_RouterReplyPrinterEx(pipes_struct *p,
10592                                      struct spoolss_RouterReplyPrinterEx *r)
10593 {
10594         p->rng_fault_state = true;
10595         return WERR_NOT_SUPPORTED;
10596 }
10597
10598 /****************************************************************
10599  _spoolss_44
10600 ****************************************************************/
10601
10602 WERROR _spoolss_44(pipes_struct *p,
10603                    struct spoolss_44 *r)
10604 {
10605         p->rng_fault_state = true;
10606         return WERR_NOT_SUPPORTED;
10607 }
10608
10609 /****************************************************************
10610  _spoolss_47
10611 ****************************************************************/
10612
10613 WERROR _spoolss_47(pipes_struct *p,
10614                    struct spoolss_47 *r)
10615 {
10616         p->rng_fault_state = true;
10617         return WERR_NOT_SUPPORTED;
10618 }
10619
10620 /****************************************************************
10621  _spoolss_EnumPrinterData
10622 ****************************************************************/
10623
10624 WERROR _spoolss_EnumPrinterData(pipes_struct *p,
10625                                 struct spoolss_EnumPrinterData *r)
10626 {
10627         p->rng_fault_state = true;
10628         return WERR_NOT_SUPPORTED;
10629 }
10630
10631 /****************************************************************
10632  _spoolss_4a
10633 ****************************************************************/
10634
10635 WERROR _spoolss_4a(pipes_struct *p,
10636                    struct spoolss_4a *r)
10637 {
10638         p->rng_fault_state = true;
10639         return WERR_NOT_SUPPORTED;
10640 }
10641
10642 /****************************************************************
10643  _spoolss_4b
10644 ****************************************************************/
10645
10646 WERROR _spoolss_4b(pipes_struct *p,
10647                    struct spoolss_4b *r)
10648 {
10649         p->rng_fault_state = true;
10650         return WERR_NOT_SUPPORTED;
10651 }
10652
10653 /****************************************************************
10654  _spoolss_4c
10655 ****************************************************************/
10656
10657 WERROR _spoolss_4c(pipes_struct *p,
10658                    struct spoolss_4c *r)
10659 {
10660         p->rng_fault_state = true;
10661         return WERR_NOT_SUPPORTED;
10662 }
10663
10664 /****************************************************************
10665  _spoolss_EnumPrinterDataEx
10666 ****************************************************************/
10667
10668 WERROR _spoolss_EnumPrinterDataEx(pipes_struct *p,
10669                                   struct spoolss_EnumPrinterDataEx *r)
10670 {
10671         p->rng_fault_state = true;
10672         return WERR_NOT_SUPPORTED;
10673 }
10674
10675 /****************************************************************
10676  _spoolss_EnumPrinterKey
10677 ****************************************************************/
10678
10679 WERROR _spoolss_EnumPrinterKey(pipes_struct *p,
10680                                struct spoolss_EnumPrinterKey *r)
10681 {
10682         p->rng_fault_state = true;
10683         return WERR_NOT_SUPPORTED;
10684 }
10685
10686 /****************************************************************
10687  _spoolss_53
10688 ****************************************************************/
10689
10690 WERROR _spoolss_53(pipes_struct *p,
10691                    struct spoolss_53 *r)
10692 {
10693         p->rng_fault_state = true;
10694         return WERR_NOT_SUPPORTED;
10695 }
10696
10697 /****************************************************************
10698  _spoolss_55
10699 ****************************************************************/
10700
10701 WERROR _spoolss_55(pipes_struct *p,
10702                    struct spoolss_55 *r)
10703 {
10704         p->rng_fault_state = true;
10705         return WERR_NOT_SUPPORTED;
10706 }
10707
10708 /****************************************************************
10709  _spoolss_56
10710 ****************************************************************/
10711
10712 WERROR _spoolss_56(pipes_struct *p,
10713                    struct spoolss_56 *r)
10714 {
10715         p->rng_fault_state = true;
10716         return WERR_NOT_SUPPORTED;
10717 }
10718
10719 /****************************************************************
10720  _spoolss_57
10721 ****************************************************************/
10722
10723 WERROR _spoolss_57(pipes_struct *p,
10724                    struct spoolss_57 *r)
10725 {
10726         p->rng_fault_state = true;
10727         return WERR_NOT_SUPPORTED;
10728 }
10729
10730 /****************************************************************
10731  _spoolss_5a
10732 ****************************************************************/
10733
10734 WERROR _spoolss_5a(pipes_struct *p,
10735                    struct spoolss_5a *r)
10736 {
10737         p->rng_fault_state = true;
10738         return WERR_NOT_SUPPORTED;
10739 }
10740
10741 /****************************************************************
10742  _spoolss_5b
10743 ****************************************************************/
10744
10745 WERROR _spoolss_5b(pipes_struct *p,
10746                    struct spoolss_5b *r)
10747 {
10748         p->rng_fault_state = true;
10749         return WERR_NOT_SUPPORTED;
10750 }
10751
10752 /****************************************************************
10753  _spoolss_5c
10754 ****************************************************************/
10755
10756 WERROR _spoolss_5c(pipes_struct *p,
10757                    struct spoolss_5c *r)
10758 {
10759         p->rng_fault_state = true;
10760         return WERR_NOT_SUPPORTED;
10761 }
10762
10763 /****************************************************************
10764  _spoolss_5d
10765 ****************************************************************/
10766
10767 WERROR _spoolss_5d(pipes_struct *p,
10768                    struct spoolss_5d *r)
10769 {
10770         p->rng_fault_state = true;
10771         return WERR_NOT_SUPPORTED;
10772 }
10773
10774 /****************************************************************
10775  _spoolss_5e
10776 ****************************************************************/
10777
10778 WERROR _spoolss_5e(pipes_struct *p,
10779                    struct spoolss_5e *r)
10780 {
10781         p->rng_fault_state = true;
10782         return WERR_NOT_SUPPORTED;
10783 }
10784
10785 /****************************************************************
10786  _spoolss_5f
10787 ****************************************************************/
10788
10789 WERROR _spoolss_5f(pipes_struct *p,
10790                    struct spoolss_5f *r)
10791 {
10792         p->rng_fault_state = true;
10793         return WERR_NOT_SUPPORTED;
10794 }
10795