s3-spoolss: add support for "AddPort" via _spoolss_XcvData for Vista.
[vlendec/samba-autobuild/.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 /* Convert a notification message to a SPOOL_NOTIFY_INFO_DATA struct */
677
678 static void notify_one_value(struct spoolss_notify_msg *msg,
679                              SPOOL_NOTIFY_INFO_DATA *data,
680                              TALLOC_CTX *mem_ctx)
681 {
682         data->notify_data.value[0] = msg->notify.value[0];
683         data->notify_data.value[1] = 0;
684 }
685
686 static void notify_string(struct spoolss_notify_msg *msg,
687                           SPOOL_NOTIFY_INFO_DATA *data,
688                           TALLOC_CTX *mem_ctx)
689 {
690         UNISTR2 unistr;
691
692         /* The length of the message includes the trailing \0 */
693
694         init_unistr2(&unistr, msg->notify.data, UNI_STR_TERMINATE);
695
696         data->notify_data.data.length = msg->len * 2;
697         data->notify_data.data.string = TALLOC_ARRAY(mem_ctx, uint16, msg->len);
698
699         if (!data->notify_data.data.string) {
700                 data->notify_data.data.length = 0;
701                 return;
702         }
703
704         memcpy(data->notify_data.data.string, unistr.buffer, msg->len * 2);
705 }
706
707 static void notify_system_time(struct spoolss_notify_msg *msg,
708                                SPOOL_NOTIFY_INFO_DATA *data,
709                                TALLOC_CTX *mem_ctx)
710 {
711         SYSTEMTIME systime;
712         prs_struct ps;
713
714         if (msg->len != sizeof(time_t)) {
715                 DEBUG(5, ("notify_system_time: received wrong sized message (%d)\n",
716                           msg->len));
717                 return;
718         }
719
720         if (!prs_init(&ps, RPC_MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL)) {
721                 DEBUG(5, ("notify_system_time: prs_init() failed\n"));
722                 return;
723         }
724
725         if (!make_systemtime(&systime, gmtime((time_t *)msg->notify.data))) {
726                 DEBUG(5, ("notify_system_time: unable to make systemtime\n"));
727                 prs_mem_free(&ps);
728                 return;
729         }
730
731         if (!spoolss_io_system_time("", &ps, 0, &systime)) {
732                 prs_mem_free(&ps);
733                 return;
734         }
735
736         data->notify_data.data.length = prs_offset(&ps);
737         if (prs_offset(&ps)) {
738                 data->notify_data.data.string = (uint16 *)
739                         TALLOC(mem_ctx, prs_offset(&ps));
740                 if (!data->notify_data.data.string) {
741                         prs_mem_free(&ps);
742                         return;
743                 }
744                 prs_copy_all_data_out((char *)data->notify_data.data.string, &ps);
745         } else {
746                 data->notify_data.data.string = NULL;
747         }
748
749         prs_mem_free(&ps);
750 }
751
752 struct notify2_message_table {
753         const char *name;
754         void (*fn)(struct spoolss_notify_msg *msg,
755                    SPOOL_NOTIFY_INFO_DATA *data, TALLOC_CTX *mem_ctx);
756 };
757
758 static struct notify2_message_table printer_notify_table[] = {
759         /* 0x00 */ { "PRINTER_NOTIFY_SERVER_NAME", notify_string },
760         /* 0x01 */ { "PRINTER_NOTIFY_PRINTER_NAME", notify_string },
761         /* 0x02 */ { "PRINTER_NOTIFY_SHARE_NAME", notify_string },
762         /* 0x03 */ { "PRINTER_NOTIFY_PORT_NAME", notify_string },
763         /* 0x04 */ { "PRINTER_NOTIFY_DRIVER_NAME", notify_string },
764         /* 0x05 */ { "PRINTER_NOTIFY_COMMENT", notify_string },
765         /* 0x06 */ { "PRINTER_NOTIFY_LOCATION", notify_string },
766         /* 0x07 */ { "PRINTER_NOTIFY_DEVMODE", NULL },
767         /* 0x08 */ { "PRINTER_NOTIFY_SEPFILE", notify_string },
768         /* 0x09 */ { "PRINTER_NOTIFY_PRINT_PROCESSOR", notify_string },
769         /* 0x0a */ { "PRINTER_NOTIFY_PARAMETERS", NULL },
770         /* 0x0b */ { "PRINTER_NOTIFY_DATATYPE", notify_string },
771         /* 0x0c */ { "PRINTER_NOTIFY_SECURITY_DESCRIPTOR", NULL },
772         /* 0x0d */ { "PRINTER_NOTIFY_ATTRIBUTES", notify_one_value },
773         /* 0x0e */ { "PRINTER_NOTIFY_PRIORITY", notify_one_value },
774         /* 0x0f */ { "PRINTER_NOTIFY_DEFAULT_PRIORITY", NULL },
775         /* 0x10 */ { "PRINTER_NOTIFY_START_TIME", NULL },
776         /* 0x11 */ { "PRINTER_NOTIFY_UNTIL_TIME", NULL },
777         /* 0x12 */ { "PRINTER_NOTIFY_STATUS", notify_one_value },
778 };
779
780 static struct notify2_message_table job_notify_table[] = {
781         /* 0x00 */ { "JOB_NOTIFY_PRINTER_NAME", NULL },
782         /* 0x01 */ { "JOB_NOTIFY_MACHINE_NAME", NULL },
783         /* 0x02 */ { "JOB_NOTIFY_PORT_NAME", NULL },
784         /* 0x03 */ { "JOB_NOTIFY_USER_NAME", notify_string },
785         /* 0x04 */ { "JOB_NOTIFY_NOTIFY_NAME", NULL },
786         /* 0x05 */ { "JOB_NOTIFY_DATATYPE", NULL },
787         /* 0x06 */ { "JOB_NOTIFY_PRINT_PROCESSOR", NULL },
788         /* 0x07 */ { "JOB_NOTIFY_PARAMETERS", NULL },
789         /* 0x08 */ { "JOB_NOTIFY_DRIVER_NAME", NULL },
790         /* 0x09 */ { "JOB_NOTIFY_DEVMODE", NULL },
791         /* 0x0a */ { "JOB_NOTIFY_STATUS", notify_one_value },
792         /* 0x0b */ { "JOB_NOTIFY_STATUS_STRING", NULL },
793         /* 0x0c */ { "JOB_NOTIFY_SECURITY_DESCRIPTOR", NULL },
794         /* 0x0d */ { "JOB_NOTIFY_DOCUMENT", notify_string },
795         /* 0x0e */ { "JOB_NOTIFY_PRIORITY", NULL },
796         /* 0x0f */ { "JOB_NOTIFY_POSITION", NULL },
797         /* 0x10 */ { "JOB_NOTIFY_SUBMITTED", notify_system_time },
798         /* 0x11 */ { "JOB_NOTIFY_START_TIME", NULL },
799         /* 0x12 */ { "JOB_NOTIFY_UNTIL_TIME", NULL },
800         /* 0x13 */ { "JOB_NOTIFY_TIME", NULL },
801         /* 0x14 */ { "JOB_NOTIFY_TOTAL_PAGES", notify_one_value },
802         /* 0x15 */ { "JOB_NOTIFY_PAGES_PRINTED", NULL },
803         /* 0x16 */ { "JOB_NOTIFY_TOTAL_BYTES", notify_one_value },
804         /* 0x17 */ { "JOB_NOTIFY_BYTES_PRINTED", NULL },
805 };
806
807
808 /***********************************************************************
809  Allocate talloc context for container object
810  **********************************************************************/
811
812 static void notify_msg_ctr_init( SPOOLSS_NOTIFY_MSG_CTR *ctr )
813 {
814         if ( !ctr )
815                 return;
816
817         ctr->ctx = talloc_init("notify_msg_ctr_init %p", ctr);
818
819         return;
820 }
821
822 /***********************************************************************
823  release all allocated memory and zero out structure
824  **********************************************************************/
825
826 static void notify_msg_ctr_destroy( SPOOLSS_NOTIFY_MSG_CTR *ctr )
827 {
828         if ( !ctr )
829                 return;
830
831         if ( ctr->ctx )
832                 talloc_destroy(ctr->ctx);
833
834         ZERO_STRUCTP(ctr);
835
836         return;
837 }
838
839 /***********************************************************************
840  **********************************************************************/
841
842 static TALLOC_CTX* notify_ctr_getctx( SPOOLSS_NOTIFY_MSG_CTR *ctr )
843 {
844         if ( !ctr )
845                 return NULL;
846
847         return ctr->ctx;
848 }
849
850 /***********************************************************************
851  **********************************************************************/
852
853 static SPOOLSS_NOTIFY_MSG_GROUP* notify_ctr_getgroup( SPOOLSS_NOTIFY_MSG_CTR *ctr, uint32 idx )
854 {
855         if ( !ctr || !ctr->msg_groups )
856                 return NULL;
857
858         if ( idx >= ctr->num_groups )
859                 return NULL;
860
861         return &ctr->msg_groups[idx];
862
863 }
864
865 /***********************************************************************
866  How many groups of change messages do we have ?
867  **********************************************************************/
868
869 static int notify_msg_ctr_numgroups( SPOOLSS_NOTIFY_MSG_CTR *ctr )
870 {
871         if ( !ctr )
872                 return 0;
873
874         return ctr->num_groups;
875 }
876
877 /***********************************************************************
878  Add a SPOOLSS_NOTIFY_MSG_CTR to the correct group
879  **********************************************************************/
880
881 static int notify_msg_ctr_addmsg( SPOOLSS_NOTIFY_MSG_CTR *ctr, SPOOLSS_NOTIFY_MSG *msg )
882 {
883         SPOOLSS_NOTIFY_MSG_GROUP        *groups = NULL;
884         SPOOLSS_NOTIFY_MSG_GROUP        *msg_grp = NULL;
885         SPOOLSS_NOTIFY_MSG              *msg_list = NULL;
886         int                             i, new_slot;
887
888         if ( !ctr || !msg )
889                 return 0;
890
891         /* loop over all groups looking for a matching printer name */
892
893         for ( i=0; i<ctr->num_groups; i++ ) {
894                 if ( strcmp(ctr->msg_groups[i].printername, msg->printer) == 0 )
895                         break;
896         }
897
898         /* add a new group? */
899
900         if ( i == ctr->num_groups ) {
901                 ctr->num_groups++;
902
903                 if ( !(groups = TALLOC_REALLOC_ARRAY( ctr->ctx, ctr->msg_groups, SPOOLSS_NOTIFY_MSG_GROUP, ctr->num_groups)) ) {
904                         DEBUG(0,("notify_msg_ctr_addmsg: talloc_realloc() failed!\n"));
905                         return 0;
906                 }
907                 ctr->msg_groups = groups;
908
909                 /* clear the new entry and set the printer name */
910
911                 ZERO_STRUCT( ctr->msg_groups[ctr->num_groups-1] );
912                 fstrcpy( ctr->msg_groups[ctr->num_groups-1].printername, msg->printer );
913         }
914
915         /* add the change messages; 'i' is the correct index now regardless */
916
917         msg_grp = &ctr->msg_groups[i];
918
919         msg_grp->num_msgs++;
920
921         if ( !(msg_list = TALLOC_REALLOC_ARRAY( ctr->ctx, msg_grp->msgs, SPOOLSS_NOTIFY_MSG, msg_grp->num_msgs )) ) {
922                 DEBUG(0,("notify_msg_ctr_addmsg: talloc_realloc() failed for new message [%d]!\n", msg_grp->num_msgs));
923                 return 0;
924         }
925         msg_grp->msgs = msg_list;
926
927         new_slot = msg_grp->num_msgs-1;
928         memcpy( &msg_grp->msgs[new_slot], msg, sizeof(SPOOLSS_NOTIFY_MSG) );
929
930         /* need to allocate own copy of data */
931
932         if ( msg->len != 0 )
933                 msg_grp->msgs[new_slot].notify.data = (char *)
934                         TALLOC_MEMDUP( ctr->ctx, msg->notify.data, msg->len );
935
936         return ctr->num_groups;
937 }
938
939 /***********************************************************************
940  Send a change notication message on all handles which have a call
941  back registered
942  **********************************************************************/
943
944 static void send_notify2_changes( SPOOLSS_NOTIFY_MSG_CTR *ctr, uint32 idx )
945 {
946         Printer_entry            *p;
947         TALLOC_CTX               *mem_ctx = notify_ctr_getctx( ctr );
948         SPOOLSS_NOTIFY_MSG_GROUP *msg_group = notify_ctr_getgroup( ctr, idx );
949         SPOOLSS_NOTIFY_MSG       *messages;
950         int                      sending_msg_count;
951
952         if ( !msg_group ) {
953                 DEBUG(5,("send_notify2_changes() called with no msg group!\n"));
954                 return;
955         }
956
957         messages = msg_group->msgs;
958
959         if ( !messages ) {
960                 DEBUG(5,("send_notify2_changes() called with no messages!\n"));
961                 return;
962         }
963
964         DEBUG(8,("send_notify2_changes: Enter...[%s]\n", msg_group->printername));
965
966         /* loop over all printers */
967
968         for (p = printers_list; p; p = p->next) {
969                 SPOOL_NOTIFY_INFO_DATA *data;
970                 uint32  data_len = 0;
971                 uint32  id;
972                 int     i;
973
974                 /* Is there notification on this handle? */
975
976                 if ( !p->notify.client_connected )
977                         continue;
978
979                 DEBUG(10,("Client connected! [\\\\%s\\%s]\n", p->servername, p->sharename));
980
981                 /* For this printer?  Print servers always receive
982                    notifications. */
983
984                 if ( ( p->printer_type == SPLHND_PRINTER )  &&
985                     ( !strequal(msg_group->printername, p->sharename) ) )
986                         continue;
987
988                 DEBUG(10,("Our printer\n"));
989
990                 /* allocate the max entries possible */
991
992                 data = TALLOC_ARRAY( mem_ctx, SPOOL_NOTIFY_INFO_DATA, msg_group->num_msgs);
993                 if (!data) {
994                         return;
995                 }
996
997                 ZERO_STRUCTP(data);
998
999                 /* build the array of change notifications */
1000
1001                 sending_msg_count = 0;
1002
1003                 for ( i=0; i<msg_group->num_msgs; i++ ) {
1004                         SPOOLSS_NOTIFY_MSG      *msg = &messages[i];
1005
1006                         /* Are we monitoring this event? */
1007
1008                         if (!is_monitoring_event(p, msg->type, msg->field))
1009                                 continue;
1010
1011                         sending_msg_count++;
1012
1013
1014                         DEBUG(10,("process_notify2_message: Sending message type [0x%x] field [0x%2x] for printer [%s]\n",
1015                                 msg->type, msg->field, p->sharename));
1016
1017                         /*
1018                          * if the is a printer notification handle and not a job notification
1019                          * type, then set the id to 0.  Other wise just use what was specified
1020                          * in the message.
1021                          *
1022                          * When registering change notification on a print server handle
1023                          * we always need to send back the id (snum) matching the printer
1024                          * for which the change took place.  For change notify registered
1025                          * on a printer handle, this does not matter and the id should be 0.
1026                          *
1027                          * --jerry
1028                          */
1029
1030                         if ( ( p->printer_type == SPLHND_PRINTER ) && ( msg->type == PRINTER_NOTIFY_TYPE ) )
1031                                 id = 0;
1032                         else
1033                                 id = msg->id;
1034
1035
1036                         /* Convert unix jobid to smb jobid */
1037
1038                         if (msg->flags & SPOOLSS_NOTIFY_MSG_UNIX_JOBID) {
1039                                 id = sysjob_to_jobid(msg->id);
1040
1041                                 if (id == -1) {
1042                                         DEBUG(3, ("no such unix jobid %d\n", msg->id));
1043                                         goto done;
1044                                 }
1045                         }
1046
1047                         construct_info_data( &data[data_len], msg->type, msg->field, id );
1048
1049                         switch(msg->type) {
1050                         case PRINTER_NOTIFY_TYPE:
1051                                 if ( printer_notify_table[msg->field].fn )
1052                                         printer_notify_table[msg->field].fn(msg, &data[data_len], mem_ctx);
1053                                 break;
1054
1055                         case JOB_NOTIFY_TYPE:
1056                                 if ( job_notify_table[msg->field].fn )
1057                                         job_notify_table[msg->field].fn(msg, &data[data_len], mem_ctx);
1058                                 break;
1059
1060                         default:
1061                                 DEBUG(5, ("Unknown notification type %d\n", msg->type));
1062                                 goto done;
1063                         }
1064
1065                         data_len++;
1066                 }
1067
1068                 if ( sending_msg_count ) {
1069                         rpccli_spoolss_rrpcn( notify_cli_pipe, mem_ctx, &p->notify.client_hnd,
1070                                         data_len, data, p->notify.change, 0 );
1071                 }
1072         }
1073
1074 done:
1075         DEBUG(8,("send_notify2_changes: Exit...\n"));
1076         return;
1077 }
1078
1079 /***********************************************************************
1080  **********************************************************************/
1081
1082 static bool notify2_unpack_msg( SPOOLSS_NOTIFY_MSG *msg, struct timeval *tv, void *buf, size_t len )
1083 {
1084
1085         uint32 tv_sec, tv_usec;
1086         size_t offset = 0;
1087
1088         /* Unpack message */
1089
1090         offset += tdb_unpack((uint8 *)buf + offset, len - offset, "f",
1091                              msg->printer);
1092
1093         offset += tdb_unpack((uint8 *)buf + offset, len - offset, "ddddddd",
1094                                 &tv_sec, &tv_usec,
1095                                 &msg->type, &msg->field, &msg->id, &msg->len, &msg->flags);
1096
1097         if (msg->len == 0)
1098                 tdb_unpack((uint8 *)buf + offset, len - offset, "dd",
1099                            &msg->notify.value[0], &msg->notify.value[1]);
1100         else
1101                 tdb_unpack((uint8 *)buf + offset, len - offset, "B",
1102                            &msg->len, &msg->notify.data);
1103
1104         DEBUG(3, ("notify2_unpack_msg: got NOTIFY2 message for printer %s, jobid %u type %d, field 0x%02x, flags 0x%04x\n",
1105                   msg->printer, (unsigned int)msg->id, msg->type, msg->field, msg->flags));
1106
1107         tv->tv_sec = tv_sec;
1108         tv->tv_usec = tv_usec;
1109
1110         if (msg->len == 0)
1111                 DEBUG(3, ("notify2_unpack_msg: value1 = %d, value2 = %d\n", msg->notify.value[0],
1112                           msg->notify.value[1]));
1113         else
1114                 dump_data(3, (uint8 *)msg->notify.data, msg->len);
1115
1116         return True;
1117 }
1118
1119 /********************************************************************
1120  Receive a notify2 message list
1121  ********************************************************************/
1122
1123 static void receive_notify2_message_list(struct messaging_context *msg,
1124                                          void *private_data,
1125                                          uint32_t msg_type,
1126                                          struct server_id server_id,
1127                                          DATA_BLOB *data)
1128 {
1129         size_t                  msg_count, i;
1130         char                    *buf = (char *)data->data;
1131         char                    *msg_ptr;
1132         size_t                  msg_len;
1133         SPOOLSS_NOTIFY_MSG      notify;
1134         SPOOLSS_NOTIFY_MSG_CTR  messages;
1135         int                     num_groups;
1136
1137         if (data->length < 4) {
1138                 DEBUG(0,("receive_notify2_message_list: bad message format (len < 4)!\n"));
1139                 return;
1140         }
1141
1142         msg_count = IVAL(buf, 0);
1143         msg_ptr = buf + 4;
1144
1145         DEBUG(5, ("receive_notify2_message_list: got %lu messages in list\n", (unsigned long)msg_count));
1146
1147         if (msg_count == 0) {
1148                 DEBUG(0,("receive_notify2_message_list: bad message format (msg_count == 0) !\n"));
1149                 return;
1150         }
1151
1152         /* initialize the container */
1153
1154         ZERO_STRUCT( messages );
1155         notify_msg_ctr_init( &messages );
1156
1157         /*
1158          * build message groups for each printer identified
1159          * in a change_notify msg.  Remember that a PCN message
1160          * includes the handle returned for the srv_spoolss_replyopenprinter()
1161          * call.  Therefore messages are grouped according to printer handle.
1162          */
1163
1164         for ( i=0; i<msg_count; i++ ) {
1165                 struct timeval msg_tv;
1166
1167                 if (msg_ptr + 4 - buf > data->length) {
1168                         DEBUG(0,("receive_notify2_message_list: bad message format (len > buf_size) !\n"));
1169                         return;
1170                 }
1171
1172                 msg_len = IVAL(msg_ptr,0);
1173                 msg_ptr += 4;
1174
1175                 if (msg_ptr + msg_len - buf > data->length) {
1176                         DEBUG(0,("receive_notify2_message_list: bad message format (bad len) !\n"));
1177                         return;
1178                 }
1179
1180                 /* unpack messages */
1181
1182                 ZERO_STRUCT( notify );
1183                 notify2_unpack_msg( &notify, &msg_tv, msg_ptr, msg_len );
1184                 msg_ptr += msg_len;
1185
1186                 /* add to correct list in container */
1187
1188                 notify_msg_ctr_addmsg( &messages, &notify );
1189
1190                 /* free memory that might have been allocated by notify2_unpack_msg() */
1191
1192                 if ( notify.len != 0 )
1193                         SAFE_FREE( notify.notify.data );
1194         }
1195
1196         /* process each group of messages */
1197
1198         num_groups = notify_msg_ctr_numgroups( &messages );
1199         for ( i=0; i<num_groups; i++ )
1200                 send_notify2_changes( &messages, i );
1201
1202
1203         /* cleanup */
1204
1205         DEBUG(10,("receive_notify2_message_list: processed %u messages\n", (uint32)msg_count ));
1206
1207         notify_msg_ctr_destroy( &messages );
1208
1209         return;
1210 }
1211
1212 /********************************************************************
1213  Send a message to ourself about new driver being installed
1214  so we can upgrade the information for each printer bound to this
1215  driver
1216  ********************************************************************/
1217
1218 static bool srv_spoolss_drv_upgrade_printer(char* drivername)
1219 {
1220         int len = strlen(drivername);
1221
1222         if (!len)
1223                 return False;
1224
1225         DEBUG(10,("srv_spoolss_drv_upgrade_printer: Sending message about driver upgrade [%s]\n",
1226                 drivername));
1227
1228         messaging_send_buf(smbd_messaging_context(), procid_self(),
1229                            MSG_PRINTER_DRVUPGRADE,
1230                            (uint8 *)drivername, len+1);
1231
1232         return True;
1233 }
1234
1235 /**********************************************************************
1236  callback to receive a MSG_PRINTER_DRVUPGRADE message and interate
1237  over all printers, upgrading ones as necessary
1238  **********************************************************************/
1239
1240 void do_drv_upgrade_printer(struct messaging_context *msg,
1241                             void *private_data,
1242                             uint32_t msg_type,
1243                             struct server_id server_id,
1244                             DATA_BLOB *data)
1245 {
1246         fstring drivername;
1247         int snum;
1248         int n_services = lp_numservices();
1249         size_t len;
1250
1251         len = MIN(data->length,sizeof(drivername)-1);
1252         strncpy(drivername, (const char *)data->data, len);
1253
1254         DEBUG(10,("do_drv_upgrade_printer: Got message for new driver [%s]\n", drivername ));
1255
1256         /* Iterate the printer list */
1257
1258         for (snum=0; snum<n_services; snum++)
1259         {
1260                 if (lp_snum_ok(snum) && lp_print_ok(snum) )
1261                 {
1262                         WERROR result;
1263                         NT_PRINTER_INFO_LEVEL *printer = NULL;
1264
1265                         result = get_a_printer(NULL, &printer, 2, lp_const_servicename(snum));
1266                         if (!W_ERROR_IS_OK(result))
1267                                 continue;
1268
1269                         if (printer && printer->info_2 && !strcmp(drivername, printer->info_2->drivername))
1270                         {
1271                                 DEBUG(6,("Updating printer [%s]\n", printer->info_2->printername));
1272
1273                                 /* all we care about currently is the change_id */
1274
1275                                 result = mod_a_printer(printer, 2);
1276                                 if (!W_ERROR_IS_OK(result)) {
1277                                         DEBUG(3,("do_drv_upgrade_printer: mod_a_printer() failed with status [%s]\n",
1278                                                 win_errstr(result)));
1279                                 }
1280                         }
1281
1282                         free_a_printer(&printer, 2);
1283                 }
1284         }
1285
1286         /* all done */
1287 }
1288
1289 /********************************************************************
1290  Update the cache for all printq's with a registered client
1291  connection
1292  ********************************************************************/
1293
1294 void update_monitored_printq_cache( void )
1295 {
1296         Printer_entry *printer = printers_list;
1297         int snum;
1298
1299         /* loop through all printers and update the cache where
1300            client_connected == True */
1301         while ( printer )
1302         {
1303                 if ( (printer->printer_type == SPLHND_PRINTER)
1304                         && printer->notify.client_connected )
1305                 {
1306                         snum = print_queue_snum(printer->sharename);
1307                         print_queue_status( snum, NULL, NULL );
1308                 }
1309
1310                 printer = printer->next;
1311         }
1312
1313         return;
1314 }
1315 /********************************************************************
1316  Send a message to ourself about new driver being installed
1317  so we can upgrade the information for each printer bound to this
1318  driver
1319  ********************************************************************/
1320
1321 static bool srv_spoolss_reset_printerdata(char* drivername)
1322 {
1323         int len = strlen(drivername);
1324
1325         if (!len)
1326                 return False;
1327
1328         DEBUG(10,("srv_spoolss_reset_printerdata: Sending message about resetting printerdata [%s]\n",
1329                 drivername));
1330
1331         messaging_send_buf(smbd_messaging_context(), procid_self(),
1332                            MSG_PRINTERDATA_INIT_RESET,
1333                            (uint8 *)drivername, len+1);
1334
1335         return True;
1336 }
1337
1338 /**********************************************************************
1339  callback to receive a MSG_PRINTERDATA_INIT_RESET message and interate
1340  over all printers, resetting printer data as neessary
1341  **********************************************************************/
1342
1343 void reset_all_printerdata(struct messaging_context *msg,
1344                            void *private_data,
1345                            uint32_t msg_type,
1346                            struct server_id server_id,
1347                            DATA_BLOB *data)
1348 {
1349         fstring drivername;
1350         int snum;
1351         int n_services = lp_numservices();
1352         size_t len;
1353
1354         len = MIN( data->length, sizeof(drivername)-1 );
1355         strncpy( drivername, (const char *)data->data, len );
1356
1357         DEBUG(10,("reset_all_printerdata: Got message for new driver [%s]\n", drivername ));
1358
1359         /* Iterate the printer list */
1360
1361         for ( snum=0; snum<n_services; snum++ )
1362         {
1363                 if ( lp_snum_ok(snum) && lp_print_ok(snum) )
1364                 {
1365                         WERROR result;
1366                         NT_PRINTER_INFO_LEVEL *printer = NULL;
1367
1368                         result = get_a_printer( NULL, &printer, 2, lp_const_servicename(snum) );
1369                         if ( !W_ERROR_IS_OK(result) )
1370                                 continue;
1371
1372                         /*
1373                          * if the printer is bound to the driver,
1374                          * then reset to the new driver initdata
1375                          */
1376
1377                         if ( printer && printer->info_2 && !strcmp(drivername, printer->info_2->drivername) )
1378                         {
1379                                 DEBUG(6,("reset_all_printerdata: Updating printer [%s]\n", printer->info_2->printername));
1380
1381                                 if ( !set_driver_init(printer, 2) ) {
1382                                         DEBUG(5,("reset_all_printerdata: Error resetting printer data for printer [%s], driver [%s]!\n",
1383                                                 printer->info_2->printername, printer->info_2->drivername));
1384                                 }
1385
1386                                 result = mod_a_printer( printer, 2 );
1387                                 if ( !W_ERROR_IS_OK(result) ) {
1388                                         DEBUG(3,("reset_all_printerdata: mod_a_printer() failed!  (%s)\n",
1389                                                 get_dos_error_msg(result)));
1390                                 }
1391                         }
1392
1393                         free_a_printer( &printer, 2 );
1394                 }
1395         }
1396
1397         /* all done */
1398
1399         return;
1400 }
1401
1402 /****************************************************************
1403  _spoolss_OpenPrinter
1404 ****************************************************************/
1405
1406 WERROR _spoolss_OpenPrinter(pipes_struct *p,
1407                             struct spoolss_OpenPrinter *r)
1408 {
1409         struct spoolss_OpenPrinterEx e;
1410         WERROR werr;
1411
1412         ZERO_STRUCT(e.in.userlevel);
1413
1414         e.in.printername        = r->in.printername;
1415         e.in.datatype           = r->in.datatype;
1416         e.in.devmode_ctr        = r->in.devmode_ctr;
1417         e.in.access_mask        = r->in.access_mask;
1418         e.in.level              = 0;
1419
1420         e.out.handle            = r->out.handle;
1421
1422         werr = _spoolss_OpenPrinterEx(p, &e);
1423
1424         if (W_ERROR_EQUAL(werr, WERR_INVALID_PARAM)) {
1425                 /* OpenPrinterEx returns this for a bad
1426                  * printer name. We must return WERR_INVALID_PRINTER_NAME
1427                  * instead.
1428                  */
1429                 werr = WERR_INVALID_PRINTER_NAME;
1430         }
1431
1432         return werr;
1433 }
1434
1435 /********************************************************************
1436  FIXME: temporary convert_devicemode_new function
1437  ********************************************************************/
1438
1439 static bool convert_devicemode_new(const char *printername,
1440                                    struct spoolss_DeviceMode *devmode,
1441                                    NT_DEVICEMODE **pp_nt_devmode)
1442 {
1443         NT_DEVICEMODE *nt_devmode = *pp_nt_devmode;
1444
1445         /*
1446          * Ensure nt_devmode is a valid pointer
1447          * as we will be overwriting it.
1448          */
1449
1450         if (nt_devmode == NULL) {
1451                 DEBUG(5, ("convert_devicemode_new: allocating a generic devmode\n"));
1452                 if ((nt_devmode = construct_nt_devicemode(printername)) == NULL)
1453                         return false;
1454         }
1455
1456         rpcstr_push(nt_devmode->devicename, devmode->devicename, 31, 0);
1457         rpcstr_push(nt_devmode->formname, devmode->formname, 31, 0);
1458
1459         nt_devmode->specversion         = devmode->specversion;
1460         nt_devmode->driverversion       = devmode->driverversion;
1461         nt_devmode->size                = devmode->size;
1462         nt_devmode->fields              = devmode->fields;
1463         nt_devmode->orientation         = devmode->orientation;
1464         nt_devmode->papersize           = devmode->papersize;
1465         nt_devmode->paperlength         = devmode->paperlength;
1466         nt_devmode->paperwidth          = devmode->paperwidth;
1467         nt_devmode->scale               = devmode->scale;
1468         nt_devmode->copies              = devmode->copies;
1469         nt_devmode->defaultsource       = devmode->defaultsource;
1470         nt_devmode->printquality        = devmode->printquality;
1471         nt_devmode->color               = devmode->color;
1472         nt_devmode->duplex              = devmode->duplex;
1473         nt_devmode->yresolution         = devmode->yresolution;
1474         nt_devmode->ttoption            = devmode->ttoption;
1475         nt_devmode->collate             = devmode->collate;
1476
1477         nt_devmode->logpixels           = devmode->logpixels;
1478         nt_devmode->bitsperpel          = devmode->bitsperpel;
1479         nt_devmode->pelswidth           = devmode->pelswidth;
1480         nt_devmode->pelsheight          = devmode->pelsheight;
1481         nt_devmode->displayflags        = devmode->displayflags;
1482         nt_devmode->displayfrequency    = devmode->displayfrequency;
1483         nt_devmode->icmmethod           = devmode->icmmethod;
1484         nt_devmode->icmintent           = devmode->icmintent;
1485         nt_devmode->mediatype           = devmode->mediatype;
1486         nt_devmode->dithertype          = devmode->dithertype;
1487         nt_devmode->reserved1           = devmode->reserved1;
1488         nt_devmode->reserved2           = devmode->reserved2;
1489         nt_devmode->panningwidth        = devmode->panningwidth;
1490         nt_devmode->panningheight       = devmode->panningheight;
1491
1492         /*
1493          * Only change private and driverextra if the incoming devmode
1494          * has a new one. JRA.
1495          */
1496
1497         if ((devmode->__driverextra_length != 0) && (devmode->driverextra_data.data != NULL)) {
1498                 SAFE_FREE(nt_devmode->nt_dev_private);
1499                 nt_devmode->driverextra = devmode->__driverextra_length;
1500                 if((nt_devmode->nt_dev_private=SMB_MALLOC_ARRAY(uint8, nt_devmode->driverextra)) == NULL)
1501                         return false;
1502                 memcpy(nt_devmode->nt_dev_private, devmode->driverextra_data.data, nt_devmode->driverextra);
1503         }
1504
1505         *pp_nt_devmode = nt_devmode;
1506
1507         return true;
1508 }
1509
1510 /****************************************************************
1511  _spoolss_OpenPrinterEx
1512 ****************************************************************/
1513
1514 WERROR _spoolss_OpenPrinterEx(pipes_struct *p,
1515                               struct spoolss_OpenPrinterEx *r)
1516 {
1517         POLICY_HND              *handle = r->out.handle;
1518         char *name = CONST_DISCARD(char *, r->in.printername);
1519         int snum;
1520         Printer_entry *Printer=NULL;
1521
1522         if (!name) {
1523                 return WERR_INVALID_PARAM;
1524         }
1525
1526         /* some sanity check because you can open a printer or a print server */
1527         /* aka: \\server\printer or \\server */
1528
1529         DEBUGADD(3,("checking name: %s\n",name));
1530
1531         if (!open_printer_hnd(p, handle, name, 0)) {
1532                 return WERR_INVALID_PARAM;
1533         }
1534
1535         Printer=find_printer_index_by_hnd(p, handle);
1536         if ( !Printer ) {
1537                 DEBUG(0,("_spoolss_OpenPrinterEx: logic error.  Can't find printer "
1538                         "handle we created for printer %s\n", name ));
1539                 close_printer_handle(p,handle);
1540                 return WERR_INVALID_PARAM;
1541         }
1542
1543         /*
1544          * First case: the user is opening the print server:
1545          *
1546          * Disallow MS AddPrinterWizard if parameter disables it. A Win2k
1547          * client 1st tries an OpenPrinterEx with access==0, MUST be allowed.
1548          *
1549          * Then both Win2k and WinNT clients try an OpenPrinterEx with
1550          * SERVER_ALL_ACCESS, which we allow only if the user is root (uid=0)
1551          * or if the user is listed in the smb.conf printer admin parameter.
1552          *
1553          * Then they try OpenPrinterEx with SERVER_READ which we allow. This lets the
1554          * client view printer folder, but does not show the MSAPW.
1555          *
1556          * Note: this test needs code to check access rights here too. Jeremy
1557          * could you look at this?
1558          *
1559          * Second case: the user is opening a printer:
1560          * NT doesn't let us connect to a printer if the connecting user
1561          * doesn't have print permission.
1562          *
1563          * Third case: user is opening a Port Monitor
1564          * access checks same as opening a handle to the print server.
1565          */
1566
1567         switch (Printer->printer_type )
1568         {
1569         case SPLHND_SERVER:
1570         case SPLHND_PORTMON_TCP:
1571         case SPLHND_PORTMON_LOCAL:
1572                 /* Printserver handles use global struct... */
1573
1574                 snum = -1;
1575
1576                 /* Map standard access rights to object specific access rights */
1577
1578                 se_map_standard(&r->in.access_mask,
1579                                 &printserver_std_mapping);
1580
1581                 /* Deny any object specific bits that don't apply to print
1582                    servers (i.e printer and job specific bits) */
1583
1584                 r->in.access_mask &= SPECIFIC_RIGHTS_MASK;
1585
1586                 if (r->in.access_mask &
1587                     ~(SERVER_ACCESS_ADMINISTER | SERVER_ACCESS_ENUMERATE)) {
1588                         DEBUG(3, ("access DENIED for non-printserver bits\n"));
1589                         close_printer_handle(p, handle);
1590                         return WERR_ACCESS_DENIED;
1591                 }
1592
1593                 /* Allow admin access */
1594
1595                 if ( r->in.access_mask & SERVER_ACCESS_ADMINISTER )
1596                 {
1597                         SE_PRIV se_printop = SE_PRINT_OPERATOR;
1598
1599                         if (!lp_ms_add_printer_wizard()) {
1600                                 close_printer_handle(p, handle);
1601                                 return WERR_ACCESS_DENIED;
1602                         }
1603
1604                         /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
1605                            and not a printer admin, then fail */
1606
1607                         if ((p->server_info->utok.uid != 0) &&
1608                             !user_has_privileges(p->server_info->ptok,
1609                                                  &se_printop ) &&
1610                             !token_contains_name_in_list(
1611                                     uidtoname(p->server_info->utok.uid),
1612                                     NULL, NULL,
1613                                     p->server_info->ptok,
1614                                     lp_printer_admin(snum))) {
1615                                 close_printer_handle(p, handle);
1616                                 return WERR_ACCESS_DENIED;
1617                         }
1618
1619                         r->in.access_mask = SERVER_ACCESS_ADMINISTER;
1620                 }
1621                 else
1622                 {
1623                         r->in.access_mask = SERVER_ACCESS_ENUMERATE;
1624                 }
1625
1626                 DEBUG(4,("Setting print server access = %s\n", (r->in.access_mask == SERVER_ACCESS_ADMINISTER)
1627                         ? "SERVER_ACCESS_ADMINISTER" : "SERVER_ACCESS_ENUMERATE" ));
1628
1629                 /* We fall through to return WERR_OK */
1630                 break;
1631
1632         case SPLHND_PRINTER:
1633                 /* NT doesn't let us connect to a printer if the connecting user
1634                    doesn't have print permission.  */
1635
1636                 if (!get_printer_snum(p, handle, &snum, NULL)) {
1637                         close_printer_handle(p, handle);
1638                         return WERR_BADFID;
1639                 }
1640
1641                 se_map_standard(&r->in.access_mask, &printer_std_mapping);
1642
1643                 /* map an empty access mask to the minimum access mask */
1644                 if (r->in.access_mask == 0x0)
1645                         r->in.access_mask = PRINTER_ACCESS_USE;
1646
1647                 /*
1648                  * If we are not serving the printer driver for this printer,
1649                  * map PRINTER_ACCESS_ADMINISTER to PRINTER_ACCESS_USE.  This
1650                  * will keep NT clients happy  --jerry
1651                  */
1652
1653                 if (lp_use_client_driver(snum)
1654                         && (r->in.access_mask & PRINTER_ACCESS_ADMINISTER))
1655                 {
1656                         r->in.access_mask = PRINTER_ACCESS_USE;
1657                 }
1658
1659                 /* check smb.conf parameters and the the sec_desc */
1660
1661                 if ( !check_access(get_client_fd(), lp_hostsallow(snum), lp_hostsdeny(snum)) ) {
1662                         DEBUG(3, ("access DENIED (hosts allow/deny) for printer open\n"));
1663                         return WERR_ACCESS_DENIED;
1664                 }
1665
1666                 if (!user_ok_token(uidtoname(p->server_info->utok.uid), NULL,
1667                                    p->server_info->ptok, snum) ||
1668                     !print_access_check(p->server_info, snum,
1669                                         r->in.access_mask)) {
1670                         DEBUG(3, ("access DENIED for printer open\n"));
1671                         close_printer_handle(p, handle);
1672                         return WERR_ACCESS_DENIED;
1673                 }
1674
1675                 if ((r->in.access_mask & SPECIFIC_RIGHTS_MASK)& ~(PRINTER_ACCESS_ADMINISTER|PRINTER_ACCESS_USE)) {
1676                         DEBUG(3, ("access DENIED for printer open - unknown bits\n"));
1677                         close_printer_handle(p, handle);
1678                         return WERR_ACCESS_DENIED;
1679                 }
1680
1681                 if (r->in.access_mask & PRINTER_ACCESS_ADMINISTER)
1682                         r->in.access_mask = PRINTER_ACCESS_ADMINISTER;
1683                 else
1684                         r->in.access_mask = PRINTER_ACCESS_USE;
1685
1686                 DEBUG(4,("Setting printer access = %s\n", (r->in.access_mask == PRINTER_ACCESS_ADMINISTER)
1687                         ? "PRINTER_ACCESS_ADMINISTER" : "PRINTER_ACCESS_USE" ));
1688
1689                 break;
1690
1691         default:
1692                 /* sanity check to prevent programmer error */
1693                 return WERR_BADFID;
1694         }
1695
1696         Printer->access_granted = r->in.access_mask;
1697
1698         /*
1699          * If the client sent a devmode in the OpenPrinter() call, then
1700          * save it here in case we get a job submission on this handle
1701          */
1702
1703          if ( (Printer->printer_type != SPLHND_SERVER)
1704                 && r->in.devmode_ctr.devmode )
1705          {
1706                 convert_devicemode_new(Printer->sharename,
1707                                        r->in.devmode_ctr.devmode,
1708                                        &Printer->nt_devmode);
1709          }
1710
1711 #if 0   /* JERRY -- I'm doubtful this is really effective */
1712         /* HACK ALERT!!! Sleep for 1/3 of a second to try trigger a LAN/WAN
1713            optimization in Windows 2000 clients  --jerry */
1714
1715         if ( (r->in.access_mask == PRINTER_ACCESS_ADMINISTER)
1716                 && (RA_WIN2K == get_remote_arch()) )
1717         {
1718                 DEBUG(10,("_spoolss_OpenPrinterEx: Enabling LAN/WAN hack for Win2k clients.\n"));
1719                 sys_usleep( 500000 );
1720         }
1721 #endif
1722
1723         return WERR_OK;
1724 }
1725
1726 /****************************************************************************
1727 ****************************************************************************/
1728
1729 static bool printer_info2_to_nt_printer_info2(struct spoolss_SetPrinterInfo2 *r,
1730                                               NT_PRINTER_INFO_LEVEL_2 *d)
1731 {
1732         DEBUG(7,("printer_info2_to_nt_printer_info2\n"));
1733
1734         if (!r || !d) {
1735                 return false;
1736         }
1737
1738         d->attributes           = r->attributes;
1739         d->priority             = r->priority;
1740         d->default_priority     = r->defaultpriority;
1741         d->starttime            = r->starttime;
1742         d->untiltime            = r->untiltime;
1743         d->status               = r->status;
1744         d->cjobs                = r->cjobs;
1745
1746         fstrcpy(d->servername,  r->servername);
1747         fstrcpy(d->printername, r->printername);
1748         fstrcpy(d->sharename,   r->sharename);
1749         fstrcpy(d->portname,    r->portname);
1750         fstrcpy(d->drivername,  r->drivername);
1751         slprintf(d->comment, sizeof(d->comment)-1, "%s", r->comment);
1752         fstrcpy(d->location,    r->location);
1753         fstrcpy(d->sepfile,     r->sepfile);
1754         fstrcpy(d->printprocessor, r->printprocessor);
1755         fstrcpy(d->datatype,    r->datatype);
1756         fstrcpy(d->parameters,  r->parameters);
1757
1758         return true;
1759 }
1760
1761 /****************************************************************************
1762 ****************************************************************************/
1763
1764 static bool convert_printer_info_new(struct spoolss_SetPrinterInfoCtr *info_ctr,
1765                                      NT_PRINTER_INFO_LEVEL *printer)
1766 {
1767         bool ret;
1768
1769         switch (info_ctr->level) {
1770         case 2:
1771                 /* allocate memory if needed.  Messy because
1772                    convert_printer_info is used to update an existing
1773                    printer or build a new one */
1774
1775                 if (!printer->info_2) {
1776                         printer->info_2 = TALLOC_ZERO_P(printer, NT_PRINTER_INFO_LEVEL_2);
1777                         if (!printer->info_2) {
1778                                 DEBUG(0,("convert_printer_info_new: "
1779                                         "talloc() failed!\n"));
1780                                 return false;
1781                         }
1782                 }
1783
1784                 ret = printer_info2_to_nt_printer_info2(info_ctr->info.info2,
1785                                                         printer->info_2);
1786                 printer->info_2->setuptime = time(NULL);
1787                 return ret;
1788         }
1789
1790         return false;
1791 }
1792
1793 static bool convert_printer_driver_info(const SPOOL_PRINTER_DRIVER_INFO_LEVEL *uni,
1794                                         NT_PRINTER_DRIVER_INFO_LEVEL *printer, uint32 level)
1795 {
1796         bool result = True;
1797
1798         switch (level) {
1799                 case 3:
1800                         printer->info_3=NULL;
1801                         if (!uni_2_asc_printer_driver_3(uni->info_3, &printer->info_3))
1802                                 result = False;
1803                         break;
1804                 case 6:
1805                         printer->info_6=NULL;
1806                         if (!uni_2_asc_printer_driver_6(uni->info_6, &printer->info_6))
1807                                 result = False;
1808                         break;
1809                 default:
1810                         break;
1811         }
1812
1813         return result;
1814 }
1815
1816 bool convert_devicemode(const char *printername, const DEVICEMODE *devmode,
1817                                 NT_DEVICEMODE **pp_nt_devmode)
1818 {
1819         NT_DEVICEMODE *nt_devmode = *pp_nt_devmode;
1820
1821         /*
1822          * Ensure nt_devmode is a valid pointer
1823          * as we will be overwriting it.
1824          */
1825
1826         if (nt_devmode == NULL) {
1827                 DEBUG(5, ("convert_devicemode: allocating a generic devmode\n"));
1828                 if ((nt_devmode = construct_nt_devicemode(printername)) == NULL)
1829                         return False;
1830         }
1831
1832         rpcstr_pull(nt_devmode->devicename,devmode->devicename.buffer, 31, -1, 0);
1833         rpcstr_pull(nt_devmode->formname,devmode->formname.buffer, 31, -1, 0);
1834
1835         nt_devmode->specversion=devmode->specversion;
1836         nt_devmode->driverversion=devmode->driverversion;
1837         nt_devmode->size=devmode->size;
1838         nt_devmode->fields=devmode->fields;
1839         nt_devmode->orientation=devmode->orientation;
1840         nt_devmode->papersize=devmode->papersize;
1841         nt_devmode->paperlength=devmode->paperlength;
1842         nt_devmode->paperwidth=devmode->paperwidth;
1843         nt_devmode->scale=devmode->scale;
1844         nt_devmode->copies=devmode->copies;
1845         nt_devmode->defaultsource=devmode->defaultsource;
1846         nt_devmode->printquality=devmode->printquality;
1847         nt_devmode->color=devmode->color;
1848         nt_devmode->duplex=devmode->duplex;
1849         nt_devmode->yresolution=devmode->yresolution;
1850         nt_devmode->ttoption=devmode->ttoption;
1851         nt_devmode->collate=devmode->collate;
1852
1853         nt_devmode->logpixels=devmode->logpixels;
1854         nt_devmode->bitsperpel=devmode->bitsperpel;
1855         nt_devmode->pelswidth=devmode->pelswidth;
1856         nt_devmode->pelsheight=devmode->pelsheight;
1857         nt_devmode->displayflags=devmode->displayflags;
1858         nt_devmode->displayfrequency=devmode->displayfrequency;
1859         nt_devmode->icmmethod=devmode->icmmethod;
1860         nt_devmode->icmintent=devmode->icmintent;
1861         nt_devmode->mediatype=devmode->mediatype;
1862         nt_devmode->dithertype=devmode->dithertype;
1863         nt_devmode->reserved1=devmode->reserved1;
1864         nt_devmode->reserved2=devmode->reserved2;
1865         nt_devmode->panningwidth=devmode->panningwidth;
1866         nt_devmode->panningheight=devmode->panningheight;
1867
1868         /*
1869          * Only change private and driverextra if the incoming devmode
1870          * has a new one. JRA.
1871          */
1872
1873         if ((devmode->driverextra != 0) && (devmode->dev_private != NULL)) {
1874                 SAFE_FREE(nt_devmode->nt_dev_private);
1875                 nt_devmode->driverextra=devmode->driverextra;
1876                 if((nt_devmode->nt_dev_private=SMB_MALLOC_ARRAY(uint8, nt_devmode->driverextra)) == NULL)
1877                         return False;
1878                 memcpy(nt_devmode->nt_dev_private, devmode->dev_private, nt_devmode->driverextra);
1879         }
1880
1881         *pp_nt_devmode = nt_devmode;
1882
1883         return True;
1884 }
1885
1886 /********************************************************************
1887  * _spoolss_enddocprinter_internal.
1888  ********************************************************************/
1889
1890 static WERROR _spoolss_enddocprinter_internal(pipes_struct *p, POLICY_HND *handle)
1891 {
1892         Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
1893         int snum;
1894
1895         if (!Printer) {
1896                 DEBUG(2,("_spoolss_enddocprinter_internal: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
1897                 return WERR_BADFID;
1898         }
1899
1900         if (!get_printer_snum(p, handle, &snum, NULL))
1901                 return WERR_BADFID;
1902
1903         Printer->document_started=False;
1904         print_job_end(snum, Printer->jobid,NORMAL_CLOSE);
1905         /* error codes unhandled so far ... */
1906
1907         return WERR_OK;
1908 }
1909
1910 /****************************************************************
1911  _spoolss_ClosePrinter
1912 ****************************************************************/
1913
1914 WERROR _spoolss_ClosePrinter(pipes_struct *p,
1915                              struct spoolss_ClosePrinter *r)
1916 {
1917         POLICY_HND *handle = r->in.handle;
1918
1919         Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
1920
1921         if (Printer && Printer->document_started)
1922                 _spoolss_enddocprinter_internal(p, handle);          /* print job was not closed */
1923
1924         if (!close_printer_handle(p, handle))
1925                 return WERR_BADFID;
1926
1927         /* clear the returned printer handle.  Observed behavior
1928            from Win2k server.  Don't think this really matters.
1929            Previous code just copied the value of the closed
1930            handle.    --jerry */
1931
1932         ZERO_STRUCTP(r->out.handle);
1933
1934         return WERR_OK;
1935 }
1936
1937 /****************************************************************
1938  _spoolss_DeletePrinter
1939 ****************************************************************/
1940
1941 WERROR _spoolss_DeletePrinter(pipes_struct *p,
1942                               struct spoolss_DeletePrinter *r)
1943 {
1944         POLICY_HND *handle = r->in.handle;
1945         Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
1946         WERROR result;
1947
1948         if (Printer && Printer->document_started)
1949                 _spoolss_enddocprinter_internal(p, handle);  /* print job was not closed */
1950
1951         result = delete_printer_handle(p, handle);
1952
1953         update_c_setprinter(False);
1954
1955         return result;
1956 }
1957
1958 /*******************************************************************
1959  * static function to lookup the version id corresponding to an
1960  * long architecture string
1961  ******************************************************************/
1962
1963 static int get_version_id (char * arch)
1964 {
1965         int i;
1966         struct table_node archi_table[]= {
1967
1968                 {"Windows 4.0",          "WIN40",       0 },
1969                 {"Windows NT x86",       "W32X86",      2 },
1970                 {"Windows NT R4000",     "W32MIPS",     2 },
1971                 {"Windows NT Alpha_AXP", "W32ALPHA",    2 },
1972                 {"Windows NT PowerPC",   "W32PPC",      2 },
1973                 {"Windows IA64",         "IA64",        3 },
1974                 {"Windows x64",          "x64",         3 },
1975                 {NULL,                   "",            -1 }
1976         };
1977
1978         for (i=0; archi_table[i].long_archi != NULL; i++)
1979         {
1980                 if (strcmp(arch, archi_table[i].long_archi) == 0)
1981                         return (archi_table[i].version);
1982         }
1983
1984         return -1;
1985 }
1986
1987 /****************************************************************
1988  _spoolss_DeletePrinterDriver
1989 ****************************************************************/
1990
1991 WERROR _spoolss_DeletePrinterDriver(pipes_struct *p,
1992                                     struct spoolss_DeletePrinterDriver *r)
1993 {
1994         char *driver;
1995         char *arch;
1996         NT_PRINTER_DRIVER_INFO_LEVEL    info;
1997         NT_PRINTER_DRIVER_INFO_LEVEL    info_win2k;
1998         int                             version;
1999         WERROR                          status;
2000         WERROR                          status_win2k = WERR_ACCESS_DENIED;
2001         SE_PRIV                         se_printop = SE_PRINT_OPERATOR;
2002
2003         /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
2004            and not a printer admin, then fail */
2005
2006         if ( (p->server_info->utok.uid != 0)
2007                 && !user_has_privileges(p->server_info->ptok, &se_printop )
2008                 && !token_contains_name_in_list(
2009                         uidtoname(p->server_info->utok.uid), NULL,
2010                         NULL, p->server_info->ptok,
2011                         lp_printer_admin(-1)) )
2012         {
2013                 return WERR_ACCESS_DENIED;
2014         }
2015
2016         driver = CONST_DISCARD(char *, r->in.driver);
2017         arch   = CONST_DISCARD(char *, r->in.architecture);
2018
2019         /* check that we have a valid driver name first */
2020
2021         if ((version=get_version_id(arch)) == -1)
2022                 return WERR_INVALID_ENVIRONMENT;
2023
2024         ZERO_STRUCT(info);
2025         ZERO_STRUCT(info_win2k);
2026
2027         if (!W_ERROR_IS_OK(get_a_printer_driver(&info, 3, driver, arch, version)))
2028         {
2029                 /* try for Win2k driver if "Windows NT x86" */
2030
2031                 if ( version == 2 ) {
2032                         version = 3;
2033                         if (!W_ERROR_IS_OK(get_a_printer_driver(&info, 3, driver, arch, version))) {
2034                                 status = WERR_UNKNOWN_PRINTER_DRIVER;
2035                                 goto done;
2036                         }
2037                 }
2038                 /* otherwise it was a failure */
2039                 else {
2040                         status = WERR_UNKNOWN_PRINTER_DRIVER;
2041                         goto done;
2042                 }
2043
2044         }
2045
2046         if (printer_driver_in_use(info.info_3)) {
2047                 status = WERR_PRINTER_DRIVER_IN_USE;
2048                 goto done;
2049         }
2050
2051         if ( version == 2 )
2052         {
2053                 if (W_ERROR_IS_OK(get_a_printer_driver(&info_win2k, 3, driver, arch, 3)))
2054                 {
2055                         /* if we get to here, we now have 2 driver info structures to remove */
2056                         /* remove the Win2k driver first*/
2057
2058                         status_win2k = delete_printer_driver(
2059                                 p, info_win2k.info_3, 3, False );
2060                         free_a_printer_driver( info_win2k, 3 );
2061
2062                         /* this should not have failed---if it did, report to client */
2063                         if ( !W_ERROR_IS_OK(status_win2k) )
2064                         {
2065                                 status = status_win2k;
2066                                 goto done;
2067                         }
2068                 }
2069         }
2070
2071         status = delete_printer_driver(p, info.info_3, version, False);
2072
2073         /* if at least one of the deletes succeeded return OK */
2074
2075         if ( W_ERROR_IS_OK(status) || W_ERROR_IS_OK(status_win2k) )
2076                 status = WERR_OK;
2077
2078 done:
2079         free_a_printer_driver( info, 3 );
2080
2081         return status;
2082 }
2083
2084 /****************************************************************
2085  _spoolss_DeletePrinterDriverEx
2086 ****************************************************************/
2087
2088 WERROR _spoolss_DeletePrinterDriverEx(pipes_struct *p,
2089                                       struct spoolss_DeletePrinterDriverEx *r)
2090 {
2091         char *driver;
2092         char *arch;
2093         NT_PRINTER_DRIVER_INFO_LEVEL    info;
2094         NT_PRINTER_DRIVER_INFO_LEVEL    info_win2k;
2095         int                             version;
2096         uint32_t                        flags = r->in.delete_flags;
2097         bool                            delete_files;
2098         WERROR                          status;
2099         WERROR                          status_win2k = WERR_ACCESS_DENIED;
2100         SE_PRIV                         se_printop = SE_PRINT_OPERATOR;
2101
2102         /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
2103            and not a printer admin, then fail */
2104
2105         if ( (p->server_info->utok.uid != 0)
2106                 && !user_has_privileges(p->server_info->ptok, &se_printop )
2107                 && !token_contains_name_in_list(
2108                         uidtoname(p->server_info->utok.uid), NULL, NULL,
2109                         p->server_info->ptok, lp_printer_admin(-1)) )
2110         {
2111                 return WERR_ACCESS_DENIED;
2112         }
2113
2114         driver = CONST_DISCARD(char *, r->in.driver);
2115         arch   = CONST_DISCARD(char *, r->in.architecture);
2116
2117         /* check that we have a valid driver name first */
2118         if ((version=get_version_id(arch)) == -1) {
2119                 /* this is what NT returns */
2120                 return WERR_INVALID_ENVIRONMENT;
2121         }
2122
2123         if ( flags & DPD_DELETE_SPECIFIC_VERSION )
2124                 version = r->in.version;
2125
2126         ZERO_STRUCT(info);
2127         ZERO_STRUCT(info_win2k);
2128
2129         status = get_a_printer_driver(&info, 3, driver, arch, version);
2130
2131         if ( !W_ERROR_IS_OK(status) )
2132         {
2133                 /*
2134                  * if the client asked for a specific version,
2135                  * or this is something other than Windows NT x86,
2136                  * then we've failed
2137                  */
2138
2139                 if ( (flags&DPD_DELETE_SPECIFIC_VERSION) || (version !=2) )
2140                         goto done;
2141
2142                 /* try for Win2k driver if "Windows NT x86" */
2143
2144                 version = 3;
2145                 if (!W_ERROR_IS_OK(get_a_printer_driver(&info, 3, driver, arch, version))) {
2146                         status = WERR_UNKNOWN_PRINTER_DRIVER;
2147                         goto done;
2148                 }
2149         }
2150
2151         if ( printer_driver_in_use(info.info_3) ) {
2152                 status = WERR_PRINTER_DRIVER_IN_USE;
2153                 goto done;
2154         }
2155
2156         /*
2157          * we have a couple of cases to consider.
2158          * (1) Are any files in use?  If so and DPD_DELTE_ALL_FILE is set,
2159          *     then the delete should fail if **any** files overlap with
2160          *     other drivers
2161          * (2) If DPD_DELTE_UNUSED_FILES is sert, then delete all
2162          *     non-overlapping files
2163          * (3) If neither DPD_DELTE_ALL_FILE nor DPD_DELTE_ALL_FILES
2164          *     is set, the do not delete any files
2165          * Refer to MSDN docs on DeletePrinterDriverEx() for details.
2166          */
2167
2168         delete_files = flags & (DPD_DELETE_ALL_FILES|DPD_DELETE_UNUSED_FILES);
2169
2170         /* fail if any files are in use and DPD_DELETE_ALL_FILES is set */
2171
2172         if ( delete_files && printer_driver_files_in_use(info.info_3) & (flags&DPD_DELETE_ALL_FILES) ) {
2173                 /* no idea of the correct error here */
2174                 status = WERR_ACCESS_DENIED;
2175                 goto done;
2176         }
2177
2178
2179         /* also check for W32X86/3 if necessary; maybe we already have? */
2180
2181         if ( (version == 2) && ((flags&DPD_DELETE_SPECIFIC_VERSION) != DPD_DELETE_SPECIFIC_VERSION)  ) {
2182                 if (W_ERROR_IS_OK(get_a_printer_driver(&info_win2k, 3, driver, arch, 3)))
2183                 {
2184
2185                         if ( delete_files && printer_driver_files_in_use(info_win2k.info_3) & (flags&DPD_DELETE_ALL_FILES) ) {
2186                                 /* no idea of the correct error here */
2187                                 free_a_printer_driver( info_win2k, 3 );
2188                                 status = WERR_ACCESS_DENIED;
2189                                 goto done;
2190                         }
2191
2192                         /* if we get to here, we now have 2 driver info structures to remove */
2193                         /* remove the Win2k driver first*/
2194
2195                         status_win2k = delete_printer_driver(
2196                                 p, info_win2k.info_3, 3, delete_files);
2197                         free_a_printer_driver( info_win2k, 3 );
2198
2199                         /* this should not have failed---if it did, report to client */
2200
2201                         if ( !W_ERROR_IS_OK(status_win2k) )
2202                                 goto done;
2203                 }
2204         }
2205
2206         status = delete_printer_driver(p, info.info_3, version, delete_files);
2207
2208         if ( W_ERROR_IS_OK(status) || W_ERROR_IS_OK(status_win2k) )
2209                 status = WERR_OK;
2210 done:
2211         free_a_printer_driver( info, 3 );
2212
2213         return status;
2214 }
2215
2216
2217 /****************************************************************************
2218  Internal routine for retreiving printerdata
2219  ***************************************************************************/
2220
2221 static WERROR get_printer_dataex( TALLOC_CTX *ctx, NT_PRINTER_INFO_LEVEL *printer,
2222                                   const char *key, const char *value, uint32 *type, uint8 **data,
2223                                   uint32 *needed, uint32 in_size  )
2224 {
2225         REGISTRY_VALUE          *val;
2226         uint32                  size;
2227         int                     data_len;
2228
2229         if ( !(val = get_printer_data( printer->info_2, key, value)) )
2230                 return WERR_BADFILE;
2231
2232         *type = regval_type( val );
2233
2234         DEBUG(5,("get_printer_dataex: allocating %d\n", in_size));
2235
2236         size = regval_size( val );
2237
2238         /* copy the min(in_size, len) */
2239
2240         if ( in_size ) {
2241                 data_len = (size > in_size) ? in_size : size*sizeof(uint8);
2242
2243                 /* special case for 0 length values */
2244                 if ( data_len ) {
2245                         if ( (*data  = (uint8 *)TALLOC_MEMDUP(ctx, regval_data_p(val), data_len)) == NULL )
2246                                 return WERR_NOMEM;
2247                 }
2248                 else {
2249                         if ( (*data  = (uint8 *)TALLOC_ZERO(ctx, in_size)) == NULL )
2250                                 return WERR_NOMEM;
2251                 }
2252         }
2253         else
2254                 *data = NULL;
2255
2256         *needed = size;
2257
2258         DEBUG(5,("get_printer_dataex: copy done\n"));
2259
2260         return WERR_OK;
2261 }
2262
2263 /****************************************************************************
2264  Internal routine for removing printerdata
2265  ***************************************************************************/
2266
2267 static WERROR delete_printer_dataex( NT_PRINTER_INFO_LEVEL *printer, const char *key, const char *value )
2268 {
2269         return delete_printer_data( printer->info_2, key, value );
2270 }
2271
2272 /****************************************************************************
2273  Internal routine for storing printerdata
2274  ***************************************************************************/
2275
2276 WERROR set_printer_dataex( NT_PRINTER_INFO_LEVEL *printer, const char *key, const char *value,
2277                                   uint32 type, uint8 *data, int real_len  )
2278 {
2279         /* the registry objects enforce uniqueness based on value name */
2280
2281         return add_printer_data( printer->info_2, key, value, type, data, real_len );
2282 }
2283
2284 /********************************************************************
2285  GetPrinterData on a printer server Handle.
2286 ********************************************************************/
2287
2288 static WERROR getprinterdata_printer_server(TALLOC_CTX *ctx, fstring value, uint32 *type, uint8 **data, uint32 *needed, uint32 in_size)
2289 {
2290         int i;
2291
2292         DEBUG(8,("getprinterdata_printer_server:%s\n", value));
2293
2294         if (!StrCaseCmp(value, "W3SvcInstalled")) {
2295                 *type = REG_DWORD;
2296                 if ( !(*data = TALLOC_ARRAY(ctx, uint8, sizeof(uint32) )) )
2297                         return WERR_NOMEM;
2298                 SIVAL(*data, 0, 0x00);
2299                 *needed = 0x4;
2300                 return WERR_OK;
2301         }
2302
2303         if (!StrCaseCmp(value, "BeepEnabled")) {
2304                 *type = REG_DWORD;
2305                 if ( !(*data = TALLOC_ARRAY(ctx, uint8, sizeof(uint32) )) )
2306                         return WERR_NOMEM;
2307                 SIVAL(*data, 0, 0x00);
2308                 *needed = 0x4;
2309                 return WERR_OK;
2310         }
2311
2312         if (!StrCaseCmp(value, "EventLog")) {
2313                 *type = REG_DWORD;
2314                 if ( !(*data = TALLOC_ARRAY(ctx, uint8, sizeof(uint32) )) )
2315                         return WERR_NOMEM;
2316                 /* formally was 0x1b */
2317                 SIVAL(*data, 0, 0x0);
2318                 *needed = 0x4;
2319                 return WERR_OK;
2320         }
2321
2322         if (!StrCaseCmp(value, "NetPopup")) {
2323                 *type = REG_DWORD;
2324                 if ( !(*data = TALLOC_ARRAY(ctx, uint8, sizeof(uint32) )) )
2325                         return WERR_NOMEM;
2326                 SIVAL(*data, 0, 0x00);
2327                 *needed = 0x4;
2328                 return WERR_OK;
2329         }
2330
2331         if (!StrCaseCmp(value, "MajorVersion")) {
2332                 *type = REG_DWORD;
2333                 if ( !(*data = TALLOC_ARRAY(ctx, uint8, sizeof(uint32) )) )
2334                         return WERR_NOMEM;
2335
2336                 /* Windows NT 4.0 seems to not allow uploading of drivers
2337                    to a server that reports 0x3 as the MajorVersion.
2338                    need to investigate more how Win2k gets around this .
2339                    -- jerry */
2340
2341                 if ( RA_WINNT == get_remote_arch() )
2342                         SIVAL(*data, 0, 2);
2343                 else
2344                         SIVAL(*data, 0, 3);
2345
2346                 *needed = 0x4;
2347                 return WERR_OK;
2348         }
2349
2350         if (!StrCaseCmp(value, "MinorVersion")) {
2351                 *type = REG_DWORD;
2352                 if ( !(*data = TALLOC_ARRAY(ctx, uint8, sizeof(uint32) )) )
2353                         return WERR_NOMEM;
2354                 SIVAL(*data, 0, 0);
2355                 *needed = 0x4;
2356                 return WERR_OK;
2357         }
2358
2359         /* REG_BINARY
2360          *  uint32 size          = 0x114
2361          *  uint32 major         = 5
2362          *  uint32 minor         = [0|1]
2363          *  uint32 build         = [2195|2600]
2364          *  extra unicode string = e.g. "Service Pack 3"
2365          */
2366         if (!StrCaseCmp(value, "OSVersion")) {
2367                 *type = REG_BINARY;
2368                 *needed = 0x114;
2369
2370                 if ( !(*data = TALLOC_ZERO_ARRAY(ctx, uint8, (*needed > in_size) ? *needed:in_size )) )
2371                         return WERR_NOMEM;
2372
2373                 SIVAL(*data, 0, *needed);       /* size */
2374                 SIVAL(*data, 4, 5);             /* Windows 2000 == 5.0 */
2375                 SIVAL(*data, 8, 0);
2376                 SIVAL(*data, 12, 2195);         /* build */
2377
2378                 /* leave extra string empty */
2379
2380                 return WERR_OK;
2381         }
2382
2383
2384         if (!StrCaseCmp(value, "DefaultSpoolDirectory")) {
2385                 const char *string="C:\\PRINTERS";
2386                 *type = REG_SZ;
2387                 *needed = 2*(strlen(string)+1);
2388                 if((*data  = (uint8 *)TALLOC(ctx, (*needed > in_size) ? *needed:in_size )) == NULL)
2389                         return WERR_NOMEM;
2390                 memset(*data, 0, (*needed > in_size) ? *needed:in_size);
2391
2392                 /* it's done by hand ready to go on the wire */
2393                 for (i=0; i<strlen(string); i++) {
2394                         (*data)[2*i]=string[i];
2395                         (*data)[2*i+1]='\0';
2396                 }
2397                 return WERR_OK;
2398         }
2399
2400         if (!StrCaseCmp(value, "Architecture")) {
2401                 const char *string="Windows NT x86";
2402                 *type = REG_SZ;
2403                 *needed = 2*(strlen(string)+1);
2404                 if((*data  = (uint8 *)TALLOC(ctx, (*needed > in_size) ? *needed:in_size )) == NULL)
2405                         return WERR_NOMEM;
2406                 memset(*data, 0, (*needed > in_size) ? *needed:in_size);
2407                 for (i=0; i<strlen(string); i++) {
2408                         (*data)[2*i]=string[i];
2409                         (*data)[2*i+1]='\0';
2410                 }
2411                 return WERR_OK;
2412         }
2413
2414         if (!StrCaseCmp(value, "DsPresent")) {
2415                 *type = REG_DWORD;
2416                 if ( !(*data = TALLOC_ARRAY(ctx, uint8, sizeof(uint32) )) )
2417                         return WERR_NOMEM;
2418
2419                 /* only show the publish check box if we are a
2420                    memeber of a AD domain */
2421
2422                 if ( lp_security() == SEC_ADS )
2423                         SIVAL(*data, 0, 0x01);
2424                 else
2425                         SIVAL(*data, 0, 0x00);
2426
2427                 *needed = 0x4;
2428                 return WERR_OK;
2429         }
2430
2431         if (!StrCaseCmp(value, "DNSMachineName")) {
2432                 const char *hostname = get_mydnsfullname();
2433
2434                 if (!hostname)
2435                         return WERR_BADFILE;
2436                 *type = REG_SZ;
2437                 *needed = 2*(strlen(hostname)+1);
2438                 if((*data  = (uint8 *)TALLOC(ctx, (*needed > in_size) ? *needed:in_size )) == NULL)
2439                         return WERR_NOMEM;
2440                 memset(*data, 0, (*needed > in_size) ? *needed:in_size);
2441                 for (i=0; i<strlen(hostname); i++) {
2442                         (*data)[2*i]=hostname[i];
2443                         (*data)[2*i+1]='\0';
2444                 }
2445                 return WERR_OK;
2446         }
2447
2448
2449         return WERR_BADFILE;
2450 }
2451
2452 /********************************************************************
2453  * spoolss_getprinterdata
2454  ********************************************************************/
2455
2456 WERROR _spoolss_getprinterdata(pipes_struct *p, SPOOL_Q_GETPRINTERDATA *q_u, SPOOL_R_GETPRINTERDATA *r_u)
2457 {
2458         POLICY_HND      *handle = &q_u->handle;
2459         UNISTR2         *valuename = &q_u->valuename;
2460         uint32          in_size = q_u->size;
2461         uint32          *type = &r_u->type;
2462         uint32          *out_size = &r_u->size;
2463         uint8           **data = &r_u->data;
2464         uint32          *needed = &r_u->needed;
2465         WERROR          status;
2466         fstring         value;
2467         Printer_entry   *Printer = find_printer_index_by_hnd(p, handle);
2468         NT_PRINTER_INFO_LEVEL   *printer = NULL;
2469         int             snum = 0;
2470
2471         /*
2472          * Reminder: when it's a string, the length is in BYTES
2473          * even if UNICODE is negociated.
2474          *
2475          * JFM, 4/19/1999
2476          */
2477
2478         *out_size = in_size;
2479
2480         /* in case of problem, return some default values */
2481
2482         *needed = 0;
2483         *type   = 0;
2484
2485         DEBUG(4,("_spoolss_getprinterdata\n"));
2486
2487         if ( !Printer ) {
2488                 DEBUG(2,("_spoolss_getprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
2489                 status = WERR_BADFID;
2490                 goto done;
2491         }
2492
2493         unistr2_to_ascii(value, valuename, sizeof(value));
2494
2495         if ( Printer->printer_type == SPLHND_SERVER )
2496                 status = getprinterdata_printer_server( p->mem_ctx, value, type, data, needed, *out_size );
2497         else
2498         {
2499                 if ( !get_printer_snum(p,handle, &snum, NULL) ) {
2500                         status = WERR_BADFID;
2501                         goto done;
2502                 }
2503
2504                 status = get_a_printer(Printer, &printer, 2, lp_servicename(snum));
2505                 if ( !W_ERROR_IS_OK(status) )
2506                         goto done;
2507
2508                 /* XP sends this and wants to change id value from the PRINTER_INFO_0 */
2509
2510                 if ( strequal(value, "ChangeId") ) {
2511                         *type = REG_DWORD;
2512                         *needed = sizeof(uint32);
2513                         if ( (*data = (uint8*)TALLOC(p->mem_ctx, sizeof(uint32))) == NULL) {
2514                                 status = WERR_NOMEM;
2515                                 goto done;
2516                         }
2517                         SIVAL( *data, 0, printer->info_2->changeid );
2518                         status = WERR_OK;
2519                 }
2520                 else
2521                         status = get_printer_dataex( p->mem_ctx, printer, SPOOL_PRINTERDATA_KEY, value, type, data, needed, *out_size );
2522         }
2523
2524         if (*needed > *out_size)
2525                 status = WERR_MORE_DATA;
2526
2527 done:
2528         if ( !W_ERROR_IS_OK(status) )
2529         {
2530                 DEBUG(5, ("error %d: allocating %d\n", W_ERROR_V(status),*out_size));
2531
2532                 /* reply this param doesn't exist */
2533
2534                 if ( *out_size ) {
2535                         if((*data=(uint8 *)TALLOC_ZERO_ARRAY(p->mem_ctx, uint8, *out_size)) == NULL) {
2536                                 if ( printer )
2537                                         free_a_printer( &printer, 2 );
2538                                 return WERR_NOMEM;
2539                         }
2540                 } else {
2541                         *data = NULL;
2542                 }
2543         }
2544
2545         /* cleanup & exit */
2546
2547         if ( printer )
2548                 free_a_printer( &printer, 2 );
2549
2550         return status;
2551 }
2552
2553 /*********************************************************
2554  Connect to the client machine.
2555 **********************************************************/
2556
2557 static bool spoolss_connect_to_client(struct rpc_pipe_client **pp_pipe,
2558                         struct sockaddr_storage *client_ss, const char *remote_machine)
2559 {
2560         NTSTATUS ret;
2561         struct cli_state *the_cli;
2562         struct sockaddr_storage rm_addr;
2563
2564         if ( is_zero_addr((struct sockaddr *)client_ss) ) {
2565                 if ( !resolve_name( remote_machine, &rm_addr, 0x20) ) {
2566                         DEBUG(2,("spoolss_connect_to_client: Can't resolve address for %s\n", remote_machine));
2567                         return False;
2568                 }
2569
2570                 if (ismyaddr((struct sockaddr *)&rm_addr)) {
2571                         DEBUG(0,("spoolss_connect_to_client: Machine %s is one of our addresses. Cannot add to ourselves.\n", remote_machine));
2572                         return False;
2573                 }
2574         } else {
2575                 char addr[INET6_ADDRSTRLEN];
2576                 rm_addr = *client_ss;
2577                 print_sockaddr(addr, sizeof(addr), &rm_addr);
2578                 DEBUG(5,("spoolss_connect_to_client: Using address %s (no name resolution necessary)\n",
2579                         addr));
2580         }
2581
2582         /* setup the connection */
2583
2584         ret = cli_full_connection( &the_cli, global_myname(), remote_machine,
2585                 &rm_addr, 0, "IPC$", "IPC",
2586                 "", /* username */
2587                 "", /* domain */
2588                 "", /* password */
2589                 0, lp_client_signing(), NULL );
2590
2591         if ( !NT_STATUS_IS_OK( ret ) ) {
2592                 DEBUG(2,("spoolss_connect_to_client: connection to [%s] failed!\n",
2593                         remote_machine ));
2594                 return False;
2595         }
2596
2597         if ( the_cli->protocol != PROTOCOL_NT1 ) {
2598                 DEBUG(0,("spoolss_connect_to_client: machine %s didn't negotiate NT protocol.\n", remote_machine));
2599                 cli_shutdown(the_cli);
2600                 return False;
2601         }
2602
2603         /*
2604          * Ok - we have an anonymous connection to the IPC$ share.
2605          * Now start the NT Domain stuff :-).
2606          */
2607
2608         ret = cli_rpc_pipe_open_noauth(the_cli, &syntax_spoolss, pp_pipe);
2609         if (!NT_STATUS_IS_OK(ret)) {
2610                 DEBUG(2,("spoolss_connect_to_client: unable to open the spoolss pipe on machine %s. Error was : %s.\n",
2611                         remote_machine, nt_errstr(ret)));
2612                 cli_shutdown(the_cli);
2613                 return False;
2614         }
2615
2616         return True;
2617 }
2618
2619 /***************************************************************************
2620  Connect to the client.
2621 ****************************************************************************/
2622
2623 static bool srv_spoolss_replyopenprinter(int snum, const char *printer,
2624                                         uint32 localprinter, uint32 type,
2625                                         POLICY_HND *handle, struct sockaddr_storage *client_ss)
2626 {
2627         WERROR result;
2628         NTSTATUS status;
2629
2630         /*
2631          * If it's the first connection, contact the client
2632          * and connect to the IPC$ share anonymously
2633          */
2634         if (smb_connections==0) {
2635                 fstring unix_printer;
2636
2637                 fstrcpy(unix_printer, printer+2); /* the +2 is to strip the leading 2 backslashs */
2638
2639                 if ( !spoolss_connect_to_client( &notify_cli_pipe, client_ss, unix_printer ))
2640                         return False;
2641
2642                 messaging_register(smbd_messaging_context(), NULL,
2643                                    MSG_PRINTER_NOTIFY2,
2644                                    receive_notify2_message_list);
2645                 /* Tell the connections db we're now interested in printer
2646                  * notify messages. */
2647                 register_message_flags( True, FLAG_MSG_PRINT_NOTIFY );
2648         }
2649
2650         /*
2651          * Tell the specific printing tdb we want messages for this printer
2652          * by registering our PID.
2653          */
2654
2655         if (!print_notify_register_pid(snum))
2656                 DEBUG(0,("print_notify_register_pid: Failed to register our pid for printer %s\n", printer ));
2657
2658         smb_connections++;
2659
2660         status = rpccli_spoolss_ReplyOpenPrinter(notify_cli_pipe, talloc_tos(),
2661                                                  printer,
2662                                                  localprinter,
2663                                                  type,
2664                                                  0,
2665                                                  NULL,
2666                                                  handle,
2667                                                  &result);
2668         if (!NT_STATUS_IS_OK(status) || !W_ERROR_IS_OK(result))
2669                 DEBUG(5,("srv_spoolss_reply_open_printer: Client RPC returned [%s]\n",
2670                         win_errstr(result)));
2671
2672         return (W_ERROR_IS_OK(result));
2673 }
2674
2675 /********************************************************************
2676  * _spoolss_rffpcnex
2677  * ReplyFindFirstPrinterChangeNotifyEx
2678  *
2679  * before replying OK: status=0 a rpc call is made to the workstation
2680  * asking ReplyOpenPrinter
2681  *
2682  * in fact ReplyOpenPrinter is the changenotify equivalent on the spoolss pipe
2683  * called from api_spoolss_rffpcnex
2684  ********************************************************************/
2685
2686 WERROR _spoolss_rffpcnex(pipes_struct *p, SPOOL_Q_RFFPCNEX *q_u, SPOOL_R_RFFPCNEX *r_u)
2687 {
2688         POLICY_HND *handle = &q_u->handle;
2689         uint32 flags = q_u->flags;
2690         uint32 options = q_u->options;
2691         UNISTR2 *localmachine = &q_u->localmachine;
2692         uint32 printerlocal = q_u->printerlocal;
2693         int snum = -1;
2694         SPOOL_NOTIFY_OPTION *option = q_u->option;
2695         struct sockaddr_storage client_ss;
2696
2697         /* store the notify value in the printer struct */
2698
2699         Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
2700
2701         if (!Printer) {
2702                 DEBUG(2,("_spoolss_rffpcnex: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
2703                 return WERR_BADFID;
2704         }
2705
2706         Printer->notify.flags=flags;
2707         Printer->notify.options=options;
2708         Printer->notify.printerlocal=printerlocal;
2709
2710         if (Printer->notify.option)
2711                 free_spool_notify_option(&Printer->notify.option);
2712
2713         Printer->notify.option=dup_spool_notify_option(option);
2714
2715         unistr2_to_ascii(Printer->notify.localmachine, localmachine,
2716                        sizeof(Printer->notify.localmachine));
2717
2718         /* Connect to the client machine and send a ReplyOpenPrinter */
2719
2720         if ( Printer->printer_type == SPLHND_SERVER)
2721                 snum = -1;
2722         else if ( (Printer->printer_type == SPLHND_PRINTER) &&
2723                         !get_printer_snum(p, handle, &snum, NULL) )
2724                 return WERR_BADFID;
2725
2726         if (!interpret_string_addr(&client_ss, p->client_address,
2727                                    AI_NUMERICHOST)) {
2728                 return WERR_SERVER_UNAVAILABLE;
2729         }
2730
2731         if(!srv_spoolss_replyopenprinter(snum, Printer->notify.localmachine,
2732                                         Printer->notify.printerlocal, 1,
2733                                         &Printer->notify.client_hnd, &client_ss))
2734                 return WERR_SERVER_UNAVAILABLE;
2735
2736         Printer->notify.client_connected=True;
2737
2738         return WERR_OK;
2739 }
2740
2741 /*******************************************************************
2742  * fill a notify_info_data with the servername
2743  ********************************************************************/
2744
2745 void spoolss_notify_server_name(int snum,
2746                                        SPOOL_NOTIFY_INFO_DATA *data,
2747                                        print_queue_struct *queue,
2748                                        NT_PRINTER_INFO_LEVEL *printer,
2749                                        TALLOC_CTX *mem_ctx)
2750 {
2751         smb_ucs2_t *temp = NULL;
2752         uint32 len;
2753
2754         len = rpcstr_push_talloc(mem_ctx, &temp, printer->info_2->servername);
2755         if (len == (uint32)-1) {
2756                 len = 0;
2757         }
2758
2759         data->notify_data.data.length = len;
2760         if (len) {
2761                 data->notify_data.data.string = (uint16 *)temp;
2762         } else {
2763                 data->notify_data.data.string = NULL;
2764         }
2765 }
2766
2767 /*******************************************************************
2768  * fill a notify_info_data with the printername (not including the servername).
2769  ********************************************************************/
2770
2771 void spoolss_notify_printer_name(int snum,
2772                                         SPOOL_NOTIFY_INFO_DATA *data,
2773                                         print_queue_struct *queue,
2774                                         NT_PRINTER_INFO_LEVEL *printer,
2775                                         TALLOC_CTX *mem_ctx)
2776 {
2777         smb_ucs2_t *temp = NULL;
2778         uint32 len;
2779
2780         /* the notify name should not contain the \\server\ part */
2781         char *p = strrchr(printer->info_2->printername, '\\');
2782
2783         if (!p) {
2784                 p = printer->info_2->printername;
2785         } else {
2786                 p++;
2787         }
2788
2789         len = rpcstr_push_talloc(mem_ctx, &temp, p);
2790         if (len == (uint32)-1) {
2791                 len = 0;
2792         }
2793
2794         data->notify_data.data.length = len;
2795         if (len) {
2796                 data->notify_data.data.string = (uint16 *)temp;
2797         } else {
2798                 data->notify_data.data.string = NULL;
2799         }
2800 }
2801
2802 /*******************************************************************
2803  * fill a notify_info_data with the servicename
2804  ********************************************************************/
2805
2806 void spoolss_notify_share_name(int snum,
2807                                       SPOOL_NOTIFY_INFO_DATA *data,
2808                                       print_queue_struct *queue,
2809                                       NT_PRINTER_INFO_LEVEL *printer,
2810                                       TALLOC_CTX *mem_ctx)
2811 {
2812         smb_ucs2_t *temp = NULL;
2813         uint32 len;
2814
2815         len = rpcstr_push_talloc(mem_ctx, &temp, lp_servicename(snum));
2816         if (len == (uint32)-1) {
2817                 len = 0;
2818         }
2819
2820         data->notify_data.data.length = len;
2821         if (len) {
2822                 data->notify_data.data.string = (uint16 *)temp;
2823         } else {
2824                 data->notify_data.data.string = NULL;
2825         }
2826
2827 }
2828
2829 /*******************************************************************
2830  * fill a notify_info_data with the port name
2831  ********************************************************************/
2832
2833 void spoolss_notify_port_name(int snum,
2834                                      SPOOL_NOTIFY_INFO_DATA *data,
2835                                      print_queue_struct *queue,
2836                                      NT_PRINTER_INFO_LEVEL *printer,
2837                                      TALLOC_CTX *mem_ctx)
2838 {
2839         smb_ucs2_t *temp = NULL;
2840         uint32 len;
2841
2842         /* even if it's strange, that's consistant in all the code */
2843
2844         len = rpcstr_push_talloc(mem_ctx, &temp, printer->info_2->portname);
2845         if (len == (uint32)-1) {
2846                 len = 0;
2847         }
2848
2849         data->notify_data.data.length = len;
2850         if (len) {
2851                 data->notify_data.data.string = (uint16 *)temp;
2852         } else {
2853                 data->notify_data.data.string = NULL;
2854         }
2855 }
2856
2857 /*******************************************************************
2858  * fill a notify_info_data with the printername
2859  * but it doesn't exist, have to see what to do
2860  ********************************************************************/
2861
2862 void spoolss_notify_driver_name(int snum,
2863                                        SPOOL_NOTIFY_INFO_DATA *data,
2864                                        print_queue_struct *queue,
2865                                        NT_PRINTER_INFO_LEVEL *printer,
2866                                        TALLOC_CTX *mem_ctx)
2867 {
2868         smb_ucs2_t *temp = NULL;
2869         uint32 len;
2870
2871         len = rpcstr_push_talloc(mem_ctx, &temp, printer->info_2->drivername);
2872         if (len == (uint32)-1) {
2873                 len = 0;
2874         }
2875
2876         data->notify_data.data.length = len;
2877         if (len) {
2878                 data->notify_data.data.string = (uint16 *)temp;
2879         } else {
2880                 data->notify_data.data.string = NULL;
2881         }
2882 }
2883
2884 /*******************************************************************
2885  * fill a notify_info_data with the comment
2886  ********************************************************************/
2887
2888 void spoolss_notify_comment(int snum,
2889                                    SPOOL_NOTIFY_INFO_DATA *data,
2890                                    print_queue_struct *queue,
2891                                    NT_PRINTER_INFO_LEVEL *printer,
2892                                    TALLOC_CTX *mem_ctx)
2893 {
2894         smb_ucs2_t *temp = NULL;
2895         uint32 len;
2896
2897         if (*printer->info_2->comment == '\0')
2898                 len = rpcstr_push_talloc(mem_ctx, &temp, lp_comment(snum));
2899         else
2900                 len = rpcstr_push_talloc(mem_ctx, &temp, printer->info_2->comment);
2901
2902         if (len == (uint32)-1) {
2903                 len = 0;
2904         }
2905         data->notify_data.data.length = len;
2906         if (len) {
2907                 data->notify_data.data.string = (uint16 *)temp;
2908         } else {
2909                 data->notify_data.data.string = NULL;
2910         }
2911 }
2912
2913 /*******************************************************************
2914  * fill a notify_info_data with the comment
2915  * location = "Room 1, floor 2, building 3"
2916  ********************************************************************/
2917
2918 void spoolss_notify_location(int snum,
2919                                     SPOOL_NOTIFY_INFO_DATA *data,
2920                                     print_queue_struct *queue,
2921                                     NT_PRINTER_INFO_LEVEL *printer,
2922                                     TALLOC_CTX *mem_ctx)
2923 {
2924         smb_ucs2_t *temp = NULL;
2925         uint32 len;
2926
2927         len = rpcstr_push_talloc(mem_ctx, &temp, printer->info_2->location);
2928         if (len == (uint32)-1) {
2929                 len = 0;
2930         }
2931
2932         data->notify_data.data.length = len;
2933         if (len) {
2934                 data->notify_data.data.string = (uint16 *)temp;
2935         } else {
2936                 data->notify_data.data.string = NULL;
2937         }
2938 }
2939
2940 /*******************************************************************
2941  * fill a notify_info_data with the device mode
2942  * jfm:xxxx don't to it for know but that's a real problem !!!
2943  ********************************************************************/
2944
2945 static void spoolss_notify_devmode(int snum,
2946                                    SPOOL_NOTIFY_INFO_DATA *data,
2947                                    print_queue_struct *queue,
2948                                    NT_PRINTER_INFO_LEVEL *printer,
2949                                    TALLOC_CTX *mem_ctx)
2950 {
2951         /* for a dummy implementation we have to zero the fields */
2952         data->notify_data.data.length = 0;
2953         data->notify_data.data.string = NULL;
2954 }
2955
2956 /*******************************************************************
2957  * fill a notify_info_data with the separator file name
2958  ********************************************************************/
2959
2960 void spoolss_notify_sepfile(int snum,
2961                                    SPOOL_NOTIFY_INFO_DATA *data,
2962                                    print_queue_struct *queue,
2963                                    NT_PRINTER_INFO_LEVEL *printer,
2964                                    TALLOC_CTX *mem_ctx)
2965 {
2966         smb_ucs2_t *temp = NULL;
2967         uint32 len;
2968
2969         len = rpcstr_push_talloc(mem_ctx, &temp, printer->info_2->sepfile);
2970         if (len == (uint32)-1) {
2971                 len = 0;
2972         }
2973
2974         data->notify_data.data.length = len;
2975         if (len) {
2976                 data->notify_data.data.string = (uint16 *)temp;
2977         } else {
2978                 data->notify_data.data.string = NULL;
2979         }
2980 }
2981
2982 /*******************************************************************
2983  * fill a notify_info_data with the print processor
2984  * jfm:xxxx return always winprint to indicate we don't do anything to it
2985  ********************************************************************/
2986
2987 void spoolss_notify_print_processor(int snum,
2988                                            SPOOL_NOTIFY_INFO_DATA *data,
2989                                            print_queue_struct *queue,
2990                                            NT_PRINTER_INFO_LEVEL *printer,
2991                                            TALLOC_CTX *mem_ctx)
2992 {
2993         smb_ucs2_t *temp = NULL;
2994         uint32 len;
2995
2996         len = rpcstr_push_talloc(mem_ctx, &temp, printer->info_2->printprocessor);
2997         if (len == (uint32)-1) {
2998                 len = 0;
2999         }
3000
3001         data->notify_data.data.length = len;
3002         if (len) {
3003                 data->notify_data.data.string = (uint16 *)temp;
3004         } else {
3005                 data->notify_data.data.string = NULL;
3006         }
3007 }
3008
3009 /*******************************************************************
3010  * fill a notify_info_data with the print processor options
3011  * jfm:xxxx send an empty string
3012  ********************************************************************/
3013
3014 void spoolss_notify_parameters(int snum,
3015                                       SPOOL_NOTIFY_INFO_DATA *data,
3016                                       print_queue_struct *queue,
3017                                       NT_PRINTER_INFO_LEVEL *printer,
3018                                       TALLOC_CTX *mem_ctx)
3019 {
3020         smb_ucs2_t *temp = NULL;
3021         uint32 len;
3022
3023         len = rpcstr_push_talloc(mem_ctx, &temp, printer->info_2->parameters);
3024         if (len == (uint32)-1) {
3025                 len = 0;
3026         }
3027
3028         data->notify_data.data.length = len;
3029         if (len) {
3030                 data->notify_data.data.string = (uint16 *)temp;
3031         } else {
3032                 data->notify_data.data.string = NULL;
3033         }
3034 }
3035
3036 /*******************************************************************
3037  * fill a notify_info_data with the data type
3038  * jfm:xxxx always send RAW as data type
3039  ********************************************************************/
3040
3041 void spoolss_notify_datatype(int snum,
3042                                     SPOOL_NOTIFY_INFO_DATA *data,
3043                                     print_queue_struct *queue,
3044                                     NT_PRINTER_INFO_LEVEL *printer,
3045                                     TALLOC_CTX *mem_ctx)
3046 {
3047         smb_ucs2_t *temp = NULL;
3048         uint32 len;
3049
3050         len = rpcstr_push_talloc(mem_ctx, &temp, printer->info_2->datatype);
3051         if (len == (uint32)-1) {
3052                 len = 0;
3053         }
3054
3055         data->notify_data.data.length = len;
3056         if (len) {
3057                 data->notify_data.data.string = (uint16 *)temp;
3058         } else {
3059                 data->notify_data.data.string = NULL;
3060         }
3061 }
3062
3063 /*******************************************************************
3064  * fill a notify_info_data with the security descriptor
3065  * jfm:xxxx send an null pointer to say no security desc
3066  * have to implement security before !
3067  ********************************************************************/
3068
3069 static void spoolss_notify_security_desc(int snum,
3070                                          SPOOL_NOTIFY_INFO_DATA *data,
3071                                          print_queue_struct *queue,
3072                                          NT_PRINTER_INFO_LEVEL *printer,
3073                                          TALLOC_CTX *mem_ctx)
3074 {
3075         data->notify_data.sd.size = printer->info_2->secdesc_buf->sd_size;
3076         data->notify_data.sd.desc = dup_sec_desc( mem_ctx, printer->info_2->secdesc_buf->sd ) ;
3077 }
3078
3079 /*******************************************************************
3080  * fill a notify_info_data with the attributes
3081  * jfm:xxxx a samba printer is always shared
3082  ********************************************************************/
3083
3084 void spoolss_notify_attributes(int snum,
3085                                       SPOOL_NOTIFY_INFO_DATA *data,
3086                                       print_queue_struct *queue,
3087                                       NT_PRINTER_INFO_LEVEL *printer,
3088                                       TALLOC_CTX *mem_ctx)
3089 {
3090         data->notify_data.value[0] = printer->info_2->attributes;
3091         data->notify_data.value[1] = 0;
3092 }
3093
3094 /*******************************************************************
3095  * fill a notify_info_data with the priority
3096  ********************************************************************/
3097
3098 static void spoolss_notify_priority(int snum,
3099                                     SPOOL_NOTIFY_INFO_DATA *data,
3100                                     print_queue_struct *queue,
3101                                     NT_PRINTER_INFO_LEVEL *printer,
3102                                     TALLOC_CTX *mem_ctx)
3103 {
3104         data->notify_data.value[0] = printer->info_2->priority;
3105         data->notify_data.value[1] = 0;
3106 }
3107
3108 /*******************************************************************
3109  * fill a notify_info_data with the default priority
3110  ********************************************************************/
3111
3112 static void spoolss_notify_default_priority(int snum,
3113                                             SPOOL_NOTIFY_INFO_DATA *data,
3114                                             print_queue_struct *queue,
3115                                             NT_PRINTER_INFO_LEVEL *printer,
3116                                             TALLOC_CTX *mem_ctx)
3117 {
3118         data->notify_data.value[0] = printer->info_2->default_priority;
3119         data->notify_data.value[1] = 0;
3120 }
3121
3122 /*******************************************************************
3123  * fill a notify_info_data with the start time
3124  ********************************************************************/
3125
3126 static void spoolss_notify_start_time(int snum,
3127                                       SPOOL_NOTIFY_INFO_DATA *data,
3128                                       print_queue_struct *queue,
3129                                       NT_PRINTER_INFO_LEVEL *printer,
3130                                       TALLOC_CTX *mem_ctx)
3131 {
3132         data->notify_data.value[0] = printer->info_2->starttime;
3133         data->notify_data.value[1] = 0;
3134 }
3135
3136 /*******************************************************************
3137  * fill a notify_info_data with the until time
3138  ********************************************************************/
3139
3140 static void spoolss_notify_until_time(int snum,
3141                                       SPOOL_NOTIFY_INFO_DATA *data,
3142                                       print_queue_struct *queue,
3143                                       NT_PRINTER_INFO_LEVEL *printer,
3144                                       TALLOC_CTX *mem_ctx)
3145 {
3146         data->notify_data.value[0] = printer->info_2->untiltime;
3147         data->notify_data.value[1] = 0;
3148 }
3149
3150 /*******************************************************************
3151  * fill a notify_info_data with the status
3152  ********************************************************************/
3153
3154 static void spoolss_notify_status(int snum,
3155                                   SPOOL_NOTIFY_INFO_DATA *data,
3156                                   print_queue_struct *queue,
3157                                   NT_PRINTER_INFO_LEVEL *printer,
3158                                   TALLOC_CTX *mem_ctx)
3159 {
3160         print_status_struct status;
3161
3162         print_queue_length(snum, &status);
3163         data->notify_data.value[0]=(uint32) status.status;
3164         data->notify_data.value[1] = 0;
3165 }
3166
3167 /*******************************************************************
3168  * fill a notify_info_data with the number of jobs queued
3169  ********************************************************************/
3170
3171 void spoolss_notify_cjobs(int snum,
3172                                  SPOOL_NOTIFY_INFO_DATA *data,
3173                                  print_queue_struct *queue,
3174                                  NT_PRINTER_INFO_LEVEL *printer,
3175                                  TALLOC_CTX *mem_ctx)
3176 {
3177         data->notify_data.value[0] = print_queue_length(snum, NULL);
3178         data->notify_data.value[1] = 0;
3179 }
3180
3181 /*******************************************************************
3182  * fill a notify_info_data with the average ppm
3183  ********************************************************************/
3184
3185 static void spoolss_notify_average_ppm(int snum,
3186                                        SPOOL_NOTIFY_INFO_DATA *data,
3187                                        print_queue_struct *queue,
3188                                        NT_PRINTER_INFO_LEVEL *printer,
3189                                        TALLOC_CTX *mem_ctx)
3190 {
3191         /* always respond 8 pages per minutes */
3192         /* a little hard ! */
3193         data->notify_data.value[0] = printer->info_2->averageppm;
3194         data->notify_data.value[1] = 0;
3195 }
3196
3197 /*******************************************************************
3198  * fill a notify_info_data with username
3199  ********************************************************************/
3200
3201 static void spoolss_notify_username(int snum,
3202                                     SPOOL_NOTIFY_INFO_DATA *data,
3203                                     print_queue_struct *queue,
3204                                     NT_PRINTER_INFO_LEVEL *printer,
3205                                     TALLOC_CTX *mem_ctx)
3206 {
3207         smb_ucs2_t *temp = NULL;
3208         uint32 len;
3209
3210         len = rpcstr_push_talloc(mem_ctx, &temp, queue->fs_user);
3211         if (len == (uint32)-1) {
3212                 len = 0;
3213         }
3214
3215         data->notify_data.data.length = len;
3216         if (len) {
3217                 data->notify_data.data.string = (uint16 *)temp;
3218         } else {
3219                 data->notify_data.data.string = NULL;
3220         }
3221 }
3222
3223 /*******************************************************************
3224  * fill a notify_info_data with job status
3225  ********************************************************************/
3226
3227 static void spoolss_notify_job_status(int snum,
3228                                       SPOOL_NOTIFY_INFO_DATA *data,
3229                                       print_queue_struct *queue,
3230                                       NT_PRINTER_INFO_LEVEL *printer,
3231                                       TALLOC_CTX *mem_ctx)
3232 {
3233         data->notify_data.value[0]=nt_printj_status(queue->status);
3234         data->notify_data.value[1] = 0;
3235 }
3236
3237 /*******************************************************************
3238  * fill a notify_info_data with job name
3239  ********************************************************************/
3240
3241 static void spoolss_notify_job_name(int snum,
3242                                     SPOOL_NOTIFY_INFO_DATA *data,
3243                                     print_queue_struct *queue,
3244                                     NT_PRINTER_INFO_LEVEL *printer,
3245                                     TALLOC_CTX *mem_ctx)
3246 {
3247         smb_ucs2_t *temp = NULL;
3248         uint32 len;
3249
3250         len = rpcstr_push_talloc(mem_ctx, &temp, queue->fs_file);
3251         if (len == (uint32)-1) {
3252                 len = 0;
3253         }
3254
3255         data->notify_data.data.length = len;
3256         if (len) {
3257                 data->notify_data.data.string = (uint16 *)temp;
3258         } else {
3259                 data->notify_data.data.string = NULL;
3260         }
3261 }
3262
3263 /*******************************************************************
3264  * fill a notify_info_data with job status
3265  ********************************************************************/
3266
3267 static void spoolss_notify_job_status_string(int snum,
3268                                              SPOOL_NOTIFY_INFO_DATA *data,
3269                                              print_queue_struct *queue,
3270                                              NT_PRINTER_INFO_LEVEL *printer,
3271                                              TALLOC_CTX *mem_ctx)
3272 {
3273         /*
3274          * Now we're returning job status codes we just return a "" here. JRA.
3275          */
3276
3277         const char *p = "";
3278         smb_ucs2_t *temp = NULL;
3279         uint32 len;
3280
3281 #if 0 /* NO LONGER NEEDED - JRA. 02/22/2001 */
3282         p = "unknown";
3283
3284         switch (queue->status) {
3285         case LPQ_QUEUED:
3286                 p = "Queued";
3287                 break;
3288         case LPQ_PAUSED:
3289                 p = "";    /* NT provides the paused string */
3290                 break;
3291         case LPQ_SPOOLING:
3292                 p = "Spooling";
3293                 break;
3294         case LPQ_PRINTING:
3295                 p = "Printing";
3296                 break;
3297         }
3298 #endif /* NO LONGER NEEDED. */
3299
3300         len = rpcstr_push_talloc(mem_ctx, &temp, p);
3301         if (len == (uint32)-1) {
3302                 len = 0;
3303         }
3304
3305         data->notify_data.data.length = len;
3306         if (len) {
3307                 data->notify_data.data.string = (uint16 *)temp;
3308         } else {
3309                 data->notify_data.data.string = NULL;
3310         }
3311 }
3312
3313 /*******************************************************************
3314  * fill a notify_info_data with job time
3315  ********************************************************************/
3316
3317 static void spoolss_notify_job_time(int snum,
3318                                     SPOOL_NOTIFY_INFO_DATA *data,
3319                                     print_queue_struct *queue,
3320                                     NT_PRINTER_INFO_LEVEL *printer,
3321                                     TALLOC_CTX *mem_ctx)
3322 {
3323         data->notify_data.value[0]=0x0;
3324         data->notify_data.value[1]=0;
3325 }
3326
3327 /*******************************************************************
3328  * fill a notify_info_data with job size
3329  ********************************************************************/
3330
3331 static void spoolss_notify_job_size(int snum,
3332                                     SPOOL_NOTIFY_INFO_DATA *data,
3333                                     print_queue_struct *queue,
3334                                     NT_PRINTER_INFO_LEVEL *printer,
3335                                     TALLOC_CTX *mem_ctx)
3336 {
3337         data->notify_data.value[0]=queue->size;
3338         data->notify_data.value[1]=0;
3339 }
3340
3341 /*******************************************************************
3342  * fill a notify_info_data with page info
3343  ********************************************************************/
3344 static void spoolss_notify_total_pages(int snum,
3345                                 SPOOL_NOTIFY_INFO_DATA *data,
3346                                 print_queue_struct *queue,
3347                                 NT_PRINTER_INFO_LEVEL *printer,
3348                                 TALLOC_CTX *mem_ctx)
3349 {
3350         data->notify_data.value[0]=queue->page_count;
3351         data->notify_data.value[1]=0;
3352 }
3353
3354 /*******************************************************************
3355  * fill a notify_info_data with pages printed info.
3356  ********************************************************************/
3357 static void spoolss_notify_pages_printed(int snum,
3358                                 SPOOL_NOTIFY_INFO_DATA *data,
3359                                 print_queue_struct *queue,
3360                                 NT_PRINTER_INFO_LEVEL *printer,
3361                                 TALLOC_CTX *mem_ctx)
3362 {
3363         data->notify_data.value[0]=0;  /* Add code when back-end tracks this */
3364         data->notify_data.value[1]=0;
3365 }
3366
3367 /*******************************************************************
3368  Fill a notify_info_data with job position.
3369  ********************************************************************/
3370
3371 static void spoolss_notify_job_position(int snum,
3372                                         SPOOL_NOTIFY_INFO_DATA *data,
3373                                         print_queue_struct *queue,
3374                                         NT_PRINTER_INFO_LEVEL *printer,
3375                                         TALLOC_CTX *mem_ctx)
3376 {
3377         data->notify_data.value[0]=queue->job;
3378         data->notify_data.value[1]=0;
3379 }
3380
3381 /*******************************************************************
3382  Fill a notify_info_data with submitted time.
3383  ********************************************************************/
3384
3385 static void spoolss_notify_submitted_time(int snum,
3386                                           SPOOL_NOTIFY_INFO_DATA *data,
3387                                           print_queue_struct *queue,
3388                                           NT_PRINTER_INFO_LEVEL *printer,
3389                                           TALLOC_CTX *mem_ctx)
3390 {
3391         struct tm *t;
3392         uint32 len;
3393         SYSTEMTIME st;
3394         char *p;
3395
3396         t=gmtime(&queue->time);
3397
3398         len = sizeof(SYSTEMTIME);
3399
3400         data->notify_data.data.length = len;
3401         data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
3402
3403         if (!data->notify_data.data.string) {
3404                 data->notify_data.data.length = 0;
3405                 return;
3406         }
3407
3408         make_systemtime(&st, t);
3409
3410         /*
3411          * Systemtime must be linearized as a set of UINT16's.
3412          * Fix from Benjamin (Bj) Kuit bj@it.uts.edu.au
3413          */
3414
3415         p = (char *)data->notify_data.data.string;
3416         SSVAL(p, 0, st.year);
3417         SSVAL(p, 2, st.month);
3418         SSVAL(p, 4, st.dayofweek);
3419         SSVAL(p, 6, st.day);
3420         SSVAL(p, 8, st.hour);
3421         SSVAL(p, 10, st.minute);
3422         SSVAL(p, 12, st.second);
3423         SSVAL(p, 14, st.milliseconds);
3424 }
3425
3426 struct s_notify_info_data_table
3427 {
3428         uint16 type;
3429         uint16 field;
3430         const char *name;
3431         uint32 size;
3432         void (*fn) (int snum, SPOOL_NOTIFY_INFO_DATA *data,
3433                     print_queue_struct *queue,
3434                     NT_PRINTER_INFO_LEVEL *printer, TALLOC_CTX *mem_ctx);
3435 };
3436
3437 /* A table describing the various print notification constants and
3438    whether the notification data is a pointer to a variable sized
3439    buffer, a one value uint32 or a two value uint32. */
3440
3441 static const struct s_notify_info_data_table notify_info_data_table[] =
3442 {
3443 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SERVER_NAME,         "PRINTER_NOTIFY_SERVER_NAME",         NOTIFY_STRING,   spoolss_notify_server_name },
3444 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PRINTER_NAME,        "PRINTER_NOTIFY_PRINTER_NAME",        NOTIFY_STRING,   spoolss_notify_printer_name },
3445 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SHARE_NAME,          "PRINTER_NOTIFY_SHARE_NAME",          NOTIFY_STRING,   spoolss_notify_share_name },
3446 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PORT_NAME,           "PRINTER_NOTIFY_PORT_NAME",           NOTIFY_STRING,   spoolss_notify_port_name },
3447 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DRIVER_NAME,         "PRINTER_NOTIFY_DRIVER_NAME",         NOTIFY_STRING,   spoolss_notify_driver_name },
3448 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_COMMENT,             "PRINTER_NOTIFY_COMMENT",             NOTIFY_STRING,   spoolss_notify_comment },
3449 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_LOCATION,            "PRINTER_NOTIFY_LOCATION",            NOTIFY_STRING,   spoolss_notify_location },
3450 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DEVMODE,             "PRINTER_NOTIFY_DEVMODE",             NOTIFY_POINTER,   spoolss_notify_devmode },
3451 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SEPFILE,             "PRINTER_NOTIFY_SEPFILE",             NOTIFY_STRING,   spoolss_notify_sepfile },
3452 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PRINT_PROCESSOR,     "PRINTER_NOTIFY_PRINT_PROCESSOR",     NOTIFY_STRING,   spoolss_notify_print_processor },
3453 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PARAMETERS,          "PRINTER_NOTIFY_PARAMETERS",          NOTIFY_STRING,   spoolss_notify_parameters },
3454 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DATATYPE,            "PRINTER_NOTIFY_DATATYPE",            NOTIFY_STRING,   spoolss_notify_datatype },
3455 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SECURITY_DESCRIPTOR, "PRINTER_NOTIFY_SECURITY_DESCRIPTOR", NOTIFY_SECDESC,   spoolss_notify_security_desc },
3456 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_ATTRIBUTES,          "PRINTER_NOTIFY_ATTRIBUTES",          NOTIFY_ONE_VALUE, spoolss_notify_attributes },
3457 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PRIORITY,            "PRINTER_NOTIFY_PRIORITY",            NOTIFY_ONE_VALUE, spoolss_notify_priority },
3458 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DEFAULT_PRIORITY,    "PRINTER_NOTIFY_DEFAULT_PRIORITY",    NOTIFY_ONE_VALUE, spoolss_notify_default_priority },
3459 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_START_TIME,          "PRINTER_NOTIFY_START_TIME",          NOTIFY_ONE_VALUE, spoolss_notify_start_time },
3460 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_UNTIL_TIME,          "PRINTER_NOTIFY_UNTIL_TIME",          NOTIFY_ONE_VALUE, spoolss_notify_until_time },
3461 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_STATUS,              "PRINTER_NOTIFY_STATUS",              NOTIFY_ONE_VALUE, spoolss_notify_status },
3462 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_STATUS_STRING,       "PRINTER_NOTIFY_STATUS_STRING",       NOTIFY_POINTER,   NULL },
3463 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_CJOBS,               "PRINTER_NOTIFY_CJOBS",               NOTIFY_ONE_VALUE, spoolss_notify_cjobs },
3464 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_AVERAGE_PPM,         "PRINTER_NOTIFY_AVERAGE_PPM",         NOTIFY_ONE_VALUE, spoolss_notify_average_ppm },
3465 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_TOTAL_PAGES,         "PRINTER_NOTIFY_TOTAL_PAGES",         NOTIFY_POINTER,   NULL },
3466 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PAGES_PRINTED,       "PRINTER_NOTIFY_PAGES_PRINTED",       NOTIFY_POINTER,   NULL },
3467 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_TOTAL_BYTES,         "PRINTER_NOTIFY_TOTAL_BYTES",         NOTIFY_POINTER,   NULL },
3468 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_BYTES_PRINTED,       "PRINTER_NOTIFY_BYTES_PRINTED",       NOTIFY_POINTER,   NULL },
3469 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_PRINTER_NAME,            "JOB_NOTIFY_PRINTER_NAME",            NOTIFY_STRING,   spoolss_notify_printer_name },
3470 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_MACHINE_NAME,            "JOB_NOTIFY_MACHINE_NAME",            NOTIFY_STRING,   spoolss_notify_server_name },
3471 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_PORT_NAME,               "JOB_NOTIFY_PORT_NAME",               NOTIFY_STRING,   spoolss_notify_port_name },
3472 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_USER_NAME,               "JOB_NOTIFY_USER_NAME",               NOTIFY_STRING,   spoolss_notify_username },
3473 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_NOTIFY_NAME,             "JOB_NOTIFY_NOTIFY_NAME",             NOTIFY_STRING,   spoolss_notify_username },
3474 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_DATATYPE,                "JOB_NOTIFY_DATATYPE",                NOTIFY_STRING,   spoolss_notify_datatype },
3475 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_PRINT_PROCESSOR,         "JOB_NOTIFY_PRINT_PROCESSOR",         NOTIFY_STRING,   spoolss_notify_print_processor },
3476 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_PARAMETERS,              "JOB_NOTIFY_PARAMETERS",              NOTIFY_STRING,   spoolss_notify_parameters },
3477 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_DRIVER_NAME,             "JOB_NOTIFY_DRIVER_NAME",             NOTIFY_STRING,   spoolss_notify_driver_name },
3478 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_DEVMODE,                 "JOB_NOTIFY_DEVMODE",                 NOTIFY_POINTER,   spoolss_notify_devmode },
3479 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_STATUS,                  "JOB_NOTIFY_STATUS",                  NOTIFY_ONE_VALUE, spoolss_notify_job_status },
3480 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_STATUS_STRING,           "JOB_NOTIFY_STATUS_STRING",           NOTIFY_STRING,   spoolss_notify_job_status_string },
3481 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_SECURITY_DESCRIPTOR,     "JOB_NOTIFY_SECURITY_DESCRIPTOR",     NOTIFY_POINTER,   NULL },
3482 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_DOCUMENT,                "JOB_NOTIFY_DOCUMENT",                NOTIFY_STRING,   spoolss_notify_job_name },
3483 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_PRIORITY,                "JOB_NOTIFY_PRIORITY",                NOTIFY_ONE_VALUE, spoolss_notify_priority },
3484 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_POSITION,                "JOB_NOTIFY_POSITION",                NOTIFY_ONE_VALUE, spoolss_notify_job_position },
3485 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_SUBMITTED,               "JOB_NOTIFY_SUBMITTED",               NOTIFY_POINTER,   spoolss_notify_submitted_time },
3486 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_START_TIME,              "JOB_NOTIFY_START_TIME",              NOTIFY_ONE_VALUE, spoolss_notify_start_time },
3487 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_UNTIL_TIME,              "JOB_NOTIFY_UNTIL_TIME",              NOTIFY_ONE_VALUE, spoolss_notify_until_time },
3488 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_TIME,                    "JOB_NOTIFY_TIME",                    NOTIFY_ONE_VALUE, spoolss_notify_job_time },
3489 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_TOTAL_PAGES,             "JOB_NOTIFY_TOTAL_PAGES",             NOTIFY_ONE_VALUE, spoolss_notify_total_pages },
3490 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_PAGES_PRINTED,           "JOB_NOTIFY_PAGES_PRINTED",           NOTIFY_ONE_VALUE, spoolss_notify_pages_printed },
3491 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_TOTAL_BYTES,             "JOB_NOTIFY_TOTAL_BYTES",             NOTIFY_ONE_VALUE, spoolss_notify_job_size },
3492 { PRINT_TABLE_END, 0x0, NULL, 0x0, NULL },
3493 };
3494
3495 /*******************************************************************
3496  Return the size of info_data structure.
3497 ********************************************************************/
3498
3499 static uint32 size_of_notify_info_data(uint16 type, uint16 field)
3500 {
3501         int i=0;
3502
3503         for (i = 0; i < (sizeof(notify_info_data_table)/sizeof(struct s_notify_info_data_table)); i++) {
3504                 if ( (notify_info_data_table[i].type == type)
3505                         && (notify_info_data_table[i].field == field) ) {
3506                         switch(notify_info_data_table[i].size) {
3507                                 case NOTIFY_ONE_VALUE:
3508                                 case NOTIFY_TWO_VALUE:
3509                                         return 1;
3510                                 case NOTIFY_STRING:
3511                                         return 2;
3512
3513                                 /* The only pointer notify data I have seen on
3514                                    the wire is the submitted time and this has
3515                                    the notify size set to 4. -tpot */
3516
3517                                 case NOTIFY_POINTER:
3518                                         return 4;
3519
3520                                 case NOTIFY_SECDESC:
3521                                         return 5;
3522                         }
3523                 }
3524         }
3525
3526         DEBUG(5, ("invalid notify data type %d/%d\n", type, field));
3527
3528         return 0;
3529 }
3530
3531 /*******************************************************************
3532  Return the type of notify_info_data.
3533 ********************************************************************/
3534
3535 static uint32 type_of_notify_info_data(uint16 type, uint16 field)
3536 {
3537         uint32 i=0;
3538
3539         for (i = 0; i < (sizeof(notify_info_data_table)/sizeof(struct s_notify_info_data_table)); i++) {
3540                 if (notify_info_data_table[i].type == type &&
3541                     notify_info_data_table[i].field == field)
3542                         return notify_info_data_table[i].size;
3543         }
3544
3545         return 0;
3546 }
3547
3548 /****************************************************************************
3549 ****************************************************************************/
3550
3551 static bool search_notify(uint16 type, uint16 field, int *value)
3552 {
3553         int i;
3554
3555         for (i = 0; notify_info_data_table[i].type != PRINT_TABLE_END; i++) {
3556                 if (notify_info_data_table[i].type == type &&
3557                     notify_info_data_table[i].field == field &&
3558                     notify_info_data_table[i].fn != NULL) {
3559                         *value = i;
3560                         return True;
3561                 }
3562         }
3563
3564         return False;
3565 }
3566
3567 /****************************************************************************
3568 ****************************************************************************/
3569
3570 void construct_info_data(SPOOL_NOTIFY_INFO_DATA *info_data, uint16 type, uint16 field, int id)
3571 {
3572         info_data->type     = type;
3573         info_data->field    = field;
3574         info_data->reserved = 0;
3575
3576         info_data->size     = size_of_notify_info_data(type, field);
3577         info_data->enc_type = type_of_notify_info_data(type, field);
3578
3579         info_data->id = id;
3580 }
3581
3582 /*******************************************************************
3583  *
3584  * fill a notify_info struct with info asked
3585  *
3586  ********************************************************************/
3587
3588 static bool construct_notify_printer_info(Printer_entry *print_hnd, SPOOL_NOTIFY_INFO *info, int
3589                                           snum, SPOOL_NOTIFY_OPTION_TYPE
3590                                           *option_type, uint32 id,
3591                                           TALLOC_CTX *mem_ctx)
3592 {
3593         int field_num,j;
3594         uint16 type;
3595         uint16 field;
3596
3597         SPOOL_NOTIFY_INFO_DATA *current_data;
3598         NT_PRINTER_INFO_LEVEL *printer = NULL;
3599         print_queue_struct *queue=NULL;
3600
3601         type=option_type->type;
3602
3603         DEBUG(4,("construct_notify_printer_info: Notify type: [%s], number of notify info: [%d] on printer: [%s]\n",
3604                 (option_type->type==PRINTER_NOTIFY_TYPE?"PRINTER_NOTIFY_TYPE":"JOB_NOTIFY_TYPE"),
3605                 option_type->count, lp_servicename(snum)));
3606
3607         if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &printer, 2, lp_const_servicename(snum))))
3608                 return False;
3609
3610         for(field_num=0; field_num<option_type->count; field_num++) {
3611                 field = option_type->fields[field_num];
3612
3613                 DEBUG(4,("construct_notify_printer_info: notify [%d]: type [%x], field [%x]\n", field_num, type, field));
3614
3615                 if (!search_notify(type, field, &j) )
3616                         continue;
3617
3618                 if((info->data=SMB_REALLOC_ARRAY(info->data, SPOOL_NOTIFY_INFO_DATA, info->count+1)) == NULL) {
3619                         DEBUG(2,("construct_notify_printer_info: failed to enlarge buffer info->data!\n"));
3620                         free_a_printer(&printer, 2);
3621                         return False;
3622                 }
3623
3624                 current_data = &info->data[info->count];
3625
3626                 construct_info_data(current_data, type, field, id);
3627
3628                 DEBUG(10,("construct_notify_printer_info: calling [%s]  snum=%d  printername=[%s])\n",
3629                                 notify_info_data_table[j].name, snum, printer->info_2->printername ));
3630
3631                 notify_info_data_table[j].fn(snum, current_data, queue,
3632                                              printer, mem_ctx);
3633
3634                 info->count++;
3635         }
3636
3637         free_a_printer(&printer, 2);
3638         return True;
3639 }
3640
3641 /*******************************************************************
3642  *
3643  * fill a notify_info struct with info asked
3644  *
3645  ********************************************************************/
3646
3647 static bool construct_notify_jobs_info(print_queue_struct *queue,
3648                                        SPOOL_NOTIFY_INFO *info,
3649                                        NT_PRINTER_INFO_LEVEL *printer,
3650                                        int snum, SPOOL_NOTIFY_OPTION_TYPE
3651                                        *option_type, uint32 id,
3652                                        TALLOC_CTX *mem_ctx)
3653 {
3654         int field_num,j;
3655         uint16 type;
3656         uint16 field;
3657
3658         SPOOL_NOTIFY_INFO_DATA *current_data;
3659
3660         DEBUG(4,("construct_notify_jobs_info\n"));
3661
3662         type = option_type->type;
3663
3664         DEBUGADD(4,("Notify type: [%s], number of notify info: [%d]\n",
3665                 (option_type->type==PRINTER_NOTIFY_TYPE?"PRINTER_NOTIFY_TYPE":"JOB_NOTIFY_TYPE"),
3666                 option_type->count));
3667
3668         for(field_num=0; field_num<option_type->count; field_num++) {
3669                 field = option_type->fields[field_num];
3670
3671                 if (!search_notify(type, field, &j) )
3672                         continue;
3673
3674                 if((info->data=SMB_REALLOC_ARRAY(info->data, SPOOL_NOTIFY_INFO_DATA, info->count+1)) == NULL) {
3675                         DEBUG(2,("construct_notify_jobs_info: failed to enlarg buffer info->data!\n"));
3676                         return False;
3677                 }
3678
3679                 current_data=&(info->data[info->count]);
3680
3681                 construct_info_data(current_data, type, field, id);
3682                 notify_info_data_table[j].fn(snum, current_data, queue,
3683                                              printer, mem_ctx);
3684                 info->count++;
3685         }
3686
3687         return True;
3688 }
3689
3690 /*
3691  * JFM: The enumeration is not that simple, it's even non obvious.
3692  *
3693  * let's take an example: I want to monitor the PRINTER SERVER for
3694  * the printer's name and the number of jobs currently queued.
3695  * So in the NOTIFY_OPTION, I have one NOTIFY_OPTION_TYPE structure.
3696  * Its type is PRINTER_NOTIFY_TYPE and it has 2 fields NAME and CJOBS.
3697  *
3698  * I have 3 printers on the back of my server.
3699  *
3700  * Now the response is a NOTIFY_INFO structure, with 6 NOTIFY_INFO_DATA
3701  * structures.
3702  *   Number     Data                    Id
3703  *      1       printer 1 name          1
3704  *      2       printer 1 cjob          1
3705  *      3       printer 2 name          2
3706  *      4       printer 2 cjob          2
3707  *      5       printer 3 name          3
3708  *      6       printer 3 name          3
3709  *
3710  * that's the print server case, the printer case is even worse.
3711  */
3712
3713 /*******************************************************************
3714  *
3715  * enumerate all printers on the printserver
3716  * fill a notify_info struct with info asked
3717  *
3718  ********************************************************************/
3719
3720 static WERROR printserver_notify_info(pipes_struct *p, POLICY_HND *hnd,
3721                                       SPOOL_NOTIFY_INFO *info,
3722                                       TALLOC_CTX *mem_ctx)
3723 {
3724         int snum;
3725         Printer_entry *Printer=find_printer_index_by_hnd(p, hnd);
3726         int n_services=lp_numservices();
3727         int i;
3728         SPOOL_NOTIFY_OPTION *option;
3729         SPOOL_NOTIFY_OPTION_TYPE *option_type;
3730
3731         DEBUG(4,("printserver_notify_info\n"));
3732
3733         if (!Printer)
3734                 return WERR_BADFID;
3735
3736         option=Printer->notify.option;
3737         info->version=2;
3738         info->data=NULL;
3739         info->count=0;
3740
3741         /* a bug in xp sp2 rc2 causes it to send a fnpcn request without
3742            sending a ffpcn() request first */
3743
3744         if ( !option )
3745                 return WERR_BADFID;
3746
3747         for (i=0; i<option->count; i++) {
3748                 option_type=&(option->ctr.type[i]);
3749
3750                 if (option_type->type!=PRINTER_NOTIFY_TYPE)
3751                         continue;
3752
3753                 for (snum=0; snum<n_services; snum++)
3754                 {
3755                         if ( lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) )
3756                                 construct_notify_printer_info ( Printer, info, snum, option_type, snum, mem_ctx );
3757                 }
3758         }
3759
3760 #if 0
3761         /*
3762          * Debugging information, don't delete.
3763          */
3764
3765         DEBUG(1,("dumping the NOTIFY_INFO\n"));
3766         DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
3767         DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3768
3769         for (i=0; i<info->count; i++) {
3770                 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3771                 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
3772                 info->data[i].id, info->data[i].size, info->data[i].enc_type));
3773         }
3774 #endif
3775
3776         return WERR_OK;
3777 }
3778
3779 /*******************************************************************
3780  *
3781  * fill a notify_info struct with info asked
3782  *
3783  ********************************************************************/
3784
3785 static WERROR printer_notify_info(pipes_struct *p, POLICY_HND *hnd, SPOOL_NOTIFY_INFO *info,
3786                                   TALLOC_CTX *mem_ctx)
3787 {
3788         int snum;
3789         Printer_entry *Printer=find_printer_index_by_hnd(p, hnd);
3790         int i;
3791         uint32 id;
3792         SPOOL_NOTIFY_OPTION *option;
3793         SPOOL_NOTIFY_OPTION_TYPE *option_type;
3794         int count,j;
3795         print_queue_struct *queue=NULL;
3796         print_status_struct status;
3797
3798         DEBUG(4,("printer_notify_info\n"));
3799
3800         if (!Printer)
3801                 return WERR_BADFID;
3802
3803         option=Printer->notify.option;
3804         id = 0x0;
3805         info->version=2;
3806         info->data=NULL;
3807         info->count=0;
3808
3809         /* a bug in xp sp2 rc2 causes it to send a fnpcn request without
3810            sending a ffpcn() request first */
3811
3812         if ( !option )
3813                 return WERR_BADFID;
3814
3815         get_printer_snum(p, hnd, &snum, NULL);
3816
3817         for (i=0; i<option->count; i++) {
3818                 option_type=&option->ctr.type[i];
3819
3820                 switch ( option_type->type ) {
3821                 case PRINTER_NOTIFY_TYPE:
3822                         if(construct_notify_printer_info(Printer, info, snum,
3823                                                          option_type, id,
3824                                                          mem_ctx))
3825                                 id--;
3826                         break;
3827
3828                 case JOB_NOTIFY_TYPE: {
3829                         NT_PRINTER_INFO_LEVEL *printer = NULL;
3830
3831                         count = print_queue_status(snum, &queue, &status);
3832
3833                         if (!W_ERROR_IS_OK(get_a_printer(Printer, &printer, 2, lp_const_servicename(snum))))
3834                                 goto done;
3835
3836                         for (j=0; j<count; j++) {
3837                                 construct_notify_jobs_info(&queue[j], info,
3838                                                            printer, snum,
3839                                                            option_type,
3840                                                            queue[j].job,
3841                                                            mem_ctx);
3842                         }
3843
3844                         free_a_printer(&printer, 2);
3845
3846                 done:
3847                         SAFE_FREE(queue);
3848                         break;
3849                 }
3850                 }
3851         }
3852
3853         /*
3854          * Debugging information, don't delete.
3855          */
3856         /*
3857         DEBUG(1,("dumping the NOTIFY_INFO\n"));
3858         DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
3859         DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3860
3861         for (i=0; i<info->count; i++) {
3862                 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3863                 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
3864                 info->data[i].id, info->data[i].size, info->data[i].enc_type));
3865         }
3866         */
3867         return WERR_OK;
3868 }
3869
3870 /********************************************************************
3871  * spoolss_rfnpcnex
3872  ********************************************************************/
3873
3874 WERROR _spoolss_rfnpcnex( pipes_struct *p, SPOOL_Q_RFNPCNEX *q_u, SPOOL_R_RFNPCNEX *r_u)
3875 {
3876         POLICY_HND *handle = &q_u->handle;
3877         SPOOL_NOTIFY_INFO *info = &r_u->info;
3878
3879         Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
3880         WERROR result = WERR_BADFID;
3881
3882         /* we always have a NOTIFY_INFO struct */
3883         r_u->info_ptr=0x1;
3884
3885         if (!Printer) {
3886                 DEBUG(2,("_spoolss_rfnpcnex: Invalid handle (%s:%u:%u).\n",
3887                          OUR_HANDLE(handle)));
3888                 goto done;
3889         }
3890
3891         DEBUG(4,("Printer type %x\n",Printer->printer_type));
3892
3893         /*
3894          *      We are now using the change value, and
3895          *      I should check for PRINTER_NOTIFY_OPTIONS_REFRESH but as
3896          *      I don't have a global notification system, I'm sending back all the
3897          *      informations even when _NOTHING_ has changed.
3898          */
3899
3900         /* We need to keep track of the change value to send back in
3901            RRPCN replies otherwise our updates are ignored. */
3902
3903         Printer->notify.fnpcn = True;
3904
3905         if (Printer->notify.client_connected) {
3906                 DEBUG(10,("_spoolss_rfnpcnex: Saving change value in request [%x]\n", q_u->change));
3907                 Printer->notify.change = q_u->change;
3908         }
3909
3910         /* just ignore the SPOOL_NOTIFY_OPTION */
3911
3912         switch (Printer->printer_type) {
3913                 case SPLHND_SERVER:
3914                         result = printserver_notify_info(p, handle, info, p->mem_ctx);
3915                         break;
3916
3917                 case SPLHND_PRINTER:
3918                         result = printer_notify_info(p, handle, info, p->mem_ctx);
3919                         break;
3920         }
3921
3922         Printer->notify.fnpcn = False;
3923
3924 done:
3925         return result;
3926 }
3927
3928 /********************************************************************
3929  * construct_printer_info_0
3930  * fill a printer_info_0 struct
3931  ********************************************************************/
3932
3933 static bool construct_printer_info_0(Printer_entry *print_hnd, PRINTER_INFO_0 *printer, int snum)
3934 {
3935         char *chaine = NULL;
3936         int count;
3937         NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
3938         counter_printer_0 *session_counter;
3939         uint32 global_counter;
3940         struct tm *t;
3941         time_t setuptime;
3942         print_status_struct status;
3943         TALLOC_CTX *ctx = talloc_tos();
3944
3945         if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
3946                 return False;
3947
3948         init_unistr(&printer->printername, ntprinter->info_2->printername);
3949
3950         chaine = talloc_asprintf(ctx, "\\\\%s", get_server_name(print_hnd));
3951         if (!chaine) {
3952                 free_a_printer(&ntprinter,2);
3953                 return false;
3954         }
3955
3956         count = print_queue_length(snum, &status);
3957
3958         /* check if we already have a counter for this printer */
3959         for(session_counter = counter_list; session_counter; session_counter = session_counter->next) {
3960                 if (session_counter->snum == snum)
3961                         break;
3962         }
3963
3964         init_unistr(&printer->servername, chaine);
3965
3966         /* it's the first time, add it to the list */
3967         if (session_counter==NULL) {
3968                 if((session_counter=SMB_MALLOC_P(counter_printer_0)) == NULL) {
3969                         free_a_printer(&ntprinter, 2);
3970                         return False;
3971                 }
3972                 ZERO_STRUCTP(session_counter);
3973                 session_counter->snum=snum;
3974                 session_counter->counter=0;
3975                 DLIST_ADD(counter_list, session_counter);
3976         }
3977
3978         /* increment it */
3979         session_counter->counter++;
3980
3981         /* JFM:
3982          * the global_counter should be stored in a TDB as it's common to all the clients
3983          * and should be zeroed on samba startup
3984          */
3985         global_counter=session_counter->counter;
3986         printer->cjobs = count;
3987         printer->total_jobs = 0;
3988         printer->total_bytes = 0;
3989
3990         setuptime = (time_t)ntprinter->info_2->setuptime;
3991         t=gmtime(&setuptime);
3992
3993         printer->year = t->tm_year+1900;
3994         printer->month = t->tm_mon+1;
3995         printer->dayofweek = t->tm_wday;
3996         printer->day = t->tm_mday;
3997         printer->hour = t->tm_hour;
3998         printer->minute = t->tm_min;
3999         printer->second = t->tm_sec;
4000         printer->milliseconds = 0;
4001
4002         printer->global_counter = global_counter;
4003         printer->total_pages = 0;
4004
4005         /* in 2.2 we reported ourselves as 0x0004 and 0x0565 */
4006         printer->major_version = 0x0005;        /* NT 5 */
4007         printer->build_version = 0x0893;        /* build 2195 */
4008
4009         printer->unknown7 = 0x1;
4010         printer->unknown8 = 0x0;
4011         printer->unknown9 = 0x0;
4012         printer->session_counter = session_counter->counter;
4013         printer->unknown11 = 0x0;
4014         printer->printer_errors = 0x0;          /* number of print failure */
4015         printer->unknown13 = 0x0;
4016         printer->unknown14 = 0x1;
4017         printer->unknown15 = 0x024a;            /* 586 Pentium ? */
4018         printer->unknown16 =  0x0;
4019         printer->change_id = ntprinter->info_2->changeid; /* ChangeID in milliseconds*/
4020         printer->unknown18 =  0x0;
4021         printer->status = nt_printq_status(status.status);
4022         printer->unknown20 =  0x0;
4023         printer->c_setprinter = get_c_setprinter(); /* monotonically increasing sum of delta printer counts */
4024         printer->unknown22 = 0x0;
4025         printer->unknown23 = 0x6;               /* 6  ???*/
4026         printer->unknown24 = 0;                 /* unknown 24 to 26 are always 0 */
4027         printer->unknown25 = 0;
4028         printer->unknown26 = 0;
4029         printer->unknown27 = 0;
4030         printer->unknown28 = 0;
4031         printer->unknown29 = 0;
4032
4033         free_a_printer(&ntprinter,2);
4034         return (True);
4035 }
4036
4037 /********************************************************************
4038  * construct_printer_info_1
4039  * fill a printer_info_1 struct
4040  ********************************************************************/
4041 static bool construct_printer_info_1(Printer_entry *print_hnd, uint32 flags, PRINTER_INFO_1 *printer, int snum)
4042 {
4043         char *chaine = NULL;
4044         NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4045         TALLOC_CTX *ctx = talloc_tos();
4046
4047         if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
4048                 return false;
4049
4050         printer->flags=flags;
4051
4052         if (*ntprinter->info_2->comment == '\0') {
4053                 init_unistr(&printer->comment, lp_comment(snum));
4054                 chaine = talloc_asprintf(ctx,
4055                                 "%s,%s,%s", ntprinter->info_2->printername,
4056                                 ntprinter->info_2->drivername, lp_comment(snum));
4057         }
4058         else {
4059                 init_unistr(&printer->comment, ntprinter->info_2->comment); /* saved comment. */
4060                 chaine = talloc_asprintf(ctx,
4061                                 "%s,%s,%s", ntprinter->info_2->printername,
4062                                 ntprinter->info_2->drivername, ntprinter->info_2->comment);
4063         }
4064
4065         if (!chaine) {
4066                 free_a_printer(&ntprinter,2);
4067                 return false;
4068         }
4069
4070         init_unistr(&printer->description, chaine);
4071         init_unistr(&printer->name, ntprinter->info_2->printername);
4072
4073         free_a_printer(&ntprinter,2);
4074
4075         return True;
4076 }
4077
4078 /****************************************************************************
4079  Free a DEVMODE struct.
4080 ****************************************************************************/
4081
4082 static void free_dev_mode(DEVICEMODE *dev)
4083 {
4084         if (dev == NULL)
4085                 return;
4086
4087         SAFE_FREE(dev->dev_private);
4088         SAFE_FREE(dev);
4089 }
4090
4091
4092 /****************************************************************************
4093  Convert an NT_DEVICEMODE to a DEVICEMODE structure.  Both pointers
4094  should be valid upon entry
4095 ****************************************************************************/
4096
4097 static bool convert_nt_devicemode( DEVICEMODE *devmode, NT_DEVICEMODE *ntdevmode )
4098 {
4099         if ( !devmode || !ntdevmode )
4100                 return False;
4101
4102         init_unistr(&devmode->devicename, ntdevmode->devicename);
4103
4104         init_unistr(&devmode->formname, ntdevmode->formname);
4105
4106         devmode->specversion      = ntdevmode->specversion;
4107         devmode->driverversion    = ntdevmode->driverversion;
4108         devmode->size             = ntdevmode->size;
4109         devmode->driverextra      = ntdevmode->driverextra;
4110         devmode->fields           = ntdevmode->fields;
4111
4112         devmode->orientation      = ntdevmode->orientation;
4113         devmode->papersize        = ntdevmode->papersize;
4114         devmode->paperlength      = ntdevmode->paperlength;
4115         devmode->paperwidth       = ntdevmode->paperwidth;
4116         devmode->scale            = ntdevmode->scale;
4117         devmode->copies           = ntdevmode->copies;
4118         devmode->defaultsource    = ntdevmode->defaultsource;
4119         devmode->printquality     = ntdevmode->printquality;
4120         devmode->color            = ntdevmode->color;
4121         devmode->duplex           = ntdevmode->duplex;
4122         devmode->yresolution      = ntdevmode->yresolution;
4123         devmode->ttoption         = ntdevmode->ttoption;
4124         devmode->collate          = ntdevmode->collate;
4125         devmode->icmmethod        = ntdevmode->icmmethod;
4126         devmode->icmintent        = ntdevmode->icmintent;
4127         devmode->mediatype        = ntdevmode->mediatype;
4128         devmode->dithertype       = ntdevmode->dithertype;
4129
4130         if (ntdevmode->nt_dev_private != NULL) {
4131                 if ((devmode->dev_private=(uint8 *)memdup(ntdevmode->nt_dev_private, ntdevmode->driverextra)) == NULL)
4132                         return False;
4133         }
4134
4135         return True;
4136 }
4137
4138 /****************************************************************************
4139  Create a DEVMODE struct. Returns malloced memory.
4140 ****************************************************************************/
4141
4142 DEVICEMODE *construct_dev_mode(const char *servicename)
4143 {
4144         NT_PRINTER_INFO_LEVEL   *printer = NULL;
4145         DEVICEMODE              *devmode = NULL;
4146
4147         DEBUG(7,("construct_dev_mode\n"));
4148
4149         DEBUGADD(8,("getting printer characteristics\n"));
4150
4151         if (!W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, servicename)))
4152                 return NULL;
4153
4154         if ( !printer->info_2->devmode ) {
4155                 DEBUG(5, ("BONG! There was no device mode!\n"));
4156                 goto done;
4157         }
4158
4159         if ((devmode = SMB_MALLOC_P(DEVICEMODE)) == NULL) {
4160                 DEBUG(2,("construct_dev_mode: malloc fail.\n"));
4161                 goto done;
4162         }
4163
4164         ZERO_STRUCTP(devmode);
4165
4166         DEBUGADD(8,("loading DEVICEMODE\n"));
4167
4168         if ( !convert_nt_devicemode( devmode, printer->info_2->devmode ) ) {
4169                 free_dev_mode( devmode );
4170                 devmode = NULL;
4171         }
4172
4173 done:
4174         free_a_printer(&printer,2);
4175
4176         return devmode;
4177 }
4178
4179 /********************************************************************
4180  * construct_printer_info_2
4181  * fill a printer_info_2 struct
4182  ********************************************************************/
4183
4184 static bool construct_printer_info_2(Printer_entry *print_hnd, PRINTER_INFO_2 *printer, int snum)
4185 {
4186         int count;
4187         NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4188
4189         print_status_struct status;
4190
4191         if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
4192                 return False;
4193
4194         count = print_queue_length(snum, &status);
4195
4196         init_unistr(&printer->servername, ntprinter->info_2->servername); /* servername*/
4197         init_unistr(&printer->printername, ntprinter->info_2->printername);                             /* printername*/
4198         init_unistr(&printer->sharename, lp_servicename(snum));                 /* sharename */
4199         init_unistr(&printer->portname, ntprinter->info_2->portname);                   /* port */
4200         init_unistr(&printer->drivername, ntprinter->info_2->drivername);       /* drivername */
4201
4202         if (*ntprinter->info_2->comment == '\0')
4203                 init_unistr(&printer->comment, lp_comment(snum));                       /* comment */
4204         else
4205                 init_unistr(&printer->comment, ntprinter->info_2->comment); /* saved comment. */
4206
4207         init_unistr(&printer->location, ntprinter->info_2->location);           /* location */
4208         init_unistr(&printer->sepfile, ntprinter->info_2->sepfile);             /* separator file */
4209         init_unistr(&printer->printprocessor, ntprinter->info_2->printprocessor);/* print processor */
4210         init_unistr(&printer->datatype, ntprinter->info_2->datatype);           /* datatype */
4211         init_unistr(&printer->parameters, ntprinter->info_2->parameters);       /* parameters (of print processor) */
4212
4213         printer->attributes = ntprinter->info_2->attributes;
4214
4215         printer->priority = ntprinter->info_2->priority;                                /* priority */
4216         printer->defaultpriority = ntprinter->info_2->default_priority;         /* default priority */
4217         printer->starttime = ntprinter->info_2->starttime;                      /* starttime */
4218         printer->untiltime = ntprinter->info_2->untiltime;                      /* untiltime */
4219         printer->status = nt_printq_status(status.status);                      /* status */
4220         printer->cjobs = count;                                                 /* jobs */
4221         printer->averageppm = ntprinter->info_2->averageppm;                    /* average pages per minute */
4222
4223         if ( !(printer->devmode = construct_dev_mode(
4224                        lp_const_servicename(snum))) )
4225                 DEBUG(8, ("Returning NULL Devicemode!\n"));
4226
4227         printer->secdesc = NULL;
4228
4229         if ( ntprinter->info_2->secdesc_buf
4230                 && ntprinter->info_2->secdesc_buf->sd_size != 0 )
4231         {
4232                 /* don't use talloc_steal() here unless you do a deep steal of all
4233                    the SEC_DESC members */
4234
4235                 printer->secdesc = dup_sec_desc( talloc_tos(),
4236                         ntprinter->info_2->secdesc_buf->sd );
4237         }
4238
4239         free_a_printer(&ntprinter, 2);
4240
4241         return True;
4242 }
4243
4244 /********************************************************************
4245  * construct_printer_info_3
4246  * fill a printer_info_3 struct
4247  ********************************************************************/
4248
4249 static bool construct_printer_info_3(Printer_entry *print_hnd, PRINTER_INFO_3 **pp_printer, int snum)
4250 {
4251         NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4252         PRINTER_INFO_3 *printer = NULL;
4253
4254         if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
4255                 return False;
4256
4257         *pp_printer = NULL;
4258         if ((printer = SMB_MALLOC_P(PRINTER_INFO_3)) == NULL) {
4259                 DEBUG(2,("construct_printer_info_3: malloc fail.\n"));
4260                 free_a_printer(&ntprinter, 2);
4261                 return False;
4262         }
4263
4264         ZERO_STRUCTP(printer);
4265
4266         /* These are the components of the SD we are returning. */
4267
4268         if (ntprinter->info_2->secdesc_buf && ntprinter->info_2->secdesc_buf->sd_size != 0) {
4269                 /* don't use talloc_steal() here unless you do a deep steal of all
4270                    the SEC_DESC members */
4271
4272                 printer->secdesc = dup_sec_desc( talloc_tos(),
4273                         ntprinter->info_2->secdesc_buf->sd );
4274         }
4275
4276         free_a_printer(&ntprinter, 2);
4277
4278         *pp_printer = printer;
4279         return True;
4280 }
4281
4282 /********************************************************************
4283  * construct_printer_info_4
4284  * fill a printer_info_4 struct
4285  ********************************************************************/
4286
4287 static bool construct_printer_info_4(Printer_entry *print_hnd, PRINTER_INFO_4 *printer, int snum)
4288 {
4289         NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4290
4291         if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
4292                 return False;
4293
4294         init_unistr(&printer->printername, ntprinter->info_2->printername);                             /* printername*/
4295         init_unistr(&printer->servername, ntprinter->info_2->servername); /* servername*/
4296         printer->attributes = ntprinter->info_2->attributes;
4297
4298         free_a_printer(&ntprinter, 2);
4299         return True;
4300 }
4301
4302 /********************************************************************
4303  * construct_printer_info_5
4304  * fill a printer_info_5 struct
4305  ********************************************************************/
4306
4307 static bool construct_printer_info_5(Printer_entry *print_hnd, PRINTER_INFO_5 *printer, int snum)
4308 {
4309         NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4310
4311         if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
4312                 return False;
4313
4314         init_unistr(&printer->printername, ntprinter->info_2->printername);
4315         init_unistr(&printer->portname, ntprinter->info_2->portname);
4316         printer->attributes = ntprinter->info_2->attributes;
4317
4318         /* these two are not used by NT+ according to MSDN */
4319
4320         printer->device_not_selected_timeout = 0x0;  /* have seen 0x3a98 */
4321         printer->transmission_retry_timeout  = 0x0;  /* have seen 0xafc8 */
4322
4323         free_a_printer(&ntprinter, 2);
4324
4325         return True;
4326 }
4327
4328 /********************************************************************
4329  * construct_printer_info_6
4330  * fill a printer_info_6 struct
4331  ********************************************************************/
4332
4333 static bool construct_printer_info_6(Printer_entry *print_hnd,
4334                                      PRINTER_INFO_6 *printer,
4335                                      int snum)
4336 {
4337         NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4338         int count;
4339         print_status_struct status;
4340
4341         if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2,
4342                                          lp_const_servicename(snum))))
4343                 return False;
4344
4345         count = print_queue_length(snum, &status);
4346
4347         printer->status = nt_printq_status(status.status);
4348
4349         free_a_printer(&ntprinter, 2);
4350
4351         return True;
4352 }
4353
4354 /********************************************************************
4355  * construct_printer_info_7
4356  * fill a printer_info_7 struct
4357  ********************************************************************/
4358
4359 static bool construct_printer_info_7(Printer_entry *print_hnd, PRINTER_INFO_7 *printer, int snum)
4360 {
4361         char *guid_str = NULL;
4362         struct GUID guid;
4363
4364         if (is_printer_published(print_hnd, snum, &guid)) {
4365                 if (asprintf(&guid_str, "{%s}",
4366                              GUID_string(talloc_tos(), &guid)) == -1) {
4367                         return false;
4368                 }
4369                 strupper_m(guid_str);
4370                 init_unistr(&printer->guid, guid_str);
4371                 SAFE_FREE(guid_str);
4372                 printer->action = SPOOL_DS_PUBLISH;
4373         } else {
4374                 init_unistr(&printer->guid, "");
4375                 printer->action = SPOOL_DS_UNPUBLISH;
4376         }
4377
4378         return True;
4379 }
4380
4381 /********************************************************************
4382  Spoolss_enumprinters.
4383 ********************************************************************/
4384
4385 static WERROR enum_all_printers_info_1(uint32 flags, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4386 {
4387         int snum;
4388         int i;
4389         int n_services=lp_numservices();
4390         PRINTER_INFO_1 *printers=NULL;
4391         PRINTER_INFO_1 current_prt;
4392         WERROR result = WERR_OK;
4393
4394         DEBUG(4,("enum_all_printers_info_1\n"));
4395
4396         for (snum=0; snum<n_services; snum++) {
4397                 if (lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) ) {
4398                         DEBUG(4,("Found a printer in smb.conf: %s[%x]\n", lp_servicename(snum), snum));
4399
4400                         if (construct_printer_info_1(NULL, flags, &current_prt, snum)) {
4401                                 if((printers=SMB_REALLOC_ARRAY(printers, PRINTER_INFO_1, *returned +1)) == NULL) {
4402                                         DEBUG(2,("enum_all_printers_info_1: failed to enlarge printers buffer!\n"));
4403                                         *returned=0;
4404                                         return WERR_NOMEM;
4405                                 }
4406                                 DEBUG(4,("ReAlloced memory for [%d] PRINTER_INFO_1\n", *returned));
4407
4408                                 memcpy(&printers[*returned], &current_prt, sizeof(PRINTER_INFO_1));
4409                                 (*returned)++;
4410                         }
4411                 }
4412         }
4413
4414         /* check the required size. */
4415         for (i=0; i<*returned; i++)
4416                 (*needed) += spoolss_size_printer_info_1(&printers[i]);
4417
4418         if (*needed > offered) {
4419                 result = WERR_INSUFFICIENT_BUFFER;
4420                 goto out;
4421         }
4422
4423         if (!rpcbuf_alloc_size(buffer, *needed)) {
4424                 result = WERR_NOMEM;
4425                 goto out;
4426         }
4427
4428         /* fill the buffer with the structures */
4429         for (i=0; i<*returned; i++)
4430                 smb_io_printer_info_1("", buffer, &printers[i], 0);
4431
4432 out:
4433         /* clear memory */
4434
4435         SAFE_FREE(printers);
4436
4437         if ( !W_ERROR_IS_OK(result) )
4438                 *returned = 0;
4439
4440         return result;
4441 }
4442
4443 /********************************************************************
4444  enum_all_printers_info_1_local.
4445 *********************************************************************/
4446
4447 static WERROR enum_all_printers_info_1_local(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4448 {
4449         DEBUG(4,("enum_all_printers_info_1_local\n"));
4450
4451         return enum_all_printers_info_1(PRINTER_ENUM_ICON8, buffer, offered, needed, returned);
4452 }
4453
4454 /********************************************************************
4455  enum_all_printers_info_1_name.
4456 *********************************************************************/
4457
4458 static WERROR enum_all_printers_info_1_name(fstring name, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4459 {
4460         char *s = name;
4461
4462         DEBUG(4,("enum_all_printers_info_1_name\n"));
4463
4464         if ((name[0] == '\\') && (name[1] == '\\'))
4465                 s = name + 2;
4466
4467         if (is_myname_or_ipaddr(s)) {
4468                 return enum_all_printers_info_1(PRINTER_ENUM_ICON8, buffer, offered, needed, returned);
4469         }
4470         else
4471                 return WERR_INVALID_NAME;
4472 }
4473
4474 #if 0   /* JERRY -- disabled for now.  Don't think this is used, tested, or correct */
4475 /********************************************************************
4476  enum_all_printers_info_1_remote.
4477 *********************************************************************/
4478
4479 static WERROR enum_all_printers_info_1_remote(fstring name, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4480 {
4481         PRINTER_INFO_1 *printer;
4482         fstring printername;
4483         fstring desc;
4484         fstring comment;
4485         DEBUG(4,("enum_all_printers_info_1_remote\n"));
4486         WERROR result = WERR_OK;
4487
4488         /* JFM: currently it's more a place holder than anything else.
4489          * In the spooler world there is a notion of server registration.
4490          * the print servers are registered on the PDC (in the same domain)
4491          *
4492          * We should have a TDB here. The registration is done thru an
4493          * undocumented RPC call.
4494          */
4495
4496         if((printer=SMB_MALLOC_P(PRINTER_INFO_1)) == NULL)
4497                 return WERR_NOMEM;
4498
4499         *returned=1;
4500
4501         slprintf(printername, sizeof(printername)-1,"Windows NT Remote Printers!!\\\\%s", name);
4502         slprintf(desc, sizeof(desc)-1,"%s", name);
4503         slprintf(comment, sizeof(comment)-1, "Logged on Domain");
4504
4505         init_unistr(&printer->description, desc);
4506         init_unistr(&printer->name, printername);
4507         init_unistr(&printer->comment, comment);
4508         printer->flags=PRINTER_ENUM_ICON3|PRINTER_ENUM_CONTAINER;
4509
4510         /* check the required size. */
4511         *needed += spoolss_size_printer_info_1(printer);
4512
4513         if (*needed > offered) {
4514                 result = WERR_INSUFFICIENT_BUFFER;
4515                 goto out;
4516         }
4517
4518         if (!rpcbuf_alloc_size(buffer, *needed)) {
4519                 result = WERR_NOMEM;
4520                 goto out;
4521         }
4522
4523         /* fill the buffer with the structures */
4524         smb_io_printer_info_1("", buffer, printer, 0);
4525
4526 out:
4527         /* clear memory */
4528         SAFE_FREE(printer);
4529
4530         if ( !W_ERROR_IS_OK(result) )
4531                 *returned = 0;
4532
4533         return result;
4534 }
4535
4536 #endif
4537
4538 /********************************************************************
4539  enum_all_printers_info_1_network.
4540 *********************************************************************/
4541
4542 static WERROR enum_all_printers_info_1_network(fstring name, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4543 {
4544         char *s = name;
4545
4546         DEBUG(4,("enum_all_printers_info_1_network\n"));
4547
4548         /* If we respond to a enum_printers level 1 on our name with flags
4549            set to PRINTER_ENUM_REMOTE with a list of printers then these
4550            printers incorrectly appear in the APW browse list.
4551            Specifically the printers for the server appear at the workgroup
4552            level where all the other servers in the domain are
4553            listed. Windows responds to this call with a
4554            WERR_CAN_NOT_COMPLETE so we should do the same. */
4555
4556         if (name[0] == '\\' && name[1] == '\\')
4557                  s = name + 2;
4558
4559         if (is_myname_or_ipaddr(s))
4560                  return WERR_CAN_NOT_COMPLETE;
4561
4562         return enum_all_printers_info_1(PRINTER_ENUM_NAME, buffer, offered, needed, returned);
4563 }
4564
4565 /********************************************************************
4566  * api_spoolss_enumprinters
4567  *
4568  * called from api_spoolss_enumprinters (see this to understand)
4569  ********************************************************************/
4570
4571 static WERROR enum_all_printers_info_2(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4572 {
4573         int snum;
4574         int i;
4575         int n_services=lp_numservices();
4576         PRINTER_INFO_2 *printers=NULL;
4577         PRINTER_INFO_2 current_prt;
4578         WERROR result = WERR_OK;
4579
4580         *returned = 0;
4581
4582         for (snum=0; snum<n_services; snum++) {
4583                 if (lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) ) {
4584                         DEBUG(4,("Found a printer in smb.conf: %s[%x]\n", lp_servicename(snum), snum));
4585
4586                         if (construct_printer_info_2(NULL, &current_prt, snum)) {
4587                                 if ( !(printers=SMB_REALLOC_ARRAY(printers, PRINTER_INFO_2, *returned +1)) ) {
4588                                         DEBUG(2,("enum_all_printers_info_2: failed to enlarge printers buffer!\n"));
4589                                         *returned = 0;
4590                                         return WERR_NOMEM;
4591                                 }
4592
4593                                 DEBUG(4,("ReAlloced memory for [%d] PRINTER_INFO_2\n", *returned + 1));
4594
4595                                 memcpy(&printers[*returned], &current_prt, sizeof(PRINTER_INFO_2));
4596
4597                                 (*returned)++;
4598                         }
4599                 }
4600         }
4601
4602         /* check the required size. */
4603         for (i=0; i<*returned; i++)
4604                 (*needed) += spoolss_size_printer_info_2(&printers[i]);
4605
4606         if (*needed > offered) {
4607                 result = WERR_INSUFFICIENT_BUFFER;
4608                 goto out;
4609         }
4610
4611         if (!rpcbuf_alloc_size(buffer, *needed)) {
4612                 result = WERR_NOMEM;
4613                 goto out;
4614         }
4615
4616         /* fill the buffer with the structures */
4617         for (i=0; i<*returned; i++)
4618                 smb_io_printer_info_2("", buffer, &(printers[i]), 0);
4619
4620 out:
4621         /* clear memory */
4622
4623         for (i=0; i<*returned; i++)
4624                 free_devmode(printers[i].devmode);
4625
4626         SAFE_FREE(printers);
4627
4628         if ( !W_ERROR_IS_OK(result) )
4629                 *returned = 0;
4630
4631         return result;
4632 }
4633
4634 /********************************************************************
4635  * handle enumeration of printers at level 1
4636  ********************************************************************/
4637
4638 static WERROR enumprinters_level1( uint32 flags, fstring name,
4639                                  RPC_BUFFER *buffer, uint32 offered,
4640                                  uint32 *needed, uint32 *returned)
4641 {
4642         /* Not all the flags are equals */
4643
4644         if (flags & PRINTER_ENUM_LOCAL)
4645                 return enum_all_printers_info_1_local(buffer, offered, needed, returned);
4646
4647         if (flags & PRINTER_ENUM_NAME)
4648                 return enum_all_printers_info_1_name(name, buffer, offered, needed, returned);
4649
4650 #if 0   /* JERRY - disabled for now */
4651         if (flags & PRINTER_ENUM_REMOTE)
4652                 return enum_all_printers_info_1_remote(name, buffer, offered, needed, returned);
4653 #endif
4654
4655         if (flags & PRINTER_ENUM_NETWORK)
4656                 return enum_all_printers_info_1_network(name, buffer, offered, needed, returned);
4657
4658         return WERR_OK; /* NT4sp5 does that */
4659 }
4660
4661 /********************************************************************
4662  * handle enumeration of printers at level 2
4663  ********************************************************************/
4664
4665 static WERROR enumprinters_level2( uint32 flags, const char *servername,
4666                                  RPC_BUFFER *buffer, uint32 offered,
4667                                  uint32 *needed, uint32 *returned)
4668 {
4669         if (flags & PRINTER_ENUM_LOCAL) {
4670                         return enum_all_printers_info_2(buffer, offered, needed, returned);
4671         }
4672
4673         if (flags & PRINTER_ENUM_NAME) {
4674                 if (is_myname_or_ipaddr(canon_servername(servername)))
4675                         return enum_all_printers_info_2(buffer, offered, needed, returned);
4676                 else
4677                         return WERR_INVALID_NAME;
4678         }
4679
4680         if (flags & PRINTER_ENUM_REMOTE)
4681                 return WERR_UNKNOWN_LEVEL;
4682
4683         return WERR_OK;
4684 }
4685
4686 /********************************************************************
4687  * handle enumeration of printers at level 5
4688  ********************************************************************/
4689
4690 static WERROR enumprinters_level5( uint32 flags, const char *servername,
4691                                  RPC_BUFFER *buffer, uint32 offered,
4692                                  uint32 *needed, uint32 *returned)
4693 {
4694 /*      return enum_all_printers_info_5(buffer, offered, needed, returned);*/
4695         return WERR_OK;
4696 }
4697
4698 /********************************************************************
4699  * api_spoolss_enumprinters
4700  *
4701  * called from api_spoolss_enumprinters (see this to understand)
4702  ********************************************************************/
4703
4704 WERROR _spoolss_enumprinters( pipes_struct *p, SPOOL_Q_ENUMPRINTERS *q_u, SPOOL_R_ENUMPRINTERS *r_u)
4705 {
4706         uint32 flags = q_u->flags;
4707         UNISTR2 *servername = &q_u->servername;
4708         uint32 level = q_u->level;
4709         RPC_BUFFER *buffer = NULL;
4710         uint32 offered = q_u->offered;
4711         uint32 *needed = &r_u->needed;
4712         uint32 *returned = &r_u->returned;
4713
4714         fstring name;
4715
4716         /* that's an [in out] buffer */
4717
4718         if (!q_u->buffer && (offered!=0)) {
4719                 return WERR_INVALID_PARAM;
4720         }
4721
4722         if (offered > MAX_RPC_DATA_SIZE) {
4723                 return WERR_INVALID_PARAM;
4724         }
4725
4726         rpcbuf_move(q_u->buffer, &r_u->buffer);
4727         buffer = r_u->buffer;
4728
4729         DEBUG(4,("_spoolss_enumprinters\n"));
4730
4731         *needed=0;
4732         *returned=0;
4733
4734         /*
4735          * Level 1:
4736          *          flags==PRINTER_ENUM_NAME
4737          *           if name=="" then enumerates all printers
4738          *           if name!="" then enumerate the printer
4739          *          flags==PRINTER_ENUM_REMOTE
4740          *          name is NULL, enumerate printers
4741          * Level 2: name!="" enumerates printers, name can't be NULL
4742          * Level 3: doesn't exist
4743          * Level 4: does a local registry lookup
4744          * Level 5: same as Level 2
4745          */
4746
4747         unistr2_to_ascii(name, servername, sizeof(name));
4748         strupper_m(name);
4749
4750         switch (level) {
4751         case 1:
4752                 return enumprinters_level1(flags, name, buffer, offered, needed, returned);
4753         case 2:
4754                 return enumprinters_level2(flags, name, buffer, offered, needed, returned);
4755         case 5:
4756                 return enumprinters_level5(flags, name, buffer, offered, needed, returned);
4757         case 3:
4758         case 4:
4759                 break;
4760         }
4761         return WERR_UNKNOWN_LEVEL;
4762 }
4763
4764 /****************************************************************************
4765 ****************************************************************************/
4766
4767 static WERROR getprinter_level_0(Printer_entry *print_hnd, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
4768 {
4769         PRINTER_INFO_0 *printer=NULL;
4770         WERROR result = WERR_OK;
4771
4772         if((printer=SMB_MALLOC_P(PRINTER_INFO_0)) == NULL)
4773                 return WERR_NOMEM;
4774
4775         construct_printer_info_0(print_hnd, printer, snum);
4776
4777         /* check the required size. */
4778         *needed += spoolss_size_printer_info_0(printer);
4779
4780         if (*needed > offered) {
4781                 result = WERR_INSUFFICIENT_BUFFER;
4782                 goto out;
4783         }
4784
4785         if (!rpcbuf_alloc_size(buffer, *needed)) {
4786                 result = WERR_NOMEM;
4787                 goto out;
4788         }
4789
4790         /* fill the buffer with the structures */
4791         smb_io_printer_info_0("", buffer, printer, 0);
4792
4793 out:
4794         /* clear memory */
4795
4796         SAFE_FREE(printer);
4797
4798         return result;
4799 }
4800
4801 /****************************************************************************
4802 ****************************************************************************/
4803
4804 static WERROR getprinter_level_1(Printer_entry *print_hnd, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
4805 {
4806         PRINTER_INFO_1 *printer=NULL;
4807         WERROR result = WERR_OK;
4808
4809         if((printer=SMB_MALLOC_P(PRINTER_INFO_1)) == NULL)
4810                 return WERR_NOMEM;
4811
4812         construct_printer_info_1(print_hnd, PRINTER_ENUM_ICON8, printer, snum);
4813
4814         /* check the required size. */
4815         *needed += spoolss_size_printer_info_1(printer);
4816
4817         if (*needed > offered) {
4818                 result = WERR_INSUFFICIENT_BUFFER;
4819                 goto out;
4820         }
4821
4822         if (!rpcbuf_alloc_size(buffer, *needed)) {
4823                 result = WERR_NOMEM;
4824                 goto out;
4825         }
4826
4827         /* fill the buffer with the structures */
4828         smb_io_printer_info_1("", buffer, printer, 0);
4829
4830 out:
4831         /* clear memory */
4832         SAFE_FREE(printer);
4833
4834         return result;
4835 }
4836
4837 /****************************************************************************
4838 ****************************************************************************/
4839
4840 static WERROR getprinter_level_2(Printer_entry *print_hnd, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
4841 {
4842         PRINTER_INFO_2 *printer=NULL;
4843         WERROR result = WERR_OK;
4844
4845         if((printer=SMB_MALLOC_P(PRINTER_INFO_2))==NULL)
4846                 return WERR_NOMEM;
4847
4848         construct_printer_info_2(print_hnd, printer, snum);
4849
4850         /* check the required size. */
4851         *needed += spoolss_size_printer_info_2(printer);
4852
4853         if (*needed > offered) {
4854                 result = WERR_INSUFFICIENT_BUFFER;
4855                 goto out;
4856         }
4857
4858         if (!rpcbuf_alloc_size(buffer, *needed)) {
4859                 result = WERR_NOMEM;
4860                 goto out;
4861         }
4862
4863         /* fill the buffer with the structures */
4864         if (!smb_io_printer_info_2("", buffer, printer, 0))
4865                 result = WERR_NOMEM;
4866
4867 out:
4868         /* clear memory */
4869         free_printer_info_2(printer);
4870
4871         return result;
4872 }
4873
4874 /****************************************************************************
4875 ****************************************************************************/
4876
4877 static WERROR getprinter_level_3(Printer_entry *print_hnd, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
4878 {
4879         PRINTER_INFO_3 *printer=NULL;
4880         WERROR result = WERR_OK;
4881
4882         if (!construct_printer_info_3(print_hnd, &printer, snum))
4883                 return WERR_NOMEM;
4884
4885         /* check the required size. */
4886         *needed += spoolss_size_printer_info_3(printer);
4887
4888         if (*needed > offered) {
4889                 result = WERR_INSUFFICIENT_BUFFER;
4890                 goto out;
4891         }
4892
4893         if (!rpcbuf_alloc_size(buffer, *needed)) {
4894                 result = WERR_NOMEM;
4895                 goto out;
4896         }
4897
4898         /* fill the buffer with the structures */
4899         smb_io_printer_info_3("", buffer, printer, 0);
4900
4901 out:
4902         /* clear memory */
4903         free_printer_info_3(printer);
4904
4905         return result;
4906 }
4907
4908 /****************************************************************************
4909 ****************************************************************************/
4910
4911 static WERROR getprinter_level_4(Printer_entry *print_hnd, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
4912 {
4913         PRINTER_INFO_4 *printer=NULL;
4914         WERROR result = WERR_OK;
4915
4916         if((printer=SMB_MALLOC_P(PRINTER_INFO_4))==NULL)
4917                 return WERR_NOMEM;
4918
4919         if (!construct_printer_info_4(print_hnd, printer, snum)) {
4920                 SAFE_FREE(printer);
4921                 return WERR_NOMEM;
4922         }
4923
4924         /* check the required size. */
4925         *needed += spoolss_size_printer_info_4(printer);
4926
4927         if (*needed > offered) {
4928                 result = WERR_INSUFFICIENT_BUFFER;
4929                 goto out;
4930         }
4931
4932         if (!rpcbuf_alloc_size(buffer, *needed)) {
4933                 result = WERR_NOMEM;
4934                 goto out;
4935         }
4936
4937         /* fill the buffer with the structures */
4938         smb_io_printer_info_4("", buffer, printer, 0);
4939
4940 out:
4941         /* clear memory */
4942         free_printer_info_4(printer);
4943
4944         return result;
4945 }
4946
4947 /****************************************************************************
4948 ****************************************************************************/
4949
4950 static WERROR getprinter_level_5(Printer_entry *print_hnd, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
4951 {
4952         PRINTER_INFO_5 *printer=NULL;
4953         WERROR result = WERR_OK;
4954
4955         if((printer=SMB_MALLOC_P(PRINTER_INFO_5))==NULL)
4956                 return WERR_NOMEM;
4957
4958         if (!construct_printer_info_5(print_hnd, printer, snum)) {
4959                 free_printer_info_5(printer);
4960                 return WERR_NOMEM;
4961         }
4962
4963         /* check the required size. */
4964         *needed += spoolss_size_printer_info_5(printer);
4965
4966         if (*needed > offered) {
4967                 result = WERR_INSUFFICIENT_BUFFER;
4968                 goto out;
4969         }
4970
4971         if (!rpcbuf_alloc_size(buffer, *needed)) {
4972                 result = WERR_NOMEM;
4973                 goto out;
4974         }
4975
4976         /* fill the buffer with the structures */
4977         smb_io_printer_info_5("", buffer, printer, 0);
4978
4979 out:
4980         /* clear memory */
4981         free_printer_info_5(printer);
4982
4983         return result;
4984 }
4985
4986 static WERROR getprinter_level_6(Printer_entry *print_hnd,
4987                                  int snum,
4988                                  RPC_BUFFER *buffer, uint32 offered,
4989                                  uint32 *needed)
4990 {
4991         PRINTER_INFO_6 *printer;
4992         WERROR result = WERR_OK;
4993
4994         if ((printer = SMB_MALLOC_P(PRINTER_INFO_6)) == NULL) {
4995                 return WERR_NOMEM;
4996         }
4997
4998         if (!construct_printer_info_6(print_hnd, printer, snum)) {
4999                 free_printer_info_6(printer);
5000                 return WERR_NOMEM;
5001         }
5002
5003         /* check the required size. */
5004         *needed += spoolss_size_printer_info_6(printer);
5005
5006         if (*needed > offered) {
5007                 result = WERR_INSUFFICIENT_BUFFER;
5008                 goto out;
5009         }
5010
5011         if (!rpcbuf_alloc_size(buffer, *needed)) {
5012                 result = WERR_NOMEM;
5013                 goto out;
5014         }
5015
5016         /* fill the buffer with the structures */
5017         smb_io_printer_info_6("", buffer, printer, 0);
5018
5019 out:
5020         /* clear memory */
5021         free_printer_info_6(printer);
5022
5023         return result;
5024 }
5025
5026 static WERROR getprinter_level_7(Printer_entry *print_hnd, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
5027 {
5028         PRINTER_INFO_7 *printer=NULL;
5029         WERROR result = WERR_OK;
5030
5031         if((printer=SMB_MALLOC_P(PRINTER_INFO_7))==NULL)
5032                 return WERR_NOMEM;
5033
5034         if (!construct_printer_info_7(print_hnd, printer, snum)) {
5035                 result = WERR_NOMEM;
5036                 goto out;
5037         }
5038
5039         /* check the required size. */
5040         *needed += spoolss_size_printer_info_7(printer);
5041
5042         if (*needed > offered) {
5043                 result = WERR_INSUFFICIENT_BUFFER;
5044                 goto out;
5045         }
5046
5047         if (!rpcbuf_alloc_size(buffer, *needed)) {
5048                 result = WERR_NOMEM;
5049                 goto out;
5050
5051         }
5052
5053         /* fill the buffer with the structures */
5054         smb_io_printer_info_7("", buffer, printer, 0);
5055
5056 out:
5057         /* clear memory */
5058         free_printer_info_7(printer);
5059
5060         return result;
5061 }
5062
5063 /****************************************************************************
5064 ****************************************************************************/
5065
5066 WERROR _spoolss_getprinter(pipes_struct *p, SPOOL_Q_GETPRINTER *q_u, SPOOL_R_GETPRINTER *r_u)
5067 {
5068         POLICY_HND *handle = &q_u->handle;
5069         uint32 level = q_u->level;
5070         RPC_BUFFER *buffer = NULL;
5071         uint32 offered = q_u->offered;
5072         uint32 *needed = &r_u->needed;
5073         Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
5074
5075         int snum;
5076
5077         /* that's an [in out] buffer */
5078
5079         if (!q_u->buffer && (offered!=0)) {
5080                 return WERR_INVALID_PARAM;
5081         }
5082
5083         if (offered > MAX_RPC_DATA_SIZE) {
5084                 return WERR_INVALID_PARAM;
5085         }
5086
5087         rpcbuf_move(q_u->buffer, &r_u->buffer);
5088         buffer = r_u->buffer;
5089
5090         *needed=0;
5091
5092         if (!get_printer_snum(p, handle, &snum, NULL))
5093                 return WERR_BADFID;
5094
5095         switch (level) {
5096         case 0:
5097                 return getprinter_level_0(Printer, snum, buffer, offered, needed);
5098         case 1:
5099                 return getprinter_level_1(Printer, snum, buffer, offered, needed);
5100         case 2:
5101                 return getprinter_level_2(Printer, snum, buffer, offered, needed);
5102         case 3:
5103                 return getprinter_level_3(Printer, snum, buffer, offered, needed);
5104         case 4:
5105                 return getprinter_level_4(Printer, snum, buffer, offered, needed);
5106         case 5:
5107                 return getprinter_level_5(Printer, snum, buffer, offered, needed);
5108         case 6:
5109                 return getprinter_level_6(Printer, snum, buffer, offered, needed);
5110         case 7:
5111                 return getprinter_level_7(Printer, snum, buffer, offered, needed);
5112         }
5113         return WERR_UNKNOWN_LEVEL;
5114 }
5115
5116 /********************************************************************
5117  * fill a DRIVER_INFO_1 struct
5118  ********************************************************************/
5119
5120 static void fill_printer_driver_info_1(DRIVER_INFO_1 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, const char *servername, fstring architecture)
5121 {
5122         init_unistr( &info->name, driver.info_3->name);
5123 }
5124
5125 /********************************************************************
5126  * construct_printer_driver_info_1
5127  ********************************************************************/
5128
5129 static WERROR construct_printer_driver_info_1(DRIVER_INFO_1 *info, int snum, const char *servername, fstring architecture, uint32 version)
5130 {
5131         NT_PRINTER_INFO_LEVEL *printer = NULL;
5132         NT_PRINTER_DRIVER_INFO_LEVEL driver;
5133
5134         ZERO_STRUCT(driver);
5135
5136         if (!W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, lp_const_servicename(snum))))
5137                 return WERR_INVALID_PRINTER_NAME;
5138
5139         if (!W_ERROR_IS_OK(get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version))) {
5140                 free_a_printer(&printer, 2);
5141                 return WERR_UNKNOWN_PRINTER_DRIVER;
5142         }
5143
5144         fill_printer_driver_info_1(info, driver, servername, architecture);
5145
5146         free_a_printer(&printer,2);
5147
5148         return WERR_OK;
5149 }
5150
5151 /********************************************************************
5152  * construct_printer_driver_info_2
5153  * fill a printer_info_2 struct
5154  ********************************************************************/
5155
5156 static void fill_printer_driver_info_2(DRIVER_INFO_2 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, const char *servername)
5157 {
5158         TALLOC_CTX *ctx = talloc_tos();
5159         char *temp = NULL;
5160         const char *cservername = canon_servername(servername);
5161
5162         info->version=driver.info_3->cversion;
5163
5164         init_unistr( &info->name, driver.info_3->name );
5165         init_unistr( &info->architecture, driver.info_3->environment );
5166
5167         if (strlen(driver.info_3->driverpath)) {
5168                 temp = talloc_asprintf(ctx,
5169                                 "\\\\%s%s",
5170                                 cservername,
5171                                 driver.info_3->driverpath);
5172                 init_unistr( &info->driverpath, temp );
5173         } else {
5174                 init_unistr( &info->driverpath, "" );
5175         }
5176
5177         TALLOC_FREE(temp);
5178         if (strlen(driver.info_3->datafile)) {
5179                 temp = talloc_asprintf(ctx,
5180                                 "\\\\%s%s",
5181                                 cservername,
5182                                 driver.info_3->datafile);
5183                 init_unistr( &info->datafile, temp );
5184         } else
5185                 init_unistr( &info->datafile, "" );
5186
5187         TALLOC_FREE(temp);
5188         if (strlen(driver.info_3->configfile)) {
5189                 temp = talloc_asprintf(ctx,
5190                                 "\\\\%s%s",
5191                                 cservername,
5192                                 driver.info_3->configfile);
5193                 init_unistr( &info->configfile, temp );
5194         } else
5195                 init_unistr( &info->configfile, "" );
5196 }
5197
5198 /********************************************************************
5199  * construct_printer_driver_info_2
5200  * fill a printer_info_2 struct
5201  ********************************************************************/
5202
5203 static WERROR construct_printer_driver_info_2(DRIVER_INFO_2 *info, int snum, const char *servername, fstring architecture, uint32 version)
5204 {
5205         NT_PRINTER_INFO_LEVEL *printer = NULL;
5206         NT_PRINTER_DRIVER_INFO_LEVEL driver;
5207
5208         ZERO_STRUCT(printer);
5209         ZERO_STRUCT(driver);
5210
5211         if (!W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, lp_const_servicename(snum))))
5212                 return WERR_INVALID_PRINTER_NAME;
5213
5214         if (!W_ERROR_IS_OK(get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version))) {
5215                 free_a_printer(&printer, 2);
5216                 return WERR_UNKNOWN_PRINTER_DRIVER;
5217         }
5218
5219         fill_printer_driver_info_2(info, driver, servername);
5220
5221         free_a_printer(&printer,2);
5222
5223         return WERR_OK;
5224 }
5225
5226 /********************************************************************
5227  * copy a strings array and convert to UNICODE
5228  *
5229  * convert an array of ascii string to a UNICODE string
5230  ********************************************************************/
5231
5232 static uint32 init_unistr_array(uint16 **uni_array, fstring *char_array, const char *servername)
5233 {
5234         int i=0;
5235         int j=0;
5236         const char *v;
5237         char *line = NULL;
5238         TALLOC_CTX *ctx = talloc_tos();
5239
5240         DEBUG(6,("init_unistr_array\n"));
5241         *uni_array=NULL;
5242
5243         while (true) {
5244                 if ( !char_array ) {
5245                         v = "";
5246                 } else {
5247                         v = char_array[i];
5248                         if (!v)
5249                                 v = ""; /* hack to handle null lists */
5250                 }
5251
5252                 /* hack to allow this to be used in places other than when generating
5253                    the list of dependent files */
5254
5255                 TALLOC_FREE(line);
5256                 if ( servername ) {
5257                         line = talloc_asprintf(ctx,
5258                                         "\\\\%s%s",
5259                                         canon_servername(servername),
5260                                         v);
5261                 } else {
5262                         line = talloc_strdup(ctx, v);
5263                 }
5264
5265                 if (!line) {
5266                         SAFE_FREE(*uni_array);
5267                         return 0;
5268                 }
5269                 DEBUGADD(6,("%d:%s:%lu\n", i, line, (unsigned long)strlen(line)));
5270
5271                 /* add one extra unit16 for the second terminating NULL */
5272
5273                 if ( (*uni_array=SMB_REALLOC_ARRAY(*uni_array, uint16, j+1+strlen(line)+2)) == NULL ) {
5274                         DEBUG(2,("init_unistr_array: Realloc error\n" ));
5275                         return 0;
5276                 }
5277
5278                 if ( !strlen(v) )
5279                         break;
5280
5281                 j += (rpcstr_push((*uni_array+j), line, sizeof(uint16)*strlen(line)+2, STR_TERMINATE) / sizeof(uint16));
5282                 i++;
5283         }
5284
5285         if (*uni_array) {
5286                 /* special case for ""; we need to add both NULL's here */
5287                 if (!j)
5288                         (*uni_array)[j++]=0x0000;
5289                 (*uni_array)[j]=0x0000;
5290         }
5291
5292         DEBUGADD(6,("last one:done\n"));
5293
5294         /* return size of array in uint16's */
5295
5296         return j+1;
5297 }
5298
5299 /********************************************************************
5300  * construct_printer_info_3
5301  * fill a printer_info_3 struct
5302  ********************************************************************/
5303
5304 static void fill_printer_driver_info_3(DRIVER_INFO_3 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, const char *servername)
5305 {
5306         char *temp = NULL;
5307         TALLOC_CTX *ctx = talloc_tos();
5308         const char *cservername = canon_servername(servername);
5309
5310         ZERO_STRUCTP(info);
5311
5312         info->version=driver.info_3->cversion;
5313
5314         init_unistr( &info->name, driver.info_3->name );
5315         init_unistr( &info->architecture, driver.info_3->environment );
5316
5317         if (strlen(driver.info_3->driverpath)) {
5318                 temp = talloc_asprintf(ctx,
5319                                 "\\\\%s%s",
5320                                 cservername,
5321                                 driver.info_3->driverpath);
5322                 init_unistr( &info->driverpath, temp );
5323         } else
5324                 init_unistr( &info->driverpath, "" );
5325
5326         TALLOC_FREE(temp);
5327         if (strlen(driver.info_3->datafile)) {
5328                 temp = talloc_asprintf(ctx,
5329                                 "\\\\%s%s",
5330                                 cservername,
5331                                 driver.info_3->datafile);
5332                 init_unistr( &info->datafile, temp );
5333         } else
5334                 init_unistr( &info->datafile, "" );
5335
5336         TALLOC_FREE(temp);
5337         if (strlen(driver.info_3->configfile)) {
5338                 temp = talloc_asprintf(ctx,
5339                                 "\\\\%s%s",
5340                                 cservername,
5341                                 driver.info_3->configfile);
5342                 init_unistr( &info->configfile, temp );
5343         } else
5344                 init_unistr( &info->configfile, "" );
5345
5346         TALLOC_FREE(temp);
5347         if (strlen(driver.info_3->helpfile)) {
5348                 temp = talloc_asprintf(ctx,
5349                                 "\\\\%s%s",
5350                                 cservername,
5351                                 driver.info_3->helpfile);
5352                 init_unistr( &info->helpfile, temp );
5353         } else
5354                 init_unistr( &info->helpfile, "" );
5355
5356         TALLOC_FREE(temp);
5357         init_unistr( &info->monitorname, driver.info_3->monitorname );
5358         init_unistr( &info->defaultdatatype, driver.info_3->defaultdatatype );
5359
5360         info->dependentfiles=NULL;
5361         init_unistr_array(&info->dependentfiles, driver.info_3->dependentfiles, cservername);
5362 }
5363
5364 /********************************************************************
5365  * construct_printer_info_3
5366  * fill a printer_info_3 struct
5367  ********************************************************************/
5368
5369 static WERROR construct_printer_driver_info_3(DRIVER_INFO_3 *info, int snum, const char *servername, fstring architecture, uint32 version)
5370 {
5371         NT_PRINTER_INFO_LEVEL *printer = NULL;
5372         NT_PRINTER_DRIVER_INFO_LEVEL driver;
5373         WERROR status;
5374         ZERO_STRUCT(driver);
5375
5376         status=get_a_printer(NULL, &printer, 2, lp_const_servicename(snum) );
5377         DEBUG(8,("construct_printer_driver_info_3: status: %s\n", win_errstr(status)));
5378         if (!W_ERROR_IS_OK(status))
5379                 return WERR_INVALID_PRINTER_NAME;
5380
5381         status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
5382         DEBUG(8,("construct_printer_driver_info_3: status: %s\n", win_errstr(status)));
5383
5384 #if 0   /* JERRY */
5385
5386         /*
5387          * I put this code in during testing.  Helpful when commenting out the
5388          * support for DRIVER_INFO_6 in regards to win2k.  Not needed in general
5389          * as win2k always queries the driver using an infor level of 6.
5390          * I've left it in (but ifdef'd out) because I'll probably
5391          * use it in experimentation again in the future.   --jerry 22/01/2002
5392          */
5393
5394         if (!W_ERROR_IS_OK(status)) {
5395                 /*
5396                  * Is this a W2k client ?
5397                  */
5398                 if (version == 3) {
5399                         /* Yes - try again with a WinNT driver. */
5400                         version = 2;
5401                         status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
5402                         DEBUG(8,("construct_printer_driver_info_3: status: %s\n", win_errstr(status)));
5403                 }
5404 #endif
5405
5406                 if (!W_ERROR_IS_OK(status)) {
5407                         free_a_printer(&printer,2);
5408                         return WERR_UNKNOWN_PRINTER_DRIVER;
5409                 }
5410
5411 #if 0   /* JERRY */
5412         }
5413 #endif
5414
5415
5416         fill_printer_driver_info_3(info, driver, servername);
5417
5418         free_a_printer(&printer,2);
5419
5420         return WERR_OK;
5421 }
5422
5423 /********************************************************************
5424  * construct_printer_info_6
5425  * fill a printer_info_6 struct - we know that driver is really level 3. This sucks. JRA.
5426  ********************************************************************/
5427
5428 static void fill_printer_driver_info_6(DRIVER_INFO_6 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, const char *servername)
5429 {
5430         char *temp = NULL;
5431         fstring nullstr;
5432         TALLOC_CTX *ctx = talloc_tos();
5433         const char *cservername = canon_servername(servername);
5434
5435         ZERO_STRUCTP(info);
5436         memset(&nullstr, '\0', sizeof(fstring));
5437
5438         info->version=driver.info_3->cversion;
5439
5440         init_unistr( &info->name, driver.info_3->name );
5441         init_unistr( &info->architecture, driver.info_3->environment );
5442
5443         if (strlen(driver.info_3->driverpath)) {
5444                 temp = talloc_asprintf(ctx,
5445                                 "\\\\%s%s",
5446                                 cservername,
5447                                 driver.info_3->driverpath);
5448                 init_unistr( &info->driverpath, temp );
5449         } else
5450                 init_unistr( &info->driverpath, "" );
5451
5452         TALLOC_FREE(temp);
5453         if (strlen(driver.info_3->datafile)) {
5454                 temp = talloc_asprintf(ctx,
5455                                 "\\\\%s%s",
5456                                 cservername,
5457                                 driver.info_3->datafile);
5458                 init_unistr( &info->datafile, temp );
5459         } else
5460                 init_unistr( &info->datafile, "" );
5461
5462         TALLOC_FREE(temp);
5463         if (strlen(driver.info_3->configfile)) {
5464                 temp = talloc_asprintf(ctx,
5465                                 "\\\\%s%s",
5466                                 cservername,
5467                                 driver.info_3->configfile);
5468                 init_unistr( &info->configfile, temp );
5469         } else
5470                 init_unistr( &info->configfile, "" );
5471
5472         TALLOC_FREE(temp);
5473         if (strlen(driver.info_3->helpfile)) {
5474                 temp = talloc_asprintf(ctx,
5475                                 "\\\\%s%s",
5476                                 cservername,
5477                                 driver.info_3->helpfile);
5478                 init_unistr( &info->helpfile, temp );
5479         } else
5480                 init_unistr( &info->helpfile, "" );
5481
5482         TALLOC_FREE(temp);
5483         init_unistr( &info->monitorname, driver.info_3->monitorname );
5484         init_unistr( &info->defaultdatatype, driver.info_3->defaultdatatype );
5485
5486         info->dependentfiles = NULL;
5487         init_unistr_array( &info->dependentfiles, driver.info_3->dependentfiles, servername );
5488
5489         info->previousdrivernames=NULL;
5490         init_unistr_array(&info->previousdrivernames, &nullstr, servername);
5491
5492         info->driver_date=0;
5493
5494         info->padding=0;
5495         info->driver_version_low=0;
5496         info->driver_version_high=0;
5497
5498         init_unistr( &info->mfgname, "");
5499         init_unistr( &info->oem_url, "");
5500         init_unistr( &info->hardware_id, "");
5501         init_unistr( &info->provider, "");
5502 }
5503
5504 /********************************************************************
5505  * construct_printer_info_6
5506  * fill a printer_info_6 struct
5507  ********************************************************************/
5508
5509 static WERROR construct_printer_driver_info_6(DRIVER_INFO_6 *info, int snum,
5510               const char *servername, fstring architecture, uint32 version)
5511 {
5512         NT_PRINTER_INFO_LEVEL           *printer = NULL;
5513         NT_PRINTER_DRIVER_INFO_LEVEL    driver;
5514         WERROR                          status;
5515
5516         ZERO_STRUCT(driver);
5517
5518         status=get_a_printer(NULL, &printer, 2, lp_const_servicename(snum) );
5519
5520         DEBUG(8,("construct_printer_driver_info_6: status: %s\n", win_errstr(status)));
5521
5522         if (!W_ERROR_IS_OK(status))
5523                 return WERR_INVALID_PRINTER_NAME;
5524
5525         status = get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
5526
5527         DEBUG(8,("construct_printer_driver_info_6: status: %s\n", win_errstr(status)));
5528
5529         if (!W_ERROR_IS_OK(status))
5530         {
5531                 /*
5532                  * Is this a W2k client ?
5533                  */
5534
5535                 if (version < 3) {
5536                         free_a_printer(&printer,2);
5537                         return WERR_UNKNOWN_PRINTER_DRIVER;
5538                 }
5539
5540                 /* Yes - try again with a WinNT driver. */
5541                 version = 2;
5542                 status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
5543                 DEBUG(8,("construct_printer_driver_info_6: status: %s\n", win_errstr(status)));
5544                 if (!W_ERROR_IS_OK(status)) {
5545                         free_a_printer(&printer,2);
5546                         return WERR_UNKNOWN_PRINTER_DRIVER;
5547                 }
5548         }
5549
5550         fill_printer_driver_info_6(info, driver, servername);
5551
5552         free_a_printer(&printer,2);
5553         free_a_printer_driver(driver, 3);
5554
5555         return WERR_OK;
5556 }
5557
5558 /****************************************************************************
5559 ****************************************************************************/
5560
5561 static void free_printer_driver_info_3(DRIVER_INFO_3 *info)
5562 {
5563         SAFE_FREE(info->dependentfiles);
5564 }
5565
5566 /****************************************************************************
5567 ****************************************************************************/
5568
5569 static void free_printer_driver_info_6(DRIVER_INFO_6 *info)
5570 {
5571         SAFE_FREE(info->dependentfiles);
5572 }
5573
5574 /****************************************************************************
5575 ****************************************************************************/
5576
5577 static WERROR getprinterdriver2_level1(const char *servername, fstring architecture, uint32 version, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
5578 {
5579         DRIVER_INFO_1 *info=NULL;
5580         WERROR result;
5581
5582         if((info=SMB_MALLOC_P(DRIVER_INFO_1)) == NULL)
5583                 return WERR_NOMEM;
5584
5585         result = construct_printer_driver_info_1(info, snum, servername, architecture, version);
5586         if (!W_ERROR_IS_OK(result))
5587                 goto out;
5588
5589         /* check the required size. */
5590         *needed += spoolss_size_printer_driver_info_1(info);
5591
5592         if (*needed > offered) {
5593                 result = WERR_INSUFFICIENT_BUFFER;
5594                 goto out;
5595         }
5596
5597         if (!rpcbuf_alloc_size(buffer, *needed)) {
5598                 result = WERR_NOMEM;
5599                 goto out;
5600         }
5601
5602         /* fill the buffer with the structures */
5603         smb_io_printer_driver_info_1("", buffer, info, 0);
5604
5605 out:
5606         /* clear memory */
5607         SAFE_FREE(info);
5608
5609         return result;
5610 }
5611
5612 /****************************************************************************
5613 ****************************************************************************/
5614
5615 static WERROR getprinterdriver2_level2(const char *servername, fstring architecture, uint32 version, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
5616 {
5617         DRIVER_INFO_2 *info=NULL;
5618         WERROR result;
5619
5620         if((info=SMB_MALLOC_P(DRIVER_INFO_2)) == NULL)
5621                 return WERR_NOMEM;
5622
5623         result = construct_printer_driver_info_2(info, snum, servername, architecture, version);
5624         if (!W_ERROR_IS_OK(result))
5625                 goto out;
5626
5627         /* check the required size. */
5628         *needed += spoolss_size_printer_driver_info_2(info);
5629
5630         if (*needed > offered) {
5631                 result = WERR_INSUFFICIENT_BUFFER;
5632                 goto out;
5633         }
5634
5635         if (!rpcbuf_alloc_size(buffer, *needed)) {
5636                 result = WERR_NOMEM;
5637                 goto out;
5638         }
5639
5640         /* fill the buffer with the structures */
5641         smb_io_printer_driver_info_2("", buffer, info, 0);
5642
5643 out:
5644         /* clear memory */
5645         SAFE_FREE(info);
5646
5647         return result;
5648 }
5649
5650 /****************************************************************************
5651 ****************************************************************************/
5652
5653 static WERROR getprinterdriver2_level3(const char *servername, fstring architecture, uint32 version, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
5654 {
5655         DRIVER_INFO_3 info;
5656         WERROR result;
5657
5658         ZERO_STRUCT(info);
5659
5660         result = construct_printer_driver_info_3(&info, snum, servername, architecture, version);
5661         if (!W_ERROR_IS_OK(result))
5662                 goto out;
5663
5664         /* check the required size. */
5665         *needed += spoolss_size_printer_driver_info_3(&info);
5666
5667         if (*needed > offered) {
5668                 result = WERR_INSUFFICIENT_BUFFER;
5669                 goto out;
5670         }
5671
5672         if (!rpcbuf_alloc_size(buffer, *needed)) {
5673                 result = WERR_NOMEM;
5674                 goto out;
5675         }
5676
5677         /* fill the buffer with the structures */
5678         smb_io_printer_driver_info_3("", buffer, &info, 0);
5679
5680 out:
5681         free_printer_driver_info_3(&info);
5682
5683         return result;
5684 }
5685
5686 /****************************************************************************
5687 ****************************************************************************/
5688
5689 static WERROR getprinterdriver2_level6(const char *servername, fstring architecture, uint32 version, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
5690 {
5691         DRIVER_INFO_6 info;
5692         WERROR result;
5693
5694         ZERO_STRUCT(info);
5695
5696         result = construct_printer_driver_info_6(&info, snum, servername, architecture, version);
5697         if (!W_ERROR_IS_OK(result))
5698                 goto out;
5699
5700         /* check the required size. */
5701         *needed += spoolss_size_printer_driver_info_6(&info);
5702
5703         if (*needed > offered) {
5704                 result = WERR_INSUFFICIENT_BUFFER;
5705                 goto out;
5706         }
5707
5708         if (!rpcbuf_alloc_size(buffer, *needed)) {
5709                 result = WERR_NOMEM;
5710                 goto out;
5711         }
5712
5713         /* fill the buffer with the structures */
5714         smb_io_printer_driver_info_6("", buffer, &info, 0);
5715
5716 out:
5717         free_printer_driver_info_6(&info);
5718
5719         return result;
5720 }
5721
5722 /****************************************************************************
5723 ****************************************************************************/
5724
5725 WERROR _spoolss_getprinterdriver2(pipes_struct *p, SPOOL_Q_GETPRINTERDRIVER2 *q_u, SPOOL_R_GETPRINTERDRIVER2 *r_u)
5726 {
5727         POLICY_HND *handle = &q_u->handle;
5728         UNISTR2 *uni_arch = &q_u->architecture;
5729         uint32 level = q_u->level;
5730         uint32 clientmajorversion = q_u->clientmajorversion;
5731         RPC_BUFFER *buffer = NULL;
5732         uint32 offered = q_u->offered;
5733         uint32 *needed = &r_u->needed;
5734         uint32 *servermajorversion = &r_u->servermajorversion;
5735         uint32 *serverminorversion = &r_u->serverminorversion;
5736         Printer_entry *printer;
5737
5738         fstring servername;
5739         fstring architecture;
5740         int snum;
5741
5742         /* that's an [in out] buffer */
5743
5744         if (!q_u->buffer && (offered!=0)) {
5745                 return WERR_INVALID_PARAM;
5746         }
5747
5748         if (offered > MAX_RPC_DATA_SIZE) {
5749                 return WERR_INVALID_PARAM;
5750         }
5751
5752         rpcbuf_move(q_u->buffer, &r_u->buffer);
5753         buffer = r_u->buffer;
5754
5755         DEBUG(4,("_spoolss_getprinterdriver2\n"));
5756
5757         if ( !(printer = find_printer_index_by_hnd( p, handle )) ) {
5758                 DEBUG(0,("_spoolss_getprinterdriver2: invalid printer handle!\n"));
5759                 return WERR_INVALID_PRINTER_NAME;
5760         }
5761
5762         *needed = 0;
5763         *servermajorversion = 0;
5764         *serverminorversion = 0;
5765
5766         fstrcpy(servername, get_server_name( printer ));
5767         unistr2_to_ascii(architecture, uni_arch, sizeof(architecture));
5768
5769         if (!get_printer_snum(p, handle, &snum, NULL))
5770                 return WERR_BADFID;
5771
5772         switch (level) {
5773         case 1:
5774                 return getprinterdriver2_level1(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
5775         case 2:
5776                 return getprinterdriver2_level2(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
5777         case 3:
5778                 return getprinterdriver2_level3(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
5779         case 6:
5780                 return getprinterdriver2_level6(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
5781 #if 0   /* JERRY */
5782         case 101:
5783                 /* apparently this call is the equivalent of
5784                    EnumPrinterDataEx() for the DsDriver key */
5785                 break;
5786 #endif
5787         }
5788
5789         return WERR_UNKNOWN_LEVEL;
5790 }
5791
5792
5793 /****************************************************************
5794  _spoolss_StartPagePrinter
5795 ****************************************************************/
5796
5797 WERROR _spoolss_StartPagePrinter(pipes_struct *p,
5798                                  struct spoolss_StartPagePrinter *r)
5799 {
5800         POLICY_HND *handle = r->in.handle;
5801
5802         Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5803
5804         if (!Printer) {
5805                 DEBUG(3,("_spoolss_StartPagePrinter: "
5806                         "Error in startpageprinter printer handle\n"));
5807                 return WERR_BADFID;
5808         }
5809
5810         Printer->page_started=True;
5811         return WERR_OK;
5812 }
5813
5814 /****************************************************************
5815  _spoolss_EndPagePrinter
5816 ****************************************************************/
5817
5818 WERROR _spoolss_EndPagePrinter(pipes_struct *p,
5819                                struct spoolss_EndPagePrinter *r)
5820 {
5821         POLICY_HND *handle = r->in.handle;
5822         int snum;
5823
5824         Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5825
5826         if (!Printer) {
5827                 DEBUG(2,("_spoolss_EndPagePrinter: Invalid handle (%s:%u:%u).\n",
5828                         OUR_HANDLE(handle)));
5829                 return WERR_BADFID;
5830         }
5831
5832         if (!get_printer_snum(p, handle, &snum, NULL))
5833                 return WERR_BADFID;
5834
5835         Printer->page_started=False;
5836         print_job_endpage(snum, Printer->jobid);
5837
5838         return WERR_OK;
5839 }
5840
5841 /****************************************************************
5842  _spoolss_StartDocPrinter
5843 ****************************************************************/
5844
5845 WERROR _spoolss_StartDocPrinter(pipes_struct *p,
5846                                 struct spoolss_StartDocPrinter *r)
5847 {
5848         POLICY_HND *handle = r->in.handle;
5849         uint32_t *jobid = r->out.job_id;
5850         struct spoolss_DocumentInfo1 *info_1;
5851         int snum;
5852         Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5853
5854         if (!Printer) {
5855                 DEBUG(2,("_spoolss_StartDocPrinter: "
5856                         "Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
5857                 return WERR_BADFID;
5858         }
5859
5860         if (r->in.level != 1) {
5861                 return WERR_UNKNOWN_LEVEL;
5862         }
5863
5864         info_1 = r->in.info.info1;
5865
5866         /*
5867          * a nice thing with NT is it doesn't listen to what you tell it.
5868          * when asked to send _only_ RAW datas, it tries to send datas
5869          * in EMF format.
5870          *
5871          * So I add checks like in NT Server ...
5872          */
5873
5874         if (info_1->datatype) {
5875                 if (strcmp(info_1->datatype, "RAW") != 0) {
5876                         (*jobid)=0;
5877                         return WERR_INVALID_DATATYPE;
5878                 }
5879         }
5880
5881         /* get the share number of the printer */
5882         if (!get_printer_snum(p, handle, &snum, NULL)) {
5883                 return WERR_BADFID;
5884         }
5885
5886         Printer->jobid = print_job_start(p->server_info, snum,
5887                                          CONST_DISCARD(char *,info_1->document_name),
5888                                          Printer->nt_devmode);
5889
5890         /* An error occured in print_job_start() so return an appropriate
5891            NT error code. */
5892
5893         if (Printer->jobid == -1) {
5894                 return map_werror_from_unix(errno);
5895         }
5896
5897         Printer->document_started=True;
5898         (*jobid) = Printer->jobid;
5899
5900         return WERR_OK;
5901 }
5902
5903 /****************************************************************
5904  _spoolss_EndDocPrinter
5905 ****************************************************************/
5906
5907 WERROR _spoolss_EndDocPrinter(pipes_struct *p,
5908                               struct spoolss_EndDocPrinter *r)
5909 {
5910         POLICY_HND *handle = r->in.handle;
5911
5912         return _spoolss_enddocprinter_internal(p, handle);
5913 }
5914
5915 /****************************************************************
5916  _spoolss_WritePrinter
5917 ****************************************************************/
5918
5919 WERROR _spoolss_WritePrinter(pipes_struct *p,
5920                              struct spoolss_WritePrinter *r)
5921 {
5922         POLICY_HND *handle = r->in.handle;
5923         uint32 buffer_size = r->in._data_size;
5924         uint8 *buffer = r->in.data.data;
5925         uint32 *buffer_written = &r->in._data_size;
5926         int snum;
5927         Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5928
5929         if (!Printer) {
5930                 DEBUG(2,("_spoolss_WritePrinter: Invalid handle (%s:%u:%u)\n",
5931                         OUR_HANDLE(handle)));
5932                 *r->out.num_written = r->in._data_size;
5933                 return WERR_BADFID;
5934         }
5935
5936         if (!get_printer_snum(p, handle, &snum, NULL))
5937                 return WERR_BADFID;
5938
5939         (*buffer_written) = (uint32)print_job_write(snum, Printer->jobid, (const char *)buffer,
5940                                         (SMB_OFF_T)-1, (size_t)buffer_size);
5941         if (*buffer_written == (uint32)-1) {
5942                 *r->out.num_written = 0;
5943                 if (errno == ENOSPC)
5944                         return WERR_NO_SPOOL_SPACE;
5945                 else
5946                         return WERR_ACCESS_DENIED;
5947         }
5948
5949         *r->out.num_written = r->in._data_size;
5950
5951         return WERR_OK;
5952 }
5953
5954 /********************************************************************
5955  * api_spoolss_getprinter
5956  * called from the spoolss dispatcher
5957  *
5958  ********************************************************************/
5959
5960 static WERROR control_printer(POLICY_HND *handle, uint32 command,
5961                               pipes_struct *p)
5962 {
5963         int snum;
5964         WERROR errcode = WERR_BADFUNC;
5965         Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5966
5967         if (!Printer) {
5968                 DEBUG(2,("control_printer: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
5969                 return WERR_BADFID;
5970         }
5971
5972         if (!get_printer_snum(p, handle, &snum, NULL))
5973                 return WERR_BADFID;
5974
5975         switch (command) {
5976         case SPOOLSS_PRINTER_CONTROL_PAUSE:
5977                 if (print_queue_pause(p->server_info, snum, &errcode)) {
5978                         errcode = WERR_OK;
5979                 }
5980                 break;
5981         case SPOOLSS_PRINTER_CONTROL_RESUME:
5982         case SPOOLSS_PRINTER_CONTROL_UNPAUSE:
5983                 if (print_queue_resume(p->server_info, snum, &errcode)) {
5984                         errcode = WERR_OK;
5985                 }
5986                 break;
5987         case SPOOLSS_PRINTER_CONTROL_PURGE:
5988                 if (print_queue_purge(p->server_info, snum, &errcode)) {
5989                         errcode = WERR_OK;
5990                 }
5991                 break;
5992         default:
5993                 return WERR_UNKNOWN_LEVEL;
5994         }
5995
5996         return errcode;
5997 }
5998
5999
6000 /****************************************************************
6001  _spoolss_AbortPrinter
6002  * From MSDN: "Deletes printer's spool file if printer is configured
6003  * for spooling"
6004 ****************************************************************/
6005
6006 WERROR _spoolss_AbortPrinter(pipes_struct *p,
6007                              struct spoolss_AbortPrinter *r)
6008 {
6009         POLICY_HND      *handle = r->in.handle;
6010         Printer_entry   *Printer = find_printer_index_by_hnd(p, handle);
6011         int             snum;
6012         WERROR          errcode = WERR_OK;
6013
6014         if (!Printer) {
6015                 DEBUG(2,("_spoolss_AbortPrinter: Invalid handle (%s:%u:%u)\n",
6016                         OUR_HANDLE(handle)));
6017                 return WERR_BADFID;
6018         }
6019
6020         if (!get_printer_snum(p, handle, &snum, NULL))
6021                 return WERR_BADFID;
6022
6023         print_job_delete(p->server_info, snum, Printer->jobid, &errcode );
6024
6025         return errcode;
6026 }
6027
6028 /********************************************************************
6029  * called by spoolss_api_setprinter
6030  * when updating a printer description
6031  ********************************************************************/
6032
6033 static WERROR update_printer_sec(POLICY_HND *handle,
6034                                  pipes_struct *p, SEC_DESC_BUF *secdesc_ctr)
6035 {
6036         SEC_DESC_BUF *new_secdesc_ctr = NULL, *old_secdesc_ctr = NULL;
6037         WERROR result;
6038         int snum;
6039
6040         Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
6041
6042         if (!Printer || !get_printer_snum(p, handle, &snum, NULL)) {
6043                 DEBUG(2,("update_printer_sec: Invalid handle (%s:%u:%u)\n",
6044                          OUR_HANDLE(handle)));
6045
6046                 result = WERR_BADFID;
6047                 goto done;
6048         }
6049
6050         if (!secdesc_ctr) {
6051                 DEBUG(10,("update_printer_sec: secdesc_ctr is NULL !\n"));
6052                 result = WERR_INVALID_PARAM;
6053                 goto done;
6054         }
6055
6056         /* Check the user has permissions to change the security
6057            descriptor.  By experimentation with two NT machines, the user
6058            requires Full Access to the printer to change security
6059            information. */
6060
6061         if ( Printer->access_granted != PRINTER_ACCESS_ADMINISTER ) {
6062                 DEBUG(4,("update_printer_sec: updated denied by printer permissions\n"));
6063                 result = WERR_ACCESS_DENIED;
6064                 goto done;
6065         }
6066
6067         /* NT seems to like setting the security descriptor even though
6068            nothing may have actually changed. */
6069
6070         if ( !nt_printing_getsec(p->mem_ctx, Printer->sharename, &old_secdesc_ctr)) {
6071                 DEBUG(2,("update_printer_sec: nt_printing_getsec() failed\n"));
6072                 result = WERR_BADFID;
6073                 goto done;
6074         }
6075
6076         if (DEBUGLEVEL >= 10) {
6077                 SEC_ACL *the_acl;
6078                 int i;
6079
6080                 the_acl = old_secdesc_ctr->sd->dacl;
6081                 DEBUG(10, ("old_secdesc_ctr for %s has %d aces:\n",
6082                            PRINTERNAME(snum), the_acl->num_aces));
6083
6084                 for (i = 0; i < the_acl->num_aces; i++) {
6085                         DEBUG(10, ("%s 0x%08x\n", sid_string_dbg(
6086                                            &the_acl->aces[i].trustee),
6087                                   the_acl->aces[i].access_mask));
6088                 }
6089
6090                 the_acl = secdesc_ctr->sd->dacl;
6091
6092                 if (the_acl) {
6093                         DEBUG(10, ("secdesc_ctr for %s has %d aces:\n",
6094                                    PRINTERNAME(snum), the_acl->num_aces));
6095
6096                         for (i = 0; i < the_acl->num_aces; i++) {
6097                                 DEBUG(10, ("%s 0x%08x\n", sid_string_dbg(
6098                                                    &the_acl->aces[i].trustee),
6099                                            the_acl->aces[i].access_mask));
6100                         }
6101                 } else {
6102                         DEBUG(10, ("dacl for secdesc_ctr is NULL\n"));
6103                 }
6104         }
6105
6106         new_secdesc_ctr = sec_desc_merge(p->mem_ctx, secdesc_ctr, old_secdesc_ctr);
6107         if (!new_secdesc_ctr) {
6108                 result = WERR_NOMEM;
6109                 goto done;
6110         }
6111
6112         if (sec_desc_equal(new_secdesc_ctr->sd, old_secdesc_ctr->sd)) {
6113                 result = WERR_OK;
6114                 goto done;
6115         }
6116
6117         result = nt_printing_setsec(Printer->sharename, new_secdesc_ctr);
6118
6119  done:
6120
6121         return result;
6122 }
6123
6124 /********************************************************************
6125  Canonicalize printer info from a client
6126
6127  ATTN: It does not matter what we set the servername to hear
6128  since we do the necessary work in get_a_printer() to set it to
6129  the correct value based on what the client sent in the
6130  _spoolss_open_printer_ex().
6131  ********************************************************************/
6132
6133 static bool check_printer_ok(NT_PRINTER_INFO_LEVEL_2 *info, int snum)
6134 {
6135         fstring printername;
6136         const char *p;
6137
6138         DEBUG(5,("check_printer_ok: servername=%s printername=%s sharename=%s "
6139                 "portname=%s drivername=%s comment=%s location=%s\n",
6140                 info->servername, info->printername, info->sharename,
6141                 info->portname, info->drivername, info->comment, info->location));
6142
6143         /* we force some elements to "correct" values */
6144         slprintf(info->servername, sizeof(info->servername)-1, "\\\\%s", global_myname());
6145         fstrcpy(info->sharename, lp_servicename(snum));
6146
6147         /* check to see if we allow printername != sharename */
6148
6149         if ( lp_force_printername(snum) ) {
6150                 slprintf(info->printername, sizeof(info->printername)-1, "\\\\%s\\%s",
6151                         global_myname(), info->sharename );
6152         } else {
6153
6154                 /* make sure printername is in \\server\printername format */
6155
6156                 fstrcpy( printername, info->printername );
6157                 p = printername;
6158                 if ( printername[0] == '\\' && printername[1] == '\\' ) {
6159                         if ( (p = strchr_m( &printername[2], '\\' )) != NULL )
6160                                 p++;
6161                 }
6162
6163                 slprintf(info->printername, sizeof(info->printername)-1, "\\\\%s\\%s",
6164                          global_myname(), p );
6165         }
6166
6167         info->attributes |= PRINTER_ATTRIBUTE_SAMBA;
6168         info->attributes &= ~PRINTER_ATTRIBUTE_NOT_SAMBA;
6169
6170
6171
6172         return True;
6173 }
6174
6175 /****************************************************************************
6176 ****************************************************************************/
6177
6178 WERROR add_port_hook(TALLOC_CTX *ctx, NT_USER_TOKEN *token, const char *portname, const char *uri )
6179 {
6180         char *cmd = lp_addport_cmd();
6181         char *command = NULL;
6182         int ret;
6183         SE_PRIV se_printop = SE_PRINT_OPERATOR;
6184         bool is_print_op = False;
6185
6186         if ( !*cmd ) {
6187                 return WERR_ACCESS_DENIED;
6188         }
6189
6190         command = talloc_asprintf(ctx,
6191                         "%s \"%s\" \"%s\"", cmd, portname, uri );
6192         if (!command) {
6193                 return WERR_NOMEM;
6194         }
6195
6196         if ( token )
6197                 is_print_op = user_has_privileges( token, &se_printop );
6198
6199         DEBUG(10,("Running [%s]\n", command));
6200
6201         /********* BEGIN SePrintOperatorPrivilege **********/
6202
6203         if ( is_print_op )
6204                 become_root();
6205
6206         ret = smbrun(command, NULL);
6207
6208         if ( is_print_op )
6209                 unbecome_root();
6210
6211         /********* END SePrintOperatorPrivilege **********/
6212
6213         DEBUGADD(10,("returned [%d]\n", ret));
6214
6215         TALLOC_FREE(command);
6216
6217         if ( ret != 0 ) {
6218                 return WERR_ACCESS_DENIED;
6219         }
6220
6221         return WERR_OK;
6222 }
6223
6224 /****************************************************************************
6225 ****************************************************************************/
6226
6227 bool add_printer_hook(TALLOC_CTX *ctx, NT_USER_TOKEN *token, NT_PRINTER_INFO_LEVEL *printer)
6228 {
6229         char *cmd = lp_addprinter_cmd();
6230         char **qlines;
6231         char *command = NULL;
6232         int numlines;
6233         int ret;
6234         int fd;
6235         SE_PRIV se_printop = SE_PRINT_OPERATOR;
6236         bool is_print_op = False;
6237         char *remote_machine = talloc_strdup(ctx, "%m");
6238
6239         if (!remote_machine) {
6240                 return false;
6241         }
6242         remote_machine = talloc_sub_basic(ctx,
6243                                 current_user_info.smb_name,
6244                                 current_user_info.domain,
6245                                 remote_machine);
6246         if (!remote_machine) {
6247                 return false;
6248         }
6249
6250         command = talloc_asprintf(ctx,
6251                         "%s \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\"",
6252                         cmd, printer->info_2->printername, printer->info_2->sharename,
6253                         printer->info_2->portname, printer->info_2->drivername,
6254                         printer->info_2->location, printer->info_2->comment, remote_machine);
6255         if (!command) {
6256                 return false;
6257         }
6258
6259         if ( token )
6260                 is_print_op = user_has_privileges( token, &se_printop );
6261
6262         DEBUG(10,("Running [%s]\n", command));
6263
6264         /********* BEGIN SePrintOperatorPrivilege **********/
6265
6266         if ( is_print_op )
6267                 become_root();
6268
6269         if ( (ret = smbrun(command, &fd)) == 0 ) {
6270                 /* Tell everyone we updated smb.conf. */
6271                 message_send_all(smbd_messaging_context(),
6272                                  MSG_SMB_CONF_UPDATED, NULL, 0, NULL);
6273         }
6274
6275         if ( is_print_op )
6276                 unbecome_root();
6277
6278         /********* END SePrintOperatorPrivilege **********/
6279
6280         DEBUGADD(10,("returned [%d]\n", ret));
6281
6282         TALLOC_FREE(command);
6283         TALLOC_FREE(remote_machine);
6284
6285         if ( ret != 0 ) {
6286                 if (fd != -1)
6287                         close(fd);
6288                 return False;
6289         }
6290
6291         /* reload our services immediately */
6292         reload_services( False );
6293
6294         numlines = 0;
6295         /* Get lines and convert them back to dos-codepage */
6296         qlines = fd_lines_load(fd, &numlines, 0, NULL);
6297         DEBUGADD(10,("Lines returned = [%d]\n", numlines));
6298         close(fd);
6299
6300         /* Set the portname to what the script says the portname should be. */
6301         /* but don't require anything to be return from the script exit a good error code */
6302
6303         if (numlines) {
6304                 /* Set the portname to what the script says the portname should be. */
6305                 strncpy(printer->info_2->portname, qlines[0], sizeof(printer->info_2->portname));
6306                 DEBUGADD(6,("Line[0] = [%s]\n", qlines[0]));
6307         }
6308
6309         TALLOC_FREE(qlines);
6310         return True;
6311 }
6312
6313
6314 /********************************************************************
6315  * Called by spoolss_api_setprinter
6316  * when updating a printer description.
6317  ********************************************************************/
6318
6319 static WERROR update_printer(pipes_struct *p, POLICY_HND *handle,
6320                              struct spoolss_SetPrinterInfoCtr *info_ctr,
6321                              struct spoolss_DeviceMode *devmode)
6322 {
6323         int snum;
6324         NT_PRINTER_INFO_LEVEL *printer = NULL, *old_printer = NULL;
6325         Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
6326         WERROR result;
6327         UNISTR2 buffer;
6328         fstring asc_buffer;
6329
6330         DEBUG(8,("update_printer\n"));
6331
6332         result = WERR_OK;
6333
6334         if (!Printer) {
6335                 result = WERR_BADFID;
6336                 goto done;
6337         }
6338
6339         if (!get_printer_snum(p, handle, &snum, NULL)) {
6340                 result = WERR_BADFID;
6341                 goto done;
6342         }
6343
6344         if (!W_ERROR_IS_OK(get_a_printer(Printer, &printer, 2, lp_const_servicename(snum))) ||
6345             (!W_ERROR_IS_OK(get_a_printer(Printer, &old_printer, 2, lp_const_servicename(snum))))) {
6346                 result = WERR_BADFID;
6347                 goto done;
6348         }
6349
6350         DEBUGADD(8,("Converting info_2 struct\n"));
6351
6352         /*
6353          * convert_printer_info converts the incoming
6354          * info from the client and overwrites the info
6355          * just read from the tdb in the pointer 'printer'.
6356          */
6357
6358         if (!convert_printer_info_new(info_ctr, printer)) {
6359                 result =  WERR_NOMEM;
6360                 goto done;
6361         }
6362
6363         if (devmode) {
6364                 /* we have a valid devmode
6365                    convert it and link it*/
6366
6367                 DEBUGADD(8,("update_printer: Converting the devicemode struct\n"));
6368                 if (!convert_devicemode_new(printer->info_2->printername,
6369                                             devmode,
6370                                             &printer->info_2->devmode)) {
6371                         result =  WERR_NOMEM;
6372                         goto done;
6373                 }
6374         }
6375
6376         /* Do sanity check on the requested changes for Samba */
6377
6378         if (!check_printer_ok(printer->info_2, snum)) {
6379                 result = WERR_INVALID_PARAM;
6380                 goto done;
6381         }
6382
6383         /* FIXME!!! If the driver has changed we really should verify that
6384            it is installed before doing much else   --jerry */
6385
6386         /* Check calling user has permission to update printer description */
6387
6388         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
6389                 DEBUG(3, ("update_printer: printer property change denied by handle\n"));
6390                 result = WERR_ACCESS_DENIED;
6391                 goto done;
6392         }
6393
6394         /* Call addprinter hook */
6395         /* Check changes to see if this is really needed */
6396
6397         if ( *lp_addprinter_cmd()
6398                 && (!strequal(printer->info_2->drivername, old_printer->info_2->drivername)
6399                         || !strequal(printer->info_2->comment, old_printer->info_2->comment)
6400                         || !strequal(printer->info_2->portname, old_printer->info_2->portname)
6401                         || !strequal(printer->info_2->location, old_printer->info_2->location)) )
6402         {
6403                 /* add_printer_hook() will call reload_services() */
6404
6405                 if ( !add_printer_hook(p->mem_ctx, p->server_info->ptok,
6406                                        printer) ) {
6407                         result = WERR_ACCESS_DENIED;
6408                         goto done;
6409                 }
6410         }
6411
6412         /*
6413          * When a *new* driver is bound to a printer, the drivername is used to
6414          * lookup previously saved driver initialization info, which is then
6415          * bound to the printer, simulating what happens in the Windows arch.
6416          */
6417         if (!strequal(printer->info_2->drivername, old_printer->info_2->drivername))
6418         {
6419                 if (!set_driver_init(printer, 2))
6420                 {
6421                         DEBUG(5,("update_printer: Error restoring driver initialization data for driver [%s]!\n",
6422                                 printer->info_2->drivername));
6423                 }
6424
6425                 DEBUG(10,("update_printer: changing driver [%s]!  Sending event!\n",
6426                         printer->info_2->drivername));
6427
6428                 notify_printer_driver(snum, printer->info_2->drivername);
6429         }
6430
6431         /*
6432          * flag which changes actually occured.  This is a small subset of
6433          * all the possible changes.  We also have to update things in the
6434          * DsSpooler key.
6435          */
6436
6437         if (!strequal(printer->info_2->comment, old_printer->info_2->comment)) {
6438                 init_unistr2( &buffer, printer->info_2->comment, UNI_STR_TERMINATE);
6439                 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "description",
6440                         REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6441
6442                 notify_printer_comment(snum, printer->info_2->comment);
6443         }
6444
6445         if (!strequal(printer->info_2->sharename, old_printer->info_2->sharename)) {
6446                 init_unistr2( &buffer, printer->info_2->sharename, UNI_STR_TERMINATE);
6447                 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "shareName",
6448                         REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6449
6450                 notify_printer_sharename(snum, printer->info_2->sharename);
6451         }
6452
6453         if (!strequal(printer->info_2->printername, old_printer->info_2->printername)) {
6454                 char *pname;
6455
6456                 if ( (pname = strchr_m( printer->info_2->printername+2, '\\' )) != NULL )
6457                         pname++;
6458                 else
6459                         pname = printer->info_2->printername;
6460
6461
6462                 init_unistr2( &buffer, pname, UNI_STR_TERMINATE);
6463                 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "printerName",
6464                         REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6465
6466                 notify_printer_printername( snum, pname );
6467         }
6468
6469         if (!strequal(printer->info_2->portname, old_printer->info_2->portname)) {
6470                 init_unistr2( &buffer, printer->info_2->portname, UNI_STR_TERMINATE);
6471                 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "portName",
6472                         REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6473
6474                 notify_printer_port(snum, printer->info_2->portname);
6475         }
6476
6477         if (!strequal(printer->info_2->location, old_printer->info_2->location)) {
6478                 init_unistr2( &buffer, printer->info_2->location, UNI_STR_TERMINATE);
6479                 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "location",
6480                         REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6481
6482                 notify_printer_location(snum, printer->info_2->location);
6483         }
6484
6485         /* here we need to update some more DsSpooler keys */
6486         /* uNCName, serverName, shortServerName */
6487
6488         init_unistr2( &buffer, global_myname(), UNI_STR_TERMINATE);
6489         set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "serverName",
6490                 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6491         set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "shortServerName",
6492                 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6493
6494         slprintf( asc_buffer, sizeof(asc_buffer)-1, "\\\\%s\\%s",
6495                  global_myname(), printer->info_2->sharename );
6496         init_unistr2( &buffer, asc_buffer, UNI_STR_TERMINATE);
6497         set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "uNCName",
6498                 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6499
6500         /* Update printer info */
6501         result = mod_a_printer(printer, 2);
6502
6503 done:
6504         free_a_printer(&printer, 2);
6505         free_a_printer(&old_printer, 2);
6506
6507
6508         return result;
6509 }
6510
6511 /****************************************************************************
6512 ****************************************************************************/
6513 static WERROR publish_or_unpublish_printer(pipes_struct *p, POLICY_HND *handle,
6514                                            struct spoolss_SetPrinterInfo7 *info7)
6515 {
6516 #ifdef HAVE_ADS
6517         int snum;
6518         Printer_entry *Printer;
6519
6520         if ( lp_security() != SEC_ADS ) {
6521                 return WERR_UNKNOWN_LEVEL;
6522         }
6523
6524         Printer = find_printer_index_by_hnd(p, handle);
6525
6526         DEBUG(5,("publish_or_unpublish_printer, action = %d\n",info7->action));
6527
6528         if (!Printer)
6529                 return WERR_BADFID;
6530
6531         if (!get_printer_snum(p, handle, &snum, NULL))
6532                 return WERR_BADFID;
6533
6534         nt_printer_publish(Printer, snum, info7->action);
6535
6536         return WERR_OK;
6537 #else
6538         return WERR_UNKNOWN_LEVEL;
6539 #endif
6540 }
6541
6542 /****************************************************************
6543  _spoolss_SetPrinter
6544 ****************************************************************/
6545
6546 WERROR _spoolss_SetPrinter(pipes_struct *p,
6547                            struct spoolss_SetPrinter *r)
6548 {
6549         POLICY_HND *handle = r->in.handle;
6550         WERROR result;
6551
6552         Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
6553
6554         if (!Printer) {
6555                 DEBUG(2,("_spoolss_SetPrinter: Invalid handle (%s:%u:%u)\n",
6556                         OUR_HANDLE(handle)));
6557                 return WERR_BADFID;
6558         }
6559
6560         /* check the level */
6561         switch (r->in.info_ctr->level) {
6562                 case 0:
6563                         return control_printer(handle, r->in.command, p);
6564                 case 2:
6565                         result = update_printer(p, handle,
6566                                                 r->in.info_ctr,
6567                                                 r->in.devmode_ctr->devmode);
6568                         if (!W_ERROR_IS_OK(result))
6569                                 return result;
6570                         if (r->in.secdesc_ctr->sd)
6571                                 result = update_printer_sec(handle, p,
6572                                                             r->in.secdesc_ctr);
6573                         return result;
6574                 case 3:
6575                         return update_printer_sec(handle, p,
6576                                                   r->in.secdesc_ctr);
6577                 case 7:
6578                         return publish_or_unpublish_printer(p, handle,
6579                                                             r->in.info_ctr->info.info7);
6580                 default:
6581                         return WERR_UNKNOWN_LEVEL;
6582         }
6583 }
6584
6585 /****************************************************************
6586  _spoolss_FindClosePrinterNotify
6587 ****************************************************************/
6588
6589 WERROR _spoolss_FindClosePrinterNotify(pipes_struct *p,
6590                                        struct spoolss_FindClosePrinterNotify *r)
6591 {
6592         POLICY_HND *handle = r->in.handle;
6593         Printer_entry *Printer= find_printer_index_by_hnd(p, handle);
6594
6595         if (!Printer) {
6596                 DEBUG(2,("_spoolss_FindClosePrinterNotify: "
6597                         "Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
6598                 return WERR_BADFID;
6599         }
6600
6601         if (Printer->notify.client_connected==True) {
6602                 int snum = -1;
6603
6604                 if ( Printer->printer_type == SPLHND_SERVER)
6605                         snum = -1;
6606                 else if ( (Printer->printer_type == SPLHND_PRINTER) &&
6607                                 !get_printer_snum(p, handle, &snum, NULL) )
6608                         return WERR_BADFID;
6609
6610                 srv_spoolss_replycloseprinter(snum, &Printer->notify.client_hnd);
6611         }
6612
6613         Printer->notify.flags=0;
6614         Printer->notify.options=0;
6615         Printer->notify.localmachine[0]='\0';
6616         Printer->notify.printerlocal=0;
6617         if (Printer->notify.option)
6618                 free_spool_notify_option(&Printer->notify.option);
6619         Printer->notify.client_connected=False;
6620
6621         return WERR_OK;
6622 }
6623
6624 /****************************************************************
6625  _spoolss_AddJob
6626 ****************************************************************/
6627
6628 WERROR _spoolss_AddJob(pipes_struct *p,
6629                        struct spoolss_AddJob *r)
6630 {
6631         if (!r->in.buffer && (r->in.offered != 0)) {
6632                 return WERR_INVALID_PARAM;
6633         }
6634
6635         /* this is what a NT server returns for AddJob. AddJob must fail on
6636          * non-local printers */
6637
6638         return WERR_INVALID_PARAM;
6639 }
6640
6641 /****************************************************************************
6642 ****************************************************************************/
6643
6644 static void fill_job_info_1(JOB_INFO_1 *job_info, const print_queue_struct *queue,
6645                             int position, int snum,
6646                             const NT_PRINTER_INFO_LEVEL *ntprinter)
6647 {
6648         struct tm *t;
6649
6650         t=gmtime(&queue->time);
6651
6652         job_info->jobid=queue->job;
6653         init_unistr(&job_info->printername, lp_servicename(snum));
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->datatype, "RAW");
6658         init_unistr(&job_info->text_status, "");
6659         job_info->status=nt_printj_status(queue->status);
6660         job_info->priority=queue->priority;
6661         job_info->position=position;
6662         job_info->totalpages=queue->page_count;
6663         job_info->pagesprinted=0;
6664
6665         make_systemtime(&job_info->submitted, t);
6666 }
6667
6668 /****************************************************************************
6669 ****************************************************************************/
6670
6671 static bool fill_job_info_2(JOB_INFO_2 *job_info, const print_queue_struct *queue,
6672                             int position, int snum,
6673                             const NT_PRINTER_INFO_LEVEL *ntprinter,
6674                             DEVICEMODE *devmode)
6675 {
6676         struct tm *t;
6677
6678         t=gmtime(&queue->time);
6679
6680         job_info->jobid=queue->job;
6681
6682         init_unistr(&job_info->printername, ntprinter->info_2->printername);
6683
6684         init_unistr(&job_info->machinename, ntprinter->info_2->servername);
6685         init_unistr(&job_info->username, queue->fs_user);
6686         init_unistr(&job_info->document, queue->fs_file);
6687         init_unistr(&job_info->notifyname, queue->fs_user);
6688         init_unistr(&job_info->datatype, "RAW");
6689         init_unistr(&job_info->printprocessor, "winprint");
6690         init_unistr(&job_info->parameters, "");
6691         init_unistr(&job_info->drivername, ntprinter->info_2->drivername);
6692         init_unistr(&job_info->text_status, "");
6693
6694 /* and here the security descriptor */
6695
6696         job_info->status=nt_printj_status(queue->status);
6697         job_info->priority=queue->priority;
6698         job_info->position=position;
6699         job_info->starttime=0;
6700         job_info->untiltime=0;
6701         job_info->totalpages=queue->page_count;
6702         job_info->size=queue->size;
6703         make_systemtime(&(job_info->submitted), t);
6704         job_info->timeelapsed=0;
6705         job_info->pagesprinted=0;
6706
6707         job_info->devmode = devmode;
6708
6709         return (True);
6710 }
6711
6712 /****************************************************************************
6713  Enumjobs at level 1.
6714 ****************************************************************************/
6715
6716 static WERROR enumjobs_level1(const print_queue_struct *queue, int snum,
6717                               const NT_PRINTER_INFO_LEVEL *ntprinter,
6718                               RPC_BUFFER *buffer, uint32 offered,
6719                               uint32 *needed, uint32 *returned)
6720 {
6721         JOB_INFO_1 *info;
6722         int i;
6723         WERROR result = WERR_OK;
6724
6725         info=SMB_MALLOC_ARRAY(JOB_INFO_1,*returned);
6726         if (info==NULL) {
6727                 *returned=0;
6728                 return WERR_NOMEM;
6729         }
6730
6731         for (i=0; i<*returned; i++)
6732                 fill_job_info_1( &info[i], &queue[i], i, snum, ntprinter );
6733
6734         /* check the required size. */
6735         for (i=0; i<*returned; i++)
6736                 (*needed) += spoolss_size_job_info_1(&info[i]);
6737
6738         if (*needed > offered) {
6739                 result = WERR_INSUFFICIENT_BUFFER;
6740                 goto out;
6741         }
6742
6743         if (!rpcbuf_alloc_size(buffer, *needed)) {
6744                 result = WERR_NOMEM;
6745                 goto out;
6746         }
6747
6748         /* fill the buffer with the structures */
6749         for (i=0; i<*returned; i++)
6750                 smb_io_job_info_1("", buffer, &info[i], 0);
6751
6752 out:
6753         /* clear memory */
6754         SAFE_FREE(info);
6755
6756         if ( !W_ERROR_IS_OK(result) )
6757                 *returned = 0;
6758
6759         return result;
6760 }
6761
6762 /****************************************************************************
6763  Enumjobs at level 2.
6764 ****************************************************************************/
6765
6766 static WERROR enumjobs_level2(const print_queue_struct *queue, int snum,
6767                               const NT_PRINTER_INFO_LEVEL *ntprinter,
6768                               RPC_BUFFER *buffer, uint32 offered,
6769                               uint32 *needed, uint32 *returned)
6770 {
6771         JOB_INFO_2 *info = NULL;
6772         int i;
6773         WERROR result = WERR_OK;
6774         DEVICEMODE *devmode = NULL;
6775
6776         if ( !(info = SMB_MALLOC_ARRAY(JOB_INFO_2,*returned)) ) {
6777                 *returned=0;
6778                 return WERR_NOMEM;
6779         }
6780
6781         /* this should not be a failure condition if the devmode is NULL */
6782
6783         devmode = construct_dev_mode(lp_const_servicename(snum));
6784
6785         for (i=0; i<*returned; i++)
6786                 fill_job_info_2(&(info[i]), &queue[i], i, snum, ntprinter, devmode);
6787
6788         /* check the required size. */
6789         for (i=0; i<*returned; i++)
6790                 (*needed) += spoolss_size_job_info_2(&info[i]);
6791
6792         if (*needed > offered) {
6793                 result = WERR_INSUFFICIENT_BUFFER;
6794                 goto out;
6795         }
6796
6797         if (!rpcbuf_alloc_size(buffer, *needed)) {
6798                 result = WERR_NOMEM;
6799                 goto out;
6800         }
6801
6802         /* fill the buffer with the structures */
6803         for (i=0; i<*returned; i++)
6804                 smb_io_job_info_2("", buffer, &info[i], 0);
6805
6806 out:
6807         free_devmode(devmode);
6808         SAFE_FREE(info);
6809
6810         if ( !W_ERROR_IS_OK(result) )
6811                 *returned = 0;
6812
6813         return result;
6814
6815 }
6816
6817 /****************************************************************************
6818  Enumjobs.
6819 ****************************************************************************/
6820
6821 WERROR _spoolss_enumjobs( pipes_struct *p, SPOOL_Q_ENUMJOBS *q_u, SPOOL_R_ENUMJOBS *r_u)
6822 {
6823         POLICY_HND *handle = &q_u->handle;
6824         uint32 level = q_u->level;
6825         RPC_BUFFER *buffer = NULL;
6826         uint32 offered = q_u->offered;
6827         uint32 *needed = &r_u->needed;
6828         uint32 *returned = &r_u->returned;
6829         WERROR wret;
6830         NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
6831         int snum;
6832         print_status_struct prt_status;
6833         print_queue_struct *queue=NULL;
6834
6835         /* that's an [in out] buffer */
6836
6837         if (!q_u->buffer && (offered!=0)) {
6838                 return WERR_INVALID_PARAM;
6839         }
6840
6841         if (offered > MAX_RPC_DATA_SIZE) {
6842                 return WERR_INVALID_PARAM;
6843         }
6844
6845         rpcbuf_move(q_u->buffer, &r_u->buffer);
6846         buffer = r_u->buffer;
6847
6848         DEBUG(4,("_spoolss_enumjobs\n"));
6849
6850         *needed=0;
6851         *returned=0;
6852
6853         /* lookup the printer snum and tdb entry */
6854
6855         if (!get_printer_snum(p, handle, &snum, NULL))
6856                 return WERR_BADFID;
6857
6858         wret = get_a_printer(NULL, &ntprinter, 2, lp_servicename(snum));
6859         if ( !W_ERROR_IS_OK(wret) )
6860                 return wret;
6861
6862         *returned = print_queue_status(snum, &queue, &prt_status);
6863         DEBUGADD(4,("count:[%d], status:[%d], [%s]\n", *returned, prt_status.status, prt_status.message));
6864
6865         if (*returned == 0) {
6866                 SAFE_FREE(queue);
6867                 free_a_printer(&ntprinter, 2);
6868                 return WERR_OK;
6869         }
6870
6871         switch (level) {
6872         case 1:
6873                 wret = enumjobs_level1(queue, snum, ntprinter, buffer, offered, needed, returned);
6874                 break;
6875         case 2:
6876                 wret = enumjobs_level2(queue, snum, ntprinter, buffer, offered, needed, returned);
6877                 break;
6878         default:
6879                 *returned=0;
6880                 wret = WERR_UNKNOWN_LEVEL;
6881                 break;
6882         }
6883
6884         SAFE_FREE(queue);
6885         free_a_printer( &ntprinter, 2 );
6886         return wret;
6887 }
6888
6889 /****************************************************************
6890  _spoolss_ScheduleJob
6891 ****************************************************************/
6892
6893 WERROR _spoolss_ScheduleJob(pipes_struct *p,
6894                             struct spoolss_ScheduleJob *r)
6895 {
6896         return WERR_OK;
6897 }
6898
6899 /****************************************************************
6900  _spoolss_SetJob
6901 ****************************************************************/
6902
6903 WERROR _spoolss_SetJob(pipes_struct *p,
6904                        struct spoolss_SetJob *r)
6905 {
6906         POLICY_HND *handle = r->in.handle;
6907         uint32 jobid = r->in.job_id;
6908         uint32 command = r->in.command;
6909
6910         int snum;
6911         WERROR errcode = WERR_BADFUNC;
6912
6913         if (!get_printer_snum(p, handle, &snum, NULL)) {
6914                 return WERR_BADFID;
6915         }
6916
6917         if (!print_job_exists(lp_const_servicename(snum), jobid)) {
6918                 return WERR_INVALID_PRINTER_NAME;
6919         }
6920
6921         switch (command) {
6922         case SPOOLSS_JOB_CONTROL_CANCEL:
6923         case SPOOLSS_JOB_CONTROL_DELETE:
6924                 if (print_job_delete(p->server_info, snum, jobid, &errcode)) {
6925                         errcode = WERR_OK;
6926                 }
6927                 break;
6928         case SPOOLSS_JOB_CONTROL_PAUSE:
6929                 if (print_job_pause(p->server_info, snum, jobid, &errcode)) {
6930                         errcode = WERR_OK;
6931                 }
6932                 break;
6933         case SPOOLSS_JOB_CONTROL_RESTART:
6934         case SPOOLSS_JOB_CONTROL_RESUME:
6935                 if (print_job_resume(p->server_info, snum, jobid, &errcode)) {
6936                         errcode = WERR_OK;
6937                 }
6938                 break;
6939         default:
6940                 return WERR_UNKNOWN_LEVEL;
6941         }
6942
6943         return errcode;
6944 }
6945
6946 /****************************************************************************
6947  Enumerates all printer drivers at level 1.
6948 ****************************************************************************/
6949
6950 static WERROR enumprinterdrivers_level1(const char *servername, fstring architecture, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
6951 {
6952         int i;
6953         int ndrivers;
6954         uint32 version;
6955         fstring *list = NULL;
6956         NT_PRINTER_DRIVER_INFO_LEVEL driver;
6957         DRIVER_INFO_1 *driver_info_1=NULL;
6958         WERROR result = WERR_OK;
6959
6960         *returned=0;
6961
6962         for (version=0; version<DRIVER_MAX_VERSION; version++) {
6963                 list=NULL;
6964                 ndrivers=get_ntdrivers(&list, architecture, version);
6965                 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
6966
6967                 if(ndrivers == -1) {
6968                         SAFE_FREE(driver_info_1);
6969                         return WERR_NOMEM;
6970                 }
6971
6972                 if(ndrivers != 0) {
6973                         if((driver_info_1=SMB_REALLOC_ARRAY(driver_info_1, DRIVER_INFO_1, *returned+ndrivers )) == NULL) {
6974                                 DEBUG(0,("enumprinterdrivers_level1: failed to enlarge driver info buffer!\n"));
6975                                 SAFE_FREE(list);
6976                                 return WERR_NOMEM;
6977                         }
6978                 }
6979
6980                 for (i=0; i<ndrivers; i++) {
6981                         WERROR status;
6982                         DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
6983                         ZERO_STRUCT(driver);
6984                         status = get_a_printer_driver(&driver, 3, list[i],
6985                                                       architecture, version);
6986                         if (!W_ERROR_IS_OK(status)) {
6987                                 SAFE_FREE(list);
6988                                 SAFE_FREE(driver_info_1);
6989                                 return status;
6990                         }
6991                         fill_printer_driver_info_1(&driver_info_1[*returned+i], driver, servername, architecture );
6992                         free_a_printer_driver(driver, 3);
6993                 }
6994
6995                 *returned+=ndrivers;
6996                 SAFE_FREE(list);
6997         }
6998
6999         /* check the required size. */
7000         for (i=0; i<*returned; i++) {
7001                 DEBUGADD(6,("adding driver [%d]'s size\n",i));
7002                 *needed += spoolss_size_printer_driver_info_1(&driver_info_1[i]);
7003         }
7004
7005         if (*needed > offered) {
7006                 result = WERR_INSUFFICIENT_BUFFER;
7007                 goto out;
7008         }
7009
7010         if (!rpcbuf_alloc_size(buffer, *needed)) {
7011                 result = WERR_NOMEM;
7012                 goto out;
7013         }
7014
7015         /* fill the buffer with the driver structures */
7016         for (i=0; i<*returned; i++) {
7017                 DEBUGADD(6,("adding driver [%d] to buffer\n",i));
7018                 smb_io_printer_driver_info_1("", buffer, &driver_info_1[i], 0);
7019         }
7020
7021 out:
7022         SAFE_FREE(driver_info_1);
7023
7024         if ( !W_ERROR_IS_OK(result) )
7025                 *returned = 0;
7026
7027         return result;
7028 }
7029
7030 /****************************************************************************
7031  Enumerates all printer drivers at level 2.
7032 ****************************************************************************/
7033
7034 static WERROR enumprinterdrivers_level2(const char *servername, fstring architecture, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
7035 {
7036         int i;
7037         int ndrivers;
7038         uint32 version;
7039         fstring *list = NULL;
7040         NT_PRINTER_DRIVER_INFO_LEVEL driver;
7041         DRIVER_INFO_2 *driver_info_2=NULL;
7042         WERROR result = WERR_OK;
7043
7044         *returned=0;
7045
7046         for (version=0; version<DRIVER_MAX_VERSION; version++) {
7047                 list=NULL;
7048                 ndrivers=get_ntdrivers(&list, architecture, version);
7049                 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
7050
7051                 if(ndrivers == -1) {
7052                         SAFE_FREE(driver_info_2);
7053                         return WERR_NOMEM;
7054                 }
7055
7056                 if(ndrivers != 0) {
7057                         if((driver_info_2=SMB_REALLOC_ARRAY(driver_info_2, DRIVER_INFO_2, *returned+ndrivers )) == NULL) {
7058                                 DEBUG(0,("enumprinterdrivers_level2: failed to enlarge driver info buffer!\n"));
7059                                 SAFE_FREE(list);
7060                                 return WERR_NOMEM;
7061                         }
7062                 }
7063
7064                 for (i=0; i<ndrivers; i++) {
7065                         WERROR status;
7066
7067                         DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
7068                         ZERO_STRUCT(driver);
7069                         status = get_a_printer_driver(&driver, 3, list[i],
7070                                                       architecture, version);
7071                         if (!W_ERROR_IS_OK(status)) {
7072                                 SAFE_FREE(list);
7073                                 SAFE_FREE(driver_info_2);
7074                                 return status;
7075                         }
7076                         fill_printer_driver_info_2(&driver_info_2[*returned+i], driver, servername);
7077                         free_a_printer_driver(driver, 3);
7078                 }
7079
7080                 *returned+=ndrivers;
7081                 SAFE_FREE(list);
7082         }
7083
7084         /* check the required size. */
7085         for (i=0; i<*returned; i++) {
7086                 DEBUGADD(6,("adding driver [%d]'s size\n",i));
7087                 *needed += spoolss_size_printer_driver_info_2(&(driver_info_2[i]));
7088         }
7089
7090         if (*needed > offered) {
7091                 result = WERR_INSUFFICIENT_BUFFER;
7092                 goto out;
7093         }
7094
7095         if (!rpcbuf_alloc_size(buffer, *needed)) {
7096                 result = WERR_NOMEM;
7097                 goto out;
7098         }
7099
7100         /* fill the buffer with the form structures */
7101         for (i=0; i<*returned; i++) {
7102                 DEBUGADD(6,("adding driver [%d] to buffer\n",i));
7103                 smb_io_printer_driver_info_2("", buffer, &(driver_info_2[i]), 0);
7104         }
7105
7106 out:
7107         SAFE_FREE(driver_info_2);
7108
7109         if ( !W_ERROR_IS_OK(result) )
7110                 *returned = 0;
7111
7112         return result;
7113 }
7114
7115 /****************************************************************************
7116  Enumerates all printer drivers at level 3.
7117 ****************************************************************************/
7118
7119 static WERROR enumprinterdrivers_level3(const char *servername, fstring architecture, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
7120 {
7121         int i;
7122         int ndrivers;
7123         uint32 version;
7124         fstring *list = NULL;
7125         DRIVER_INFO_3 *driver_info_3=NULL;
7126         NT_PRINTER_DRIVER_INFO_LEVEL driver;
7127         WERROR result = WERR_OK;
7128
7129         *returned=0;
7130
7131         for (version=0; version<DRIVER_MAX_VERSION; version++) {
7132                 list=NULL;
7133                 ndrivers=get_ntdrivers(&list, architecture, version);
7134                 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
7135
7136                 if(ndrivers == -1) {
7137                         SAFE_FREE(driver_info_3);
7138                         return WERR_NOMEM;
7139                 }
7140
7141                 if(ndrivers != 0) {
7142                         if((driver_info_3=SMB_REALLOC_ARRAY(driver_info_3, DRIVER_INFO_3, *returned+ndrivers )) == NULL) {
7143                                 DEBUG(0,("enumprinterdrivers_level3: failed to enlarge driver info buffer!\n"));
7144                                 SAFE_FREE(list);
7145                                 return WERR_NOMEM;
7146                         }
7147                 }
7148
7149                 for (i=0; i<ndrivers; i++) {
7150                         WERROR status;
7151
7152                         DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
7153                         ZERO_STRUCT(driver);
7154                         status = get_a_printer_driver(&driver, 3, list[i],
7155                                                       architecture, version);
7156                         if (!W_ERROR_IS_OK(status)) {
7157                                 SAFE_FREE(list);
7158                                 SAFE_FREE(driver_info_3);
7159                                 return status;
7160                         }
7161                         fill_printer_driver_info_3(&driver_info_3[*returned+i], driver, servername);
7162                         free_a_printer_driver(driver, 3);
7163                 }
7164
7165                 *returned+=ndrivers;
7166                 SAFE_FREE(list);
7167         }
7168
7169         /* check the required size. */
7170         for (i=0; i<*returned; i++) {
7171                 DEBUGADD(6,("adding driver [%d]'s size\n",i));
7172                 *needed += spoolss_size_printer_driver_info_3(&driver_info_3[i]);
7173         }
7174
7175         if (*needed > offered) {
7176                 result = WERR_INSUFFICIENT_BUFFER;
7177                 goto out;
7178         }
7179
7180         if (!rpcbuf_alloc_size(buffer, *needed)) {
7181                 result = WERR_NOMEM;
7182                 goto out;
7183         }
7184
7185         /* fill the buffer with the driver structures */
7186         for (i=0; i<*returned; i++) {
7187                 DEBUGADD(6,("adding driver [%d] to buffer\n",i));
7188                 smb_io_printer_driver_info_3("", buffer, &driver_info_3[i], 0);
7189         }
7190
7191 out:
7192         for (i=0; i<*returned; i++) {
7193                 SAFE_FREE(driver_info_3[i].dependentfiles);
7194         }
7195
7196         SAFE_FREE(driver_info_3);
7197
7198         if ( !W_ERROR_IS_OK(result) )
7199                 *returned = 0;
7200
7201         return result;
7202 }
7203
7204 /****************************************************************************
7205  Enumerates all printer drivers.
7206 ****************************************************************************/
7207
7208 WERROR _spoolss_enumprinterdrivers( pipes_struct *p, SPOOL_Q_ENUMPRINTERDRIVERS *q_u, SPOOL_R_ENUMPRINTERDRIVERS *r_u)
7209 {
7210         uint32 level = q_u->level;
7211         RPC_BUFFER *buffer = NULL;
7212         uint32 offered = q_u->offered;
7213         uint32 *needed = &r_u->needed;
7214         uint32 *returned = &r_u->returned;
7215         const char *cservername;
7216         fstring servername;
7217         fstring architecture;
7218
7219         /* that's an [in out] buffer */
7220
7221         if (!q_u->buffer && (offered!=0)) {
7222                 return WERR_INVALID_PARAM;
7223         }
7224
7225         if (offered > MAX_RPC_DATA_SIZE) {
7226                 return WERR_INVALID_PARAM;
7227         }
7228
7229         rpcbuf_move(q_u->buffer, &r_u->buffer);
7230         buffer = r_u->buffer;
7231
7232         DEBUG(4,("_spoolss_enumprinterdrivers\n"));
7233
7234         *needed   = 0;
7235         *returned = 0;
7236
7237         unistr2_to_ascii(architecture, &q_u->environment, sizeof(architecture));
7238         unistr2_to_ascii(servername, &q_u->name, sizeof(servername));
7239
7240         cservername = canon_servername(servername);
7241
7242         if (!is_myname_or_ipaddr(cservername))
7243                 return WERR_UNKNOWN_PRINTER_DRIVER;
7244
7245         switch (level) {
7246         case 1:
7247                 return enumprinterdrivers_level1(cservername, architecture, buffer, offered, needed, returned);
7248         case 2:
7249                 return enumprinterdrivers_level2(cservername, architecture, buffer, offered, needed, returned);
7250         case 3:
7251                 return enumprinterdrivers_level3(cservername, architecture, buffer, offered, needed, returned);
7252         default:
7253                 return WERR_UNKNOWN_LEVEL;
7254         }
7255 }
7256
7257 /****************************************************************************
7258 ****************************************************************************/
7259
7260 static void fill_form_1(FORM_1 *form, nt_forms_struct *list)
7261 {
7262         form->flag=list->flag;
7263         init_unistr(&form->name, list->name);
7264         form->width=list->width;
7265         form->length=list->length;
7266         form->left=list->left;
7267         form->top=list->top;
7268         form->right=list->right;
7269         form->bottom=list->bottom;
7270 }
7271
7272 /****************************************************************************
7273 ****************************************************************************/
7274
7275 static WERROR fill_form_info_1(TALLOC_CTX *mem_ctx,
7276                                struct spoolss_FormInfo1 *form,
7277                                nt_forms_struct *list)
7278 {
7279         form->form_name         = talloc_strdup(mem_ctx, list->name);
7280         W_ERROR_HAVE_NO_MEMORY(form->form_name);
7281
7282         form->flags             = list->flag;
7283         form->size.width        = list->width;
7284         form->size.height       = list->length;
7285         form->area.left         = list->left;
7286         form->area.top          = list->top;
7287         form->area.right        = list->right;
7288         form->area.bottom       = list->bottom;
7289
7290         return WERR_OK;
7291 }
7292
7293 /****************************************************************************
7294 ****************************************************************************/
7295
7296 WERROR _spoolss_enumforms(pipes_struct *p, SPOOL_Q_ENUMFORMS *q_u, SPOOL_R_ENUMFORMS *r_u)
7297 {
7298         uint32 level = q_u->level;
7299         RPC_BUFFER *buffer = NULL;
7300         uint32 offered = q_u->offered;
7301         uint32 *needed = &r_u->needed;
7302         uint32 *numofforms = &r_u->numofforms;
7303         uint32 numbuiltinforms;
7304
7305         nt_forms_struct *list=NULL;
7306         nt_forms_struct *builtinlist=NULL;
7307         FORM_1 *forms_1;
7308         int buffer_size=0;
7309         int i;
7310
7311         /* that's an [in out] buffer */
7312
7313         if (!q_u->buffer && (offered!=0) ) {
7314                 return WERR_INVALID_PARAM;
7315         }
7316
7317         if (offered > MAX_RPC_DATA_SIZE) {
7318                 return WERR_INVALID_PARAM;
7319         }
7320
7321         rpcbuf_move(q_u->buffer, &r_u->buffer);
7322         buffer = r_u->buffer;
7323
7324         DEBUG(4,("_spoolss_enumforms\n"));
7325         DEBUGADD(5,("Offered buffer size [%d]\n", offered));
7326         DEBUGADD(5,("Info level [%d]\n",          level));
7327
7328         numbuiltinforms = get_builtin_ntforms(&builtinlist);
7329         DEBUGADD(5,("Number of builtin forms [%d]\n",     numbuiltinforms));
7330         *numofforms = get_ntforms(&list);
7331         DEBUGADD(5,("Number of user forms [%d]\n",     *numofforms));
7332         *numofforms += numbuiltinforms;
7333
7334         if (*numofforms == 0) {
7335                 SAFE_FREE(builtinlist);
7336                 SAFE_FREE(list);
7337                 return WERR_NO_MORE_ITEMS;
7338         }
7339
7340         switch (level) {
7341         case 1:
7342                 if ((forms_1=SMB_MALLOC_ARRAY(FORM_1, *numofforms)) == NULL) {
7343                         SAFE_FREE(builtinlist);
7344                         SAFE_FREE(list);
7345                         *numofforms=0;
7346                         return WERR_NOMEM;
7347                 }
7348
7349                 /* construct the list of form structures */
7350                 for (i=0; i<numbuiltinforms; i++) {
7351                         DEBUGADD(6,("Filling form number [%d]\n",i));
7352                         fill_form_1(&forms_1[i], &builtinlist[i]);
7353                 }
7354
7355                 SAFE_FREE(builtinlist);
7356
7357                 for (; i<*numofforms; i++) {
7358                         DEBUGADD(6,("Filling form number [%d]\n",i));
7359                         fill_form_1(&forms_1[i], &list[i-numbuiltinforms]);
7360                 }
7361
7362                 SAFE_FREE(list);
7363
7364                 /* check the required size. */
7365                 for (i=0; i<numbuiltinforms; i++) {
7366                         DEBUGADD(6,("adding form [%d]'s size\n",i));
7367                         buffer_size += spoolss_size_form_1(&forms_1[i]);
7368                 }
7369                 for (; i<*numofforms; i++) {
7370                         DEBUGADD(6,("adding form [%d]'s size\n",i));
7371                         buffer_size += spoolss_size_form_1(&forms_1[i]);
7372                 }
7373
7374                 *needed=buffer_size;
7375
7376                 if (*needed > offered) {
7377                         SAFE_FREE(forms_1);
7378                         *numofforms=0;
7379                         return WERR_INSUFFICIENT_BUFFER;
7380                 }
7381
7382                 if (!rpcbuf_alloc_size(buffer, buffer_size)){
7383                         SAFE_FREE(forms_1);
7384                         *numofforms=0;
7385                         return WERR_NOMEM;
7386                 }
7387
7388                 /* fill the buffer with the form structures */
7389                 for (i=0; i<numbuiltinforms; i++) {
7390                         DEBUGADD(6,("adding form [%d] to buffer\n",i));
7391                         smb_io_form_1("", buffer, &forms_1[i], 0);
7392                 }
7393                 for (; i<*numofforms; i++) {
7394                         DEBUGADD(6,("adding form [%d] to buffer\n",i));
7395                         smb_io_form_1("", buffer, &forms_1[i], 0);
7396                 }
7397
7398                 SAFE_FREE(forms_1);
7399
7400                 return WERR_OK;
7401
7402         default:
7403                 SAFE_FREE(list);
7404                 SAFE_FREE(builtinlist);
7405                 return WERR_UNKNOWN_LEVEL;
7406         }
7407 }
7408
7409 /****************************************************************
7410  _spoolss_GetForm
7411 ****************************************************************/
7412
7413 WERROR _spoolss_GetForm(pipes_struct *p,
7414                         struct spoolss_GetForm *r)
7415 {
7416         uint32 level = r->in.level;
7417         uint32 offered = r->in.offered;
7418         uint32 *needed = r->out.needed;
7419
7420         nt_forms_struct *list=NULL;
7421         nt_forms_struct builtin_form;
7422         bool foundBuiltin;
7423         union spoolss_FormInfo info;
7424         struct spoolss_FormInfo1 form_1;
7425         int numofforms=0, i=0;
7426
7427         /* that's an [in out] buffer */
7428
7429         if (!r->in.buffer && (offered!=0)) {
7430                 return WERR_INVALID_PARAM;
7431         }
7432
7433         DEBUG(4,("_spoolss_GetForm\n"));
7434         DEBUGADD(5,("Offered buffer size [%d]\n", offered));
7435         DEBUGADD(5,("Info level [%d]\n",          level));
7436
7437         foundBuiltin = get_a_builtin_ntform_by_string(r->in.form_name, &builtin_form);
7438         if (!foundBuiltin) {
7439                 numofforms = get_ntforms(&list);
7440                 DEBUGADD(5,("Number of forms [%d]\n",     numofforms));
7441
7442                 if (numofforms == 0)
7443                         return WERR_BADFID;
7444         }
7445
7446         ZERO_STRUCT(form_1);
7447
7448         switch (level) {
7449         case 1:
7450                 if (foundBuiltin) {
7451                         fill_form_info_1(p->mem_ctx, &form_1, &builtin_form);
7452                 } else {
7453
7454                         /* Check if the requested name is in the list of form structures */
7455                         for (i=0; i<numofforms; i++) {
7456
7457                                 DEBUG(4,("_spoolss_GetForm: checking form %s (want %s)\n",
7458                                         list[i].name, r->in.form_name));
7459
7460                                 if (strequal(r->in.form_name, list[i].name)) {
7461                                         DEBUGADD(6,("Found form %s number [%d]\n",
7462                                                 r->in.form_name, i));
7463                                         fill_form_info_1(p->mem_ctx, &form_1, &list[i]);
7464                                         break;
7465                                 }
7466                         }
7467
7468                         SAFE_FREE(list);
7469                         if (i == numofforms) {
7470                                 return WERR_BADFID;
7471                         }
7472                 }
7473                 /* check the required size. */
7474
7475                 info.info1 = form_1;
7476
7477                 *needed = ndr_size_spoolss_FormInfo(&info, 1, NULL, 0);
7478
7479                 if (*needed > offered) {
7480                         r->out.info = NULL;
7481                         return WERR_INSUFFICIENT_BUFFER;
7482                 }
7483
7484                 r->out.info->info1 = form_1;
7485
7486                 /* fill the buffer with the form structures */
7487                 DEBUGADD(6,("adding form %s [%d] to buffer\n",
7488                         r->in.form_name, i));
7489
7490                 return WERR_OK;
7491
7492         default:
7493                 SAFE_FREE(list);
7494                 return WERR_UNKNOWN_LEVEL;
7495         }
7496 }
7497
7498 /****************************************************************************
7499 ****************************************************************************/
7500
7501 static void fill_port_1(PORT_INFO_1 *port, const char *name)
7502 {
7503         init_unistr(&port->port_name, name);
7504 }
7505
7506 /****************************************************************************
7507  TODO: This probably needs distinguish between TCP/IP and Local ports
7508  somehow.
7509 ****************************************************************************/
7510
7511 static void fill_port_2(PORT_INFO_2 *port, const char *name)
7512 {
7513         init_unistr(&port->port_name, name);
7514         init_unistr(&port->monitor_name, "Local Monitor");
7515         init_unistr(&port->description, SPL_LOCAL_PORT );
7516         port->port_type=PORT_TYPE_WRITE;
7517         port->reserved=0x0;
7518 }
7519
7520
7521 /****************************************************************************
7522  wrapper around the enumer ports command
7523 ****************************************************************************/
7524
7525 WERROR enumports_hook(TALLOC_CTX *ctx, int *count, char ***lines )
7526 {
7527         char *cmd = lp_enumports_cmd();
7528         char **qlines = NULL;
7529         char *command = NULL;
7530         int numlines;
7531         int ret;
7532         int fd;
7533
7534         *count = 0;
7535         *lines = NULL;
7536
7537         /* if no hook then just fill in the default port */
7538
7539         if ( !*cmd ) {
7540                 if (!(qlines = TALLOC_ARRAY( NULL, char*, 2 ))) {
7541                         return WERR_NOMEM;
7542                 }
7543                 if (!(qlines[0] = talloc_strdup(qlines, SAMBA_PRINTER_PORT_NAME ))) {
7544                         TALLOC_FREE(qlines);
7545                         return WERR_NOMEM;
7546                 }
7547                 qlines[1] = NULL;
7548                 numlines = 1;
7549         }
7550         else {
7551                 /* we have a valid enumport command */
7552
7553                 command = talloc_asprintf(ctx, "%s \"%d\"", cmd, 1);
7554                 if (!command) {
7555                         return WERR_NOMEM;
7556                 }
7557
7558                 DEBUG(10,("Running [%s]\n", command));
7559                 ret = smbrun(command, &fd);
7560                 DEBUG(10,("Returned [%d]\n", ret));
7561                 TALLOC_FREE(command);
7562                 if (ret != 0) {
7563                         if (fd != -1) {
7564                                 close(fd);
7565                         }
7566                         return WERR_ACCESS_DENIED;
7567                 }
7568
7569                 numlines = 0;
7570                 qlines = fd_lines_load(fd, &numlines, 0, NULL);
7571                 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
7572                 close(fd);
7573         }
7574
7575         *count = numlines;
7576         *lines = qlines;
7577
7578         return WERR_OK;
7579 }
7580
7581 /****************************************************************************
7582  enumports level 1.
7583 ****************************************************************************/
7584
7585 static WERROR enumports_level_1(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
7586 {
7587         PORT_INFO_1 *ports=NULL;
7588         int i=0;
7589         WERROR result = WERR_OK;
7590         char **qlines = NULL;
7591         int numlines = 0;
7592
7593         result = enumports_hook(talloc_tos(), &numlines, &qlines );
7594         if (!W_ERROR_IS_OK(result)) {
7595                 TALLOC_FREE(qlines);
7596                 return result;
7597         }
7598
7599         if(numlines) {
7600                 if((ports=SMB_MALLOC_ARRAY( PORT_INFO_1, numlines )) == NULL) {
7601                         DEBUG(10,("Returning WERR_NOMEM [%s]\n",
7602                                   win_errstr(WERR_NOMEM)));
7603                         TALLOC_FREE(qlines);
7604                         return WERR_NOMEM;
7605                 }
7606
7607                 for (i=0; i<numlines; i++) {
7608                         DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
7609                         fill_port_1(&ports[i], qlines[i]);
7610                 }
7611         }
7612         TALLOC_FREE(qlines);
7613
7614         *returned = numlines;
7615
7616         /* check the required size. */
7617         for (i=0; i<*returned; i++) {
7618                 DEBUGADD(6,("adding port [%d]'s size\n", i));
7619                 *needed += spoolss_size_port_info_1(&ports[i]);
7620         }
7621
7622         if (*needed > offered) {
7623                 result = WERR_INSUFFICIENT_BUFFER;
7624                 goto out;
7625         }
7626
7627         if (!rpcbuf_alloc_size(buffer, *needed)) {
7628                 result = WERR_NOMEM;
7629                 goto out;
7630         }
7631
7632         /* fill the buffer with the ports structures */
7633         for (i=0; i<*returned; i++) {
7634                 DEBUGADD(6,("adding port [%d] to buffer\n", i));
7635                 smb_io_port_1("", buffer, &ports[i], 0);
7636         }
7637
7638 out:
7639         SAFE_FREE(ports);
7640
7641         if ( !W_ERROR_IS_OK(result) )
7642                 *returned = 0;
7643
7644         return result;
7645 }
7646
7647 /****************************************************************************
7648  enumports level 2.
7649 ****************************************************************************/
7650
7651 static WERROR enumports_level_2(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
7652 {
7653         PORT_INFO_2 *ports=NULL;
7654         int i=0;
7655         WERROR result = WERR_OK;
7656         char **qlines = NULL;
7657         int numlines = 0;
7658
7659         result = enumports_hook(talloc_tos(), &numlines, &qlines );
7660         if ( !W_ERROR_IS_OK(result)) {
7661                 TALLOC_FREE(qlines);
7662                 return result;
7663         }
7664
7665         if(numlines) {
7666                 if((ports=SMB_MALLOC_ARRAY( PORT_INFO_2, numlines)) == NULL) {
7667                         TALLOC_FREE(qlines);
7668                         return WERR_NOMEM;
7669                 }
7670
7671                 for (i=0; i<numlines; i++) {
7672                         DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
7673                         fill_port_2(&(ports[i]), qlines[i]);
7674                 }
7675         }
7676
7677         TALLOC_FREE(qlines);
7678
7679         *returned = numlines;
7680
7681         /* check the required size. */
7682         for (i=0; i<*returned; i++) {
7683                 DEBUGADD(6,("adding port [%d]'s size\n", i));
7684                 *needed += spoolss_size_port_info_2(&ports[i]);
7685         }
7686
7687         if (*needed > offered) {
7688                 result = WERR_INSUFFICIENT_BUFFER;
7689                 goto out;
7690         }
7691
7692         if (!rpcbuf_alloc_size(buffer, *needed)) {
7693                 result = WERR_NOMEM;
7694                 goto out;
7695         }
7696
7697         /* fill the buffer with the ports structures */
7698         for (i=0; i<*returned; i++) {
7699                 DEBUGADD(6,("adding port [%d] to buffer\n", i));
7700                 smb_io_port_2("", buffer, &ports[i], 0);
7701         }
7702
7703 out:
7704         SAFE_FREE(ports);
7705
7706         if ( !W_ERROR_IS_OK(result) )
7707                 *returned = 0;
7708
7709         return result;
7710 }
7711
7712 /****************************************************************************
7713  enumports.
7714 ****************************************************************************/
7715
7716 WERROR _spoolss_enumports( pipes_struct *p, SPOOL_Q_ENUMPORTS *q_u, SPOOL_R_ENUMPORTS *r_u)
7717 {
7718         uint32 level = q_u->level;
7719         RPC_BUFFER *buffer = NULL;
7720         uint32 offered = q_u->offered;
7721         uint32 *needed = &r_u->needed;
7722         uint32 *returned = &r_u->returned;
7723
7724         /* that's an [in out] buffer */
7725
7726         if (!q_u->buffer && (offered!=0)) {
7727                 return WERR_INVALID_PARAM;
7728         }
7729
7730         if (offered > MAX_RPC_DATA_SIZE) {
7731                 return WERR_INVALID_PARAM;
7732         }
7733
7734         rpcbuf_move(q_u->buffer, &r_u->buffer);
7735         buffer = r_u->buffer;
7736
7737         DEBUG(4,("_spoolss_enumports\n"));
7738
7739         *returned=0;
7740         *needed=0;
7741
7742         switch (level) {
7743         case 1:
7744                 return enumports_level_1(buffer, offered, needed, returned);
7745         case 2:
7746                 return enumports_level_2(buffer, offered, needed, returned);
7747         default:
7748                 return WERR_UNKNOWN_LEVEL;
7749         }
7750 }
7751
7752 /****************************************************************************
7753 ****************************************************************************/
7754
7755 static WERROR spoolss_addprinterex_level_2(pipes_struct *p,
7756                                            const char *server,
7757                                            struct spoolss_SetPrinterInfoCtr *info_ctr,
7758                                            struct spoolss_DeviceMode *devmode,
7759                                            struct security_descriptor *sec_desc,
7760                                            struct spoolss_UserLevelCtr *user_ctr,
7761                                            POLICY_HND *handle)
7762 {
7763         NT_PRINTER_INFO_LEVEL *printer = NULL;
7764         fstring name;
7765         int     snum;
7766         WERROR err = WERR_OK;
7767
7768         if ( !(printer = TALLOC_ZERO_P(NULL, NT_PRINTER_INFO_LEVEL)) ) {
7769                 DEBUG(0,("spoolss_addprinterex_level_2: malloc fail.\n"));
7770                 return WERR_NOMEM;
7771         }
7772
7773         /* convert from UNICODE to ASCII - this allocates the info_2 struct inside *printer.*/
7774         if (!convert_printer_info_new(info_ctr, printer)) {
7775                 free_a_printer(&printer, 2);
7776                 return WERR_NOMEM;
7777         }
7778
7779         /* check to see if the printer already exists */
7780
7781         if ((snum = print_queue_snum(printer->info_2->sharename)) != -1) {
7782                 DEBUG(5, ("spoolss_addprinterex_level_2: Attempted to add a printer named [%s] when one already existed!\n",
7783                         printer->info_2->sharename));
7784                 free_a_printer(&printer, 2);
7785                 return WERR_PRINTER_ALREADY_EXISTS;
7786         }
7787
7788         /* FIXME!!!  smbd should check to see if the driver is installed before
7789            trying to add a printer like this  --jerry */
7790
7791         if (*lp_addprinter_cmd() ) {
7792                 if ( !add_printer_hook(p->mem_ctx, p->server_info->ptok,
7793                                        printer) ) {
7794                         free_a_printer(&printer,2);
7795                         return WERR_ACCESS_DENIED;
7796                 }
7797         } else {
7798                 DEBUG(0,("spoolss_addprinterex_level_2: add printer for printer %s called and no"
7799                         "smb.conf parameter \"addprinter command\" is defined. This"
7800                         "parameter must exist for this call to succeed\n",
7801                         printer->info_2->sharename ));
7802         }
7803
7804         /* use our primary netbios name since get_a_printer() will convert
7805            it to what the client expects on a case by case basis */
7806
7807         slprintf(name, sizeof(name)-1, "\\\\%s\\%s", global_myname(),
7808              printer->info_2->sharename);
7809
7810
7811         if ((snum = print_queue_snum(printer->info_2->sharename)) == -1) {
7812                 free_a_printer(&printer,2);
7813                 return WERR_ACCESS_DENIED;
7814         }
7815
7816         /* you must be a printer admin to add a new printer */
7817         if (!print_access_check(NULL, snum, PRINTER_ACCESS_ADMINISTER)) {
7818                 free_a_printer(&printer,2);
7819                 return WERR_ACCESS_DENIED;
7820         }
7821
7822         /*
7823          * Do sanity check on the requested changes for Samba.
7824          */
7825
7826         if (!check_printer_ok(printer->info_2, snum)) {
7827                 free_a_printer(&printer,2);
7828                 return WERR_INVALID_PARAM;
7829         }
7830
7831         /*
7832          * When a printer is created, the drivername bound to the printer is used
7833          * to lookup previously saved driver initialization info, which is then
7834          * bound to the new printer, simulating what happens in the Windows arch.
7835          */
7836
7837         if (!devmode)
7838         {
7839                 set_driver_init(printer, 2);
7840         }
7841         else
7842         {
7843                 /* A valid devmode was included, convert and link it
7844                 */
7845                 DEBUGADD(10, ("spoolss_addprinterex_level_2: devmode included, converting\n"));
7846
7847                 if (!convert_devicemode_new(printer->info_2->printername,
7848                                             devmode,
7849                                             &printer->info_2->devmode))
7850                         return  WERR_NOMEM;
7851         }
7852
7853         /* write the ASCII on disk */
7854         err = mod_a_printer(printer, 2);
7855         if (!W_ERROR_IS_OK(err)) {
7856                 free_a_printer(&printer,2);
7857                 return err;
7858         }
7859
7860         if (!open_printer_hnd(p, handle, name, PRINTER_ACCESS_ADMINISTER)) {
7861                 /* Handle open failed - remove addition. */
7862                 del_a_printer(printer->info_2->sharename);
7863                 free_a_printer(&printer,2);
7864                 return WERR_ACCESS_DENIED;
7865         }
7866
7867         update_c_setprinter(False);
7868         free_a_printer(&printer,2);
7869
7870         return WERR_OK;
7871 }
7872
7873 /****************************************************************
7874  _spoolss_AddPrinterEx
7875 ****************************************************************/
7876
7877 WERROR _spoolss_AddPrinterEx(pipes_struct *p,
7878                              struct spoolss_AddPrinterEx *r)
7879 {
7880         switch (r->in.info_ctr->level) {
7881         case 1:
7882                 /* we don't handle yet */
7883                 /* but I know what to do ... */
7884                 return WERR_UNKNOWN_LEVEL;
7885         case 2:
7886                 return spoolss_addprinterex_level_2(p, r->in.server,
7887                                                     r->in.info_ctr,
7888                                                     r->in.devmode_ctr->devmode,
7889                                                     r->in.secdesc_ctr->sd,
7890                                                     r->in.userlevel_ctr,
7891                                                     r->out.handle);
7892         default:
7893                 return WERR_UNKNOWN_LEVEL;
7894         }
7895 }
7896
7897 /****************************************************************************
7898 ****************************************************************************/
7899
7900 WERROR _spoolss_addprinterdriver(pipes_struct *p, SPOOL_Q_ADDPRINTERDRIVER *q_u, SPOOL_R_ADDPRINTERDRIVER *r_u)
7901 {
7902         uint32 level = q_u->level;
7903         SPOOL_PRINTER_DRIVER_INFO_LEVEL *info = &q_u->info;
7904         WERROR err = WERR_OK;
7905         NT_PRINTER_DRIVER_INFO_LEVEL driver;
7906         fstring driver_name;
7907         uint32 version;
7908
7909         ZERO_STRUCT(driver);
7910
7911         if (!convert_printer_driver_info(info, &driver, level)) {
7912                 err = WERR_NOMEM;
7913                 goto done;
7914         }
7915
7916         DEBUG(5,("Cleaning driver's information\n"));
7917         err = clean_up_driver_struct(p, driver, level);
7918         if (!W_ERROR_IS_OK(err))
7919                 goto done;
7920
7921         DEBUG(5,("Moving driver to final destination\n"));
7922         if( !W_ERROR_IS_OK(err = move_driver_to_download_area(p, driver, level,
7923                                                               &err)) ) {
7924                 goto done;
7925         }
7926
7927         if (add_a_printer_driver(driver, level)!=0) {
7928                 err = WERR_ACCESS_DENIED;
7929                 goto done;
7930         }
7931
7932         switch(level) {
7933         case 3:
7934                 fstrcpy(driver_name,
7935                         driver.info_3->name ? driver.info_3->name : "");
7936                 break;
7937         case 6:
7938                 fstrcpy(driver_name,
7939                         driver.info_6->name ?  driver.info_6->name : "");
7940                 break;
7941         }
7942
7943         /*
7944          * I think this is where he DrvUpgradePrinter() hook would be
7945          * be called in a driver's interface DLL on a Windows NT 4.0/2k
7946          * server.  Right now, we just need to send ourselves a message
7947          * to update each printer bound to this driver.   --jerry
7948          */
7949
7950         if (!srv_spoolss_drv_upgrade_printer(driver_name)) {
7951                 DEBUG(0,("_spoolss_addprinterdriver: Failed to send message about upgrading driver [%s]!\n",
7952                         driver_name));
7953         }
7954
7955         /*
7956          * Based on the version (e.g. driver destination dir: 0=9x,2=Nt/2k,3=2k/Xp),
7957          * decide if the driver init data should be deleted. The rules are:
7958          *  1) never delete init data if it is a 9x driver, they don't use it anyway
7959          *  2) delete init data only if there is no 2k/Xp driver
7960          *  3) always delete init data
7961          * The generalized rule is always use init data from the highest order driver.
7962          * It is necessary to follow the driver install by an initialization step to
7963          * finish off this process.
7964         */
7965         if (level == 3)
7966                 version = driver.info_3->cversion;
7967         else if (level == 6)
7968                 version = driver.info_6->version;
7969         else
7970                 version = -1;
7971         switch (version) {
7972                 /*
7973                  * 9x printer driver - never delete init data
7974                 */
7975                 case 0:
7976                         DEBUG(10,("_spoolss_addprinterdriver: init data not deleted for 9x driver [%s]\n",
7977                                         driver_name));
7978                         break;
7979
7980                 /*
7981                  * Nt or 2k (compatiblity mode) printer driver - only delete init data if
7982                  * there is no 2k/Xp driver init data for this driver name.
7983                 */
7984                 case 2:
7985                 {
7986                         NT_PRINTER_DRIVER_INFO_LEVEL driver1;
7987
7988                         if (!W_ERROR_IS_OK(get_a_printer_driver(&driver1, 3, driver_name, "Windows NT x86", 3))) {
7989                                 /*
7990                                  * No 2k/Xp driver found, delete init data (if any) for the new Nt driver.
7991                                 */
7992                                 if (!del_driver_init(driver_name))
7993                                         DEBUG(6,("_spoolss_addprinterdriver: del_driver_init(%s) Nt failed!\n", driver_name));
7994                         } else {
7995                                 /*
7996                                  * a 2k/Xp driver was found, don't delete init data because Nt driver will use it.
7997                                 */
7998                                 free_a_printer_driver(driver1,3);
7999                                 DEBUG(10,("_spoolss_addprinterdriver: init data not deleted for Nt driver [%s]\n",
8000                                                 driver_name));
8001                         }
8002                 }
8003                 break;
8004
8005                 /*
8006                  * 2k or Xp printer driver - always delete init data
8007                 */
8008                 case 3:
8009                         if (!del_driver_init(driver_name))
8010                                 DEBUG(6,("_spoolss_addprinterdriver: del_driver_init(%s) 2k/Xp failed!\n", driver_name));
8011                         break;
8012
8013                 default:
8014                         DEBUG(0,("_spoolss_addprinterdriver: invalid level=%d\n", level));
8015                         break;
8016         }
8017
8018
8019 done:
8020         free_a_printer_driver(driver, level);
8021         return err;
8022 }
8023
8024 /********************************************************************
8025  * spoolss_addprinterdriverex
8026  ********************************************************************/
8027
8028 WERROR _spoolss_addprinterdriverex(pipes_struct *p, SPOOL_Q_ADDPRINTERDRIVEREX *q_u, SPOOL_R_ADDPRINTERDRIVEREX *r_u)
8029 {
8030         SPOOL_Q_ADDPRINTERDRIVER q_u_local;
8031         SPOOL_R_ADDPRINTERDRIVER r_u_local;
8032
8033         /*
8034          * we only support the semantics of AddPrinterDriver()
8035          * i.e. only copy files that are newer than existing ones
8036          */
8037
8038         if ( q_u->copy_flags != APD_COPY_NEW_FILES )
8039                 return WERR_ACCESS_DENIED;
8040
8041         ZERO_STRUCT(q_u_local);
8042         ZERO_STRUCT(r_u_local);
8043
8044         /* just pass the information off to _spoolss_addprinterdriver() */
8045         q_u_local.server_name_ptr = q_u->server_name_ptr;
8046         copy_unistr2(&q_u_local.server_name, &q_u->server_name);
8047         q_u_local.level = q_u->level;
8048         memcpy( &q_u_local.info, &q_u->info, sizeof(SPOOL_PRINTER_DRIVER_INFO_LEVEL) );
8049
8050         return _spoolss_addprinterdriver( p, &q_u_local, &r_u_local );
8051 }
8052
8053 /****************************************************************************
8054 ****************************************************************************/
8055
8056 static void fill_driverdir_1(DRIVER_DIRECTORY_1 *info, char *name)
8057 {
8058         init_unistr(&info->name, name);
8059 }
8060
8061 /****************************************************************************
8062 ****************************************************************************/
8063
8064 static WERROR getprinterdriverdir_level_1(UNISTR2 *name, UNISTR2 *uni_environment, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
8065 {
8066         char *path = NULL;
8067         char *long_archi = NULL;
8068         char *servername = NULL;
8069         const char *pservername = NULL;
8070         const char *short_archi;
8071         DRIVER_DIRECTORY_1 *info=NULL;
8072         WERROR result = WERR_OK;
8073         TALLOC_CTX *ctx = talloc_tos();
8074
8075         servername = unistr2_to_ascii_talloc(ctx, name);
8076         if (!servername) {
8077                 return WERR_NOMEM;
8078         }
8079         long_archi = unistr2_to_ascii_talloc(ctx, uni_environment);
8080         if (!long_archi) {
8081                 return WERR_NOMEM;
8082         }
8083
8084         pservername = canon_servername(servername);
8085
8086         if ( !is_myname_or_ipaddr(pservername))
8087                 return WERR_INVALID_PARAM;
8088
8089         if (!(short_archi = get_short_archi(long_archi)))
8090                 return WERR_INVALID_ENVIRONMENT;
8091
8092         if((info=SMB_MALLOC_P(DRIVER_DIRECTORY_1)) == NULL)
8093                 return WERR_NOMEM;
8094
8095         path = talloc_asprintf(ctx,
8096                         "\\\\%s\\print$\\%s", pservername, short_archi);
8097         if (!path) {
8098                 result = WERR_NOMEM;
8099                 goto out;
8100         }
8101
8102         DEBUG(4,("printer driver directory: [%s]\n", path));
8103
8104         fill_driverdir_1(info, path);
8105
8106         *needed += spoolss_size_driverdir_info_1(info);
8107
8108         if (*needed > offered) {
8109                 result = WERR_INSUFFICIENT_BUFFER;
8110                 goto out;
8111         }
8112
8113         if (!rpcbuf_alloc_size(buffer, *needed)) {
8114                 result = WERR_NOMEM;
8115                 goto out;
8116         }
8117
8118         smb_io_driverdir_1("", buffer, info, 0);
8119
8120 out:
8121         SAFE_FREE(info);
8122
8123         return result;
8124 }
8125
8126 /****************************************************************************
8127 ****************************************************************************/
8128
8129 WERROR _spoolss_getprinterdriverdirectory(pipes_struct *p, SPOOL_Q_GETPRINTERDRIVERDIR *q_u, SPOOL_R_GETPRINTERDRIVERDIR *r_u)
8130 {
8131         UNISTR2 *name = &q_u->name;
8132         UNISTR2 *uni_environment = &q_u->environment;
8133         uint32 level = q_u->level;
8134         RPC_BUFFER *buffer = NULL;
8135         uint32 offered = q_u->offered;
8136         uint32 *needed = &r_u->needed;
8137
8138         /* that's an [in out] buffer */
8139
8140         if (!q_u->buffer && (offered!=0)) {
8141                 return WERR_INVALID_PARAM;
8142         }
8143
8144         if (offered > MAX_RPC_DATA_SIZE) {
8145                 return WERR_INVALID_PARAM;
8146         }
8147
8148         rpcbuf_move(q_u->buffer, &r_u->buffer);
8149         buffer = r_u->buffer;
8150
8151         DEBUG(4,("_spoolss_getprinterdriverdirectory\n"));
8152
8153         *needed=0;
8154
8155         switch(level) {
8156         case 1:
8157                 return getprinterdriverdir_level_1(name, uni_environment, buffer, offered, needed);
8158         default:
8159                 return WERR_UNKNOWN_LEVEL;
8160         }
8161 }
8162
8163 /****************************************************************************
8164 ****************************************************************************/
8165
8166 WERROR _spoolss_enumprinterdata(pipes_struct *p, SPOOL_Q_ENUMPRINTERDATA *q_u, SPOOL_R_ENUMPRINTERDATA *r_u)
8167 {
8168         POLICY_HND *handle = &q_u->handle;
8169         uint32 idx               = q_u->index;
8170         uint32 in_value_len      = q_u->valuesize;
8171         uint32 in_data_len       = q_u->datasize;
8172         uint32 *out_max_value_len = &r_u->valuesize;
8173         uint16 **out_value       = &r_u->value;
8174         uint32 *out_value_len    = &r_u->realvaluesize;
8175         uint32 *out_type         = &r_u->type;
8176         uint32 *out_max_data_len = &r_u->datasize;
8177         uint8  **data_out        = &r_u->data;
8178         uint32 *out_data_len     = &r_u->realdatasize;
8179
8180         NT_PRINTER_INFO_LEVEL *printer = NULL;
8181
8182         uint32          biggest_valuesize;
8183         uint32          biggest_datasize;
8184         uint32          data_len;
8185         Printer_entry   *Printer = find_printer_index_by_hnd(p, handle);
8186         int             snum;
8187         WERROR          result;
8188         REGISTRY_VALUE  *val = NULL;
8189         NT_PRINTER_DATA *p_data;
8190         int             i, key_index, num_values;
8191         int             name_length;
8192
8193         *out_type = 0;
8194
8195         *out_max_data_len = 0;
8196         *data_out         = NULL;
8197         *out_data_len     = 0;
8198
8199         DEBUG(5,("spoolss_enumprinterdata\n"));
8200
8201         if (!Printer) {
8202                 DEBUG(2,("_spoolss_enumprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8203                 return WERR_BADFID;
8204         }
8205
8206         if (!get_printer_snum(p,handle, &snum, NULL))
8207                 return WERR_BADFID;
8208
8209         result = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8210         if (!W_ERROR_IS_OK(result))
8211                 return result;
8212
8213         p_data = printer->info_2->data;
8214         key_index = lookup_printerkey( p_data, SPOOL_PRINTERDATA_KEY );
8215
8216         result = WERR_OK;
8217
8218         /*
8219          * The NT machine wants to know the biggest size of value and data
8220          *
8221          * cf: MSDN EnumPrinterData remark section
8222          */
8223
8224         if ( !in_value_len && !in_data_len && (key_index != -1) )
8225         {
8226                 DEBUGADD(6,("Activating NT mega-hack to find sizes\n"));
8227
8228                 biggest_valuesize = 0;
8229                 biggest_datasize  = 0;
8230
8231                 num_values = regval_ctr_numvals( p_data->keys[key_index].values );
8232
8233                 for ( i=0; i<num_values; i++ )
8234                 {
8235                         val = regval_ctr_specific_value( p_data->keys[key_index].values, i );
8236
8237                         name_length = strlen(val->valuename);
8238                         if ( strlen(val->valuename) > biggest_valuesize )
8239                                 biggest_valuesize = name_length;
8240
8241                         if ( val->size > biggest_datasize )
8242                                 biggest_datasize = val->size;
8243
8244                         DEBUG(6,("current values: [%d], [%d]\n", biggest_valuesize,
8245                                 biggest_datasize));
8246                 }
8247
8248                 /* the value is an UNICODE string but real_value_size is the length
8249                    in bytes including the trailing 0 */
8250
8251                 *out_value_len = 2 * (1+biggest_valuesize);
8252                 *out_data_len  = biggest_datasize;
8253
8254                 DEBUG(6,("final values: [%d], [%d]\n", *out_value_len, *out_data_len));
8255
8256                 goto done;
8257         }
8258
8259         /*
8260          * the value len is wrong in NT sp3
8261          * that's the number of bytes not the number of unicode chars
8262          */
8263
8264         if ( key_index != -1 )
8265                 val = regval_ctr_specific_value( p_data->keys[key_index].values, idx );
8266
8267         if ( !val )
8268         {
8269
8270                 /* out_value should default to "" or else NT4 has
8271                    problems unmarshalling the response */
8272
8273                 *out_max_value_len=(in_value_len/sizeof(uint16));
8274
8275                 if (in_value_len) {
8276                         if((*out_value=(uint16 *)TALLOC_ZERO(p->mem_ctx, in_value_len*sizeof(uint8))) == NULL)
8277                         {
8278                                 result = WERR_NOMEM;
8279                                 goto done;
8280                         }
8281                         *out_value_len = (uint32)rpcstr_push((char *)*out_value, "", in_value_len, 0);
8282                 } else {
8283                         *out_value=NULL;
8284                         *out_value_len = 0;
8285                 }
8286
8287                 /* the data is counted in bytes */
8288
8289                 *out_max_data_len = in_data_len;
8290                 *out_data_len     = in_data_len;
8291
8292                 /* only allocate when given a non-zero data_len */
8293
8294                 if ( in_data_len && ((*data_out=(uint8 *)TALLOC_ZERO(p->mem_ctx, in_data_len*sizeof(uint8))) == NULL) )
8295                 {
8296                         result = WERR_NOMEM;
8297                         goto done;
8298                 }
8299
8300                 result = WERR_NO_MORE_ITEMS;
8301         }
8302         else
8303         {
8304                 /*
8305                  * the value is:
8306                  * - counted in bytes in the request
8307                  * - counted in UNICODE chars in the max reply
8308                  * - counted in bytes in the real size
8309                  *
8310                  * take a pause *before* coding not *during* coding
8311                  */
8312
8313                 /* name */
8314                 *out_max_value_len=(in_value_len/sizeof(uint16));
8315                 if (in_value_len) {
8316                         if ( (*out_value = (uint16 *)TALLOC_ZERO(p->mem_ctx, in_value_len*sizeof(uint8))) == NULL )
8317                         {
8318                                 result = WERR_NOMEM;
8319                                 goto done;
8320                         }
8321
8322                         *out_value_len = (uint32)rpcstr_push((char *)*out_value, regval_name(val), (size_t)in_value_len, 0);
8323                 } else {
8324                         *out_value = NULL;
8325                         *out_value_len = 0;
8326                 }
8327
8328                 /* type */
8329
8330                 *out_type = regval_type( val );
8331
8332                 /* data - counted in bytes */
8333
8334                 *out_max_data_len = in_data_len;
8335                 if ( in_data_len && (*data_out = (uint8 *)TALLOC_ZERO(p->mem_ctx, in_data_len*sizeof(uint8))) == NULL)
8336                 {
8337                         result = WERR_NOMEM;
8338                         goto done;
8339                 }
8340                 data_len = regval_size(val);
8341                 if ( *data_out && data_len )
8342                         memcpy( *data_out, regval_data_p(val), data_len );
8343                 *out_data_len = data_len;
8344         }
8345
8346 done:
8347         free_a_printer(&printer, 2);
8348         return result;
8349 }
8350
8351 /****************************************************************************
8352 ****************************************************************************/
8353
8354 WERROR _spoolss_setprinterdata( pipes_struct *p, SPOOL_Q_SETPRINTERDATA *q_u, SPOOL_R_SETPRINTERDATA *r_u)
8355 {
8356         POLICY_HND              *handle = &q_u->handle;
8357         UNISTR2                 *value = &q_u->value;
8358         uint32                  type = q_u->type;
8359         uint8                   *data = q_u->data;
8360         uint32                  real_len = q_u->real_len;
8361
8362         NT_PRINTER_INFO_LEVEL   *printer = NULL;
8363         int                     snum=0;
8364         WERROR                  status = WERR_OK;
8365         Printer_entry           *Printer=find_printer_index_by_hnd(p, handle);
8366         fstring                 valuename;
8367
8368         DEBUG(5,("spoolss_setprinterdata\n"));
8369
8370         if (!Printer) {
8371                 DEBUG(2,("_spoolss_setprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8372                 return WERR_BADFID;
8373         }
8374
8375         if ( Printer->printer_type == SPLHND_SERVER ) {
8376                 DEBUG(10,("_spoolss_setprinterdata: Not implemented for server handles yet\n"));
8377                 return WERR_INVALID_PARAM;
8378         }
8379
8380         if (!get_printer_snum(p,handle, &snum, NULL))
8381                 return WERR_BADFID;
8382
8383         /*
8384          * Access check : NT returns "access denied" if you make a
8385          * SetPrinterData call without the necessary privildge.
8386          * we were originally returning OK if nothing changed
8387          * which made Win2k issue **a lot** of SetPrinterData
8388          * when connecting to a printer  --jerry
8389          */
8390
8391         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER)
8392         {
8393                 DEBUG(3, ("_spoolss_setprinterdata: change denied by handle access permissions\n"));
8394                 status = WERR_ACCESS_DENIED;
8395                 goto done;
8396         }
8397
8398         status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8399         if (!W_ERROR_IS_OK(status))
8400                 return status;
8401
8402         unistr2_to_ascii(valuename, value, sizeof(valuename));
8403
8404         /*
8405          * When client side code sets a magic printer data key, detect it and save
8406          * the current printer data and the magic key's data (its the DEVMODE) for
8407          * future printer/driver initializations.
8408          */
8409         if ( (type == REG_BINARY) && strequal( valuename, PHANTOM_DEVMODE_KEY))
8410         {
8411                 /* Set devmode and printer initialization info */
8412                 status = save_driver_init( printer, 2, data, real_len );
8413
8414                 srv_spoolss_reset_printerdata( printer->info_2->drivername );
8415         }
8416         else
8417         {
8418         status = set_printer_dataex( printer, SPOOL_PRINTERDATA_KEY, valuename,
8419                                         type, data, real_len );
8420                 if ( W_ERROR_IS_OK(status) )
8421                         status = mod_a_printer(printer, 2);
8422         }
8423
8424 done:
8425         free_a_printer(&printer, 2);
8426
8427         return status;
8428 }
8429
8430 /****************************************************************
8431  _spoolss_ResetPrinter
8432 ****************************************************************/
8433
8434 WERROR _spoolss_ResetPrinter(pipes_struct *p,
8435                              struct spoolss_ResetPrinter *r)
8436 {
8437         POLICY_HND      *handle = r->in.handle;
8438         Printer_entry   *Printer=find_printer_index_by_hnd(p, handle);
8439         int             snum;
8440
8441         DEBUG(5,("_spoolss_ResetPrinter\n"));
8442
8443         /*
8444          * All we do is to check to see if the handle and queue is valid.
8445          * This call really doesn't mean anything to us because we only
8446          * support RAW printing.   --jerry
8447          */
8448
8449         if (!Printer) {
8450                 DEBUG(2,("_spoolss_ResetPrinter: Invalid handle (%s:%u:%u).\n",
8451                         OUR_HANDLE(handle)));
8452                 return WERR_BADFID;
8453         }
8454
8455         if (!get_printer_snum(p,handle, &snum, NULL))
8456                 return WERR_BADFID;
8457
8458
8459         /* blindly return success */
8460         return WERR_OK;
8461 }
8462
8463 /****************************************************************
8464  _spoolss_DeletePrinterData
8465 ****************************************************************/
8466
8467 WERROR _spoolss_DeletePrinterData(pipes_struct *p,
8468                                   struct spoolss_DeletePrinterData *r)
8469 {
8470         POLICY_HND      *handle = r->in.handle;
8471         NT_PRINTER_INFO_LEVEL   *printer = NULL;
8472         int             snum=0;
8473         WERROR          status = WERR_OK;
8474         Printer_entry   *Printer=find_printer_index_by_hnd(p, handle);
8475
8476         DEBUG(5,("_spoolss_DeletePrinterData\n"));
8477
8478         if (!Printer) {
8479                 DEBUG(2,("_spoolss_DeletePrinterData: Invalid handle (%s:%u:%u).\n",
8480                         OUR_HANDLE(handle)));
8481                 return WERR_BADFID;
8482         }
8483
8484         if (!get_printer_snum(p, handle, &snum, NULL))
8485                 return WERR_BADFID;
8486
8487         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
8488                 DEBUG(3, ("_spoolss_DeletePrinterData: "
8489                         "printer properties change denied by handle\n"));
8490                 return WERR_ACCESS_DENIED;
8491         }
8492
8493         status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8494         if (!W_ERROR_IS_OK(status))
8495                 return status;
8496
8497         if (!r->in.value_name) {
8498                 free_a_printer(&printer, 2);
8499                 return WERR_NOMEM;
8500         }
8501
8502         status = delete_printer_dataex( printer, SPOOL_PRINTERDATA_KEY,
8503                                         r->in.value_name );
8504
8505         if ( W_ERROR_IS_OK(status) )
8506                 mod_a_printer( printer, 2 );
8507
8508         free_a_printer(&printer, 2);
8509
8510         return status;
8511 }
8512
8513 /****************************************************************
8514  _spoolss_AddForm
8515 ****************************************************************/
8516
8517 WERROR _spoolss_AddForm(pipes_struct *p,
8518                         struct spoolss_AddForm *r)
8519 {
8520         POLICY_HND *handle = r->in.handle;
8521         struct spoolss_AddFormInfo1 *form = r->in.info.info1;
8522         nt_forms_struct tmpForm;
8523         int snum;
8524         WERROR status = WERR_OK;
8525         NT_PRINTER_INFO_LEVEL *printer = NULL;
8526
8527         int count=0;
8528         nt_forms_struct *list=NULL;
8529         Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8530
8531         DEBUG(5,("_spoolss_AddForm\n"));
8532
8533         if (!Printer) {
8534                 DEBUG(2,("_spoolss_AddForm: Invalid handle (%s:%u:%u).\n",
8535                         OUR_HANDLE(handle)));
8536                 return WERR_BADFID;
8537         }
8538
8539
8540         /* forms can be added on printer of on the print server handle */
8541
8542         if ( Printer->printer_type == SPLHND_PRINTER )
8543         {
8544                 if (!get_printer_snum(p,handle, &snum, NULL))
8545                         return WERR_BADFID;
8546
8547                 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8548                 if (!W_ERROR_IS_OK(status))
8549                         goto done;
8550         }
8551
8552         if ( !(Printer->access_granted & (PRINTER_ACCESS_ADMINISTER|SERVER_ACCESS_ADMINISTER)) ) {
8553                 DEBUG(2,("_spoolss_addform: denied by handle permissions.\n"));
8554                 status = WERR_ACCESS_DENIED;
8555                 goto done;
8556         }
8557
8558         /* can't add if builtin */
8559
8560         if (get_a_builtin_ntform_by_string(form->form_name, &tmpForm)) {
8561                 status = WERR_FILE_EXISTS;
8562                 goto done;
8563         }
8564
8565         count = get_ntforms(&list);
8566
8567         if(!add_a_form(&list, form, &count)) {
8568                 status =  WERR_NOMEM;
8569                 goto done;
8570         }
8571
8572         write_ntforms(&list, count);
8573
8574         /*
8575          * ChangeID must always be set if this is a printer
8576          */
8577
8578         if ( Printer->printer_type == SPLHND_PRINTER )
8579                 status = mod_a_printer(printer, 2);
8580
8581 done:
8582         if ( printer )
8583                 free_a_printer(&printer, 2);
8584         SAFE_FREE(list);
8585
8586         return status;
8587 }
8588
8589 /****************************************************************
8590  _spoolss_DeleteForm
8591 ****************************************************************/
8592
8593 WERROR _spoolss_DeleteForm(pipes_struct *p,
8594                            struct spoolss_DeleteForm *r)
8595 {
8596         POLICY_HND *handle = r->in.handle;
8597         const char *form_name = r->in.form_name;
8598         nt_forms_struct tmpForm;
8599         int count=0;
8600         nt_forms_struct *list=NULL;
8601         Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8602         int snum;
8603         WERROR status = WERR_OK;
8604         NT_PRINTER_INFO_LEVEL *printer = NULL;
8605
8606         DEBUG(5,("_spoolss_DeleteForm\n"));
8607
8608         if (!Printer) {
8609                 DEBUG(2,("_spoolss_DeleteForm: Invalid handle (%s:%u:%u).\n",
8610                         OUR_HANDLE(handle)));
8611                 return WERR_BADFID;
8612         }
8613
8614         /* forms can be deleted on printer of on the print server handle */
8615
8616         if ( Printer->printer_type == SPLHND_PRINTER )
8617         {
8618                 if (!get_printer_snum(p,handle, &snum, NULL))
8619                         return WERR_BADFID;
8620
8621                 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8622                 if (!W_ERROR_IS_OK(status))
8623                         goto done;
8624         }
8625
8626         if ( !(Printer->access_granted & (PRINTER_ACCESS_ADMINISTER|SERVER_ACCESS_ADMINISTER)) ) {
8627                 DEBUG(2,("_spoolss_DeleteForm: denied by handle permissions.\n"));
8628                 status = WERR_ACCESS_DENIED;
8629                 goto done;
8630         }
8631
8632         /* can't delete if builtin */
8633
8634         if (get_a_builtin_ntform_by_string(form_name,&tmpForm)) {
8635                 status = WERR_INVALID_PARAM;
8636                 goto done;
8637         }
8638
8639         count = get_ntforms(&list);
8640
8641         if ( !delete_a_form(&list, form_name, &count, &status ))
8642                 goto done;
8643
8644         /*
8645          * ChangeID must always be set if this is a printer
8646          */
8647
8648         if ( Printer->printer_type == SPLHND_PRINTER )
8649                 status = mod_a_printer(printer, 2);
8650
8651 done:
8652         if ( printer )
8653                 free_a_printer(&printer, 2);
8654         SAFE_FREE(list);
8655
8656         return status;
8657 }
8658
8659 /****************************************************************
8660  _spoolss_SetForm
8661 ****************************************************************/
8662
8663 WERROR _spoolss_SetForm(pipes_struct *p,
8664                         struct spoolss_SetForm *r)
8665 {
8666         POLICY_HND *handle = r->in.handle;
8667         struct spoolss_AddFormInfo1 *form = r->in.info.info1;
8668         nt_forms_struct tmpForm;
8669         int snum;
8670         WERROR status = WERR_OK;
8671         NT_PRINTER_INFO_LEVEL *printer = NULL;
8672
8673         int count=0;
8674         nt_forms_struct *list=NULL;
8675         Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8676
8677         DEBUG(5,("_spoolss_SetForm\n"));
8678
8679         if (!Printer) {
8680                 DEBUG(2,("_spoolss_SetForm: Invalid handle (%s:%u:%u).\n",
8681                         OUR_HANDLE(handle)));
8682                 return WERR_BADFID;
8683         }
8684
8685         /* forms can be modified on printer of on the print server handle */
8686
8687         if ( Printer->printer_type == SPLHND_PRINTER )
8688         {
8689                 if (!get_printer_snum(p,handle, &snum, NULL))
8690                         return WERR_BADFID;
8691
8692                 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8693                 if (!W_ERROR_IS_OK(status))
8694                         goto done;
8695         }
8696
8697         if ( !(Printer->access_granted & (PRINTER_ACCESS_ADMINISTER|SERVER_ACCESS_ADMINISTER)) ) {
8698                 DEBUG(2,("_spoolss_SetForm: denied by handle permissions\n"));
8699                 status = WERR_ACCESS_DENIED;
8700                 goto done;
8701         }
8702
8703         /* can't set if builtin */
8704         if (get_a_builtin_ntform_by_string(form->form_name, &tmpForm)) {
8705                 status = WERR_INVALID_PARAM;
8706                 goto done;
8707         }
8708
8709         count = get_ntforms(&list);
8710         update_a_form(&list, form, count);
8711         write_ntforms(&list, count);
8712
8713         /*
8714          * ChangeID must always be set if this is a printer
8715          */
8716
8717         if ( Printer->printer_type == SPLHND_PRINTER )
8718                 status = mod_a_printer(printer, 2);
8719
8720
8721 done:
8722         if ( printer )
8723                 free_a_printer(&printer, 2);
8724         SAFE_FREE(list);
8725
8726         return status;
8727 }
8728
8729 /****************************************************************************
8730  enumprintprocessors level 1.
8731 ****************************************************************************/
8732
8733 static WERROR enumprintprocessors_level_1(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
8734 {
8735         PRINTPROCESSOR_1 *info_1=NULL;
8736         WERROR result = WERR_OK;
8737
8738         if((info_1 = SMB_MALLOC_P(PRINTPROCESSOR_1)) == NULL)
8739                 return WERR_NOMEM;
8740
8741         (*returned) = 0x1;
8742
8743         init_unistr(&info_1->name, "winprint");
8744
8745         *needed += spoolss_size_printprocessor_info_1(info_1);
8746
8747         if (*needed > offered) {
8748                 result = WERR_INSUFFICIENT_BUFFER;
8749                 goto out;
8750         }
8751
8752         if (!rpcbuf_alloc_size(buffer, *needed)) {
8753                 result = WERR_NOMEM;
8754                 goto out;
8755         }
8756
8757         smb_io_printprocessor_info_1("", buffer, info_1, 0);
8758
8759 out:
8760         SAFE_FREE(info_1);
8761
8762         if ( !W_ERROR_IS_OK(result) )
8763                 *returned = 0;
8764
8765         return result;
8766 }
8767
8768 /****************************************************************************
8769 ****************************************************************************/
8770
8771 WERROR _spoolss_enumprintprocessors(pipes_struct *p, SPOOL_Q_ENUMPRINTPROCESSORS *q_u, SPOOL_R_ENUMPRINTPROCESSORS *r_u)
8772 {
8773         uint32 level = q_u->level;
8774         RPC_BUFFER *buffer = NULL;
8775         uint32 offered = q_u->offered;
8776         uint32 *needed = &r_u->needed;
8777         uint32 *returned = &r_u->returned;
8778
8779         /* that's an [in out] buffer */
8780
8781         if (!q_u->buffer && (offered!=0)) {
8782                 return WERR_INVALID_PARAM;
8783         }
8784
8785         if (offered > MAX_RPC_DATA_SIZE) {
8786                 return WERR_INVALID_PARAM;
8787         }
8788
8789         rpcbuf_move(q_u->buffer, &r_u->buffer);
8790         buffer = r_u->buffer;
8791
8792         DEBUG(5,("spoolss_enumprintprocessors\n"));
8793
8794         /*
8795          * Enumerate the print processors ...
8796          *
8797          * Just reply with "winprint", to keep NT happy
8798          * and I can use my nice printer checker.
8799          */
8800
8801         *returned=0;
8802         *needed=0;
8803
8804         switch (level) {
8805         case 1:
8806                 return enumprintprocessors_level_1(buffer, offered, needed, returned);
8807         default:
8808                 return WERR_UNKNOWN_LEVEL;
8809         }
8810 }
8811
8812 /****************************************************************************
8813  enumprintprocdatatypes level 1.
8814 ****************************************************************************/
8815
8816 static WERROR enumprintprocdatatypes_level_1(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
8817 {
8818         PRINTPROCDATATYPE_1 *info_1=NULL;
8819         WERROR result = WERR_OK;
8820
8821         if((info_1 = SMB_MALLOC_P(PRINTPROCDATATYPE_1)) == NULL)
8822                 return WERR_NOMEM;
8823
8824         (*returned) = 0x1;
8825
8826         init_unistr(&info_1->name, "RAW");
8827
8828         *needed += spoolss_size_printprocdatatype_info_1(info_1);
8829
8830         if (*needed > offered) {
8831                 result = WERR_INSUFFICIENT_BUFFER;
8832                 goto out;
8833         }
8834
8835         if (!rpcbuf_alloc_size(buffer, *needed)) {
8836                 result = WERR_NOMEM;
8837                 goto out;
8838         }
8839
8840         smb_io_printprocdatatype_info_1("", buffer, info_1, 0);
8841
8842 out:
8843         SAFE_FREE(info_1);
8844
8845         if ( !W_ERROR_IS_OK(result) )
8846                 *returned = 0;
8847
8848         return result;
8849 }
8850
8851 /****************************************************************************
8852 ****************************************************************************/
8853
8854 WERROR _spoolss_enumprintprocdatatypes(pipes_struct *p, SPOOL_Q_ENUMPRINTPROCDATATYPES *q_u, SPOOL_R_ENUMPRINTPROCDATATYPES *r_u)
8855 {
8856         uint32 level = q_u->level;
8857         RPC_BUFFER *buffer = NULL;
8858         uint32 offered = q_u->offered;
8859         uint32 *needed = &r_u->needed;
8860         uint32 *returned = &r_u->returned;
8861
8862         /* that's an [in out] buffer */
8863
8864         if (!q_u->buffer && (offered!=0)) {
8865                 return WERR_INVALID_PARAM;
8866         }
8867
8868         if (offered > MAX_RPC_DATA_SIZE) {
8869                 return WERR_INVALID_PARAM;
8870         }
8871
8872         rpcbuf_move(q_u->buffer, &r_u->buffer);
8873         buffer = r_u->buffer;
8874
8875         DEBUG(5,("_spoolss_enumprintprocdatatypes\n"));
8876
8877         *returned=0;
8878         *needed=0;
8879
8880         switch (level) {
8881         case 1:
8882                 return enumprintprocdatatypes_level_1(buffer, offered, needed, returned);
8883         default:
8884                 return WERR_UNKNOWN_LEVEL;
8885         }
8886 }
8887
8888 /****************************************************************************
8889  enumprintmonitors level 1.
8890 ****************************************************************************/
8891
8892 static WERROR enumprintmonitors_level_1(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
8893 {
8894         PRINTMONITOR_1 *info_1;
8895         WERROR result = WERR_OK;
8896         int i;
8897
8898         if((info_1 = SMB_MALLOC_ARRAY(PRINTMONITOR_1, 2)) == NULL)
8899                 return WERR_NOMEM;
8900
8901         *returned = 2;
8902
8903         init_unistr(&(info_1[0].name), SPL_LOCAL_PORT );
8904         init_unistr(&(info_1[1].name), SPL_TCPIP_PORT );
8905
8906         for ( i=0; i<*returned; i++ ) {
8907                 *needed += spoolss_size_printmonitor_info_1(&info_1[i]);
8908         }
8909
8910         if (*needed > offered) {
8911                 result = WERR_INSUFFICIENT_BUFFER;
8912                 goto out;
8913         }
8914
8915         if (!rpcbuf_alloc_size(buffer, *needed)) {
8916                 result = WERR_NOMEM;
8917                 goto out;
8918         }
8919
8920         for ( i=0; i<*returned; i++ ) {
8921                 smb_io_printmonitor_info_1("", buffer, &info_1[i], 0);
8922         }
8923
8924 out:
8925         SAFE_FREE(info_1);
8926
8927         if ( !W_ERROR_IS_OK(result) )
8928                 *returned = 0;
8929
8930         return result;
8931 }
8932
8933 /****************************************************************************
8934  enumprintmonitors level 2.
8935 ****************************************************************************/
8936
8937 static WERROR enumprintmonitors_level_2(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
8938 {
8939         PRINTMONITOR_2 *info_2;
8940         WERROR result = WERR_OK;
8941         int i;
8942
8943         if((info_2 = SMB_MALLOC_ARRAY(PRINTMONITOR_2, 2)) == NULL)
8944                 return WERR_NOMEM;
8945
8946         *returned = 2;
8947
8948         init_unistr( &(info_2[0].name), SPL_LOCAL_PORT );
8949         init_unistr( &(info_2[0].environment), "Windows NT X86" );
8950         init_unistr( &(info_2[0].dll_name), "localmon.dll" );
8951
8952         init_unistr( &(info_2[1].name), SPL_TCPIP_PORT );
8953         init_unistr( &(info_2[1].environment), "Windows NT X86" );
8954         init_unistr( &(info_2[1].dll_name), "tcpmon.dll" );
8955
8956         for ( i=0; i<*returned; i++ ) {
8957                 *needed += spoolss_size_printmonitor_info_2(&info_2[i]);
8958         }
8959
8960         if (*needed > offered) {
8961                 result = WERR_INSUFFICIENT_BUFFER;
8962                 goto out;
8963         }
8964
8965         if (!rpcbuf_alloc_size(buffer, *needed)) {
8966                 result = WERR_NOMEM;
8967                 goto out;
8968         }
8969
8970         for ( i=0; i<*returned; i++ ) {
8971                 smb_io_printmonitor_info_2("", buffer, &info_2[i], 0);
8972         }
8973
8974 out:
8975         SAFE_FREE(info_2);
8976
8977         if ( !W_ERROR_IS_OK(result) )
8978                 *returned = 0;
8979
8980         return result;
8981 }
8982
8983 /****************************************************************************
8984 ****************************************************************************/
8985
8986 WERROR _spoolss_enumprintmonitors(pipes_struct *p, SPOOL_Q_ENUMPRINTMONITORS *q_u, SPOOL_R_ENUMPRINTMONITORS *r_u)
8987 {
8988         uint32 level = q_u->level;
8989         RPC_BUFFER *buffer = NULL;
8990         uint32 offered = q_u->offered;
8991         uint32 *needed = &r_u->needed;
8992         uint32 *returned = &r_u->returned;
8993
8994         /* that's an [in out] buffer */
8995
8996         if (!q_u->buffer && (offered!=0)) {
8997                 return WERR_INVALID_PARAM;
8998         }
8999
9000         if (offered > MAX_RPC_DATA_SIZE) {
9001                 return WERR_INVALID_PARAM;
9002         }
9003
9004         rpcbuf_move(q_u->buffer, &r_u->buffer);
9005         buffer = r_u->buffer;
9006
9007         DEBUG(5,("spoolss_enumprintmonitors\n"));
9008
9009         /*
9010          * Enumerate the print monitors ...
9011          *
9012          * Just reply with "Local Port", to keep NT happy
9013          * and I can use my nice printer checker.
9014          */
9015
9016         *returned=0;
9017         *needed=0;
9018
9019         switch (level) {
9020         case 1:
9021                 return enumprintmonitors_level_1(buffer, offered, needed, returned);
9022         case 2:
9023                 return enumprintmonitors_level_2(buffer, offered, needed, returned);
9024         default:
9025                 return WERR_UNKNOWN_LEVEL;
9026         }
9027 }
9028
9029 /****************************************************************************
9030 ****************************************************************************/
9031
9032 static WERROR getjob_level_1(print_queue_struct **queue, int count, int snum,
9033                              NT_PRINTER_INFO_LEVEL *ntprinter,
9034                              uint32 jobid, RPC_BUFFER *buffer, uint32 offered,
9035                              uint32 *needed)
9036 {
9037         int i=0;
9038         bool found=False;
9039         JOB_INFO_1 *info_1=NULL;
9040         WERROR result = WERR_OK;
9041
9042         info_1=SMB_MALLOC_P(JOB_INFO_1);
9043
9044         if (info_1 == NULL) {
9045                 return WERR_NOMEM;
9046         }
9047
9048         for (i=0; i<count && found==False; i++) {
9049                 if ((*queue)[i].job==(int)jobid)
9050                         found=True;
9051         }
9052
9053         if (found==False) {
9054                 SAFE_FREE(info_1);
9055                 /* NT treats not found as bad param... yet another bad choice */
9056                 return WERR_INVALID_PARAM;
9057         }
9058
9059         fill_job_info_1( info_1, &((*queue)[i-1]), i, snum, ntprinter );
9060
9061         *needed += spoolss_size_job_info_1(info_1);
9062
9063         if (*needed > offered) {
9064                 result = WERR_INSUFFICIENT_BUFFER;
9065                 goto out;
9066         }
9067
9068         if (!rpcbuf_alloc_size(buffer, *needed)) {
9069                 result = WERR_NOMEM;
9070                 goto out;
9071         }
9072
9073         smb_io_job_info_1("", buffer, info_1, 0);
9074
9075 out:
9076         SAFE_FREE(info_1);
9077
9078         return result;
9079 }
9080
9081 /****************************************************************************
9082 ****************************************************************************/
9083
9084 static WERROR getjob_level_2(print_queue_struct **queue, int count, int snum,
9085                              NT_PRINTER_INFO_LEVEL *ntprinter,
9086                              uint32 jobid, RPC_BUFFER *buffer, uint32 offered,
9087                              uint32 *needed)
9088 {
9089         int             i = 0;
9090         bool            found = False;
9091         JOB_INFO_2      *info_2;
9092         WERROR          result;
9093         DEVICEMODE      *devmode = NULL;
9094         NT_DEVICEMODE   *nt_devmode = NULL;
9095
9096         if ( !(info_2=SMB_MALLOC_P(JOB_INFO_2)) )
9097                 return WERR_NOMEM;
9098
9099         ZERO_STRUCTP(info_2);
9100
9101         for ( i=0; i<count && found==False; i++ )
9102         {
9103                 if ((*queue)[i].job == (int)jobid)
9104                         found = True;
9105         }
9106
9107         if ( !found ) {
9108                 /* NT treats not found as bad param... yet another bad
9109                    choice */
9110                 result = WERR_INVALID_PARAM;
9111                 goto done;
9112         }
9113
9114         /*
9115          * if the print job does not have a DEVMODE associated with it,
9116          * just use the one for the printer. A NULL devicemode is not
9117          *  a failure condition
9118          */
9119
9120         if ( !(nt_devmode=print_job_devmode( lp_const_servicename(snum), jobid )) )
9121                 devmode = construct_dev_mode(lp_const_servicename(snum));
9122         else {
9123                 if ((devmode = SMB_MALLOC_P(DEVICEMODE)) != NULL) {
9124                         ZERO_STRUCTP( devmode );
9125                         convert_nt_devicemode( devmode, nt_devmode );
9126                 }
9127         }
9128
9129         fill_job_info_2(info_2, &((*queue)[i-1]), i, snum, ntprinter, devmode);
9130
9131         *needed += spoolss_size_job_info_2(info_2);
9132
9133         if (*needed > offered) {
9134                 result = WERR_INSUFFICIENT_BUFFER;
9135                 goto done;
9136         }
9137
9138         if (!rpcbuf_alloc_size(buffer, *needed)) {
9139                 result = WERR_NOMEM;
9140                 goto done;
9141         }
9142
9143         smb_io_job_info_2("", buffer, info_2, 0);
9144
9145         result = WERR_OK;
9146
9147  done:
9148         /* Cleanup allocated memory */
9149
9150         free_job_info_2(info_2);        /* Also frees devmode */
9151         SAFE_FREE(info_2);
9152
9153         return result;
9154 }
9155
9156 /****************************************************************************
9157 ****************************************************************************/
9158
9159 WERROR _spoolss_getjob( pipes_struct *p, SPOOL_Q_GETJOB *q_u, SPOOL_R_GETJOB *r_u)
9160 {
9161         POLICY_HND *handle = &q_u->handle;
9162         uint32 jobid = q_u->jobid;
9163         uint32 level = q_u->level;
9164         RPC_BUFFER *buffer = NULL;
9165         uint32 offered = q_u->offered;
9166         uint32 *needed = &r_u->needed;
9167         WERROR          wstatus = WERR_OK;
9168         NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
9169         int snum;
9170         int count;
9171         print_queue_struct      *queue = NULL;
9172         print_status_struct prt_status;
9173
9174         /* that's an [in out] buffer */
9175
9176         if (!q_u->buffer && (offered!=0)) {
9177                 return WERR_INVALID_PARAM;
9178         }
9179
9180         if (offered > MAX_RPC_DATA_SIZE) {
9181                 return WERR_INVALID_PARAM;
9182         }
9183
9184         rpcbuf_move(q_u->buffer, &r_u->buffer);
9185         buffer = r_u->buffer;
9186
9187         DEBUG(5,("spoolss_getjob\n"));
9188
9189         *needed = 0;
9190
9191         if (!get_printer_snum(p, handle, &snum, NULL))
9192                 return WERR_BADFID;
9193
9194         wstatus = get_a_printer(NULL, &ntprinter, 2, lp_servicename(snum));
9195         if ( !W_ERROR_IS_OK(wstatus) )
9196                 return wstatus;
9197
9198         count = print_queue_status(snum, &queue, &prt_status);
9199
9200         DEBUGADD(4,("count:[%d], prt_status:[%d], [%s]\n",
9201                      count, prt_status.status, prt_status.message));
9202
9203         switch ( level ) {
9204         case 1:
9205                         wstatus = getjob_level_1(&queue, count, snum, ntprinter, jobid,
9206                                 buffer, offered, needed);
9207                         break;
9208         case 2:
9209                         wstatus = getjob_level_2(&queue, count, snum, ntprinter, jobid,
9210                                 buffer, offered, needed);
9211                         break;
9212         default:
9213                         wstatus = WERR_UNKNOWN_LEVEL;
9214                         break;
9215         }
9216
9217         SAFE_FREE(queue);
9218         free_a_printer( &ntprinter, 2 );
9219
9220         return wstatus;
9221 }
9222
9223 /****************************************************************
9224  _spoolss_GetPrinterDataEx
9225
9226  From MSDN documentation of GetPrinterDataEx: pass request
9227  to GetPrinterData if key is "PrinterDriverData".
9228 ****************************************************************/
9229
9230 WERROR _spoolss_GetPrinterDataEx(pipes_struct *p,
9231                                  struct spoolss_GetPrinterDataEx *r)
9232 {
9233         POLICY_HND      *handle = r->in.handle;
9234         uint8           *data = NULL;
9235         const char      *keyname = r->in.key_name;
9236         const char      *valuename = r->in.value_name;
9237
9238         Printer_entry   *Printer = find_printer_index_by_hnd(p, handle);
9239
9240         NT_PRINTER_INFO_LEVEL   *printer = NULL;
9241         int                     snum = 0;
9242         WERROR                  status = WERR_OK;
9243
9244         DEBUG(4,("_spoolss_GetPrinterDataEx\n"));
9245
9246         DEBUG(10, ("_spoolss_GetPrinterDataEx: key => [%s], value => [%s]\n",
9247                 keyname, valuename));
9248
9249         /* in case of problem, return some default values */
9250
9251         *r->out.needed  = 0;
9252         *r->out.type    = 0;
9253
9254         if (!Printer) {
9255                 DEBUG(2,("_spoolss_GetPrinterDataEx: "
9256                         "Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
9257                 status = WERR_BADFID;
9258                 goto done;
9259         }
9260
9261         /* Is the handle to a printer or to the server? */
9262
9263         if (Printer->printer_type == SPLHND_SERVER) {
9264                 DEBUG(10,("_spoolss_GetPrinterDataEx: "
9265                         "Not implemented for server handles yet\n"));
9266                 status = WERR_INVALID_PARAM;
9267                 goto done;
9268         }
9269
9270         if ( !get_printer_snum(p,handle, &snum, NULL) )
9271                 return WERR_BADFID;
9272
9273         status = get_a_printer(Printer, &printer, 2, lp_servicename(snum));
9274         if ( !W_ERROR_IS_OK(status) )
9275                 goto done;
9276
9277         /* check to see if the keyname is valid */
9278         if ( !strlen(keyname) ) {
9279                 status = WERR_INVALID_PARAM;
9280                 goto done;
9281         }
9282
9283         if ( lookup_printerkey( printer->info_2->data, keyname ) == -1 ) {
9284                 DEBUG(4,("_spoolss_GetPrinterDataEx: "
9285                         "Invalid keyname [%s]\n", keyname ));
9286                 free_a_printer( &printer, 2 );
9287                 status = WERR_BADFILE;
9288                 goto done;
9289         }
9290
9291         /* When given a new keyname, we should just create it */
9292
9293         status = get_printer_dataex( p->mem_ctx, printer, keyname, valuename,
9294                                      r->out.type, &data, r->out.needed,
9295                                      r->in.offered );
9296
9297         if (*r->out.needed > r->in.offered) {
9298                 status = WERR_MORE_DATA;
9299         }
9300
9301         if (W_ERROR_IS_OK(status)) {
9302                 memcpy(r->out.buffer, data, r->in.offered);
9303         }
9304
9305 done:
9306         if ( printer )
9307         free_a_printer( &printer, 2 );
9308
9309         return status;
9310 }
9311
9312 /****************************************************************
9313  _spoolss_SetPrinterDataEx
9314 ****************************************************************/
9315
9316 WERROR _spoolss_SetPrinterDataEx(pipes_struct *p,
9317                                  struct spoolss_SetPrinterDataEx *r)
9318 {
9319         POLICY_HND              *handle = r->in.handle;
9320         NT_PRINTER_INFO_LEVEL   *printer = NULL;
9321         int                     snum = 0;
9322         WERROR                  status = WERR_OK;
9323         Printer_entry           *Printer = find_printer_index_by_hnd(p, handle);
9324         char                    *oid_string;
9325
9326         DEBUG(4,("_spoolss_SetPrinterDataEx\n"));
9327
9328         /* From MSDN documentation of SetPrinterDataEx: pass request to
9329            SetPrinterData if key is "PrinterDriverData" */
9330
9331         if (!Printer) {
9332                 DEBUG(2,("_spoolss_SetPrinterDataEx: "
9333                         "Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
9334                 return WERR_BADFID;
9335         }
9336
9337         if ( Printer->printer_type == SPLHND_SERVER ) {
9338                 DEBUG(10,("_spoolss_SetPrinterDataEx: "
9339                         "Not implemented for server handles yet\n"));
9340                 return WERR_INVALID_PARAM;
9341         }
9342
9343         if ( !get_printer_snum(p,handle, &snum, NULL) )
9344                 return WERR_BADFID;
9345
9346         /*
9347          * Access check : NT returns "access denied" if you make a
9348          * SetPrinterData call without the necessary privildge.
9349          * we were originally returning OK if nothing changed
9350          * which made Win2k issue **a lot** of SetPrinterData
9351          * when connecting to a printer  --jerry
9352          */
9353
9354         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER)
9355         {
9356                 DEBUG(3, ("_spoolss_SetPrinterDataEx: "
9357                         "change denied by handle access permissions\n"));
9358                 return WERR_ACCESS_DENIED;
9359         }
9360
9361         status = get_a_printer(Printer, &printer, 2, lp_servicename(snum));
9362         if (!W_ERROR_IS_OK(status))
9363                 return status;
9364
9365         /* check for OID in valuename */
9366
9367         if ( (oid_string = strchr( r->in.value_name, ',' )) != NULL )
9368         {
9369                 *oid_string = '\0';
9370                 oid_string++;
9371         }
9372
9373         /* save the registry data */
9374
9375         status = set_printer_dataex( printer, r->in.key_name, r->in.value_name,
9376                                      r->in.type, r->in.buffer, r->in.offered );
9377
9378         if ( W_ERROR_IS_OK(status) )
9379         {
9380                 /* save the OID if one was specified */
9381                 if ( oid_string ) {
9382                         char *str = talloc_asprintf(p->mem_ctx, "%s\\%s",
9383                                 r->in.key_name, SPOOL_OID_KEY);
9384                         if (!str) {
9385                                 return WERR_NOMEM;
9386                         }
9387
9388                         /*
9389                          * I'm not checking the status here on purpose.  Don't know
9390                          * if this is right, but I'm returning the status from the
9391                          * previous set_printer_dataex() call.  I have no idea if
9392                          * this is right.    --jerry
9393                          */
9394
9395                         set_printer_dataex( printer, str, r->in.value_name,
9396                                             REG_SZ, (uint8 *)oid_string,
9397                                             strlen(oid_string)+1 );
9398                 }
9399
9400                 status = mod_a_printer(printer, 2);
9401         }
9402
9403         free_a_printer(&printer, 2);
9404
9405         return status;
9406 }
9407
9408 /****************************************************************
9409  _spoolss_DeletePrinterDataEx
9410 ****************************************************************/
9411
9412 WERROR _spoolss_DeletePrinterDataEx(pipes_struct *p,
9413                                     struct spoolss_DeletePrinterDataEx *r)
9414 {
9415         POLICY_HND      *handle = r->in.handle;
9416         NT_PRINTER_INFO_LEVEL   *printer = NULL;
9417         int             snum=0;
9418         WERROR          status = WERR_OK;
9419         Printer_entry   *Printer=find_printer_index_by_hnd(p, handle);
9420
9421         DEBUG(5,("_spoolss_DeletePrinterDataEx\n"));
9422
9423         if (!Printer) {
9424                 DEBUG(2,("_spoolss_DeletePrinterDataEx: "
9425                         "Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
9426                 return WERR_BADFID;
9427         }
9428
9429         if (!get_printer_snum(p, handle, &snum, NULL))
9430                 return WERR_BADFID;
9431
9432         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
9433                 DEBUG(3, ("_spoolss_DeletePrinterDataEx: "
9434                         "printer properties change denied by handle\n"));
9435                 return WERR_ACCESS_DENIED;
9436         }
9437
9438         if (!r->in.value_name || !r->in.key_name) {
9439                 return WERR_NOMEM;
9440         }
9441
9442         status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
9443         if (!W_ERROR_IS_OK(status))
9444                 return status;
9445
9446         status = delete_printer_dataex( printer, r->in.key_name, r->in.value_name );
9447
9448         if ( W_ERROR_IS_OK(status) )
9449                 mod_a_printer( printer, 2 );
9450
9451         free_a_printer(&printer, 2);
9452
9453         return status;
9454 }
9455
9456 /********************************************************************
9457  * spoolss_enumprinterkey
9458  ********************************************************************/
9459
9460
9461 WERROR _spoolss_enumprinterkey(pipes_struct *p, SPOOL_Q_ENUMPRINTERKEY *q_u, SPOOL_R_ENUMPRINTERKEY *r_u)
9462 {
9463         fstring         key;
9464         fstring         *keynames = NULL;
9465         uint16          *enumkeys = NULL;
9466         int             num_keys;
9467         int             printerkey_len;
9468         POLICY_HND      *handle = &q_u->handle;
9469         Printer_entry   *Printer = find_printer_index_by_hnd(p, handle);
9470         NT_PRINTER_DATA *data;
9471         NT_PRINTER_INFO_LEVEL   *printer = NULL;
9472         int             snum = 0;
9473         WERROR          status = WERR_BADFILE;
9474
9475
9476         DEBUG(4,("_spoolss_enumprinterkey\n"));
9477
9478         if (!Printer) {
9479                 DEBUG(2,("_spoolss_enumprinterkey: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
9480                 return WERR_BADFID;
9481         }
9482
9483         if ( !get_printer_snum(p,handle, &snum, NULL) )
9484                 return WERR_BADFID;
9485
9486         status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
9487         if (!W_ERROR_IS_OK(status))
9488                 return status;
9489
9490         /* get the list of subkey names */
9491
9492         unistr2_to_ascii(key, &q_u->key, sizeof(key));
9493         data = printer->info_2->data;
9494
9495         num_keys = get_printer_subkeys( data, key, &keynames );
9496
9497         if ( num_keys == -1 ) {
9498                 status = WERR_BADFILE;
9499                 goto done;
9500         }
9501
9502         printerkey_len = init_unistr_array( &enumkeys,  keynames, NULL );
9503
9504         r_u->needed = printerkey_len*2;
9505
9506         if ( q_u->size < r_u->needed ) {
9507                 status = WERR_MORE_DATA;
9508                 goto done;
9509         }
9510
9511         if (!make_spoolss_buffer5(p->mem_ctx, &r_u->keys, printerkey_len, enumkeys)) {
9512                 status = WERR_NOMEM;
9513                 goto done;
9514         }
9515
9516         status = WERR_OK;
9517
9518         if ( q_u->size < r_u->needed )
9519                 status = WERR_MORE_DATA;
9520
9521 done:
9522         free_a_printer( &printer, 2 );
9523         SAFE_FREE( keynames );
9524
9525         return status;
9526 }
9527
9528 /****************************************************************
9529  _spoolss_DeletePrinterKey
9530 ****************************************************************/
9531
9532 WERROR _spoolss_DeletePrinterKey(pipes_struct *p,
9533                                  struct spoolss_DeletePrinterKey *r)
9534 {
9535         POLICY_HND              *handle = r->in.handle;
9536         Printer_entry           *Printer = find_printer_index_by_hnd(p, handle);
9537         NT_PRINTER_INFO_LEVEL   *printer = NULL;
9538         int                     snum=0;
9539         WERROR                  status;
9540
9541         DEBUG(5,("_spoolss_DeletePrinterKey\n"));
9542
9543         if (!Printer) {
9544                 DEBUG(2,("_spoolss_DeletePrinterKey: Invalid handle (%s:%u:%u).\n",
9545                         OUR_HANDLE(handle)));
9546                 return WERR_BADFID;
9547         }
9548
9549         /* if keyname == NULL, return error */
9550
9551         if ( !r->in.key_name )
9552                 return WERR_INVALID_PARAM;
9553
9554         if (!get_printer_snum(p, handle, &snum, NULL))
9555                 return WERR_BADFID;
9556
9557         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
9558                 DEBUG(3, ("_spoolss_DeletePrinterKey: "
9559                         "printer properties change denied by handle\n"));
9560                 return WERR_ACCESS_DENIED;
9561         }
9562
9563         status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
9564         if (!W_ERROR_IS_OK(status))
9565                 return status;
9566
9567         /* delete the key and all subneys */
9568
9569         status = delete_all_printer_data( printer->info_2, r->in.key_name );
9570
9571         if ( W_ERROR_IS_OK(status) )
9572                 status = mod_a_printer(printer, 2);
9573
9574         free_a_printer( &printer, 2 );
9575
9576         return status;
9577 }
9578
9579
9580 /********************************************************************
9581  * spoolss_enumprinterdataex
9582  ********************************************************************/
9583
9584 WERROR _spoolss_enumprinterdataex(pipes_struct *p, SPOOL_Q_ENUMPRINTERDATAEX *q_u, SPOOL_R_ENUMPRINTERDATAEX *r_u)
9585 {
9586         POLICY_HND      *handle = &q_u->handle;
9587         uint32          in_size = q_u->size;
9588         uint32          num_entries,
9589                         needed;
9590         NT_PRINTER_INFO_LEVEL   *printer = NULL;
9591         PRINTER_ENUM_VALUES     *enum_values = NULL;
9592         NT_PRINTER_DATA         *p_data;
9593         fstring         key;
9594         Printer_entry   *Printer = find_printer_index_by_hnd(p, handle);
9595         int             snum;
9596         WERROR          result;
9597         int             key_index;
9598         int             i;
9599         REGISTRY_VALUE  *val;
9600         char            *value_name;
9601         uint32          data_len;
9602
9603
9604         DEBUG(4,("_spoolss_enumprinterdataex\n"));
9605
9606         if (!Printer) {
9607                 DEBUG(2,("_spoolss_enumprinterdataex: Invalid handle (%s:%u:%u1<).\n", OUR_HANDLE(handle)));
9608                 return WERR_BADFID;
9609         }
9610
9611         /*
9612          * first check for a keyname of NULL or "".  Win2k seems to send
9613          * this a lot and we should send back WERR_INVALID_PARAM
9614          * no need to spend time looking up the printer in this case.
9615          * --jerry
9616          */
9617
9618         unistr2_to_ascii(key, &q_u->key, sizeof(key));
9619         if ( !strlen(key) ) {
9620                 result = WERR_INVALID_PARAM;
9621                 goto done;
9622         }
9623
9624         /* get the printer off of disk */
9625
9626         if (!get_printer_snum(p,handle, &snum, NULL))
9627                 return WERR_BADFID;
9628
9629         ZERO_STRUCT(printer);
9630         result = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
9631         if (!W_ERROR_IS_OK(result))
9632                 return result;
9633
9634         /* now look for a match on the key name */
9635
9636         p_data = printer->info_2->data;
9637
9638         unistr2_to_ascii(key, &q_u->key, sizeof(key));
9639         if ( (key_index = lookup_printerkey( p_data, key)) == -1  )
9640         {
9641                 DEBUG(10,("_spoolss_enumprinterdataex: Unknown keyname [%s]\n", key));
9642                 result = WERR_INVALID_PARAM;
9643                 goto done;
9644         }
9645
9646         result = WERR_OK;
9647         needed = 0;
9648
9649         /* allocate the memory for the array of pointers -- if necessary */
9650
9651         num_entries = regval_ctr_numvals( p_data->keys[key_index].values );
9652         if ( num_entries )
9653         {
9654                 if ( (enum_values=TALLOC_ARRAY(p->mem_ctx, PRINTER_ENUM_VALUES, num_entries)) == NULL )
9655                 {
9656                         DEBUG(0,("_spoolss_enumprinterdataex: talloc() failed to allocate memory for [%lu] bytes!\n",
9657                                 (unsigned long)num_entries*sizeof(PRINTER_ENUM_VALUES)));
9658                         result = WERR_NOMEM;
9659                         goto done;
9660                 }
9661
9662                 memset( enum_values, 0x0, num_entries*sizeof(PRINTER_ENUM_VALUES) );
9663         }
9664
9665         /*
9666          * loop through all params and build the array to pass
9667          * back to the  client
9668          */
9669
9670         for ( i=0; i<num_entries; i++ )
9671         {
9672                 /* lookup the registry value */
9673
9674                 val = regval_ctr_specific_value( p_data->keys[key_index].values, i );
9675                 DEBUG(10,("retrieved value number [%d] [%s]\n", i, regval_name(val) ));
9676
9677                 /* copy the data */
9678
9679                 value_name = regval_name( val );
9680                 init_unistr( &enum_values[i].valuename, value_name );
9681                 enum_values[i].value_len = (strlen(value_name)+1) * 2;
9682                 enum_values[i].type      = regval_type( val );
9683
9684                 data_len = regval_size( val );
9685                 if ( data_len ) {
9686                         if ( !(enum_values[i].data = (uint8 *)TALLOC_MEMDUP(p->mem_ctx, regval_data_p(val), data_len)) )
9687                         {
9688                                 DEBUG(0,("TALLOC_MEMDUP failed to allocate memory [data_len=%d] for data!\n",
9689                                         data_len ));
9690                                 result = WERR_NOMEM;
9691                                 goto done;
9692                         }
9693                 }
9694                 enum_values[i].data_len = data_len;
9695
9696                 /* keep track of the size of the array in bytes */
9697
9698                 needed += spoolss_size_printer_enum_values(&enum_values[i]);
9699         }
9700
9701         /* housekeeping information in the reply */
9702
9703         /* Fix from Martin Zielinski <mz@seh.de> - ensure
9704          * the hand marshalled container size is a multiple
9705          * of 4 bytes for RPC alignment.
9706          */
9707
9708         if (needed % 4) {
9709                 needed += 4-(needed % 4);
9710         }
9711
9712         r_u->needed     = needed;
9713         r_u->returned   = num_entries;
9714
9715         if (needed > in_size) {
9716                 result = WERR_MORE_DATA;
9717                 goto done;
9718         }
9719
9720         /* copy data into the reply */
9721
9722         /* mz: Vista x64 returns 0x6f7 (The stub received bad data), if the
9723            response buffer size is != the offered buffer size
9724
9725                 r_u->ctr.size           = r_u->needed;
9726         */
9727         r_u->ctr.size           = in_size;
9728
9729         r_u->ctr.size_of_array  = r_u->returned;
9730         r_u->ctr.values         = enum_values;
9731
9732 done:
9733         if ( printer )
9734         free_a_printer(&printer, 2);
9735
9736         return result;
9737 }
9738
9739 /****************************************************************************
9740 ****************************************************************************/
9741
9742 static void fill_printprocessordirectory_1(PRINTPROCESSOR_DIRECTORY_1 *info, const char *name)
9743 {
9744         init_unistr(&info->name, name);
9745 }
9746
9747 static WERROR getprintprocessordirectory_level_1(UNISTR2 *name,
9748                                                  UNISTR2 *environment,
9749                                                  RPC_BUFFER *buffer,
9750                                                  uint32 offered,
9751                                                  uint32 *needed)
9752 {
9753         char *long_archi = NULL;
9754         PRINTPROCESSOR_DIRECTORY_1 *info=NULL;
9755         WERROR result = WERR_OK;
9756         TALLOC_CTX *ctx = talloc_tos();
9757
9758         long_archi = unistr2_to_ascii_talloc(ctx, environment);
9759         if (!long_archi) {
9760                 return WERR_NOMEM;
9761         }
9762
9763         if (!get_short_archi(long_archi))
9764                 return WERR_INVALID_ENVIRONMENT;
9765
9766         if((info=SMB_MALLOC_P(PRINTPROCESSOR_DIRECTORY_1)) == NULL)
9767                 return WERR_NOMEM;
9768
9769         fill_printprocessordirectory_1(info, "C:\\WINNT\\System32\\spool\\PRTPROCS\\W32X86");
9770
9771         *needed += spoolss_size_printprocessordirectory_info_1(info);
9772
9773         if (*needed > offered) {
9774                 result = WERR_INSUFFICIENT_BUFFER;
9775                 goto out;
9776         }
9777
9778         if (!rpcbuf_alloc_size(buffer, *needed)) {
9779                 result = WERR_INSUFFICIENT_BUFFER;
9780                 goto out;
9781         }
9782
9783         smb_io_printprocessordirectory_1("", buffer, info, 0);
9784
9785 out:
9786         SAFE_FREE(info);
9787
9788         return result;
9789 }
9790
9791 WERROR _spoolss_getprintprocessordirectory(pipes_struct *p, SPOOL_Q_GETPRINTPROCESSORDIRECTORY *q_u, SPOOL_R_GETPRINTPROCESSORDIRECTORY *r_u)
9792 {
9793         uint32 level = q_u->level;
9794         RPC_BUFFER *buffer = NULL;
9795         uint32 offered = q_u->offered;
9796         uint32 *needed = &r_u->needed;
9797         WERROR result;
9798
9799         /* that's an [in out] buffer */
9800
9801         if (!q_u->buffer && (offered!=0)) {
9802                 return WERR_INVALID_PARAM;
9803         }
9804
9805         if (offered > MAX_RPC_DATA_SIZE) {
9806                 return WERR_INVALID_PARAM;
9807         }
9808
9809         rpcbuf_move(q_u->buffer, &r_u->buffer);
9810         buffer = r_u->buffer;
9811
9812         DEBUG(5,("_spoolss_getprintprocessordirectory\n"));
9813
9814         *needed=0;
9815
9816         switch(level) {
9817         case 1:
9818                 result = getprintprocessordirectory_level_1
9819                   (&q_u->name, &q_u->environment, buffer, offered, needed);
9820                 break;
9821         default:
9822                 result = WERR_UNKNOWN_LEVEL;
9823         }
9824
9825         return result;
9826 }
9827
9828 /*******************************************************************
9829  ********************************************************************/
9830
9831 static bool push_monitorui_buf(TALLOC_CTX *mem_ctx, DATA_BLOB *buf,
9832                                const char *dllname)
9833 {
9834         enum ndr_err_code ndr_err;
9835         struct spoolss_MonitorUi ui;
9836
9837         ui.dll_name = dllname;
9838
9839         ndr_err = ndr_push_struct_blob(buf, mem_ctx, NULL, &ui,
9840                        (ndr_push_flags_fn_t)ndr_push_spoolss_MonitorUi);
9841         if (NDR_ERR_CODE_IS_SUCCESS(ndr_err) && (DEBUGLEVEL >= 10)) {
9842                 NDR_PRINT_DEBUG(spoolss_MonitorUi, &ui);
9843         }
9844         return NDR_ERR_CODE_IS_SUCCESS(ndr_err);
9845 }
9846
9847 /*******************************************************************
9848  Streams the monitor UI DLL name in UNICODE
9849 *******************************************************************/
9850
9851 static WERROR xcvtcp_monitorui(TALLOC_CTX *mem_ctx,
9852                                NT_USER_TOKEN *token, DATA_BLOB *in,
9853                                DATA_BLOB *out, uint32_t *needed)
9854 {
9855         const char *dllname = "tcpmonui.dll";
9856
9857         *needed = (strlen(dllname)+1) * 2;
9858
9859         if (out->length < *needed) {
9860                 return WERR_INSUFFICIENT_BUFFER;
9861         }
9862
9863         if (!push_monitorui_buf(mem_ctx, out, dllname)) {
9864                 return WERR_NOMEM;
9865         }
9866
9867         return WERR_OK;
9868 }
9869
9870 /*******************************************************************
9871  ********************************************************************/
9872
9873 static bool pull_port_data_1(TALLOC_CTX *mem_ctx,
9874                              struct spoolss_PortData1 *port1,
9875                              const DATA_BLOB *buf)
9876 {
9877         enum ndr_err_code ndr_err;
9878         ndr_err = ndr_pull_struct_blob(buf, mem_ctx, NULL, port1,
9879                        (ndr_pull_flags_fn_t)ndr_pull_spoolss_PortData1);
9880         if (NDR_ERR_CODE_IS_SUCCESS(ndr_err) && (DEBUGLEVEL >= 10)) {
9881                 NDR_PRINT_DEBUG(spoolss_PortData1, port1);
9882         }
9883         return NDR_ERR_CODE_IS_SUCCESS(ndr_err);
9884 }
9885
9886 /*******************************************************************
9887  ********************************************************************/
9888
9889 static bool pull_port_data_2(TALLOC_CTX *mem_ctx,
9890                              struct spoolss_PortData2 *port2,
9891                              const DATA_BLOB *buf)
9892 {
9893         enum ndr_err_code ndr_err;
9894         ndr_err = ndr_pull_struct_blob(buf, mem_ctx, NULL, port2,
9895                        (ndr_pull_flags_fn_t)ndr_pull_spoolss_PortData2);
9896         if (NDR_ERR_CODE_IS_SUCCESS(ndr_err) && (DEBUGLEVEL >= 10)) {
9897                 NDR_PRINT_DEBUG(spoolss_PortData2, port2);
9898         }
9899         return NDR_ERR_CODE_IS_SUCCESS(ndr_err);
9900 }
9901
9902 /*******************************************************************
9903  Create a new TCP/IP port
9904 *******************************************************************/
9905
9906 static WERROR xcvtcp_addport(TALLOC_CTX *mem_ctx,
9907                              NT_USER_TOKEN *token, DATA_BLOB *in,
9908                              DATA_BLOB *out, uint32_t *needed)
9909 {
9910         struct spoolss_PortData1 port1;
9911         struct spoolss_PortData2 port2;
9912         char *device_uri = NULL;
9913         uint32_t version;
9914
9915         const char *portname;
9916         const char *hostaddress;
9917         const char *queue;
9918         uint32_t port_number;
9919         uint32_t protocol;
9920
9921         /* peek for spoolss_PortData version */
9922
9923         if (!in || (in->length < (128 + 4))) {
9924                 return WERR_GENERAL_FAILURE;
9925         }
9926
9927         version = IVAL(in->data, 128);
9928
9929         switch (version) {
9930                 case 1:
9931                         ZERO_STRUCT(port1);
9932
9933                         if (!pull_port_data_1(mem_ctx, &port1, in)) {
9934                                 return WERR_NOMEM;
9935                         }
9936
9937                         portname        = port1.portname;
9938                         hostaddress     = port1.hostaddress;
9939                         queue           = port1.queue;
9940                         protocol        = port1.protocol;
9941                         port_number     = port1.port_number;
9942
9943                         break;
9944                 case 2:
9945                         ZERO_STRUCT(port2);
9946
9947                         if (!pull_port_data_2(mem_ctx, &port2, in)) {
9948                                 return WERR_NOMEM;
9949                         }
9950
9951                         portname        = port2.portname;
9952                         hostaddress     = port2.hostaddress;
9953                         queue           = port2.queue;
9954                         protocol        = port2.protocol;
9955                         port_number     = port2.port_number;
9956
9957                         break;
9958                 default:
9959                         DEBUG(1,("xcvtcp_addport: "
9960                                 "unknown version of port_data: %d\n", version));
9961                         return WERR_UNKNOWN_PORT;
9962         }
9963
9964         /* create the device URI and call the add_port_hook() */
9965
9966         switch (protocol) {
9967         case PROTOCOL_RAWTCP_TYPE:
9968                 device_uri = talloc_asprintf(mem_ctx,
9969                                 "socket://%s:%d/", hostaddress,
9970                                 port_number);
9971                 break;
9972
9973         case PROTOCOL_LPR_TYPE:
9974                 device_uri = talloc_asprintf(mem_ctx,
9975                         "lpr://%s/%s", hostaddress, queue );
9976                 break;
9977
9978         default:
9979                 return WERR_UNKNOWN_PORT;
9980         }
9981
9982         if (!device_uri) {
9983                 return WERR_NOMEM;
9984         }
9985
9986         return add_port_hook(mem_ctx, token, portname, device_uri);
9987 }
9988
9989 /*******************************************************************
9990 *******************************************************************/
9991
9992 struct xcv_api_table xcvtcp_cmds[] = {
9993         { "MonitorUI",  xcvtcp_monitorui },
9994         { "AddPort",    xcvtcp_addport},
9995         { NULL,         NULL }
9996 };
9997
9998 static WERROR process_xcvtcp_command(TALLOC_CTX *mem_ctx,
9999                                      NT_USER_TOKEN *token, const char *command,
10000                                      DATA_BLOB *inbuf,
10001                                      DATA_BLOB *outbuf,
10002                                      uint32_t *needed )
10003 {
10004         int i;
10005
10006         DEBUG(10,("process_xcvtcp_command: Received command \"%s\"\n", command));
10007
10008         for ( i=0; xcvtcp_cmds[i].name; i++ ) {
10009                 if ( strcmp( command, xcvtcp_cmds[i].name ) == 0 )
10010                         return xcvtcp_cmds[i].fn(mem_ctx, token, inbuf, outbuf, needed);
10011         }
10012
10013         return WERR_BADFUNC;
10014 }
10015
10016 /*******************************************************************
10017 *******************************************************************/
10018 #if 0   /* don't support management using the "Local Port" monitor */
10019
10020 static WERROR xcvlocal_monitorui(TALLOC_CTX *mem_ctx,
10021                                  NT_USER_TOKEN *token, DATA_BLOB *in,
10022                                  DATA_BLOB *out, uint32_t *needed)
10023 {
10024         const char *dllname = "localui.dll";
10025
10026         *needed = (strlen(dllname)+1) * 2;
10027
10028         if (out->length < *needed) {
10029                 return WERR_INSUFFICIENT_BUFFER;
10030         }
10031
10032         if (!push_monitorui_buf(mem_ctx, out, dllname)) {
10033                 return WERR_NOMEM;
10034         }
10035
10036         return WERR_OK;
10037 }
10038
10039 /*******************************************************************
10040 *******************************************************************/
10041
10042 struct xcv_api_table xcvlocal_cmds[] = {
10043         { "MonitorUI",  xcvlocal_monitorui },
10044         { NULL,         NULL }
10045 };
10046 #else
10047 struct xcv_api_table xcvlocal_cmds[] = {
10048         { NULL,         NULL }
10049 };
10050 #endif
10051
10052
10053
10054 /*******************************************************************
10055 *******************************************************************/
10056
10057 static WERROR process_xcvlocal_command(TALLOC_CTX *mem_ctx,
10058                                        NT_USER_TOKEN *token, const char *command,
10059                                        DATA_BLOB *inbuf, DATA_BLOB *outbuf,
10060                                        uint32_t *needed)
10061 {
10062         int i;
10063
10064         DEBUG(10,("process_xcvlocal_command: Received command \"%s\"\n", command));
10065
10066         for ( i=0; xcvlocal_cmds[i].name; i++ ) {
10067                 if ( strcmp( command, xcvlocal_cmds[i].name ) == 0 )
10068                         return xcvlocal_cmds[i].fn(mem_ctx, token, inbuf, outbuf, needed);
10069         }
10070         return WERR_BADFUNC;
10071 }
10072
10073 /****************************************************************
10074  _spoolss_XcvData
10075 ****************************************************************/
10076
10077 WERROR _spoolss_XcvData(pipes_struct *p,
10078                         struct spoolss_XcvData *r)
10079 {
10080         Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
10081         DATA_BLOB out_data;
10082         WERROR werror;
10083
10084         if (!Printer) {
10085                 DEBUG(2,("_spoolss_XcvData: Invalid handle (%s:%u:%u).\n",
10086                         OUR_HANDLE(r->in.handle)));
10087                 return WERR_BADFID;
10088         }
10089
10090         /* Has to be a handle to the TCP/IP port monitor */
10091
10092         if ( !(Printer->printer_type & (SPLHND_PORTMON_LOCAL|SPLHND_PORTMON_TCP)) ) {
10093                 DEBUG(2,("_spoolss_XcvData: Call only valid for Port Monitors\n"));
10094                 return WERR_BADFID;
10095         }
10096
10097         /* requires administrative access to the server */
10098
10099         if ( !(Printer->access_granted & SERVER_ACCESS_ADMINISTER) ) {
10100                 DEBUG(2,("_spoolss_XcvData: denied by handle permissions.\n"));
10101                 return WERR_ACCESS_DENIED;
10102         }
10103
10104         /* Allocate the outgoing buffer */
10105
10106         if (r->in.out_data_size) {
10107                 out_data = data_blob_talloc_zero(p->mem_ctx, r->in.out_data_size);
10108                 if (out_data.data == NULL) {
10109                         return WERR_NOMEM;
10110                 }
10111         }
10112
10113         switch ( Printer->printer_type ) {
10114         case SPLHND_PORTMON_TCP:
10115                 werror = process_xcvtcp_command(p->mem_ctx,
10116                                                 p->server_info->ptok,
10117                                                 r->in.function_name,
10118                                                 &r->in.in_data, &out_data,
10119                                                 r->out.needed);
10120                 break;
10121         case SPLHND_PORTMON_LOCAL:
10122                 werror = process_xcvlocal_command(p->mem_ctx,
10123                                                   p->server_info->ptok,
10124                                                   r->in.function_name,
10125                                                   &r->in.in_data, &out_data,
10126                                                   r->out.needed);
10127                 break;
10128         default:
10129                 werror = WERR_INVALID_PRINT_MONITOR;
10130         }
10131
10132         if (!W_ERROR_IS_OK(werror)) {
10133                 return werror;
10134         }
10135
10136         *r->out.status_code = 0;
10137
10138         memcpy(r->out.out_data, out_data.data, out_data.length);
10139
10140         return WERR_OK;
10141 }
10142
10143 /****************************************************************
10144  _spoolss_AddPrintProcessor
10145 ****************************************************************/
10146
10147 WERROR _spoolss_AddPrintProcessor(pipes_struct *p,
10148                                   struct spoolss_AddPrintProcessor *r)
10149 {
10150         /* for now, just indicate success and ignore the add.  We'll
10151            automatically set the winprint processor for printer
10152            entries later.  Used to debug the LexMark Optra S 1855 PCL
10153            driver --jerry */
10154
10155         return WERR_OK;
10156 }
10157
10158 /****************************************************************
10159  _spoolss_EnumPrinters
10160 ****************************************************************/
10161
10162 WERROR _spoolss_EnumPrinters(pipes_struct *p,
10163                              struct spoolss_EnumPrinters *r)
10164 {
10165         p->rng_fault_state = true;
10166         return WERR_NOT_SUPPORTED;
10167 }
10168
10169 /****************************************************************
10170  _spoolss_GetJob
10171 ****************************************************************/
10172
10173 WERROR _spoolss_GetJob(pipes_struct *p,
10174                        struct spoolss_GetJob *r)
10175 {
10176         p->rng_fault_state = true;
10177         return WERR_NOT_SUPPORTED;
10178 }
10179
10180 /****************************************************************
10181  _spoolss_EnumJobs
10182 ****************************************************************/
10183
10184 WERROR _spoolss_EnumJobs(pipes_struct *p,
10185                          struct spoolss_EnumJobs *r)
10186 {
10187         p->rng_fault_state = true;
10188         return WERR_NOT_SUPPORTED;
10189 }
10190
10191 /****************************************************************
10192  _spoolss_AddPrinter
10193 ****************************************************************/
10194
10195 WERROR _spoolss_AddPrinter(pipes_struct *p,
10196                            struct spoolss_AddPrinter *r)
10197 {
10198         p->rng_fault_state = true;
10199         return WERR_NOT_SUPPORTED;
10200 }
10201
10202 /****************************************************************
10203  _spoolss_GetPrinter
10204 ****************************************************************/
10205
10206 WERROR _spoolss_GetPrinter(pipes_struct *p,
10207                            struct spoolss_GetPrinter *r)
10208 {
10209         p->rng_fault_state = true;
10210         return WERR_NOT_SUPPORTED;
10211 }
10212
10213 /****************************************************************
10214  _spoolss_AddPrinterDriver
10215 ****************************************************************/
10216
10217 WERROR _spoolss_AddPrinterDriver(pipes_struct *p,
10218                                  struct spoolss_AddPrinterDriver *r)
10219 {
10220         p->rng_fault_state = true;
10221         return WERR_NOT_SUPPORTED;
10222 }
10223
10224 /****************************************************************
10225  _spoolss_EnumPrinterDrivers
10226 ****************************************************************/
10227
10228 WERROR _spoolss_EnumPrinterDrivers(pipes_struct *p,
10229                                    struct spoolss_EnumPrinterDrivers *r)
10230 {
10231         p->rng_fault_state = true;
10232         return WERR_NOT_SUPPORTED;
10233 }
10234
10235 /****************************************************************
10236  _spoolss_GetPrinterDriver
10237 ****************************************************************/
10238
10239 WERROR _spoolss_GetPrinterDriver(pipes_struct *p,
10240                                  struct spoolss_GetPrinterDriver *r)
10241 {
10242         p->rng_fault_state = true;
10243         return WERR_NOT_SUPPORTED;
10244 }
10245
10246 /****************************************************************
10247  _spoolss_GetPrinterDriverDirectory
10248 ****************************************************************/
10249
10250 WERROR _spoolss_GetPrinterDriverDirectory(pipes_struct *p,
10251                                           struct spoolss_GetPrinterDriverDirectory *r)
10252 {
10253         p->rng_fault_state = true;
10254         return WERR_NOT_SUPPORTED;
10255 }
10256
10257 /****************************************************************
10258  _spoolss_EnumPrintProcessors
10259 ****************************************************************/
10260
10261 WERROR _spoolss_EnumPrintProcessors(pipes_struct *p,
10262                                     struct spoolss_EnumPrintProcessors *r)
10263 {
10264         p->rng_fault_state = true;
10265         return WERR_NOT_SUPPORTED;
10266 }
10267
10268 /****************************************************************
10269  _spoolss_GetPrintProcessorDirectory
10270 ****************************************************************/
10271
10272 WERROR _spoolss_GetPrintProcessorDirectory(pipes_struct *p,
10273                                            struct spoolss_GetPrintProcessorDirectory *r)
10274 {
10275         p->rng_fault_state = true;
10276         return WERR_NOT_SUPPORTED;
10277 }
10278
10279 /****************************************************************
10280  _spoolss_ReadPrinter
10281 ****************************************************************/
10282
10283 WERROR _spoolss_ReadPrinter(pipes_struct *p,
10284                             struct spoolss_ReadPrinter *r)
10285 {
10286         p->rng_fault_state = true;
10287         return WERR_NOT_SUPPORTED;
10288 }
10289
10290 /****************************************************************
10291  _spoolss_GetPrinterData
10292 ****************************************************************/
10293
10294 WERROR _spoolss_GetPrinterData(pipes_struct *p,
10295                                struct spoolss_GetPrinterData *r)
10296 {
10297         p->rng_fault_state = true;
10298         return WERR_NOT_SUPPORTED;
10299 }
10300
10301 /****************************************************************
10302  _spoolss_SetPrinterData
10303 ****************************************************************/
10304
10305 WERROR _spoolss_SetPrinterData(pipes_struct *p,
10306                                struct spoolss_SetPrinterData *r)
10307 {
10308         p->rng_fault_state = true;
10309         return WERR_NOT_SUPPORTED;
10310 }
10311
10312 /****************************************************************
10313  _spoolss_WaitForPrinterChange
10314 ****************************************************************/
10315
10316 WERROR _spoolss_WaitForPrinterChange(pipes_struct *p,
10317                                      struct spoolss_WaitForPrinterChange *r)
10318 {
10319         p->rng_fault_state = true;
10320         return WERR_NOT_SUPPORTED;
10321 }
10322
10323 /****************************************************************
10324  _spoolss_EnumForms
10325 ****************************************************************/
10326
10327 WERROR _spoolss_EnumForms(pipes_struct *p,
10328                           struct spoolss_EnumForms *r)
10329 {
10330         p->rng_fault_state = true;
10331         return WERR_NOT_SUPPORTED;
10332 }
10333
10334 /****************************************************************
10335  _spoolss_EnumPorts
10336 ****************************************************************/
10337
10338 WERROR _spoolss_EnumPorts(pipes_struct *p,
10339                           struct spoolss_EnumPorts *r)
10340 {
10341         p->rng_fault_state = true;
10342         return WERR_NOT_SUPPORTED;
10343 }
10344
10345 /****************************************************************
10346  _spoolss_EnumMonitors
10347 ****************************************************************/
10348
10349 WERROR _spoolss_EnumMonitors(pipes_struct *p,
10350                              struct spoolss_EnumMonitors *r)
10351 {
10352         p->rng_fault_state = true;
10353         return WERR_NOT_SUPPORTED;
10354 }
10355
10356 /****************************************************************
10357  _spoolss_AddPort
10358 ****************************************************************/
10359
10360 WERROR _spoolss_AddPort(pipes_struct *p,
10361                         struct spoolss_AddPort *r)
10362 {
10363         p->rng_fault_state = true;
10364         return WERR_NOT_SUPPORTED;
10365 }
10366
10367 /****************************************************************
10368  _spoolss_ConfigurePort
10369 ****************************************************************/
10370
10371 WERROR _spoolss_ConfigurePort(pipes_struct *p,
10372                               struct spoolss_ConfigurePort *r)
10373 {
10374         p->rng_fault_state = true;
10375         return WERR_NOT_SUPPORTED;
10376 }
10377
10378 /****************************************************************
10379  _spoolss_DeletePort
10380 ****************************************************************/
10381
10382 WERROR _spoolss_DeletePort(pipes_struct *p,
10383                            struct spoolss_DeletePort *r)
10384 {
10385         p->rng_fault_state = true;
10386         return WERR_NOT_SUPPORTED;
10387 }
10388
10389 /****************************************************************
10390  _spoolss_CreatePrinterIC
10391 ****************************************************************/
10392
10393 WERROR _spoolss_CreatePrinterIC(pipes_struct *p,
10394                                 struct spoolss_CreatePrinterIC *r)
10395 {
10396         p->rng_fault_state = true;
10397         return WERR_NOT_SUPPORTED;
10398 }
10399
10400 /****************************************************************
10401  _spoolss_PlayGDIScriptOnPrinterIC
10402 ****************************************************************/
10403
10404 WERROR _spoolss_PlayGDIScriptOnPrinterIC(pipes_struct *p,
10405                                          struct spoolss_PlayGDIScriptOnPrinterIC *r)
10406 {
10407         p->rng_fault_state = true;
10408         return WERR_NOT_SUPPORTED;
10409 }
10410
10411 /****************************************************************
10412  _spoolss_DeletePrinterIC
10413 ****************************************************************/
10414
10415 WERROR _spoolss_DeletePrinterIC(pipes_struct *p,
10416                                 struct spoolss_DeletePrinterIC *r)
10417 {
10418         p->rng_fault_state = true;
10419         return WERR_NOT_SUPPORTED;
10420 }
10421
10422 /****************************************************************
10423  _spoolss_AddPrinterConnection
10424 ****************************************************************/
10425
10426 WERROR _spoolss_AddPrinterConnection(pipes_struct *p,
10427                                      struct spoolss_AddPrinterConnection *r)
10428 {
10429         p->rng_fault_state = true;
10430         return WERR_NOT_SUPPORTED;
10431 }
10432
10433 /****************************************************************
10434  _spoolss_DeletePrinterConnection
10435 ****************************************************************/
10436
10437 WERROR _spoolss_DeletePrinterConnection(pipes_struct *p,
10438                                         struct spoolss_DeletePrinterConnection *r)
10439 {
10440         p->rng_fault_state = true;
10441         return WERR_NOT_SUPPORTED;
10442 }
10443
10444 /****************************************************************
10445  _spoolss_PrinterMessageBox
10446 ****************************************************************/
10447
10448 WERROR _spoolss_PrinterMessageBox(pipes_struct *p,
10449                                   struct spoolss_PrinterMessageBox *r)
10450 {
10451         p->rng_fault_state = true;
10452         return WERR_NOT_SUPPORTED;
10453 }
10454
10455 /****************************************************************
10456  _spoolss_AddMonitor
10457 ****************************************************************/
10458
10459 WERROR _spoolss_AddMonitor(pipes_struct *p,
10460                            struct spoolss_AddMonitor *r)
10461 {
10462         p->rng_fault_state = true;
10463         return WERR_NOT_SUPPORTED;
10464 }
10465
10466 /****************************************************************
10467  _spoolss_DeleteMonitor
10468 ****************************************************************/
10469
10470 WERROR _spoolss_DeleteMonitor(pipes_struct *p,
10471                               struct spoolss_DeleteMonitor *r)
10472 {
10473         p->rng_fault_state = true;
10474         return WERR_NOT_SUPPORTED;
10475 }
10476
10477 /****************************************************************
10478  _spoolss_DeletePrintProcessor
10479 ****************************************************************/
10480
10481 WERROR _spoolss_DeletePrintProcessor(pipes_struct *p,
10482                                      struct spoolss_DeletePrintProcessor *r)
10483 {
10484         p->rng_fault_state = true;
10485         return WERR_NOT_SUPPORTED;
10486 }
10487
10488 /****************************************************************
10489  _spoolss_AddPrintProvidor
10490 ****************************************************************/
10491
10492 WERROR _spoolss_AddPrintProvidor(pipes_struct *p,
10493                                  struct spoolss_AddPrintProvidor *r)
10494 {
10495         p->rng_fault_state = true;
10496         return WERR_NOT_SUPPORTED;
10497 }
10498
10499 /****************************************************************
10500  _spoolss_DeletePrintProvidor
10501 ****************************************************************/
10502
10503 WERROR _spoolss_DeletePrintProvidor(pipes_struct *p,
10504                                     struct spoolss_DeletePrintProvidor *r)
10505 {
10506         p->rng_fault_state = true;
10507         return WERR_NOT_SUPPORTED;
10508 }
10509
10510 /****************************************************************
10511  _spoolss_EnumPrintProcDataTypes
10512 ****************************************************************/
10513
10514 WERROR _spoolss_EnumPrintProcDataTypes(pipes_struct *p,
10515                                        struct spoolss_EnumPrintProcDataTypes *r)
10516 {
10517         p->rng_fault_state = true;
10518         return WERR_NOT_SUPPORTED;
10519 }
10520
10521 /****************************************************************
10522  _spoolss_GetPrinterDriver2
10523 ****************************************************************/
10524
10525 WERROR _spoolss_GetPrinterDriver2(pipes_struct *p,
10526                                   struct spoolss_GetPrinterDriver2 *r)
10527 {
10528         p->rng_fault_state = true;
10529         return WERR_NOT_SUPPORTED;
10530 }
10531
10532 /****************************************************************
10533  _spoolss_FindFirstPrinterChangeNotification
10534 ****************************************************************/
10535
10536 WERROR _spoolss_FindFirstPrinterChangeNotification(pipes_struct *p,
10537                                                    struct spoolss_FindFirstPrinterChangeNotification *r)
10538 {
10539         p->rng_fault_state = true;
10540         return WERR_NOT_SUPPORTED;
10541 }
10542
10543 /****************************************************************
10544  _spoolss_FindNextPrinterChangeNotification
10545 ****************************************************************/
10546
10547 WERROR _spoolss_FindNextPrinterChangeNotification(pipes_struct *p,
10548                                                   struct spoolss_FindNextPrinterChangeNotification *r)
10549 {
10550         p->rng_fault_state = true;
10551         return WERR_NOT_SUPPORTED;
10552 }
10553
10554 /****************************************************************
10555  _spoolss_RouterFindFirstPrinterChangeNotificationOld
10556 ****************************************************************/
10557
10558 WERROR _spoolss_RouterFindFirstPrinterChangeNotificationOld(pipes_struct *p,
10559                                                             struct spoolss_RouterFindFirstPrinterChangeNotificationOld *r)
10560 {
10561         p->rng_fault_state = true;
10562         return WERR_NOT_SUPPORTED;
10563 }
10564
10565 /****************************************************************
10566  _spoolss_ReplyOpenPrinter
10567 ****************************************************************/
10568
10569 WERROR _spoolss_ReplyOpenPrinter(pipes_struct *p,
10570                                  struct spoolss_ReplyOpenPrinter *r)
10571 {
10572         p->rng_fault_state = true;
10573         return WERR_NOT_SUPPORTED;
10574 }
10575
10576 /****************************************************************
10577  _spoolss_RouterReplyPrinter
10578 ****************************************************************/
10579
10580 WERROR _spoolss_RouterReplyPrinter(pipes_struct *p,
10581                                    struct spoolss_RouterReplyPrinter *r)
10582 {
10583         p->rng_fault_state = true;
10584         return WERR_NOT_SUPPORTED;
10585 }
10586
10587 /****************************************************************
10588  _spoolss_ReplyClosePrinter
10589 ****************************************************************/
10590
10591 WERROR _spoolss_ReplyClosePrinter(pipes_struct *p,
10592                                   struct spoolss_ReplyClosePrinter *r)
10593 {
10594         p->rng_fault_state = true;
10595         return WERR_NOT_SUPPORTED;
10596 }
10597
10598 /****************************************************************
10599  _spoolss_AddPortEx
10600 ****************************************************************/
10601
10602 WERROR _spoolss_AddPortEx(pipes_struct *p,
10603                           struct spoolss_AddPortEx *r)
10604 {
10605         p->rng_fault_state = true;
10606         return WERR_NOT_SUPPORTED;
10607 }
10608
10609 /****************************************************************
10610  _spoolss_RouterFindFirstPrinterChangeNotification
10611 ****************************************************************/
10612
10613 WERROR _spoolss_RouterFindFirstPrinterChangeNotification(pipes_struct *p,
10614                                                          struct spoolss_RouterFindFirstPrinterChangeNotification *r)
10615 {
10616         p->rng_fault_state = true;
10617         return WERR_NOT_SUPPORTED;
10618 }
10619
10620 /****************************************************************
10621  _spoolss_SpoolerInit
10622 ****************************************************************/
10623
10624 WERROR _spoolss_SpoolerInit(pipes_struct *p,
10625                             struct spoolss_SpoolerInit *r)
10626 {
10627         p->rng_fault_state = true;
10628         return WERR_NOT_SUPPORTED;
10629 }
10630
10631 /****************************************************************
10632  _spoolss_ResetPrinterEx
10633 ****************************************************************/
10634
10635 WERROR _spoolss_ResetPrinterEx(pipes_struct *p,
10636                                struct spoolss_ResetPrinterEx *r)
10637 {
10638         p->rng_fault_state = true;
10639         return WERR_NOT_SUPPORTED;
10640 }
10641
10642 /****************************************************************
10643  _spoolss_RemoteFindFirstPrinterChangeNotifyEx
10644 ****************************************************************/
10645
10646 WERROR _spoolss_RemoteFindFirstPrinterChangeNotifyEx(pipes_struct *p,
10647                                                      struct spoolss_RemoteFindFirstPrinterChangeNotifyEx *r)
10648 {
10649         p->rng_fault_state = true;
10650         return WERR_NOT_SUPPORTED;
10651 }
10652
10653 /****************************************************************
10654  _spoolss_RouterReplyPrinterEx
10655 ****************************************************************/
10656
10657 WERROR _spoolss_RouterReplyPrinterEx(pipes_struct *p,
10658                                      struct spoolss_RouterReplyPrinterEx *r)
10659 {
10660         p->rng_fault_state = true;
10661         return WERR_NOT_SUPPORTED;
10662 }
10663
10664 /****************************************************************
10665  _dcesrv_spoolss_RouterRefreshPrinterChangeNotify
10666 ****************************************************************/
10667
10668 WERROR _spoolss_RouterRefreshPrinterChangeNotify(pipes_struct *p,
10669                                                  struct spoolss_RouterRefreshPrinterChangeNotify *r)
10670 {
10671         p->rng_fault_state = true;
10672         return WERR_NOT_SUPPORTED;
10673 }
10674
10675 /****************************************************************
10676  _spoolss_44
10677 ****************************************************************/
10678
10679 WERROR _spoolss_44(pipes_struct *p,
10680                    struct spoolss_44 *r)
10681 {
10682         p->rng_fault_state = true;
10683         return WERR_NOT_SUPPORTED;
10684 }
10685
10686 /****************************************************************
10687  _spoolss_47
10688 ****************************************************************/
10689
10690 WERROR _spoolss_47(pipes_struct *p,
10691                    struct spoolss_47 *r)
10692 {
10693         p->rng_fault_state = true;
10694         return WERR_NOT_SUPPORTED;
10695 }
10696
10697 /****************************************************************
10698  _spoolss_EnumPrinterData
10699 ****************************************************************/
10700
10701 WERROR _spoolss_EnumPrinterData(pipes_struct *p,
10702                                 struct spoolss_EnumPrinterData *r)
10703 {
10704         p->rng_fault_state = true;
10705         return WERR_NOT_SUPPORTED;
10706 }
10707
10708 /****************************************************************
10709  _spoolss_4a
10710 ****************************************************************/
10711
10712 WERROR _spoolss_4a(pipes_struct *p,
10713                    struct spoolss_4a *r)
10714 {
10715         p->rng_fault_state = true;
10716         return WERR_NOT_SUPPORTED;
10717 }
10718
10719 /****************************************************************
10720  _spoolss_4b
10721 ****************************************************************/
10722
10723 WERROR _spoolss_4b(pipes_struct *p,
10724                    struct spoolss_4b *r)
10725 {
10726         p->rng_fault_state = true;
10727         return WERR_NOT_SUPPORTED;
10728 }
10729
10730 /****************************************************************
10731  _spoolss_4c
10732 ****************************************************************/
10733
10734 WERROR _spoolss_4c(pipes_struct *p,
10735                    struct spoolss_4c *r)
10736 {
10737         p->rng_fault_state = true;
10738         return WERR_NOT_SUPPORTED;
10739 }
10740
10741 /****************************************************************
10742  _spoolss_EnumPrinterDataEx
10743 ****************************************************************/
10744
10745 WERROR _spoolss_EnumPrinterDataEx(pipes_struct *p,
10746                                   struct spoolss_EnumPrinterDataEx *r)
10747 {
10748         p->rng_fault_state = true;
10749         return WERR_NOT_SUPPORTED;
10750 }
10751
10752 /****************************************************************
10753  _spoolss_EnumPrinterKey
10754 ****************************************************************/
10755
10756 WERROR _spoolss_EnumPrinterKey(pipes_struct *p,
10757                                struct spoolss_EnumPrinterKey *r)
10758 {
10759         p->rng_fault_state = true;
10760         return WERR_NOT_SUPPORTED;
10761 }
10762
10763 /****************************************************************
10764  _spoolss_53
10765 ****************************************************************/
10766
10767 WERROR _spoolss_53(pipes_struct *p,
10768                    struct spoolss_53 *r)
10769 {
10770         p->rng_fault_state = true;
10771         return WERR_NOT_SUPPORTED;
10772 }
10773
10774 /****************************************************************
10775  _spoolss_55
10776 ****************************************************************/
10777
10778 WERROR _spoolss_55(pipes_struct *p,
10779                    struct spoolss_55 *r)
10780 {
10781         p->rng_fault_state = true;
10782         return WERR_NOT_SUPPORTED;
10783 }
10784
10785 /****************************************************************
10786  _spoolss_56
10787 ****************************************************************/
10788
10789 WERROR _spoolss_56(pipes_struct *p,
10790                    struct spoolss_56 *r)
10791 {
10792         p->rng_fault_state = true;
10793         return WERR_NOT_SUPPORTED;
10794 }
10795
10796 /****************************************************************
10797  _spoolss_57
10798 ****************************************************************/
10799
10800 WERROR _spoolss_57(pipes_struct *p,
10801                    struct spoolss_57 *r)
10802 {
10803         p->rng_fault_state = true;
10804         return WERR_NOT_SUPPORTED;
10805 }
10806
10807 /****************************************************************
10808  _spoolss_AddPrinterDriverEx
10809 ****************************************************************/
10810
10811 WERROR _spoolss_AddPrinterDriverEx(pipes_struct *p,
10812                                    struct spoolss_AddPrinterDriverEx *r)
10813 {
10814         p->rng_fault_state = true;
10815         return WERR_NOT_SUPPORTED;
10816 }
10817
10818 /****************************************************************
10819  _spoolss_5a
10820 ****************************************************************/
10821
10822 WERROR _spoolss_5a(pipes_struct *p,
10823                    struct spoolss_5a *r)
10824 {
10825         p->rng_fault_state = true;
10826         return WERR_NOT_SUPPORTED;
10827 }
10828
10829 /****************************************************************
10830  _spoolss_5b
10831 ****************************************************************/
10832
10833 WERROR _spoolss_5b(pipes_struct *p,
10834                    struct spoolss_5b *r)
10835 {
10836         p->rng_fault_state = true;
10837         return WERR_NOT_SUPPORTED;
10838 }
10839
10840 /****************************************************************
10841  _spoolss_5c
10842 ****************************************************************/
10843
10844 WERROR _spoolss_5c(pipes_struct *p,
10845                    struct spoolss_5c *r)
10846 {
10847         p->rng_fault_state = true;
10848         return WERR_NOT_SUPPORTED;
10849 }
10850
10851 /****************************************************************
10852  _spoolss_5d
10853 ****************************************************************/
10854
10855 WERROR _spoolss_5d(pipes_struct *p,
10856                    struct spoolss_5d *r)
10857 {
10858         p->rng_fault_state = true;
10859         return WERR_NOT_SUPPORTED;
10860 }
10861
10862 /****************************************************************
10863  _spoolss_5e
10864 ****************************************************************/
10865
10866 WERROR _spoolss_5e(pipes_struct *p,
10867                    struct spoolss_5e *r)
10868 {
10869         p->rng_fault_state = true;
10870         return WERR_NOT_SUPPORTED;
10871 }
10872
10873 /****************************************************************
10874  _spoolss_5f
10875 ****************************************************************/
10876
10877 WERROR _spoolss_5f(pipes_struct *p,
10878                    struct spoolss_5f *r)
10879 {
10880         p->rng_fault_state = true;
10881         return WERR_NOT_SUPPORTED;
10882 }
10883