s3-spoolss: Fix Coverity ID #891 (UNINIT).
[ira/wip.git] / source3 / rpc_server / srv_spoolss_nt.c
1 /*
2  *  Unix SMB/CIFS implementation.
3  *  RPC Pipe client / server routines
4  *  Copyright (C) Andrew Tridgell              1992-2000,
5  *  Copyright (C) Luke Kenneth Casson Leighton 1996-2000,
6  *  Copyright (C) Jean François Micouleau      1998-2000,
7  *  Copyright (C) Jeremy Allison               2001-2002,
8  *  Copyright (C) Gerald Carter                2000-2004,
9  *  Copyright (C) Tim Potter                   2001-2002.
10  *
11  *  This program is free software; you can redistribute it and/or modify
12  *  it under the terms of the GNU General Public License as published by
13  *  the Free Software Foundation; either version 3 of the License, or
14  *  (at your option) any later version.
15  *
16  *  This program is distributed in the hope that it will be useful,
17  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
18  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19  *  GNU General Public License for more details.
20  *
21  *  You should have received a copy of the GNU General Public License
22  *  along with this program; if not, see <http://www.gnu.org/licenses/>.
23  */
24
25 /* Since the SPOOLSS rpc routines are basically DOS 16-bit calls wrapped
26    up, all the errors returned are DOS errors, not NT status codes. */
27
28 #include "includes.h"
29
30 extern userdom_struct current_user_info;
31
32 #undef DBGC_CLASS
33 #define DBGC_CLASS DBGC_RPC_SRV
34
35 #ifndef MAX_OPEN_PRINTER_EXS
36 #define MAX_OPEN_PRINTER_EXS 50
37 #endif
38
39 #define MAGIC_DISPLAY_FREQUENCY 0xfade2bad
40 #define PHANTOM_DEVMODE_KEY "_p_f_a_n_t_0_m_"
41
42 struct table_node {
43         const char    *long_archi;
44         const char    *short_archi;
45         int     version;
46 };
47
48 static Printer_entry *printers_list;
49
50 typedef struct _counter_printer_0 {
51         struct _counter_printer_0 *next;
52         struct _counter_printer_0 *prev;
53
54         int snum;
55         uint32 counter;
56 } counter_printer_0;
57
58 static counter_printer_0 *counter_list;
59
60 static struct rpc_pipe_client *notify_cli_pipe; /* print notify back-channel pipe handle*/
61 static uint32 smb_connections=0;
62
63
64 /* in printing/nt_printing.c */
65
66 extern struct standard_mapping printer_std_mapping, printserver_std_mapping;
67
68 /* API table for Xcv Monitor functions */
69
70 struct xcv_api_table {
71         const char *name;
72         WERROR(*fn) (TALLOC_CTX *mem_ctx, NT_USER_TOKEN *token, DATA_BLOB *in, DATA_BLOB *out, uint32_t *needed);
73 };
74
75 /********************************************************************
76  * Canonicalize servername.
77  ********************************************************************/
78
79 static const char *canon_servername(const char *servername)
80 {
81         const char *pservername = servername;
82         while (*pservername == '\\') {
83                 pservername++;
84         }
85         return pservername;
86 }
87
88 /* translate between internal status numbers and NT status numbers */
89 static int nt_printj_status(int v)
90 {
91         switch (v) {
92         case LPQ_QUEUED:
93                 return 0;
94         case LPQ_PAUSED:
95                 return JOB_STATUS_PAUSED;
96         case LPQ_SPOOLING:
97                 return JOB_STATUS_SPOOLING;
98         case LPQ_PRINTING:
99                 return JOB_STATUS_PRINTING;
100         case LPQ_ERROR:
101                 return JOB_STATUS_ERROR;
102         case LPQ_DELETING:
103                 return JOB_STATUS_DELETING;
104         case LPQ_OFFLINE:
105                 return JOB_STATUS_OFFLINE;
106         case LPQ_PAPEROUT:
107                 return JOB_STATUS_PAPEROUT;
108         case LPQ_PRINTED:
109                 return JOB_STATUS_PRINTED;
110         case LPQ_DELETED:
111                 return JOB_STATUS_DELETED;
112         case LPQ_BLOCKED:
113                 return JOB_STATUS_BLOCKED_DEVQ;
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  Disconnect from the client
135 ****************************************************************************/
136
137 static void srv_spoolss_replycloseprinter(int snum, POLICY_HND *handle)
138 {
139         WERROR result;
140         NTSTATUS status;
141
142         /*
143          * Tell the specific printing tdb we no longer want messages for this printer
144          * by deregistering our PID.
145          */
146
147         if (!print_notify_deregister_pid(snum))
148                 DEBUG(0,("print_notify_register_pid: Failed to register our pid for printer %s\n", lp_const_servicename(snum) ));
149
150         /* weird if the test succeds !!! */
151         if (smb_connections==0) {
152                 DEBUG(0,("srv_spoolss_replycloseprinter:Trying to close non-existant notify backchannel !\n"));
153                 return;
154         }
155
156         status = rpccli_spoolss_ReplyClosePrinter(notify_cli_pipe, talloc_tos(),
157                                                   handle,
158                                                   &result);
159         if (!NT_STATUS_IS_OK(status) || !W_ERROR_IS_OK(result))
160                 DEBUG(0,("srv_spoolss_replycloseprinter: reply_close_printer failed [%s].\n",
161                         win_errstr(result)));
162
163         /* if it's the last connection, deconnect the IPC$ share */
164         if (smb_connections==1) {
165
166                 cli_shutdown( rpc_pipe_np_smb_conn(notify_cli_pipe) );
167                 notify_cli_pipe = NULL; /* The above call shuts downn the pipe also. */
168
169                 messaging_deregister(smbd_messaging_context(),
170                                      MSG_PRINTER_NOTIFY2, NULL);
171
172                 /* Tell the connections db we're no longer interested in
173                  * printer notify messages. */
174
175                 register_message_flags( False, FLAG_MSG_PRINT_NOTIFY );
176         }
177
178         smb_connections--;
179 }
180
181 /****************************************************************************
182  Functions to free a printer entry datastruct.
183 ****************************************************************************/
184
185 static int printer_entry_destructor(Printer_entry *Printer)
186 {
187         if (Printer->notify.client_connected==True) {
188                 int snum = -1;
189
190                 if ( Printer->printer_type == SPLHND_SERVER) {
191                         snum = -1;
192                         srv_spoolss_replycloseprinter(snum, &Printer->notify.client_hnd);
193                 } else if (Printer->printer_type == SPLHND_PRINTER) {
194                         snum = print_queue_snum(Printer->sharename);
195                         if (snum != -1)
196                                 srv_spoolss_replycloseprinter(snum,
197                                                 &Printer->notify.client_hnd);
198                 }
199         }
200
201         Printer->notify.flags=0;
202         Printer->notify.options=0;
203         Printer->notify.localmachine[0]='\0';
204         Printer->notify.printerlocal=0;
205         TALLOC_FREE(Printer->notify.option);
206         Printer->notify.client_connected=False;
207
208         free_nt_devicemode( &Printer->nt_devmode );
209         free_a_printer( &Printer->printer_info, 2 );
210
211         /* Remove from the internal list. */
212         DLIST_REMOVE(printers_list, Printer);
213         return 0;
214 }
215
216 /****************************************************************************
217   find printer index by handle
218 ****************************************************************************/
219
220 static Printer_entry *find_printer_index_by_hnd(pipes_struct *p, POLICY_HND *hnd)
221 {
222         Printer_entry *find_printer = NULL;
223
224         if(!find_policy_by_hnd(p,hnd,(void **)(void *)&find_printer)) {
225                 DEBUG(2,("find_printer_index_by_hnd: Printer handle not found: "));
226                 return NULL;
227         }
228
229         return find_printer;
230 }
231
232 /****************************************************************************
233  Close printer index by handle.
234 ****************************************************************************/
235
236 static bool close_printer_handle(pipes_struct *p, POLICY_HND *hnd)
237 {
238         Printer_entry *Printer = find_printer_index_by_hnd(p, hnd);
239
240         if (!Printer) {
241                 DEBUG(2,("close_printer_handle: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(hnd)));
242                 return False;
243         }
244
245         close_policy_hnd(p, hnd);
246
247         return True;
248 }
249
250 /****************************************************************************
251  Delete a printer given a handle.
252 ****************************************************************************/
253
254 WERROR delete_printer_hook(TALLOC_CTX *ctx, NT_USER_TOKEN *token, const char *sharename )
255 {
256         char *cmd = lp_deleteprinter_cmd();
257         char *command = NULL;
258         int ret;
259         SE_PRIV se_printop = SE_PRINT_OPERATOR;
260         bool is_print_op = False;
261
262         /* can't fail if we don't try */
263
264         if ( !*cmd )
265                 return WERR_OK;
266
267         command = talloc_asprintf(ctx,
268                         "%s \"%s\"",
269                         cmd, sharename);
270         if (!command) {
271                 return WERR_NOMEM;
272         }
273         if ( token )
274                 is_print_op = user_has_privileges( token, &se_printop );
275
276         DEBUG(10,("Running [%s]\n", command));
277
278         /********** BEGIN SePrintOperatorPrivlege BLOCK **********/
279
280         if ( is_print_op )
281                 become_root();
282
283         if ( (ret = smbrun(command, NULL)) == 0 ) {
284                 /* Tell everyone we updated smb.conf. */
285                 message_send_all(smbd_messaging_context(),
286                                  MSG_SMB_CONF_UPDATED, NULL, 0, NULL);
287         }
288
289         if ( is_print_op )
290                 unbecome_root();
291
292         /********** END SePrintOperatorPrivlege BLOCK **********/
293
294         DEBUGADD(10,("returned [%d]\n", ret));
295
296         TALLOC_FREE(command);
297
298         if (ret != 0)
299                 return WERR_BADFID; /* What to return here? */
300
301         /* go ahead and re-read the services immediately */
302         reload_services( False );
303
304         if ( lp_servicenumber( sharename )  < 0 )
305                 return WERR_ACCESS_DENIED;
306
307         return WERR_OK;
308 }
309
310 /****************************************************************************
311  Delete a printer given a handle.
312 ****************************************************************************/
313
314 static WERROR delete_printer_handle(pipes_struct *p, POLICY_HND *hnd)
315 {
316         Printer_entry *Printer = find_printer_index_by_hnd(p, hnd);
317
318         if (!Printer) {
319                 DEBUG(2,("delete_printer_handle: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(hnd)));
320                 return WERR_BADFID;
321         }
322
323         /*
324          * It turns out that Windows allows delete printer on a handle
325          * opened by an admin user, then used on a pipe handle created
326          * by an anonymous user..... but they're working on security.... riiight !
327          * JRA.
328          */
329
330         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
331                 DEBUG(3, ("delete_printer_handle: denied by handle\n"));
332                 return WERR_ACCESS_DENIED;
333         }
334
335         /* this does not need a become root since the access check has been
336            done on the handle already */
337
338         if (del_a_printer( Printer->sharename ) != 0) {
339                 DEBUG(3,("Error deleting printer %s\n", Printer->sharename));
340                 return WERR_BADFID;
341         }
342
343         return delete_printer_hook(p->mem_ctx, p->server_info->ptok,
344                                    Printer->sharename );
345 }
346
347 /****************************************************************************
348  Return the snum of a printer corresponding to an handle.
349 ****************************************************************************/
350
351 static bool get_printer_snum(pipes_struct *p, POLICY_HND *hnd, int *number,
352                              struct share_params **params)
353 {
354         Printer_entry *Printer = find_printer_index_by_hnd(p, hnd);
355
356         if (!Printer) {
357                 DEBUG(2,("get_printer_snum: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(hnd)));
358                 return False;
359         }
360
361         switch (Printer->printer_type) {
362                 case SPLHND_PRINTER:
363                         DEBUG(4,("short name:%s\n", Printer->sharename));
364                         *number = print_queue_snum(Printer->sharename);
365                         return (*number != -1);
366                 case SPLHND_SERVER:
367                         return False;
368                 default:
369                         return False;
370         }
371 }
372
373 /****************************************************************************
374  Set printer handle type.
375  Check if it's \\server or \\server\printer
376 ****************************************************************************/
377
378 static bool set_printer_hnd_printertype(Printer_entry *Printer, char *handlename)
379 {
380         DEBUG(3,("Setting printer type=%s\n", handlename));
381
382         if ( strlen(handlename) < 3 ) {
383                 DEBUGADD(4,("A print server must have at least 1 char ! %s\n", handlename));
384                 return False;
385         }
386
387         /* it's a print server */
388         if (*handlename=='\\' && *(handlename+1)=='\\' && !strchr_m(handlename+2, '\\')) {
389                 DEBUGADD(4,("Printer is a print server\n"));
390                 Printer->printer_type = SPLHND_SERVER;
391         }
392         /* it's a printer (set_printer_hnd_name() will handle port monitors */
393         else {
394                 DEBUGADD(4,("Printer is a printer\n"));
395                 Printer->printer_type = SPLHND_PRINTER;
396         }
397
398         return True;
399 }
400
401 /****************************************************************************
402  Set printer handle name..  Accept names like \\server, \\server\printer,
403  \\server\SHARE, & "\\server\,XcvMonitor Standard TCP/IP Port"    See
404  the MSDN docs regarding OpenPrinter() for details on the XcvData() and
405  XcvDataPort() interface.
406 ****************************************************************************/
407
408 static bool set_printer_hnd_name(Printer_entry *Printer, char *handlename)
409 {
410         int snum;
411         int n_services=lp_numservices();
412         char *aprinter, *printername;
413         const char *servername;
414         fstring sname;
415         bool found=False;
416         NT_PRINTER_INFO_LEVEL *printer = NULL;
417         WERROR result;
418
419         DEBUG(4,("Setting printer name=%s (len=%lu)\n", handlename, (unsigned long)strlen(handlename)));
420
421         aprinter = handlename;
422         if ( *handlename == '\\' ) {
423                 servername = canon_servername(handlename);
424                 if ( (aprinter = strchr_m( servername, '\\' )) != NULL ) {
425                         *aprinter = '\0';
426                         aprinter++;
427                 }
428         } else {
429                 servername = "";
430         }
431
432         /* save the servername to fill in replies on this handle */
433
434         if ( !is_myname_or_ipaddr( servername ) )
435                 return False;
436
437         fstrcpy( Printer->servername, servername );
438
439         if ( Printer->printer_type == SPLHND_SERVER )
440                 return True;
441
442         if ( Printer->printer_type != SPLHND_PRINTER )
443                 return False;
444
445         DEBUGADD(5, ("searching for [%s]\n", aprinter ));
446
447         /* check for the Port Monitor Interface */
448
449         if ( strequal( aprinter, SPL_XCV_MONITOR_TCPMON ) ) {
450                 Printer->printer_type = SPLHND_PORTMON_TCP;
451                 fstrcpy(sname, SPL_XCV_MONITOR_TCPMON);
452                 found = True;
453         }
454         else if ( strequal( aprinter, SPL_XCV_MONITOR_LOCALMON ) ) {
455                 Printer->printer_type = SPLHND_PORTMON_LOCAL;
456                 fstrcpy(sname, SPL_XCV_MONITOR_LOCALMON);
457                 found = True;
458         }
459
460         /* Search all sharenames first as this is easier than pulling
461            the printer_info_2 off of disk. Don't use find_service() since
462            that calls out to map_username() */
463
464         /* do another loop to look for printernames */
465
466         for (snum=0; !found && snum<n_services; snum++) {
467
468                 /* no point going on if this is not a printer */
469
470                 if ( !(lp_snum_ok(snum) && lp_print_ok(snum)) )
471                         continue;
472
473                 fstrcpy(sname, lp_servicename(snum));
474                 if ( strequal( aprinter, sname ) ) {
475                         found = True;
476                         break;
477                 }
478
479                 /* no point looking up the printer object if
480                    we aren't allowing printername != sharename */
481
482                 if ( lp_force_printername(snum) )
483                         continue;
484
485                 fstrcpy(sname, lp_servicename(snum));
486
487                 printer = NULL;
488
489                 /* This call doesn't fill in the location or comment from
490                  * a CUPS server for efficiency with large numbers of printers.
491                  * JRA.
492                  */
493
494                 result = get_a_printer_search( NULL, &printer, 2, sname );
495                 if ( !W_ERROR_IS_OK(result) ) {
496                         DEBUG(0,("set_printer_hnd_name: failed to lookup printer [%s] -- result [%s]\n",
497                                 sname, win_errstr(result)));
498                         continue;
499                 }
500
501                 /* printername is always returned as \\server\printername */
502                 if ( !(printername = strchr_m(&printer->info_2->printername[2], '\\')) ) {
503                         DEBUG(0,("set_printer_hnd_name: info2->printername in wrong format! [%s]\n",
504                                 printer->info_2->printername));
505                         free_a_printer( &printer, 2);
506                         continue;
507                 }
508
509                 printername++;
510
511                 if ( strequal(printername, aprinter) ) {
512                         free_a_printer( &printer, 2);
513                         found = True;
514                         break;
515                 }
516
517                 DEBUGADD(10, ("printername: %s\n", printername));
518
519                 free_a_printer( &printer, 2);
520         }
521
522         free_a_printer( &printer, 2);
523
524         if ( !found ) {
525                 DEBUGADD(4,("Printer not found\n"));
526                 return False;
527         }
528
529         DEBUGADD(4,("set_printer_hnd_name: Printer found: %s -> %s\n", aprinter, sname));
530
531         fstrcpy(Printer->sharename, sname);
532
533         return True;
534 }
535
536 /****************************************************************************
537  Find first available printer slot. creates a printer handle for you.
538  ****************************************************************************/
539
540 static bool open_printer_hnd(pipes_struct *p, POLICY_HND *hnd, char *name, uint32 access_granted)
541 {
542         Printer_entry *new_printer;
543
544         DEBUG(10,("open_printer_hnd: name [%s]\n", name));
545
546         new_printer = TALLOC_ZERO_P(NULL, Printer_entry);
547         if (new_printer == NULL) {
548                 return false;
549         }
550         talloc_set_destructor(new_printer, printer_entry_destructor);
551
552         if (!create_policy_hnd(p, hnd, new_printer)) {
553                 TALLOC_FREE(new_printer);
554                 return False;
555         }
556
557         /* Add to the internal list. */
558         DLIST_ADD(printers_list, new_printer);
559
560         new_printer->notify.option=NULL;
561
562         if (!set_printer_hnd_printertype(new_printer, name)) {
563                 close_printer_handle(p, hnd);
564                 return False;
565         }
566
567         if (!set_printer_hnd_name(new_printer, name)) {
568                 close_printer_handle(p, hnd);
569                 return False;
570         }
571
572         new_printer->access_granted = access_granted;
573
574         DEBUG(5, ("%d printer handles active\n", (int)p->pipe_handles->count ));
575
576         return True;
577 }
578
579 /***************************************************************************
580  check to see if the client motify handle is monitoring the notification
581  given by (notify_type, notify_field).
582  **************************************************************************/
583
584 static bool is_monitoring_event_flags(uint32 flags, uint16 notify_type,
585                                       uint16 notify_field)
586 {
587         return True;
588 }
589
590 static bool is_monitoring_event(Printer_entry *p, uint16 notify_type,
591                                 uint16 notify_field)
592 {
593         struct spoolss_NotifyOption *option = p->notify.option;
594         uint32 i, j;
595
596         /*
597          * Flags should always be zero when the change notify
598          * is registered by the client's spooler.  A user Win32 app
599          * might use the flags though instead of the NOTIFY_OPTION_INFO
600          * --jerry
601          */
602
603         if (!option) {
604                 return False;
605         }
606
607         if (p->notify.flags)
608                 return is_monitoring_event_flags(
609                         p->notify.flags, notify_type, notify_field);
610
611         for (i = 0; i < option->count; i++) {
612
613                 /* Check match for notify_type */
614
615                 if (option->types[i].type != notify_type)
616                         continue;
617
618                 /* Check match for field */
619
620                 for (j = 0; j < option->types[i].count; j++) {
621                         if (option->types[i].fields[j] == notify_field) {
622                                 return True;
623                         }
624                 }
625         }
626
627         DEBUG(10, ("Open handle for \\\\%s\\%s is not monitoring 0x%02x/0x%02x\n",
628                    p->servername, p->sharename, notify_type, notify_field));
629
630         return False;
631 }
632
633 #define SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(_data, _integer) \
634         _data->data.integer[0] = _integer; \
635         _data->data.integer[1] = 0;
636
637
638 #define SETUP_SPOOLSS_NOTIFY_DATA_STRING(_data, _p) \
639         _data->data.string.string = talloc_strdup(mem_ctx, _p); \
640         if (!_data->data.string.string) {\
641                 _data->data.string.size = 0; \
642         } \
643         _data->data.string.size = strlen_m_term(_p) * 2;
644
645 #define SETUP_SPOOLSS_NOTIFY_DATA_DEVMODE(_data, _devmode) \
646         _data->data.devmode.devmode = _devmode;
647
648 #define SETUP_SPOOLSS_NOTIFY_DATA_SECDESC(_data, _size, _sd) \
649         _data->data.sd.sd = dup_sec_desc(mem_ctx, _sd); \
650         if (!_data->data.sd.sd) { \
651                 _data->data.sd.sd_size = 0; \
652         } \
653         _data->data.sd.sd_size = _size;
654
655 static void init_systemtime_buffer(TALLOC_CTX *mem_ctx,
656                                    struct tm *t,
657                                    const char **pp,
658                                    uint32_t *plen)
659 {
660         struct spoolss_Time st;
661         uint32_t len = 16;
662         char *p;
663
664         if (!init_systemtime(&st, t)) {
665                 return;
666         }
667
668         p = talloc_array(mem_ctx, char, len);
669         if (!p) {
670                 return;
671         }
672
673         /*
674          * Systemtime must be linearized as a set of UINT16's.
675          * Fix from Benjamin (Bj) Kuit bj@it.uts.edu.au
676          */
677
678         SSVAL(p, 0, st.year);
679         SSVAL(p, 2, st.month);
680         SSVAL(p, 4, st.day_of_week);
681         SSVAL(p, 6, st.day);
682         SSVAL(p, 8, st.hour);
683         SSVAL(p, 10, st.minute);
684         SSVAL(p, 12, st.second);
685         SSVAL(p, 14, st.millisecond);
686
687         *pp = p;
688         *plen = len;
689 }
690
691 /* Convert a notification message to a struct spoolss_Notify */
692
693 static void notify_one_value(struct spoolss_notify_msg *msg,
694                              struct spoolss_Notify *data,
695                              TALLOC_CTX *mem_ctx)
696 {
697         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, msg->notify.value[0]);
698 }
699
700 static void notify_string(struct spoolss_notify_msg *msg,
701                           struct spoolss_Notify *data,
702                           TALLOC_CTX *mem_ctx)
703 {
704         /* The length of the message includes the trailing \0 */
705
706         data->data.string.size = msg->len * 2;
707         data->data.string.string = talloc_strdup(mem_ctx, msg->notify.data);
708         if (!data->data.string.string) {
709                 data->data.string.size = 0;
710                 return;
711         }
712 }
713
714 static void notify_system_time(struct spoolss_notify_msg *msg,
715                                struct spoolss_Notify *data,
716                                TALLOC_CTX *mem_ctx)
717 {
718         data->data.string.string = NULL;
719         data->data.string.size = 0;
720
721         if (msg->len != sizeof(time_t)) {
722                 DEBUG(5, ("notify_system_time: received wrong sized message (%d)\n",
723                           msg->len));
724                 return;
725         }
726
727         init_systemtime_buffer(mem_ctx, gmtime((time_t *)msg->notify.data),
728                                &data->data.string.string,
729                                &data->data.string.size);
730 }
731
732 struct notify2_message_table {
733         const char *name;
734         void (*fn)(struct spoolss_notify_msg *msg,
735                    struct spoolss_Notify *data, TALLOC_CTX *mem_ctx);
736 };
737
738 static struct notify2_message_table printer_notify_table[] = {
739         /* 0x00 */ { "PRINTER_NOTIFY_SERVER_NAME", notify_string },
740         /* 0x01 */ { "PRINTER_NOTIFY_PRINTER_NAME", notify_string },
741         /* 0x02 */ { "PRINTER_NOTIFY_SHARE_NAME", notify_string },
742         /* 0x03 */ { "PRINTER_NOTIFY_PORT_NAME", notify_string },
743         /* 0x04 */ { "PRINTER_NOTIFY_DRIVER_NAME", notify_string },
744         /* 0x05 */ { "PRINTER_NOTIFY_COMMENT", notify_string },
745         /* 0x06 */ { "PRINTER_NOTIFY_LOCATION", notify_string },
746         /* 0x07 */ { "PRINTER_NOTIFY_DEVMODE", NULL },
747         /* 0x08 */ { "PRINTER_NOTIFY_SEPFILE", notify_string },
748         /* 0x09 */ { "PRINTER_NOTIFY_PRINT_PROCESSOR", notify_string },
749         /* 0x0a */ { "PRINTER_NOTIFY_PARAMETERS", NULL },
750         /* 0x0b */ { "PRINTER_NOTIFY_DATATYPE", notify_string },
751         /* 0x0c */ { "PRINTER_NOTIFY_SECURITY_DESCRIPTOR", NULL },
752         /* 0x0d */ { "PRINTER_NOTIFY_ATTRIBUTES", notify_one_value },
753         /* 0x0e */ { "PRINTER_NOTIFY_PRIORITY", notify_one_value },
754         /* 0x0f */ { "PRINTER_NOTIFY_DEFAULT_PRIORITY", NULL },
755         /* 0x10 */ { "PRINTER_NOTIFY_START_TIME", NULL },
756         /* 0x11 */ { "PRINTER_NOTIFY_UNTIL_TIME", NULL },
757         /* 0x12 */ { "PRINTER_NOTIFY_STATUS", notify_one_value },
758 };
759
760 static struct notify2_message_table job_notify_table[] = {
761         /* 0x00 */ { "JOB_NOTIFY_PRINTER_NAME", NULL },
762         /* 0x01 */ { "JOB_NOTIFY_MACHINE_NAME", NULL },
763         /* 0x02 */ { "JOB_NOTIFY_PORT_NAME", NULL },
764         /* 0x03 */ { "JOB_NOTIFY_USER_NAME", notify_string },
765         /* 0x04 */ { "JOB_NOTIFY_NOTIFY_NAME", NULL },
766         /* 0x05 */ { "JOB_NOTIFY_DATATYPE", NULL },
767         /* 0x06 */ { "JOB_NOTIFY_PRINT_PROCESSOR", NULL },
768         /* 0x07 */ { "JOB_NOTIFY_PARAMETERS", NULL },
769         /* 0x08 */ { "JOB_NOTIFY_DRIVER_NAME", NULL },
770         /* 0x09 */ { "JOB_NOTIFY_DEVMODE", NULL },
771         /* 0x0a */ { "JOB_NOTIFY_STATUS", notify_one_value },
772         /* 0x0b */ { "JOB_NOTIFY_STATUS_STRING", NULL },
773         /* 0x0c */ { "JOB_NOTIFY_SECURITY_DESCRIPTOR", NULL },
774         /* 0x0d */ { "JOB_NOTIFY_DOCUMENT", notify_string },
775         /* 0x0e */ { "JOB_NOTIFY_PRIORITY", NULL },
776         /* 0x0f */ { "JOB_NOTIFY_POSITION", NULL },
777         /* 0x10 */ { "JOB_NOTIFY_SUBMITTED", notify_system_time },
778         /* 0x11 */ { "JOB_NOTIFY_START_TIME", NULL },
779         /* 0x12 */ { "JOB_NOTIFY_UNTIL_TIME", NULL },
780         /* 0x13 */ { "JOB_NOTIFY_TIME", NULL },
781         /* 0x14 */ { "JOB_NOTIFY_TOTAL_PAGES", notify_one_value },
782         /* 0x15 */ { "JOB_NOTIFY_PAGES_PRINTED", NULL },
783         /* 0x16 */ { "JOB_NOTIFY_TOTAL_BYTES", notify_one_value },
784         /* 0x17 */ { "JOB_NOTIFY_BYTES_PRINTED", NULL },
785 };
786
787
788 /***********************************************************************
789  Allocate talloc context for container object
790  **********************************************************************/
791
792 static void notify_msg_ctr_init( SPOOLSS_NOTIFY_MSG_CTR *ctr )
793 {
794         if ( !ctr )
795                 return;
796
797         ctr->ctx = talloc_init("notify_msg_ctr_init %p", ctr);
798
799         return;
800 }
801
802 /***********************************************************************
803  release all allocated memory and zero out structure
804  **********************************************************************/
805
806 static void notify_msg_ctr_destroy( SPOOLSS_NOTIFY_MSG_CTR *ctr )
807 {
808         if ( !ctr )
809                 return;
810
811         if ( ctr->ctx )
812                 talloc_destroy(ctr->ctx);
813
814         ZERO_STRUCTP(ctr);
815
816         return;
817 }
818
819 /***********************************************************************
820  **********************************************************************/
821
822 static TALLOC_CTX* notify_ctr_getctx( SPOOLSS_NOTIFY_MSG_CTR *ctr )
823 {
824         if ( !ctr )
825                 return NULL;
826
827         return ctr->ctx;
828 }
829
830 /***********************************************************************
831  **********************************************************************/
832
833 static SPOOLSS_NOTIFY_MSG_GROUP* notify_ctr_getgroup( SPOOLSS_NOTIFY_MSG_CTR *ctr, uint32 idx )
834 {
835         if ( !ctr || !ctr->msg_groups )
836                 return NULL;
837
838         if ( idx >= ctr->num_groups )
839                 return NULL;
840
841         return &ctr->msg_groups[idx];
842
843 }
844
845 /***********************************************************************
846  How many groups of change messages do we have ?
847  **********************************************************************/
848
849 static int notify_msg_ctr_numgroups( SPOOLSS_NOTIFY_MSG_CTR *ctr )
850 {
851         if ( !ctr )
852                 return 0;
853
854         return ctr->num_groups;
855 }
856
857 /***********************************************************************
858  Add a SPOOLSS_NOTIFY_MSG_CTR to the correct group
859  **********************************************************************/
860
861 static int notify_msg_ctr_addmsg( SPOOLSS_NOTIFY_MSG_CTR *ctr, SPOOLSS_NOTIFY_MSG *msg )
862 {
863         SPOOLSS_NOTIFY_MSG_GROUP        *groups = NULL;
864         SPOOLSS_NOTIFY_MSG_GROUP        *msg_grp = NULL;
865         SPOOLSS_NOTIFY_MSG              *msg_list = NULL;
866         int                             i, new_slot;
867
868         if ( !ctr || !msg )
869                 return 0;
870
871         /* loop over all groups looking for a matching printer name */
872
873         for ( i=0; i<ctr->num_groups; i++ ) {
874                 if ( strcmp(ctr->msg_groups[i].printername, msg->printer) == 0 )
875                         break;
876         }
877
878         /* add a new group? */
879
880         if ( i == ctr->num_groups ) {
881                 ctr->num_groups++;
882
883                 if ( !(groups = TALLOC_REALLOC_ARRAY( ctr->ctx, ctr->msg_groups, SPOOLSS_NOTIFY_MSG_GROUP, ctr->num_groups)) ) {
884                         DEBUG(0,("notify_msg_ctr_addmsg: talloc_realloc() failed!\n"));
885                         return 0;
886                 }
887                 ctr->msg_groups = groups;
888
889                 /* clear the new entry and set the printer name */
890
891                 ZERO_STRUCT( ctr->msg_groups[ctr->num_groups-1] );
892                 fstrcpy( ctr->msg_groups[ctr->num_groups-1].printername, msg->printer );
893         }
894
895         /* add the change messages; 'i' is the correct index now regardless */
896
897         msg_grp = &ctr->msg_groups[i];
898
899         msg_grp->num_msgs++;
900
901         if ( !(msg_list = TALLOC_REALLOC_ARRAY( ctr->ctx, msg_grp->msgs, SPOOLSS_NOTIFY_MSG, msg_grp->num_msgs )) ) {
902                 DEBUG(0,("notify_msg_ctr_addmsg: talloc_realloc() failed for new message [%d]!\n", msg_grp->num_msgs));
903                 return 0;
904         }
905         msg_grp->msgs = msg_list;
906
907         new_slot = msg_grp->num_msgs-1;
908         memcpy( &msg_grp->msgs[new_slot], msg, sizeof(SPOOLSS_NOTIFY_MSG) );
909
910         /* need to allocate own copy of data */
911
912         if ( msg->len != 0 )
913                 msg_grp->msgs[new_slot].notify.data = (char *)
914                         TALLOC_MEMDUP( ctr->ctx, msg->notify.data, msg->len );
915
916         return ctr->num_groups;
917 }
918
919 /***********************************************************************
920  Send a change notication message on all handles which have a call
921  back registered
922  **********************************************************************/
923
924 static void send_notify2_changes( SPOOLSS_NOTIFY_MSG_CTR *ctr, uint32 idx )
925 {
926         Printer_entry            *p;
927         TALLOC_CTX               *mem_ctx = notify_ctr_getctx( ctr );
928         SPOOLSS_NOTIFY_MSG_GROUP *msg_group = notify_ctr_getgroup( ctr, idx );
929         SPOOLSS_NOTIFY_MSG       *messages;
930         int                      sending_msg_count;
931
932         if ( !msg_group ) {
933                 DEBUG(5,("send_notify2_changes() called with no msg group!\n"));
934                 return;
935         }
936
937         messages = msg_group->msgs;
938
939         if ( !messages ) {
940                 DEBUG(5,("send_notify2_changes() called with no messages!\n"));
941                 return;
942         }
943
944         DEBUG(8,("send_notify2_changes: Enter...[%s]\n", msg_group->printername));
945
946         /* loop over all printers */
947
948         for (p = printers_list; p; p = p->next) {
949                 struct spoolss_Notify *notifies;
950                 uint32_t count = 0;
951                 uint32_t id;
952                 int     i;
953
954                 /* Is there notification on this handle? */
955
956                 if ( !p->notify.client_connected )
957                         continue;
958
959                 DEBUG(10,("Client connected! [\\\\%s\\%s]\n", p->servername, p->sharename));
960
961                 /* For this printer?  Print servers always receive
962                    notifications. */
963
964                 if ( ( p->printer_type == SPLHND_PRINTER )  &&
965                     ( !strequal(msg_group->printername, p->sharename) ) )
966                         continue;
967
968                 DEBUG(10,("Our printer\n"));
969
970                 /* allocate the max entries possible */
971
972                 notifies = TALLOC_ZERO_ARRAY(mem_ctx, struct spoolss_Notify, msg_group->num_msgs);
973                 if (!notifies) {
974                         return;
975                 }
976
977                 /* build the array of change notifications */
978
979                 sending_msg_count = 0;
980
981                 for ( i=0; i<msg_group->num_msgs; i++ ) {
982                         SPOOLSS_NOTIFY_MSG      *msg = &messages[i];
983
984                         /* Are we monitoring this event? */
985
986                         if (!is_monitoring_event(p, msg->type, msg->field))
987                                 continue;
988
989                         sending_msg_count++;
990
991
992                         DEBUG(10,("process_notify2_message: Sending message type [0x%x] field [0x%2x] for printer [%s]\n",
993                                 msg->type, msg->field, p->sharename));
994
995                         /*
996                          * if the is a printer notification handle and not a job notification
997                          * type, then set the id to 0.  Other wise just use what was specified
998                          * in the message.
999                          *
1000                          * When registering change notification on a print server handle
1001                          * we always need to send back the id (snum) matching the printer
1002                          * for which the change took place.  For change notify registered
1003                          * on a printer handle, this does not matter and the id should be 0.
1004                          *
1005                          * --jerry
1006                          */
1007
1008                         if ( ( p->printer_type == SPLHND_PRINTER ) && ( msg->type == PRINTER_NOTIFY_TYPE ) )
1009                                 id = 0;
1010                         else
1011                                 id = msg->id;
1012
1013
1014                         /* Convert unix jobid to smb jobid */
1015
1016                         if (msg->flags & SPOOLSS_NOTIFY_MSG_UNIX_JOBID) {
1017                                 id = sysjob_to_jobid(msg->id);
1018
1019                                 if (id == -1) {
1020                                         DEBUG(3, ("no such unix jobid %d\n", msg->id));
1021                                         goto done;
1022                                 }
1023                         }
1024
1025                         construct_info_data( &notifies[count], msg->type, msg->field, id );
1026
1027                         switch(msg->type) {
1028                         case PRINTER_NOTIFY_TYPE:
1029                                 if ( printer_notify_table[msg->field].fn )
1030                                         printer_notify_table[msg->field].fn(msg, &notifies[count], mem_ctx);
1031                                 break;
1032
1033                         case JOB_NOTIFY_TYPE:
1034                                 if ( job_notify_table[msg->field].fn )
1035                                         job_notify_table[msg->field].fn(msg, &notifies[count], mem_ctx);
1036                                 break;
1037
1038                         default:
1039                                 DEBUG(5, ("Unknown notification type %d\n", msg->type));
1040                                 goto done;
1041                         }
1042
1043                         count++;
1044                 }
1045
1046                 if ( sending_msg_count ) {
1047                         NTSTATUS status;
1048                         WERROR werr;
1049                         union spoolss_ReplyPrinterInfo info;
1050                         struct spoolss_NotifyInfo info0;
1051                         uint32_t reply_result;
1052
1053                         info0.version   = 0x2;
1054                         info0.flags     = count ? 0x00020000 /* ??? */ : PRINTER_NOTIFY_INFO_DISCARDED;
1055                         info0.count     = count;
1056                         info0.notifies  = notifies;
1057
1058                         info.info0 = &info0;
1059
1060                         status = rpccli_spoolss_RouterReplyPrinterEx(notify_cli_pipe, mem_ctx,
1061                                                                      &p->notify.client_hnd,
1062                                                                      p->notify.change, /* color */
1063                                                                      p->notify.flags,
1064                                                                      &reply_result,
1065                                                                      0, /* reply_type, must be 0 */
1066                                                                      info,
1067                                                                      &werr);
1068                         if (!NT_STATUS_IS_OK(status) || !W_ERROR_IS_OK(werr)) {
1069                                 DEBUG(1,("RouterReplyPrinterEx to client: %s failed: %s\n",
1070                                         notify_cli_pipe->srv_name_slash,
1071                                         win_errstr(werr)));
1072                         }
1073                         switch (reply_result) {
1074                                 case 0:
1075                                         break;
1076                                 case PRINTER_NOTIFY_INFO_DISCARDED:
1077                                 case PRINTER_NOTIFY_INFO_DISCARDNOTED:
1078                                 case PRINTER_NOTIFY_INFO_COLOR_MISMATCH:
1079                                         break;
1080                                 default:
1081                                         break;
1082                         }
1083                 }
1084         }
1085
1086 done:
1087         DEBUG(8,("send_notify2_changes: Exit...\n"));
1088         return;
1089 }
1090
1091 /***********************************************************************
1092  **********************************************************************/
1093
1094 static bool notify2_unpack_msg( SPOOLSS_NOTIFY_MSG *msg, struct timeval *tv, void *buf, size_t len )
1095 {
1096
1097         uint32 tv_sec, tv_usec;
1098         size_t offset = 0;
1099
1100         /* Unpack message */
1101
1102         offset += tdb_unpack((uint8 *)buf + offset, len - offset, "f",
1103                              msg->printer);
1104
1105         offset += tdb_unpack((uint8 *)buf + offset, len - offset, "ddddddd",
1106                                 &tv_sec, &tv_usec,
1107                                 &msg->type, &msg->field, &msg->id, &msg->len, &msg->flags);
1108
1109         if (msg->len == 0)
1110                 tdb_unpack((uint8 *)buf + offset, len - offset, "dd",
1111                            &msg->notify.value[0], &msg->notify.value[1]);
1112         else
1113                 tdb_unpack((uint8 *)buf + offset, len - offset, "B",
1114                            &msg->len, &msg->notify.data);
1115
1116         DEBUG(3, ("notify2_unpack_msg: got NOTIFY2 message for printer %s, jobid %u type %d, field 0x%02x, flags 0x%04x\n",
1117                   msg->printer, (unsigned int)msg->id, msg->type, msg->field, msg->flags));
1118
1119         tv->tv_sec = tv_sec;
1120         tv->tv_usec = tv_usec;
1121
1122         if (msg->len == 0)
1123                 DEBUG(3, ("notify2_unpack_msg: value1 = %d, value2 = %d\n", msg->notify.value[0],
1124                           msg->notify.value[1]));
1125         else
1126                 dump_data(3, (uint8 *)msg->notify.data, msg->len);
1127
1128         return True;
1129 }
1130
1131 /********************************************************************
1132  Receive a notify2 message list
1133  ********************************************************************/
1134
1135 static void receive_notify2_message_list(struct messaging_context *msg,
1136                                          void *private_data,
1137                                          uint32_t msg_type,
1138                                          struct server_id server_id,
1139                                          DATA_BLOB *data)
1140 {
1141         size_t                  msg_count, i;
1142         char                    *buf = (char *)data->data;
1143         char                    *msg_ptr;
1144         size_t                  msg_len;
1145         SPOOLSS_NOTIFY_MSG      notify;
1146         SPOOLSS_NOTIFY_MSG_CTR  messages;
1147         int                     num_groups;
1148
1149         if (data->length < 4) {
1150                 DEBUG(0,("receive_notify2_message_list: bad message format (len < 4)!\n"));
1151                 return;
1152         }
1153
1154         msg_count = IVAL(buf, 0);
1155         msg_ptr = buf + 4;
1156
1157         DEBUG(5, ("receive_notify2_message_list: got %lu messages in list\n", (unsigned long)msg_count));
1158
1159         if (msg_count == 0) {
1160                 DEBUG(0,("receive_notify2_message_list: bad message format (msg_count == 0) !\n"));
1161                 return;
1162         }
1163
1164         /* initialize the container */
1165
1166         ZERO_STRUCT( messages );
1167         notify_msg_ctr_init( &messages );
1168
1169         /*
1170          * build message groups for each printer identified
1171          * in a change_notify msg.  Remember that a PCN message
1172          * includes the handle returned for the srv_spoolss_replyopenprinter()
1173          * call.  Therefore messages are grouped according to printer handle.
1174          */
1175
1176         for ( i=0; i<msg_count; i++ ) {
1177                 struct timeval msg_tv;
1178
1179                 if (msg_ptr + 4 - buf > data->length) {
1180                         DEBUG(0,("receive_notify2_message_list: bad message format (len > buf_size) !\n"));
1181                         return;
1182                 }
1183
1184                 msg_len = IVAL(msg_ptr,0);
1185                 msg_ptr += 4;
1186
1187                 if (msg_ptr + msg_len - buf > data->length) {
1188                         DEBUG(0,("receive_notify2_message_list: bad message format (bad len) !\n"));
1189                         return;
1190                 }
1191
1192                 /* unpack messages */
1193
1194                 ZERO_STRUCT( notify );
1195                 notify2_unpack_msg( &notify, &msg_tv, msg_ptr, msg_len );
1196                 msg_ptr += msg_len;
1197
1198                 /* add to correct list in container */
1199
1200                 notify_msg_ctr_addmsg( &messages, &notify );
1201
1202                 /* free memory that might have been allocated by notify2_unpack_msg() */
1203
1204                 if ( notify.len != 0 )
1205                         SAFE_FREE( notify.notify.data );
1206         }
1207
1208         /* process each group of messages */
1209
1210         num_groups = notify_msg_ctr_numgroups( &messages );
1211         for ( i=0; i<num_groups; i++ )
1212                 send_notify2_changes( &messages, i );
1213
1214
1215         /* cleanup */
1216
1217         DEBUG(10,("receive_notify2_message_list: processed %u messages\n", (uint32)msg_count ));
1218
1219         notify_msg_ctr_destroy( &messages );
1220
1221         return;
1222 }
1223
1224 /********************************************************************
1225  Send a message to ourself about new driver being installed
1226  so we can upgrade the information for each printer bound to this
1227  driver
1228  ********************************************************************/
1229
1230 static bool srv_spoolss_drv_upgrade_printer(char* drivername)
1231 {
1232         int len = strlen(drivername);
1233
1234         if (!len)
1235                 return False;
1236
1237         DEBUG(10,("srv_spoolss_drv_upgrade_printer: Sending message about driver upgrade [%s]\n",
1238                 drivername));
1239
1240         messaging_send_buf(smbd_messaging_context(), procid_self(),
1241                            MSG_PRINTER_DRVUPGRADE,
1242                            (uint8 *)drivername, len+1);
1243
1244         return True;
1245 }
1246
1247 /**********************************************************************
1248  callback to receive a MSG_PRINTER_DRVUPGRADE message and interate
1249  over all printers, upgrading ones as necessary
1250  **********************************************************************/
1251
1252 void do_drv_upgrade_printer(struct messaging_context *msg,
1253                             void *private_data,
1254                             uint32_t msg_type,
1255                             struct server_id server_id,
1256                             DATA_BLOB *data)
1257 {
1258         fstring drivername;
1259         int snum;
1260         int n_services = lp_numservices();
1261         size_t len;
1262
1263         len = MIN(data->length,sizeof(drivername)-1);
1264         strncpy(drivername, (const char *)data->data, len);
1265
1266         DEBUG(10,("do_drv_upgrade_printer: Got message for new driver [%s]\n", drivername ));
1267
1268         /* Iterate the printer list */
1269
1270         for (snum=0; snum<n_services; snum++)
1271         {
1272                 if (lp_snum_ok(snum) && lp_print_ok(snum) )
1273                 {
1274                         WERROR result;
1275                         NT_PRINTER_INFO_LEVEL *printer = NULL;
1276
1277                         result = get_a_printer(NULL, &printer, 2, lp_const_servicename(snum));
1278                         if (!W_ERROR_IS_OK(result))
1279                                 continue;
1280
1281                         if (printer && printer->info_2 && !strcmp(drivername, printer->info_2->drivername))
1282                         {
1283                                 DEBUG(6,("Updating printer [%s]\n", printer->info_2->printername));
1284
1285                                 /* all we care about currently is the change_id */
1286
1287                                 result = mod_a_printer(printer, 2);
1288                                 if (!W_ERROR_IS_OK(result)) {
1289                                         DEBUG(3,("do_drv_upgrade_printer: mod_a_printer() failed with status [%s]\n",
1290                                                 win_errstr(result)));
1291                                 }
1292                         }
1293
1294                         free_a_printer(&printer, 2);
1295                 }
1296         }
1297
1298         /* all done */
1299 }
1300
1301 /********************************************************************
1302  Update the cache for all printq's with a registered client
1303  connection
1304  ********************************************************************/
1305
1306 void update_monitored_printq_cache( void )
1307 {
1308         Printer_entry *printer = printers_list;
1309         int snum;
1310
1311         /* loop through all printers and update the cache where
1312            client_connected == True */
1313         while ( printer )
1314         {
1315                 if ( (printer->printer_type == SPLHND_PRINTER)
1316                         && printer->notify.client_connected )
1317                 {
1318                         snum = print_queue_snum(printer->sharename);
1319                         print_queue_status( snum, NULL, NULL );
1320                 }
1321
1322                 printer = printer->next;
1323         }
1324
1325         return;
1326 }
1327 /********************************************************************
1328  Send a message to ourself about new driver being installed
1329  so we can upgrade the information for each printer bound to this
1330  driver
1331  ********************************************************************/
1332
1333 static bool srv_spoolss_reset_printerdata(char* drivername)
1334 {
1335         int len = strlen(drivername);
1336
1337         if (!len)
1338                 return False;
1339
1340         DEBUG(10,("srv_spoolss_reset_printerdata: Sending message about resetting printerdata [%s]\n",
1341                 drivername));
1342
1343         messaging_send_buf(smbd_messaging_context(), procid_self(),
1344                            MSG_PRINTERDATA_INIT_RESET,
1345                            (uint8 *)drivername, len+1);
1346
1347         return True;
1348 }
1349
1350 /**********************************************************************
1351  callback to receive a MSG_PRINTERDATA_INIT_RESET message and interate
1352  over all printers, resetting printer data as neessary
1353  **********************************************************************/
1354
1355 void reset_all_printerdata(struct messaging_context *msg,
1356                            void *private_data,
1357                            uint32_t msg_type,
1358                            struct server_id server_id,
1359                            DATA_BLOB *data)
1360 {
1361         fstring drivername;
1362         int snum;
1363         int n_services = lp_numservices();
1364         size_t len;
1365
1366         len = MIN( data->length, sizeof(drivername)-1 );
1367         strncpy( drivername, (const char *)data->data, len );
1368
1369         DEBUG(10,("reset_all_printerdata: Got message for new driver [%s]\n", drivername ));
1370
1371         /* Iterate the printer list */
1372
1373         for ( snum=0; snum<n_services; snum++ )
1374         {
1375                 if ( lp_snum_ok(snum) && lp_print_ok(snum) )
1376                 {
1377                         WERROR result;
1378                         NT_PRINTER_INFO_LEVEL *printer = NULL;
1379
1380                         result = get_a_printer( NULL, &printer, 2, lp_const_servicename(snum) );
1381                         if ( !W_ERROR_IS_OK(result) )
1382                                 continue;
1383
1384                         /*
1385                          * if the printer is bound to the driver,
1386                          * then reset to the new driver initdata
1387                          */
1388
1389                         if ( printer && printer->info_2 && !strcmp(drivername, printer->info_2->drivername) )
1390                         {
1391                                 DEBUG(6,("reset_all_printerdata: Updating printer [%s]\n", printer->info_2->printername));
1392
1393                                 if ( !set_driver_init(printer, 2) ) {
1394                                         DEBUG(5,("reset_all_printerdata: Error resetting printer data for printer [%s], driver [%s]!\n",
1395                                                 printer->info_2->printername, printer->info_2->drivername));
1396                                 }
1397
1398                                 result = mod_a_printer( printer, 2 );
1399                                 if ( !W_ERROR_IS_OK(result) ) {
1400                                         DEBUG(3,("reset_all_printerdata: mod_a_printer() failed!  (%s)\n",
1401                                                 get_dos_error_msg(result)));
1402                                 }
1403                         }
1404
1405                         free_a_printer( &printer, 2 );
1406                 }
1407         }
1408
1409         /* all done */
1410
1411         return;
1412 }
1413
1414 /****************************************************************
1415  _spoolss_OpenPrinter
1416 ****************************************************************/
1417
1418 WERROR _spoolss_OpenPrinter(pipes_struct *p,
1419                             struct spoolss_OpenPrinter *r)
1420 {
1421         struct spoolss_OpenPrinterEx e;
1422         WERROR werr;
1423
1424         ZERO_STRUCT(e.in.userlevel);
1425
1426         e.in.printername        = r->in.printername;
1427         e.in.datatype           = r->in.datatype;
1428         e.in.devmode_ctr        = r->in.devmode_ctr;
1429         e.in.access_mask        = r->in.access_mask;
1430         e.in.level              = 0;
1431
1432         e.out.handle            = r->out.handle;
1433
1434         werr = _spoolss_OpenPrinterEx(p, &e);
1435
1436         if (W_ERROR_EQUAL(werr, WERR_INVALID_PARAM)) {
1437                 /* OpenPrinterEx returns this for a bad
1438                  * printer name. We must return WERR_INVALID_PRINTER_NAME
1439                  * instead.
1440                  */
1441                 werr = WERR_INVALID_PRINTER_NAME;
1442         }
1443
1444         return werr;
1445 }
1446
1447 /********************************************************************
1448  FIXME: temporary convert_devicemode_new function
1449  ********************************************************************/
1450
1451 static bool convert_devicemode_new(const char *printername,
1452                                    struct spoolss_DeviceMode *devmode,
1453                                    NT_DEVICEMODE **pp_nt_devmode)
1454 {
1455         NT_DEVICEMODE *nt_devmode = *pp_nt_devmode;
1456
1457         /*
1458          * Ensure nt_devmode is a valid pointer
1459          * as we will be overwriting it.
1460          */
1461
1462         if (nt_devmode == NULL) {
1463                 DEBUG(5, ("convert_devicemode_new: allocating a generic devmode\n"));
1464                 if ((nt_devmode = construct_nt_devicemode(printername)) == NULL)
1465                         return false;
1466         }
1467
1468         rpcstr_push(nt_devmode->devicename, devmode->devicename, 31, 0);
1469         rpcstr_push(nt_devmode->formname, devmode->formname, 31, 0);
1470
1471         nt_devmode->specversion         = devmode->specversion;
1472         nt_devmode->driverversion       = devmode->driverversion;
1473         nt_devmode->size                = devmode->size;
1474         nt_devmode->fields              = devmode->fields;
1475         nt_devmode->orientation         = devmode->orientation;
1476         nt_devmode->papersize           = devmode->papersize;
1477         nt_devmode->paperlength         = devmode->paperlength;
1478         nt_devmode->paperwidth          = devmode->paperwidth;
1479         nt_devmode->scale               = devmode->scale;
1480         nt_devmode->copies              = devmode->copies;
1481         nt_devmode->defaultsource       = devmode->defaultsource;
1482         nt_devmode->printquality        = devmode->printquality;
1483         nt_devmode->color               = devmode->color;
1484         nt_devmode->duplex              = devmode->duplex;
1485         nt_devmode->yresolution         = devmode->yresolution;
1486         nt_devmode->ttoption            = devmode->ttoption;
1487         nt_devmode->collate             = devmode->collate;
1488
1489         nt_devmode->logpixels           = devmode->logpixels;
1490         nt_devmode->bitsperpel          = devmode->bitsperpel;
1491         nt_devmode->pelswidth           = devmode->pelswidth;
1492         nt_devmode->pelsheight          = devmode->pelsheight;
1493         nt_devmode->displayflags        = devmode->displayflags;
1494         nt_devmode->displayfrequency    = devmode->displayfrequency;
1495         nt_devmode->icmmethod           = devmode->icmmethod;
1496         nt_devmode->icmintent           = devmode->icmintent;
1497         nt_devmode->mediatype           = devmode->mediatype;
1498         nt_devmode->dithertype          = devmode->dithertype;
1499         nt_devmode->reserved1           = devmode->reserved1;
1500         nt_devmode->reserved2           = devmode->reserved2;
1501         nt_devmode->panningwidth        = devmode->panningwidth;
1502         nt_devmode->panningheight       = devmode->panningheight;
1503
1504         /*
1505          * Only change private and driverextra if the incoming devmode
1506          * has a new one. JRA.
1507          */
1508
1509         if ((devmode->__driverextra_length != 0) && (devmode->driverextra_data.data != NULL)) {
1510                 SAFE_FREE(nt_devmode->nt_dev_private);
1511                 nt_devmode->driverextra = devmode->__driverextra_length;
1512                 if((nt_devmode->nt_dev_private=SMB_MALLOC_ARRAY(uint8, nt_devmode->driverextra)) == NULL)
1513                         return false;
1514                 memcpy(nt_devmode->nt_dev_private, devmode->driverextra_data.data, nt_devmode->driverextra);
1515         }
1516
1517         *pp_nt_devmode = nt_devmode;
1518
1519         return true;
1520 }
1521
1522 /****************************************************************
1523  _spoolss_OpenPrinterEx
1524 ****************************************************************/
1525
1526 WERROR _spoolss_OpenPrinterEx(pipes_struct *p,
1527                               struct spoolss_OpenPrinterEx *r)
1528 {
1529         POLICY_HND              *handle = r->out.handle;
1530         char *name = CONST_DISCARD(char *, r->in.printername);
1531         int snum;
1532         Printer_entry *Printer=NULL;
1533
1534         if (!name) {
1535                 return WERR_INVALID_PARAM;
1536         }
1537
1538         /* some sanity check because you can open a printer or a print server */
1539         /* aka: \\server\printer or \\server */
1540
1541         DEBUGADD(3,("checking name: %s\n",name));
1542
1543         if (!open_printer_hnd(p, handle, name, 0)) {
1544                 ZERO_STRUCTP(r->out.handle);
1545                 return WERR_INVALID_PARAM;
1546         }
1547
1548         Printer=find_printer_index_by_hnd(p, handle);
1549         if ( !Printer ) {
1550                 DEBUG(0,("_spoolss_OpenPrinterEx: logic error.  Can't find printer "
1551                         "handle we created for printer %s\n", name ));
1552                 close_printer_handle(p,handle);
1553                 ZERO_STRUCTP(r->out.handle);
1554                 return WERR_INVALID_PARAM;
1555         }
1556
1557         /*
1558          * First case: the user is opening the print server:
1559          *
1560          * Disallow MS AddPrinterWizard if parameter disables it. A Win2k
1561          * client 1st tries an OpenPrinterEx with access==0, MUST be allowed.
1562          *
1563          * Then both Win2k and WinNT clients try an OpenPrinterEx with
1564          * SERVER_ALL_ACCESS, which we allow only if the user is root (uid=0)
1565          * or if the user is listed in the smb.conf printer admin parameter.
1566          *
1567          * Then they try OpenPrinterEx with SERVER_READ which we allow. This lets the
1568          * client view printer folder, but does not show the MSAPW.
1569          *
1570          * Note: this test needs code to check access rights here too. Jeremy
1571          * could you look at this?
1572          *
1573          * Second case: the user is opening a printer:
1574          * NT doesn't let us connect to a printer if the connecting user
1575          * doesn't have print permission.
1576          *
1577          * Third case: user is opening a Port Monitor
1578          * access checks same as opening a handle to the print server.
1579          */
1580
1581         switch (Printer->printer_type )
1582         {
1583         case SPLHND_SERVER:
1584         case SPLHND_PORTMON_TCP:
1585         case SPLHND_PORTMON_LOCAL:
1586                 /* Printserver handles use global struct... */
1587
1588                 snum = -1;
1589
1590                 /* Map standard access rights to object specific access rights */
1591
1592                 se_map_standard(&r->in.access_mask,
1593                                 &printserver_std_mapping);
1594
1595                 /* Deny any object specific bits that don't apply to print
1596                    servers (i.e printer and job specific bits) */
1597
1598                 r->in.access_mask &= SPECIFIC_RIGHTS_MASK;
1599
1600                 if (r->in.access_mask &
1601                     ~(SERVER_ACCESS_ADMINISTER | SERVER_ACCESS_ENUMERATE)) {
1602                         DEBUG(3, ("access DENIED for non-printserver bits\n"));
1603                         close_printer_handle(p, handle);
1604                         ZERO_STRUCTP(r->out.handle);
1605                         return WERR_ACCESS_DENIED;
1606                 }
1607
1608                 /* Allow admin access */
1609
1610                 if ( r->in.access_mask & SERVER_ACCESS_ADMINISTER )
1611                 {
1612                         SE_PRIV se_printop = SE_PRINT_OPERATOR;
1613
1614                         if (!lp_ms_add_printer_wizard()) {
1615                                 close_printer_handle(p, handle);
1616                                 ZERO_STRUCTP(r->out.handle);
1617                                 return WERR_ACCESS_DENIED;
1618                         }
1619
1620                         /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
1621                            and not a printer admin, then fail */
1622
1623                         if ((p->server_info->utok.uid != 0) &&
1624                             !user_has_privileges(p->server_info->ptok,
1625                                                  &se_printop ) &&
1626                             !token_contains_name_in_list(
1627                                     uidtoname(p->server_info->utok.uid),
1628                                     NULL, NULL,
1629                                     p->server_info->ptok,
1630                                     lp_printer_admin(snum))) {
1631                                 close_printer_handle(p, handle);
1632                                 ZERO_STRUCTP(r->out.handle);
1633                                 return WERR_ACCESS_DENIED;
1634                         }
1635
1636                         r->in.access_mask = SERVER_ACCESS_ADMINISTER;
1637                 }
1638                 else
1639                 {
1640                         r->in.access_mask = SERVER_ACCESS_ENUMERATE;
1641                 }
1642
1643                 DEBUG(4,("Setting print server access = %s\n", (r->in.access_mask == SERVER_ACCESS_ADMINISTER)
1644                         ? "SERVER_ACCESS_ADMINISTER" : "SERVER_ACCESS_ENUMERATE" ));
1645
1646                 /* We fall through to return WERR_OK */
1647                 break;
1648
1649         case SPLHND_PRINTER:
1650                 /* NT doesn't let us connect to a printer if the connecting user
1651                    doesn't have print permission.  */
1652
1653                 if (!get_printer_snum(p, handle, &snum, NULL)) {
1654                         close_printer_handle(p, handle);
1655                         ZERO_STRUCTP(r->out.handle);
1656                         return WERR_BADFID;
1657                 }
1658
1659                 se_map_standard(&r->in.access_mask, &printer_std_mapping);
1660
1661                 /* map an empty access mask to the minimum access mask */
1662                 if (r->in.access_mask == 0x0)
1663                         r->in.access_mask = PRINTER_ACCESS_USE;
1664
1665                 /*
1666                  * If we are not serving the printer driver for this printer,
1667                  * map PRINTER_ACCESS_ADMINISTER to PRINTER_ACCESS_USE.  This
1668                  * will keep NT clients happy  --jerry
1669                  */
1670
1671                 if (lp_use_client_driver(snum)
1672                         && (r->in.access_mask & PRINTER_ACCESS_ADMINISTER))
1673                 {
1674                         r->in.access_mask = PRINTER_ACCESS_USE;
1675                 }
1676
1677                 /* check smb.conf parameters and the the sec_desc */
1678
1679                 if ( !check_access(get_client_fd(), lp_hostsallow(snum), lp_hostsdeny(snum)) ) {
1680                         DEBUG(3, ("access DENIED (hosts allow/deny) for printer open\n"));
1681                         ZERO_STRUCTP(r->out.handle);
1682                         return WERR_ACCESS_DENIED;
1683                 }
1684
1685                 if (!user_ok_token(uidtoname(p->server_info->utok.uid), NULL,
1686                                    p->server_info->ptok, snum) ||
1687                     !print_access_check(p->server_info, snum,
1688                                         r->in.access_mask)) {
1689                         DEBUG(3, ("access DENIED for printer open\n"));
1690                         close_printer_handle(p, handle);
1691                         ZERO_STRUCTP(r->out.handle);
1692                         return WERR_ACCESS_DENIED;
1693                 }
1694
1695                 if ((r->in.access_mask & SPECIFIC_RIGHTS_MASK)& ~(PRINTER_ACCESS_ADMINISTER|PRINTER_ACCESS_USE)) {
1696                         DEBUG(3, ("access DENIED for printer open - unknown bits\n"));
1697                         close_printer_handle(p, handle);
1698                         ZERO_STRUCTP(r->out.handle);
1699                         return WERR_ACCESS_DENIED;
1700                 }
1701
1702                 if (r->in.access_mask & PRINTER_ACCESS_ADMINISTER)
1703                         r->in.access_mask = PRINTER_ACCESS_ADMINISTER;
1704                 else
1705                         r->in.access_mask = PRINTER_ACCESS_USE;
1706
1707                 DEBUG(4,("Setting printer access = %s\n", (r->in.access_mask == PRINTER_ACCESS_ADMINISTER)
1708                         ? "PRINTER_ACCESS_ADMINISTER" : "PRINTER_ACCESS_USE" ));
1709
1710                 break;
1711
1712         default:
1713                 /* sanity check to prevent programmer error */
1714                 ZERO_STRUCTP(r->out.handle);
1715                 return WERR_BADFID;
1716         }
1717
1718         Printer->access_granted = r->in.access_mask;
1719
1720         /*
1721          * If the client sent a devmode in the OpenPrinter() call, then
1722          * save it here in case we get a job submission on this handle
1723          */
1724
1725          if ( (Printer->printer_type != SPLHND_SERVER)
1726                 && r->in.devmode_ctr.devmode )
1727          {
1728                 convert_devicemode_new(Printer->sharename,
1729                                        r->in.devmode_ctr.devmode,
1730                                        &Printer->nt_devmode);
1731          }
1732
1733 #if 0   /* JERRY -- I'm doubtful this is really effective */
1734         /* HACK ALERT!!! Sleep for 1/3 of a second to try trigger a LAN/WAN
1735            optimization in Windows 2000 clients  --jerry */
1736
1737         if ( (r->in.access_mask == PRINTER_ACCESS_ADMINISTER)
1738                 && (RA_WIN2K == get_remote_arch()) )
1739         {
1740                 DEBUG(10,("_spoolss_OpenPrinterEx: Enabling LAN/WAN hack for Win2k clients.\n"));
1741                 sys_usleep( 500000 );
1742         }
1743 #endif
1744
1745         return WERR_OK;
1746 }
1747
1748 /****************************************************************************
1749 ****************************************************************************/
1750
1751 static bool printer_info2_to_nt_printer_info2(struct spoolss_SetPrinterInfo2 *r,
1752                                               NT_PRINTER_INFO_LEVEL_2 *d)
1753 {
1754         DEBUG(7,("printer_info2_to_nt_printer_info2\n"));
1755
1756         if (!r || !d) {
1757                 return false;
1758         }
1759
1760         d->attributes           = r->attributes;
1761         d->priority             = r->priority;
1762         d->default_priority     = r->defaultpriority;
1763         d->starttime            = r->starttime;
1764         d->untiltime            = r->untiltime;
1765         d->status               = r->status;
1766         d->cjobs                = r->cjobs;
1767
1768         fstrcpy(d->servername,  r->servername);
1769         fstrcpy(d->printername, r->printername);
1770         fstrcpy(d->sharename,   r->sharename);
1771         fstrcpy(d->portname,    r->portname);
1772         fstrcpy(d->drivername,  r->drivername);
1773         slprintf(d->comment, sizeof(d->comment)-1, "%s", r->comment);
1774         fstrcpy(d->location,    r->location);
1775         fstrcpy(d->sepfile,     r->sepfile);
1776         fstrcpy(d->printprocessor, r->printprocessor);
1777         fstrcpy(d->datatype,    r->datatype);
1778         fstrcpy(d->parameters,  r->parameters);
1779
1780         return true;
1781 }
1782
1783 /****************************************************************************
1784 ****************************************************************************/
1785
1786 static bool convert_printer_info_new(struct spoolss_SetPrinterInfoCtr *info_ctr,
1787                                      NT_PRINTER_INFO_LEVEL *printer)
1788 {
1789         bool ret;
1790
1791         switch (info_ctr->level) {
1792         case 2:
1793                 /* allocate memory if needed.  Messy because
1794                    convert_printer_info is used to update an existing
1795                    printer or build a new one */
1796
1797                 if (!printer->info_2) {
1798                         printer->info_2 = TALLOC_ZERO_P(printer, NT_PRINTER_INFO_LEVEL_2);
1799                         if (!printer->info_2) {
1800                                 DEBUG(0,("convert_printer_info_new: "
1801                                         "talloc() failed!\n"));
1802                                 return false;
1803                         }
1804                 }
1805
1806                 ret = printer_info2_to_nt_printer_info2(info_ctr->info.info2,
1807                                                         printer->info_2);
1808                 printer->info_2->setuptime = time(NULL);
1809                 return ret;
1810         }
1811
1812         return false;
1813 }
1814
1815 /*******************************************************************
1816 ********************************************************************/
1817
1818 static bool string_array_to_fstring_array(const char **sarray, fstring **farray)
1819 {
1820         int i;
1821
1822         if (!sarray) {
1823                 *farray = NULL;
1824                 return true;
1825         }
1826
1827         *farray = SMB_MALLOC_ARRAY(fstring, 1);
1828         if (!*farray) {
1829                 return false;
1830         }
1831
1832         for (i=0; sarray[i] != NULL; i++) {
1833                 *farray = SMB_REALLOC_ARRAY(*farray, fstring, i+2);
1834                 if (!*farray) {
1835                         return false;
1836                 }
1837                 fstrcpy((*farray)[i], sarray[i]);
1838         }
1839
1840         fstrcpy((*farray)[i], "");
1841
1842         return true;
1843 }
1844
1845 /*******************************************************************
1846 ********************************************************************/
1847
1848 static bool driver_info3_to_nt_driver_info3(struct spoolss_AddDriverInfo3 *r,
1849                                             NT_PRINTER_DRIVER_INFO_LEVEL_3 **p)
1850 {
1851         NT_PRINTER_DRIVER_INFO_LEVEL_3 *d;
1852
1853         DEBUG(7,("driver_info3_to_nt_driver_info3: Converting from UNICODE to ASCII\n"));
1854
1855         if (*p == NULL) {
1856                 *p = SMB_MALLOC_P(NT_PRINTER_DRIVER_INFO_LEVEL_3);
1857                 if (*p == NULL) {
1858                         return false;
1859                 }
1860                 ZERO_STRUCTP(*p);
1861         }
1862
1863         d = *p;
1864
1865         d->cversion =                   r->version;
1866
1867         fstrcpy(d->name,                r->driver_name);
1868         fstrcpy(d->environment,         r->architecture);
1869         fstrcpy(d->driverpath,          r->driver_path);
1870         fstrcpy(d->datafile,            r->data_file);
1871         fstrcpy(d->configfile,          r->config_file);
1872         fstrcpy(d->helpfile,            r->help_file);
1873         fstrcpy(d->monitorname,         r->monitor_name);
1874         fstrcpy(d->defaultdatatype,     r->default_datatype);
1875
1876         DEBUGADD(8,( "version:         %d\n", d->cversion));
1877         DEBUGADD(8,( "name:            %s\n", d->name));
1878         DEBUGADD(8,( "environment:     %s\n", d->environment));
1879         DEBUGADD(8,( "driverpath:      %s\n", d->driverpath));
1880         DEBUGADD(8,( "datafile:        %s\n", d->datafile));
1881         DEBUGADD(8,( "configfile:      %s\n", d->configfile));
1882         DEBUGADD(8,( "helpfile:        %s\n", d->helpfile));
1883         DEBUGADD(8,( "monitorname:     %s\n", d->monitorname));
1884         DEBUGADD(8,( "defaultdatatype: %s\n", d->defaultdatatype));
1885
1886         if (r->dependent_files) {
1887                 if (!string_array_to_fstring_array(r->dependent_files->string,
1888                                                    &d->dependentfiles)) {
1889                         SAFE_FREE(*p);
1890                         return false;
1891                 }
1892         }
1893
1894         return true;
1895 }
1896
1897 /*******************************************************************
1898 ********************************************************************/
1899
1900 static bool driver_info6_to_nt_driver_info6(struct spoolss_AddDriverInfo6 *r,
1901                                             NT_PRINTER_DRIVER_INFO_LEVEL_6 **p)
1902 {
1903         NT_PRINTER_DRIVER_INFO_LEVEL_6 *d;
1904
1905         DEBUG(7,("driver_info6_to_nt_driver_info6: Converting from UNICODE to ASCII\n"));
1906
1907         if (*p == NULL) {
1908                 *p = SMB_MALLOC_P(NT_PRINTER_DRIVER_INFO_LEVEL_6);
1909                 if (*p == NULL) {
1910                         return false;
1911                 }
1912                 ZERO_STRUCTP(*p);
1913         }
1914
1915         d = *p;
1916
1917         d->version =                    r->version;
1918
1919         fstrcpy(d->name,                r->driver_name);
1920         fstrcpy(d->environment,         r->architecture);
1921         fstrcpy(d->driverpath,          r->driver_path);
1922         fstrcpy(d->datafile,            r->data_file);
1923         fstrcpy(d->configfile,          r->config_file);
1924         fstrcpy(d->helpfile,            r->help_file);
1925         fstrcpy(d->monitorname,         r->monitor_name);
1926         fstrcpy(d->defaultdatatype,     r->default_datatype);
1927
1928         DEBUGADD(8,( "version:         %d\n", d->version));
1929         DEBUGADD(8,( "name:            %s\n", d->name));
1930         DEBUGADD(8,( "environment:     %s\n", d->environment));
1931         DEBUGADD(8,( "driverpath:      %s\n", d->driverpath));
1932         DEBUGADD(8,( "datafile:        %s\n", d->datafile));
1933         DEBUGADD(8,( "configfile:      %s\n", d->configfile));
1934         DEBUGADD(8,( "helpfile:        %s\n", d->helpfile));
1935         DEBUGADD(8,( "monitorname:     %s\n", d->monitorname));
1936         DEBUGADD(8,( "defaultdatatype: %s\n", d->defaultdatatype));
1937
1938         if (r->dependent_files) {
1939                 if (!string_array_to_fstring_array(r->dependent_files->string,
1940                                                    &d->dependentfiles)) {
1941                         goto error;
1942                 }
1943         }
1944
1945         if (r->previous_names) {
1946                 if (!string_array_to_fstring_array(r->previous_names->string,
1947                                                    &d->previousnames)) {
1948                         goto error;
1949                 }
1950         }
1951
1952         return true;
1953
1954  error:
1955         SAFE_FREE(*p);
1956         return false;
1957 }
1958
1959 /********************************************************************
1960  ********************************************************************/
1961
1962 static bool convert_printer_driver_info(const struct spoolss_AddDriverInfoCtr *r,
1963                                         NT_PRINTER_DRIVER_INFO_LEVEL *printer,
1964                                         uint32_t level)
1965 {
1966         switch (level) {
1967         case 3:
1968                 printer->info_3 = NULL;
1969                 if (!driver_info3_to_nt_driver_info3(r->info.info3, &printer->info_3)) {
1970                         return false;
1971                 }
1972                 break;
1973         case 6:
1974                 printer->info_6 = NULL;
1975                 if (!driver_info6_to_nt_driver_info6(r->info.info6, &printer->info_6)) {
1976                         return false;
1977                 }
1978                 break;
1979         default:
1980                 return false;
1981         }
1982
1983         return true;
1984 }
1985
1986 bool convert_devicemode(const char *printername, const DEVICEMODE *devmode,
1987                                 NT_DEVICEMODE **pp_nt_devmode)
1988 {
1989         NT_DEVICEMODE *nt_devmode = *pp_nt_devmode;
1990
1991         /*
1992          * Ensure nt_devmode is a valid pointer
1993          * as we will be overwriting it.
1994          */
1995
1996         if (nt_devmode == NULL) {
1997                 DEBUG(5, ("convert_devicemode: allocating a generic devmode\n"));
1998                 if ((nt_devmode = construct_nt_devicemode(printername)) == NULL)
1999                         return False;
2000         }
2001
2002         rpcstr_pull(nt_devmode->devicename,devmode->devicename.buffer, 31, -1, 0);
2003         rpcstr_pull(nt_devmode->formname,devmode->formname.buffer, 31, -1, 0);
2004
2005         nt_devmode->specversion=devmode->specversion;
2006         nt_devmode->driverversion=devmode->driverversion;
2007         nt_devmode->size=devmode->size;
2008         nt_devmode->fields=devmode->fields;
2009         nt_devmode->orientation=devmode->orientation;
2010         nt_devmode->papersize=devmode->papersize;
2011         nt_devmode->paperlength=devmode->paperlength;
2012         nt_devmode->paperwidth=devmode->paperwidth;
2013         nt_devmode->scale=devmode->scale;
2014         nt_devmode->copies=devmode->copies;
2015         nt_devmode->defaultsource=devmode->defaultsource;
2016         nt_devmode->printquality=devmode->printquality;
2017         nt_devmode->color=devmode->color;
2018         nt_devmode->duplex=devmode->duplex;
2019         nt_devmode->yresolution=devmode->yresolution;
2020         nt_devmode->ttoption=devmode->ttoption;
2021         nt_devmode->collate=devmode->collate;
2022
2023         nt_devmode->logpixels=devmode->logpixels;
2024         nt_devmode->bitsperpel=devmode->bitsperpel;
2025         nt_devmode->pelswidth=devmode->pelswidth;
2026         nt_devmode->pelsheight=devmode->pelsheight;
2027         nt_devmode->displayflags=devmode->displayflags;
2028         nt_devmode->displayfrequency=devmode->displayfrequency;
2029         nt_devmode->icmmethod=devmode->icmmethod;
2030         nt_devmode->icmintent=devmode->icmintent;
2031         nt_devmode->mediatype=devmode->mediatype;
2032         nt_devmode->dithertype=devmode->dithertype;
2033         nt_devmode->reserved1=devmode->reserved1;
2034         nt_devmode->reserved2=devmode->reserved2;
2035         nt_devmode->panningwidth=devmode->panningwidth;
2036         nt_devmode->panningheight=devmode->panningheight;
2037
2038         /*
2039          * Only change private and driverextra if the incoming devmode
2040          * has a new one. JRA.
2041          */
2042
2043         if ((devmode->driverextra != 0) && (devmode->dev_private != NULL)) {
2044                 SAFE_FREE(nt_devmode->nt_dev_private);
2045                 nt_devmode->driverextra=devmode->driverextra;
2046                 if((nt_devmode->nt_dev_private=SMB_MALLOC_ARRAY(uint8, nt_devmode->driverextra)) == NULL)
2047                         return False;
2048                 memcpy(nt_devmode->nt_dev_private, devmode->dev_private, nt_devmode->driverextra);
2049         }
2050
2051         *pp_nt_devmode = nt_devmode;
2052
2053         return True;
2054 }
2055
2056 /********************************************************************
2057  * _spoolss_enddocprinter_internal.
2058  ********************************************************************/
2059
2060 static WERROR _spoolss_enddocprinter_internal(pipes_struct *p, POLICY_HND *handle)
2061 {
2062         Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
2063         int snum;
2064
2065         if (!Printer) {
2066                 DEBUG(2,("_spoolss_enddocprinter_internal: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
2067                 return WERR_BADFID;
2068         }
2069
2070         if (!get_printer_snum(p, handle, &snum, NULL))
2071                 return WERR_BADFID;
2072
2073         Printer->document_started=False;
2074         print_job_end(snum, Printer->jobid,NORMAL_CLOSE);
2075         /* error codes unhandled so far ... */
2076
2077         return WERR_OK;
2078 }
2079
2080 /****************************************************************
2081  _spoolss_ClosePrinter
2082 ****************************************************************/
2083
2084 WERROR _spoolss_ClosePrinter(pipes_struct *p,
2085                              struct spoolss_ClosePrinter *r)
2086 {
2087         POLICY_HND *handle = r->in.handle;
2088
2089         Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
2090
2091         if (Printer && Printer->document_started)
2092                 _spoolss_enddocprinter_internal(p, handle);          /* print job was not closed */
2093
2094         if (!close_printer_handle(p, handle))
2095                 return WERR_BADFID;
2096
2097         /* clear the returned printer handle.  Observed behavior
2098            from Win2k server.  Don't think this really matters.
2099            Previous code just copied the value of the closed
2100            handle.    --jerry */
2101
2102         ZERO_STRUCTP(r->out.handle);
2103
2104         return WERR_OK;
2105 }
2106
2107 /****************************************************************
2108  _spoolss_DeletePrinter
2109 ****************************************************************/
2110
2111 WERROR _spoolss_DeletePrinter(pipes_struct *p,
2112                               struct spoolss_DeletePrinter *r)
2113 {
2114         POLICY_HND *handle = r->in.handle;
2115         Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
2116         WERROR result;
2117
2118         if (Printer && Printer->document_started)
2119                 _spoolss_enddocprinter_internal(p, handle);  /* print job was not closed */
2120
2121         result = delete_printer_handle(p, handle);
2122
2123         update_c_setprinter(False);
2124
2125         return result;
2126 }
2127
2128 /*******************************************************************
2129  * static function to lookup the version id corresponding to an
2130  * long architecture string
2131  ******************************************************************/
2132
2133 static int get_version_id (char * arch)
2134 {
2135         int i;
2136         struct table_node archi_table[]= {
2137
2138                 {"Windows 4.0",          "WIN40",       0 },
2139                 {"Windows NT x86",       "W32X86",      2 },
2140                 {"Windows NT R4000",     "W32MIPS",     2 },
2141                 {"Windows NT Alpha_AXP", "W32ALPHA",    2 },
2142                 {"Windows NT PowerPC",   "W32PPC",      2 },
2143                 {"Windows IA64",         "IA64",        3 },
2144                 {"Windows x64",          "x64",         3 },
2145                 {NULL,                   "",            -1 }
2146         };
2147
2148         for (i=0; archi_table[i].long_archi != NULL; i++)
2149         {
2150                 if (strcmp(arch, archi_table[i].long_archi) == 0)
2151                         return (archi_table[i].version);
2152         }
2153
2154         return -1;
2155 }
2156
2157 /****************************************************************
2158  _spoolss_DeletePrinterDriver
2159 ****************************************************************/
2160
2161 WERROR _spoolss_DeletePrinterDriver(pipes_struct *p,
2162                                     struct spoolss_DeletePrinterDriver *r)
2163 {
2164         char *driver;
2165         char *arch;
2166         NT_PRINTER_DRIVER_INFO_LEVEL    info;
2167         NT_PRINTER_DRIVER_INFO_LEVEL    info_win2k;
2168         int                             version;
2169         WERROR                          status;
2170         WERROR                          status_win2k = WERR_ACCESS_DENIED;
2171         SE_PRIV                         se_printop = SE_PRINT_OPERATOR;
2172
2173         /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
2174            and not a printer admin, then fail */
2175
2176         if ( (p->server_info->utok.uid != 0)
2177                 && !user_has_privileges(p->server_info->ptok, &se_printop )
2178                 && !token_contains_name_in_list(
2179                         uidtoname(p->server_info->utok.uid), NULL,
2180                         NULL, p->server_info->ptok,
2181                         lp_printer_admin(-1)) )
2182         {
2183                 return WERR_ACCESS_DENIED;
2184         }
2185
2186         driver = CONST_DISCARD(char *, r->in.driver);
2187         arch   = CONST_DISCARD(char *, r->in.architecture);
2188
2189         /* check that we have a valid driver name first */
2190
2191         if ((version=get_version_id(arch)) == -1)
2192                 return WERR_INVALID_ENVIRONMENT;
2193
2194         ZERO_STRUCT(info);
2195         ZERO_STRUCT(info_win2k);
2196
2197         if (!W_ERROR_IS_OK(get_a_printer_driver(&info, 3, driver, arch, version)))
2198         {
2199                 /* try for Win2k driver if "Windows NT x86" */
2200
2201                 if ( version == 2 ) {
2202                         version = 3;
2203                         if (!W_ERROR_IS_OK(get_a_printer_driver(&info, 3, driver, arch, version))) {
2204                                 status = WERR_UNKNOWN_PRINTER_DRIVER;
2205                                 goto done;
2206                         }
2207                 }
2208                 /* otherwise it was a failure */
2209                 else {
2210                         status = WERR_UNKNOWN_PRINTER_DRIVER;
2211                         goto done;
2212                 }
2213
2214         }
2215
2216         if (printer_driver_in_use(info.info_3)) {
2217                 status = WERR_PRINTER_DRIVER_IN_USE;
2218                 goto done;
2219         }
2220
2221         if ( version == 2 )
2222         {
2223                 if (W_ERROR_IS_OK(get_a_printer_driver(&info_win2k, 3, driver, arch, 3)))
2224                 {
2225                         /* if we get to here, we now have 2 driver info structures to remove */
2226                         /* remove the Win2k driver first*/
2227
2228                         status_win2k = delete_printer_driver(
2229                                 p, info_win2k.info_3, 3, False );
2230                         free_a_printer_driver( info_win2k, 3 );
2231
2232                         /* this should not have failed---if it did, report to client */
2233                         if ( !W_ERROR_IS_OK(status_win2k) )
2234                         {
2235                                 status = status_win2k;
2236                                 goto done;
2237                         }
2238                 }
2239         }
2240
2241         status = delete_printer_driver(p, info.info_3, version, False);
2242
2243         /* if at least one of the deletes succeeded return OK */
2244
2245         if ( W_ERROR_IS_OK(status) || W_ERROR_IS_OK(status_win2k) )
2246                 status = WERR_OK;
2247
2248 done:
2249         free_a_printer_driver( info, 3 );
2250
2251         return status;
2252 }
2253
2254 /****************************************************************
2255  _spoolss_DeletePrinterDriverEx
2256 ****************************************************************/
2257
2258 WERROR _spoolss_DeletePrinterDriverEx(pipes_struct *p,
2259                                       struct spoolss_DeletePrinterDriverEx *r)
2260 {
2261         char *driver;
2262         char *arch;
2263         NT_PRINTER_DRIVER_INFO_LEVEL    info;
2264         NT_PRINTER_DRIVER_INFO_LEVEL    info_win2k;
2265         int                             version;
2266         uint32_t                        flags = r->in.delete_flags;
2267         bool                            delete_files;
2268         WERROR                          status;
2269         WERROR                          status_win2k = WERR_ACCESS_DENIED;
2270         SE_PRIV                         se_printop = SE_PRINT_OPERATOR;
2271
2272         /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
2273            and not a printer admin, then fail */
2274
2275         if ( (p->server_info->utok.uid != 0)
2276                 && !user_has_privileges(p->server_info->ptok, &se_printop )
2277                 && !token_contains_name_in_list(
2278                         uidtoname(p->server_info->utok.uid), NULL, NULL,
2279                         p->server_info->ptok, lp_printer_admin(-1)) )
2280         {
2281                 return WERR_ACCESS_DENIED;
2282         }
2283
2284         driver = CONST_DISCARD(char *, r->in.driver);
2285         arch   = CONST_DISCARD(char *, r->in.architecture);
2286
2287         /* check that we have a valid driver name first */
2288         if ((version=get_version_id(arch)) == -1) {
2289                 /* this is what NT returns */
2290                 return WERR_INVALID_ENVIRONMENT;
2291         }
2292
2293         if ( flags & DPD_DELETE_SPECIFIC_VERSION )
2294                 version = r->in.version;
2295
2296         ZERO_STRUCT(info);
2297         ZERO_STRUCT(info_win2k);
2298
2299         status = get_a_printer_driver(&info, 3, driver, arch, version);
2300
2301         if ( !W_ERROR_IS_OK(status) )
2302         {
2303                 /*
2304                  * if the client asked for a specific version,
2305                  * or this is something other than Windows NT x86,
2306                  * then we've failed
2307                  */
2308
2309                 if ( (flags&DPD_DELETE_SPECIFIC_VERSION) || (version !=2) )
2310                         goto done;
2311
2312                 /* try for Win2k driver if "Windows NT x86" */
2313
2314                 version = 3;
2315                 if (!W_ERROR_IS_OK(get_a_printer_driver(&info, 3, driver, arch, version))) {
2316                         status = WERR_UNKNOWN_PRINTER_DRIVER;
2317                         goto done;
2318                 }
2319         }
2320
2321         if ( printer_driver_in_use(info.info_3) ) {
2322                 status = WERR_PRINTER_DRIVER_IN_USE;
2323                 goto done;
2324         }
2325
2326         /*
2327          * we have a couple of cases to consider.
2328          * (1) Are any files in use?  If so and DPD_DELTE_ALL_FILE is set,
2329          *     then the delete should fail if **any** files overlap with
2330          *     other drivers
2331          * (2) If DPD_DELTE_UNUSED_FILES is sert, then delete all
2332          *     non-overlapping files
2333          * (3) If neither DPD_DELTE_ALL_FILE nor DPD_DELTE_ALL_FILES
2334          *     is set, the do not delete any files
2335          * Refer to MSDN docs on DeletePrinterDriverEx() for details.
2336          */
2337
2338         delete_files = flags & (DPD_DELETE_ALL_FILES|DPD_DELETE_UNUSED_FILES);
2339
2340         /* fail if any files are in use and DPD_DELETE_ALL_FILES is set */
2341
2342         if ( delete_files && printer_driver_files_in_use(info.info_3) & (flags&DPD_DELETE_ALL_FILES) ) {
2343                 /* no idea of the correct error here */
2344                 status = WERR_ACCESS_DENIED;
2345                 goto done;
2346         }
2347
2348
2349         /* also check for W32X86/3 if necessary; maybe we already have? */
2350
2351         if ( (version == 2) && ((flags&DPD_DELETE_SPECIFIC_VERSION) != DPD_DELETE_SPECIFIC_VERSION)  ) {
2352                 if (W_ERROR_IS_OK(get_a_printer_driver(&info_win2k, 3, driver, arch, 3)))
2353                 {
2354
2355                         if ( delete_files && printer_driver_files_in_use(info_win2k.info_3) & (flags&DPD_DELETE_ALL_FILES) ) {
2356                                 /* no idea of the correct error here */
2357                                 free_a_printer_driver( info_win2k, 3 );
2358                                 status = WERR_ACCESS_DENIED;
2359                                 goto done;
2360                         }
2361
2362                         /* if we get to here, we now have 2 driver info structures to remove */
2363                         /* remove the Win2k driver first*/
2364
2365                         status_win2k = delete_printer_driver(
2366                                 p, info_win2k.info_3, 3, delete_files);
2367                         free_a_printer_driver( info_win2k, 3 );
2368
2369                         /* this should not have failed---if it did, report to client */
2370
2371                         if ( !W_ERROR_IS_OK(status_win2k) )
2372                                 goto done;
2373                 }
2374         }
2375
2376         status = delete_printer_driver(p, info.info_3, version, delete_files);
2377
2378         if ( W_ERROR_IS_OK(status) || W_ERROR_IS_OK(status_win2k) )
2379                 status = WERR_OK;
2380 done:
2381         free_a_printer_driver( info, 3 );
2382
2383         return status;
2384 }
2385
2386
2387 /****************************************************************************
2388  Internal routine for retreiving printerdata
2389  ***************************************************************************/
2390
2391 static WERROR get_printer_dataex( TALLOC_CTX *ctx, NT_PRINTER_INFO_LEVEL *printer,
2392                                   const char *key, const char *value, uint32 *type, uint8 **data,
2393                                   uint32 *needed, uint32 in_size  )
2394 {
2395         REGISTRY_VALUE          *val;
2396         uint32                  size;
2397         int                     data_len;
2398
2399         if ( !(val = get_printer_data( printer->info_2, key, value)) )
2400                 return WERR_BADFILE;
2401
2402         *type = regval_type( val );
2403
2404         DEBUG(5,("get_printer_dataex: allocating %d\n", in_size));
2405
2406         size = regval_size( val );
2407
2408         /* copy the min(in_size, len) */
2409
2410         if ( in_size ) {
2411                 data_len = (size > in_size) ? in_size : size*sizeof(uint8);
2412
2413                 /* special case for 0 length values */
2414                 if ( data_len ) {
2415                         if ( (*data  = (uint8 *)TALLOC_MEMDUP(ctx, regval_data_p(val), data_len)) == NULL )
2416                                 return WERR_NOMEM;
2417                 }
2418                 else {
2419                         if ( (*data  = (uint8 *)TALLOC_ZERO(ctx, in_size)) == NULL )
2420                                 return WERR_NOMEM;
2421                 }
2422         }
2423         else
2424                 *data = NULL;
2425
2426         *needed = size;
2427
2428         DEBUG(5,("get_printer_dataex: copy done\n"));
2429
2430         return WERR_OK;
2431 }
2432
2433 /****************************************************************************
2434  Internal routine for removing printerdata
2435  ***************************************************************************/
2436
2437 static WERROR delete_printer_dataex( NT_PRINTER_INFO_LEVEL *printer, const char *key, const char *value )
2438 {
2439         return delete_printer_data( printer->info_2, key, value );
2440 }
2441
2442 /****************************************************************************
2443  Internal routine for storing printerdata
2444  ***************************************************************************/
2445
2446 WERROR set_printer_dataex( NT_PRINTER_INFO_LEVEL *printer, const char *key, const char *value,
2447                                   uint32 type, uint8 *data, int real_len  )
2448 {
2449         /* the registry objects enforce uniqueness based on value name */
2450
2451         return add_printer_data( printer->info_2, key, value, type, data, real_len );
2452 }
2453
2454 /********************************************************************
2455  GetPrinterData on a printer server Handle.
2456 ********************************************************************/
2457
2458 static WERROR getprinterdata_printer_server(TALLOC_CTX *ctx, fstring value, uint32 *type, uint8 **data, uint32 *needed, uint32 in_size)
2459 {
2460         int i;
2461
2462         DEBUG(8,("getprinterdata_printer_server:%s\n", value));
2463
2464         if (!StrCaseCmp(value, "W3SvcInstalled")) {
2465                 *type = REG_DWORD;
2466                 if ( !(*data = TALLOC_ARRAY(ctx, uint8, sizeof(uint32) )) )
2467                         return WERR_NOMEM;
2468                 SIVAL(*data, 0, 0x00);
2469                 *needed = 0x4;
2470                 return WERR_OK;
2471         }
2472
2473         if (!StrCaseCmp(value, "BeepEnabled")) {
2474                 *type = REG_DWORD;
2475                 if ( !(*data = TALLOC_ARRAY(ctx, uint8, sizeof(uint32) )) )
2476                         return WERR_NOMEM;
2477                 SIVAL(*data, 0, 0x00);
2478                 *needed = 0x4;
2479                 return WERR_OK;
2480         }
2481
2482         if (!StrCaseCmp(value, "EventLog")) {
2483                 *type = REG_DWORD;
2484                 if ( !(*data = TALLOC_ARRAY(ctx, uint8, sizeof(uint32) )) )
2485                         return WERR_NOMEM;
2486                 /* formally was 0x1b */
2487                 SIVAL(*data, 0, 0x0);
2488                 *needed = 0x4;
2489                 return WERR_OK;
2490         }
2491
2492         if (!StrCaseCmp(value, "NetPopup")) {
2493                 *type = REG_DWORD;
2494                 if ( !(*data = TALLOC_ARRAY(ctx, uint8, sizeof(uint32) )) )
2495                         return WERR_NOMEM;
2496                 SIVAL(*data, 0, 0x00);
2497                 *needed = 0x4;
2498                 return WERR_OK;
2499         }
2500
2501         if (!StrCaseCmp(value, "MajorVersion")) {
2502                 *type = REG_DWORD;
2503                 if ( !(*data = TALLOC_ARRAY(ctx, uint8, sizeof(uint32) )) )
2504                         return WERR_NOMEM;
2505
2506                 /* Windows NT 4.0 seems to not allow uploading of drivers
2507                    to a server that reports 0x3 as the MajorVersion.
2508                    need to investigate more how Win2k gets around this .
2509                    -- jerry */
2510
2511                 if ( RA_WINNT == get_remote_arch() )
2512                         SIVAL(*data, 0, 2);
2513                 else
2514                         SIVAL(*data, 0, 3);
2515
2516                 *needed = 0x4;
2517                 return WERR_OK;
2518         }
2519
2520         if (!StrCaseCmp(value, "MinorVersion")) {
2521                 *type = REG_DWORD;
2522                 if ( !(*data = TALLOC_ARRAY(ctx, uint8, sizeof(uint32) )) )
2523                         return WERR_NOMEM;
2524                 SIVAL(*data, 0, 0);
2525                 *needed = 0x4;
2526                 return WERR_OK;
2527         }
2528
2529         /* REG_BINARY
2530          *  uint32 size          = 0x114
2531          *  uint32 major         = 5
2532          *  uint32 minor         = [0|1]
2533          *  uint32 build         = [2195|2600]
2534          *  extra unicode string = e.g. "Service Pack 3"
2535          */
2536         if (!StrCaseCmp(value, "OSVersion")) {
2537                 *type = REG_BINARY;
2538                 *needed = 0x114;
2539
2540                 if ( !(*data = TALLOC_ZERO_ARRAY(ctx, uint8, (*needed > in_size) ? *needed:in_size )) )
2541                         return WERR_NOMEM;
2542
2543                 SIVAL(*data, 0, *needed);       /* size */
2544                 SIVAL(*data, 4, 5);             /* Windows 2000 == 5.0 */
2545                 SIVAL(*data, 8, 0);
2546                 SIVAL(*data, 12, 2195);         /* build */
2547
2548                 /* leave extra string empty */
2549
2550                 return WERR_OK;
2551         }
2552
2553
2554         if (!StrCaseCmp(value, "DefaultSpoolDirectory")) {
2555                 const char *string="C:\\PRINTERS";
2556                 *type = REG_SZ;
2557                 *needed = 2*(strlen(string)+1);
2558                 if((*data  = (uint8 *)TALLOC(ctx, (*needed > in_size) ? *needed:in_size )) == NULL)
2559                         return WERR_NOMEM;
2560                 memset(*data, 0, (*needed > in_size) ? *needed:in_size);
2561
2562                 /* it's done by hand ready to go on the wire */
2563                 for (i=0; i<strlen(string); i++) {
2564                         (*data)[2*i]=string[i];
2565                         (*data)[2*i+1]='\0';
2566                 }
2567                 return WERR_OK;
2568         }
2569
2570         if (!StrCaseCmp(value, "Architecture")) {
2571                 const char *string="Windows NT x86";
2572                 *type = REG_SZ;
2573                 *needed = 2*(strlen(string)+1);
2574                 if((*data  = (uint8 *)TALLOC(ctx, (*needed > in_size) ? *needed:in_size )) == NULL)
2575                         return WERR_NOMEM;
2576                 memset(*data, 0, (*needed > in_size) ? *needed:in_size);
2577                 for (i=0; i<strlen(string); i++) {
2578                         (*data)[2*i]=string[i];
2579                         (*data)[2*i+1]='\0';
2580                 }
2581                 return WERR_OK;
2582         }
2583
2584         if (!StrCaseCmp(value, "DsPresent")) {
2585                 *type = REG_DWORD;
2586                 if ( !(*data = TALLOC_ARRAY(ctx, uint8, sizeof(uint32) )) )
2587                         return WERR_NOMEM;
2588
2589                 /* only show the publish check box if we are a
2590                    memeber of a AD domain */
2591
2592                 if ( lp_security() == SEC_ADS )
2593                         SIVAL(*data, 0, 0x01);
2594                 else
2595                         SIVAL(*data, 0, 0x00);
2596
2597                 *needed = 0x4;
2598                 return WERR_OK;
2599         }
2600
2601         if (!StrCaseCmp(value, "DNSMachineName")) {
2602                 const char *hostname = get_mydnsfullname();
2603
2604                 if (!hostname)
2605                         return WERR_BADFILE;
2606                 *type = REG_SZ;
2607                 *needed = 2*(strlen(hostname)+1);
2608                 if((*data  = (uint8 *)TALLOC(ctx, (*needed > in_size) ? *needed:in_size )) == NULL)
2609                         return WERR_NOMEM;
2610                 memset(*data, 0, (*needed > in_size) ? *needed:in_size);
2611                 for (i=0; i<strlen(hostname); i++) {
2612                         (*data)[2*i]=hostname[i];
2613                         (*data)[2*i+1]='\0';
2614                 }
2615                 return WERR_OK;
2616         }
2617
2618
2619         return WERR_BADFILE;
2620 }
2621
2622 /********************************************************************
2623  * spoolss_getprinterdata
2624  ********************************************************************/
2625
2626 WERROR _spoolss_getprinterdata(pipes_struct *p, SPOOL_Q_GETPRINTERDATA *q_u, SPOOL_R_GETPRINTERDATA *r_u)
2627 {
2628         POLICY_HND      *handle = &q_u->handle;
2629         UNISTR2         *valuename = &q_u->valuename;
2630         uint32          in_size = q_u->size;
2631         uint32          *type = &r_u->type;
2632         uint32          *out_size = &r_u->size;
2633         uint8           **data = &r_u->data;
2634         uint32          *needed = &r_u->needed;
2635         WERROR          status;
2636         fstring         value;
2637         Printer_entry   *Printer = find_printer_index_by_hnd(p, handle);
2638         NT_PRINTER_INFO_LEVEL   *printer = NULL;
2639         int             snum = 0;
2640
2641         /*
2642          * Reminder: when it's a string, the length is in BYTES
2643          * even if UNICODE is negociated.
2644          *
2645          * JFM, 4/19/1999
2646          */
2647
2648         *out_size = in_size;
2649
2650         /* in case of problem, return some default values */
2651
2652         *needed = 0;
2653         *type   = 0;
2654
2655         DEBUG(4,("_spoolss_getprinterdata\n"));
2656
2657         if ( !Printer ) {
2658                 DEBUG(2,("_spoolss_getprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
2659                 status = WERR_BADFID;
2660                 goto done;
2661         }
2662
2663         unistr2_to_ascii(value, valuename, sizeof(value));
2664
2665         if ( Printer->printer_type == SPLHND_SERVER )
2666                 status = getprinterdata_printer_server( p->mem_ctx, value, type, data, needed, *out_size );
2667         else
2668         {
2669                 if ( !get_printer_snum(p,handle, &snum, NULL) ) {
2670                         status = WERR_BADFID;
2671                         goto done;
2672                 }
2673
2674                 status = get_a_printer(Printer, &printer, 2, lp_servicename(snum));
2675                 if ( !W_ERROR_IS_OK(status) )
2676                         goto done;
2677
2678                 /* XP sends this and wants to change id value from the PRINTER_INFO_0 */
2679
2680                 if ( strequal(value, "ChangeId") ) {
2681                         *type = REG_DWORD;
2682                         *needed = sizeof(uint32);
2683                         if ( (*data = (uint8*)TALLOC(p->mem_ctx, sizeof(uint32))) == NULL) {
2684                                 status = WERR_NOMEM;
2685                                 goto done;
2686                         }
2687                         SIVAL( *data, 0, printer->info_2->changeid );
2688                         status = WERR_OK;
2689                 }
2690                 else
2691                         status = get_printer_dataex( p->mem_ctx, printer, SPOOL_PRINTERDATA_KEY, value, type, data, needed, *out_size );
2692         }
2693
2694         if (*needed > *out_size)
2695                 status = WERR_MORE_DATA;
2696
2697 done:
2698         if ( !W_ERROR_IS_OK(status) )
2699         {
2700                 DEBUG(5, ("error %d: allocating %d\n", W_ERROR_V(status),*out_size));
2701
2702                 /* reply this param doesn't exist */
2703
2704                 if ( *out_size ) {
2705                         if((*data=(uint8 *)TALLOC_ZERO_ARRAY(p->mem_ctx, uint8, *out_size)) == NULL) {
2706                                 if ( printer )
2707                                         free_a_printer( &printer, 2 );
2708                                 return WERR_NOMEM;
2709                         }
2710                 } else {
2711                         *data = NULL;
2712                 }
2713         }
2714
2715         /* cleanup & exit */
2716
2717         if ( printer )
2718                 free_a_printer( &printer, 2 );
2719
2720         return status;
2721 }
2722
2723 /*********************************************************
2724  Connect to the client machine.
2725 **********************************************************/
2726
2727 static bool spoolss_connect_to_client(struct rpc_pipe_client **pp_pipe,
2728                         struct sockaddr_storage *client_ss, const char *remote_machine)
2729 {
2730         NTSTATUS ret;
2731         struct cli_state *the_cli;
2732         struct sockaddr_storage rm_addr;
2733
2734         if ( is_zero_addr((struct sockaddr *)client_ss) ) {
2735                 if ( !resolve_name( remote_machine, &rm_addr, 0x20) ) {
2736                         DEBUG(2,("spoolss_connect_to_client: Can't resolve address for %s\n", remote_machine));
2737                         return False;
2738                 }
2739
2740                 if (ismyaddr((struct sockaddr *)&rm_addr)) {
2741                         DEBUG(0,("spoolss_connect_to_client: Machine %s is one of our addresses. Cannot add to ourselves.\n", remote_machine));
2742                         return False;
2743                 }
2744         } else {
2745                 char addr[INET6_ADDRSTRLEN];
2746                 rm_addr = *client_ss;
2747                 print_sockaddr(addr, sizeof(addr), &rm_addr);
2748                 DEBUG(5,("spoolss_connect_to_client: Using address %s (no name resolution necessary)\n",
2749                         addr));
2750         }
2751
2752         /* setup the connection */
2753
2754         ret = cli_full_connection( &the_cli, global_myname(), remote_machine,
2755                 &rm_addr, 0, "IPC$", "IPC",
2756                 "", /* username */
2757                 "", /* domain */
2758                 "", /* password */
2759                 0, lp_client_signing(), NULL );
2760
2761         if ( !NT_STATUS_IS_OK( ret ) ) {
2762                 DEBUG(2,("spoolss_connect_to_client: connection to [%s] failed!\n",
2763                         remote_machine ));
2764                 return False;
2765         }
2766
2767         if ( the_cli->protocol != PROTOCOL_NT1 ) {
2768                 DEBUG(0,("spoolss_connect_to_client: machine %s didn't negotiate NT protocol.\n", remote_machine));
2769                 cli_shutdown(the_cli);
2770                 return False;
2771         }
2772
2773         /*
2774          * Ok - we have an anonymous connection to the IPC$ share.
2775          * Now start the NT Domain stuff :-).
2776          */
2777
2778         ret = cli_rpc_pipe_open_noauth(the_cli, &syntax_spoolss, pp_pipe);
2779         if (!NT_STATUS_IS_OK(ret)) {
2780                 DEBUG(2,("spoolss_connect_to_client: unable to open the spoolss pipe on machine %s. Error was : %s.\n",
2781                         remote_machine, nt_errstr(ret)));
2782                 cli_shutdown(the_cli);
2783                 return False;
2784         }
2785
2786         return True;
2787 }
2788
2789 /***************************************************************************
2790  Connect to the client.
2791 ****************************************************************************/
2792
2793 static bool srv_spoolss_replyopenprinter(int snum, const char *printer,
2794                                         uint32 localprinter, uint32 type,
2795                                         POLICY_HND *handle, struct sockaddr_storage *client_ss)
2796 {
2797         WERROR result;
2798         NTSTATUS status;
2799
2800         /*
2801          * If it's the first connection, contact the client
2802          * and connect to the IPC$ share anonymously
2803          */
2804         if (smb_connections==0) {
2805                 fstring unix_printer;
2806
2807                 fstrcpy(unix_printer, printer+2); /* the +2 is to strip the leading 2 backslashs */
2808
2809                 if ( !spoolss_connect_to_client( &notify_cli_pipe, client_ss, unix_printer ))
2810                         return False;
2811
2812                 messaging_register(smbd_messaging_context(), NULL,
2813                                    MSG_PRINTER_NOTIFY2,
2814                                    receive_notify2_message_list);
2815                 /* Tell the connections db we're now interested in printer
2816                  * notify messages. */
2817                 register_message_flags( True, FLAG_MSG_PRINT_NOTIFY );
2818         }
2819
2820         /*
2821          * Tell the specific printing tdb we want messages for this printer
2822          * by registering our PID.
2823          */
2824
2825         if (!print_notify_register_pid(snum))
2826                 DEBUG(0,("print_notify_register_pid: Failed to register our pid for printer %s\n", printer ));
2827
2828         smb_connections++;
2829
2830         status = rpccli_spoolss_ReplyOpenPrinter(notify_cli_pipe, talloc_tos(),
2831                                                  printer,
2832                                                  localprinter,
2833                                                  type,
2834                                                  0,
2835                                                  NULL,
2836                                                  handle,
2837                                                  &result);
2838         if (!NT_STATUS_IS_OK(status) || !W_ERROR_IS_OK(result))
2839                 DEBUG(5,("srv_spoolss_reply_open_printer: Client RPC returned [%s]\n",
2840                         win_errstr(result)));
2841
2842         return (W_ERROR_IS_OK(result));
2843 }
2844
2845 /****************************************************************
2846  ****************************************************************/
2847
2848 static struct spoolss_NotifyOption *dup_spoolss_NotifyOption(TALLOC_CTX *mem_ctx,
2849                                                              const struct spoolss_NotifyOption *r)
2850 {
2851         struct spoolss_NotifyOption *option;
2852         uint32_t i,k;
2853
2854         if (!r) {
2855                 return NULL;
2856         }
2857
2858         option = talloc_zero(mem_ctx, struct spoolss_NotifyOption);
2859         if (!option) {
2860                 return NULL;
2861         }
2862
2863         *option = *r;
2864
2865         if (!option->count) {
2866                 return option;
2867         }
2868
2869         option->types = talloc_zero_array(option,
2870                 struct spoolss_NotifyOptionType, option->count);
2871         if (!option->types) {
2872                 talloc_free(option);
2873                 return NULL;
2874         }
2875
2876         for (i=0; i < option->count; i++) {
2877                 option->types[i] = r->types[i];
2878
2879                 if (option->types[i].count) {
2880                         option->types[i].fields = talloc_zero_array(option,
2881                                 enum spoolss_Field, option->types[i].count);
2882                         if (!option->types[i].fields) {
2883                                 talloc_free(option);
2884                                 return NULL;
2885                         }
2886                         for (k=0; k<option->types[i].count; k++) {
2887                                 option->types[i].fields[k] =
2888                                         r->types[i].fields[k];
2889                         }
2890                 }
2891         }
2892
2893         return option;
2894 }
2895
2896 /****************************************************************
2897  * _spoolss_RemoteFindFirstPrinterChangeNotifyEx
2898  *
2899  * before replying OK: status=0 a rpc call is made to the workstation
2900  * asking ReplyOpenPrinter
2901  *
2902  * in fact ReplyOpenPrinter is the changenotify equivalent on the spoolss pipe
2903  * called from api_spoolss_rffpcnex
2904 ****************************************************************/
2905
2906 WERROR _spoolss_RemoteFindFirstPrinterChangeNotifyEx(pipes_struct *p,
2907                                                      struct spoolss_RemoteFindFirstPrinterChangeNotifyEx *r)
2908 {
2909         POLICY_HND *handle = r->in.handle;
2910         int snum = -1;
2911         struct spoolss_NotifyOption *option = r->in.notify_options;
2912         struct sockaddr_storage client_ss;
2913
2914         /* store the notify value in the printer struct */
2915
2916         Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
2917
2918         if (!Printer) {
2919                 DEBUG(2,("_spoolss_RemoteFindFirstPrinterChangeNotifyEx: "
2920                         "Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
2921                 return WERR_BADFID;
2922         }
2923
2924         Printer->notify.flags           = r->in.flags;
2925         Printer->notify.options         = r->in.options;
2926         Printer->notify.printerlocal    = r->in.printer_local;
2927
2928         TALLOC_FREE(Printer->notify.option);
2929         Printer->notify.option = dup_spoolss_NotifyOption(Printer, option);
2930
2931         fstrcpy(Printer->notify.localmachine, r->in.local_machine);
2932
2933         /* Connect to the client machine and send a ReplyOpenPrinter */
2934
2935         if ( Printer->printer_type == SPLHND_SERVER)
2936                 snum = -1;
2937         else if ( (Printer->printer_type == SPLHND_PRINTER) &&
2938                         !get_printer_snum(p, handle, &snum, NULL) )
2939                 return WERR_BADFID;
2940
2941         if (!interpret_string_addr(&client_ss, p->client_address,
2942                                    AI_NUMERICHOST)) {
2943                 return WERR_SERVER_UNAVAILABLE;
2944         }
2945
2946         if(!srv_spoolss_replyopenprinter(snum, Printer->notify.localmachine,
2947                                         Printer->notify.printerlocal, 1,
2948                                         &Printer->notify.client_hnd, &client_ss))
2949                 return WERR_SERVER_UNAVAILABLE;
2950
2951         Printer->notify.client_connected=True;
2952
2953         return WERR_OK;
2954 }
2955
2956 /*******************************************************************
2957  * fill a notify_info_data with the servername
2958  ********************************************************************/
2959
2960 void spoolss_notify_server_name(int snum,
2961                                        struct spoolss_Notify *data,
2962                                        print_queue_struct *queue,
2963                                        NT_PRINTER_INFO_LEVEL *printer,
2964                                        TALLOC_CTX *mem_ctx)
2965 {
2966         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, printer->info_2->servername);
2967 }
2968
2969 /*******************************************************************
2970  * fill a notify_info_data with the printername (not including the servername).
2971  ********************************************************************/
2972
2973 void spoolss_notify_printer_name(int snum,
2974                                         struct spoolss_Notify *data,
2975                                         print_queue_struct *queue,
2976                                         NT_PRINTER_INFO_LEVEL *printer,
2977                                         TALLOC_CTX *mem_ctx)
2978 {
2979         /* the notify name should not contain the \\server\ part */
2980         char *p = strrchr(printer->info_2->printername, '\\');
2981
2982         if (!p) {
2983                 p = printer->info_2->printername;
2984         } else {
2985                 p++;
2986         }
2987
2988         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, p);
2989 }
2990
2991 /*******************************************************************
2992  * fill a notify_info_data with the servicename
2993  ********************************************************************/
2994
2995 void spoolss_notify_share_name(int snum,
2996                                       struct spoolss_Notify *data,
2997                                       print_queue_struct *queue,
2998                                       NT_PRINTER_INFO_LEVEL *printer,
2999                                       TALLOC_CTX *mem_ctx)
3000 {
3001         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, lp_servicename(snum));
3002 }
3003
3004 /*******************************************************************
3005  * fill a notify_info_data with the port name
3006  ********************************************************************/
3007
3008 void spoolss_notify_port_name(int snum,
3009                                      struct spoolss_Notify *data,
3010                                      print_queue_struct *queue,
3011                                      NT_PRINTER_INFO_LEVEL *printer,
3012                                      TALLOC_CTX *mem_ctx)
3013 {
3014         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, printer->info_2->portname);
3015 }
3016
3017 /*******************************************************************
3018  * fill a notify_info_data with the printername
3019  * but it doesn't exist, have to see what to do
3020  ********************************************************************/
3021
3022 void spoolss_notify_driver_name(int snum,
3023                                        struct spoolss_Notify *data,
3024                                        print_queue_struct *queue,
3025                                        NT_PRINTER_INFO_LEVEL *printer,
3026                                        TALLOC_CTX *mem_ctx)
3027 {
3028         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, printer->info_2->drivername);
3029 }
3030
3031 /*******************************************************************
3032  * fill a notify_info_data with the comment
3033  ********************************************************************/
3034
3035 void spoolss_notify_comment(int snum,
3036                                    struct spoolss_Notify *data,
3037                                    print_queue_struct *queue,
3038                                    NT_PRINTER_INFO_LEVEL *printer,
3039                                    TALLOC_CTX *mem_ctx)
3040 {
3041         char *p;
3042
3043         if (*printer->info_2->comment == '\0') {
3044                 p = lp_comment(snum);
3045         } else {
3046                 p = printer->info_2->comment;
3047         }
3048
3049         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, printer->info_2->comment);
3050 }
3051
3052 /*******************************************************************
3053  * fill a notify_info_data with the comment
3054  * location = "Room 1, floor 2, building 3"
3055  ********************************************************************/
3056
3057 void spoolss_notify_location(int snum,
3058                                     struct spoolss_Notify *data,
3059                                     print_queue_struct *queue,
3060                                     NT_PRINTER_INFO_LEVEL *printer,
3061                                     TALLOC_CTX *mem_ctx)
3062 {
3063         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, printer->info_2->location);
3064 }
3065
3066 /*******************************************************************
3067  * fill a notify_info_data with the device mode
3068  * jfm:xxxx don't to it for know but that's a real problem !!!
3069  ********************************************************************/
3070
3071 static void spoolss_notify_devmode(int snum,
3072                                    struct spoolss_Notify *data,
3073                                    print_queue_struct *queue,
3074                                    NT_PRINTER_INFO_LEVEL *printer,
3075                                    TALLOC_CTX *mem_ctx)
3076 {
3077         /* for a dummy implementation we have to zero the fields */
3078         SETUP_SPOOLSS_NOTIFY_DATA_DEVMODE(data, NULL);
3079 }
3080
3081 /*******************************************************************
3082  * fill a notify_info_data with the separator file name
3083  ********************************************************************/
3084
3085 void spoolss_notify_sepfile(int snum,
3086                                    struct spoolss_Notify *data,
3087                                    print_queue_struct *queue,
3088                                    NT_PRINTER_INFO_LEVEL *printer,
3089                                    TALLOC_CTX *mem_ctx)
3090 {
3091         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, printer->info_2->sepfile);
3092 }
3093
3094 /*******************************************************************
3095  * fill a notify_info_data with the print processor
3096  * jfm:xxxx return always winprint to indicate we don't do anything to it
3097  ********************************************************************/
3098
3099 void spoolss_notify_print_processor(int snum,
3100                                            struct spoolss_Notify *data,
3101                                            print_queue_struct *queue,
3102                                            NT_PRINTER_INFO_LEVEL *printer,
3103                                            TALLOC_CTX *mem_ctx)
3104 {
3105         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, printer->info_2->printprocessor);
3106 }
3107
3108 /*******************************************************************
3109  * fill a notify_info_data with the print processor options
3110  * jfm:xxxx send an empty string
3111  ********************************************************************/
3112
3113 void spoolss_notify_parameters(int snum,
3114                                       struct spoolss_Notify *data,
3115                                       print_queue_struct *queue,
3116                                       NT_PRINTER_INFO_LEVEL *printer,
3117                                       TALLOC_CTX *mem_ctx)
3118 {
3119         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, printer->info_2->parameters);
3120 }
3121
3122 /*******************************************************************
3123  * fill a notify_info_data with the data type
3124  * jfm:xxxx always send RAW as data type
3125  ********************************************************************/
3126
3127 void spoolss_notify_datatype(int snum,
3128                                     struct spoolss_Notify *data,
3129                                     print_queue_struct *queue,
3130                                     NT_PRINTER_INFO_LEVEL *printer,
3131                                     TALLOC_CTX *mem_ctx)
3132 {
3133         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, printer->info_2->datatype);
3134 }
3135
3136 /*******************************************************************
3137  * fill a notify_info_data with the security descriptor
3138  * jfm:xxxx send an null pointer to say no security desc
3139  * have to implement security before !
3140  ********************************************************************/
3141
3142 static void spoolss_notify_security_desc(int snum,
3143                                          struct spoolss_Notify *data,
3144                                          print_queue_struct *queue,
3145                                          NT_PRINTER_INFO_LEVEL *printer,
3146                                          TALLOC_CTX *mem_ctx)
3147 {
3148         SETUP_SPOOLSS_NOTIFY_DATA_SECDESC(data,
3149                                           printer->info_2->secdesc_buf->sd_size,
3150                                           printer->info_2->secdesc_buf->sd);
3151 }
3152
3153 /*******************************************************************
3154  * fill a notify_info_data with the attributes
3155  * jfm:xxxx a samba printer is always shared
3156  ********************************************************************/
3157
3158 void spoolss_notify_attributes(int snum,
3159                                       struct spoolss_Notify *data,
3160                                       print_queue_struct *queue,
3161                                       NT_PRINTER_INFO_LEVEL *printer,
3162                                       TALLOC_CTX *mem_ctx)
3163 {
3164         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, printer->info_2->attributes);
3165 }
3166
3167 /*******************************************************************
3168  * fill a notify_info_data with the priority
3169  ********************************************************************/
3170
3171 static void spoolss_notify_priority(int snum,
3172                                     struct spoolss_Notify *data,
3173                                     print_queue_struct *queue,
3174                                     NT_PRINTER_INFO_LEVEL *printer,
3175                                     TALLOC_CTX *mem_ctx)
3176 {
3177         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, printer->info_2->priority);
3178 }
3179
3180 /*******************************************************************
3181  * fill a notify_info_data with the default priority
3182  ********************************************************************/
3183
3184 static void spoolss_notify_default_priority(int snum,
3185                                             struct spoolss_Notify *data,
3186                                             print_queue_struct *queue,
3187                                             NT_PRINTER_INFO_LEVEL *printer,
3188                                             TALLOC_CTX *mem_ctx)
3189 {
3190         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, printer->info_2->default_priority);
3191 }
3192
3193 /*******************************************************************
3194  * fill a notify_info_data with the start time
3195  ********************************************************************/
3196
3197 static void spoolss_notify_start_time(int snum,
3198                                       struct spoolss_Notify *data,
3199                                       print_queue_struct *queue,
3200                                       NT_PRINTER_INFO_LEVEL *printer,
3201                                       TALLOC_CTX *mem_ctx)
3202 {
3203         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, printer->info_2->starttime);
3204 }
3205
3206 /*******************************************************************
3207  * fill a notify_info_data with the until time
3208  ********************************************************************/
3209
3210 static void spoolss_notify_until_time(int snum,
3211                                       struct spoolss_Notify *data,
3212                                       print_queue_struct *queue,
3213                                       NT_PRINTER_INFO_LEVEL *printer,
3214                                       TALLOC_CTX *mem_ctx)
3215 {
3216         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, printer->info_2->untiltime);
3217 }
3218
3219 /*******************************************************************
3220  * fill a notify_info_data with the status
3221  ********************************************************************/
3222
3223 static void spoolss_notify_status(int snum,
3224                                   struct spoolss_Notify *data,
3225                                   print_queue_struct *queue,
3226                                   NT_PRINTER_INFO_LEVEL *printer,
3227                                   TALLOC_CTX *mem_ctx)
3228 {
3229         print_status_struct status;
3230
3231         print_queue_length(snum, &status);
3232         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, status.status);
3233 }
3234
3235 /*******************************************************************
3236  * fill a notify_info_data with the number of jobs queued
3237  ********************************************************************/
3238
3239 void spoolss_notify_cjobs(int snum,
3240                                  struct spoolss_Notify *data,
3241                                  print_queue_struct *queue,
3242                                  NT_PRINTER_INFO_LEVEL *printer,
3243                                  TALLOC_CTX *mem_ctx)
3244 {
3245         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, print_queue_length(snum, NULL));
3246 }
3247
3248 /*******************************************************************
3249  * fill a notify_info_data with the average ppm
3250  ********************************************************************/
3251
3252 static void spoolss_notify_average_ppm(int snum,
3253                                        struct spoolss_Notify *data,
3254                                        print_queue_struct *queue,
3255                                        NT_PRINTER_INFO_LEVEL *printer,
3256                                        TALLOC_CTX *mem_ctx)
3257 {
3258         /* always respond 8 pages per minutes */
3259         /* a little hard ! */
3260         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, printer->info_2->averageppm);
3261 }
3262
3263 /*******************************************************************
3264  * fill a notify_info_data with username
3265  ********************************************************************/
3266
3267 static void spoolss_notify_username(int snum,
3268                                     struct spoolss_Notify *data,
3269                                     print_queue_struct *queue,
3270                                     NT_PRINTER_INFO_LEVEL *printer,
3271                                     TALLOC_CTX *mem_ctx)
3272 {
3273         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, queue->fs_user);
3274 }
3275
3276 /*******************************************************************
3277  * fill a notify_info_data with job status
3278  ********************************************************************/
3279
3280 static void spoolss_notify_job_status(int snum,
3281                                       struct spoolss_Notify *data,
3282                                       print_queue_struct *queue,
3283                                       NT_PRINTER_INFO_LEVEL *printer,
3284                                       TALLOC_CTX *mem_ctx)
3285 {
3286         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, nt_printj_status(queue->status));
3287 }
3288
3289 /*******************************************************************
3290  * fill a notify_info_data with job name
3291  ********************************************************************/
3292
3293 static void spoolss_notify_job_name(int snum,
3294                                     struct spoolss_Notify *data,
3295                                     print_queue_struct *queue,
3296                                     NT_PRINTER_INFO_LEVEL *printer,
3297                                     TALLOC_CTX *mem_ctx)
3298 {
3299         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, queue->fs_file);
3300 }
3301
3302 /*******************************************************************
3303  * fill a notify_info_data with job status
3304  ********************************************************************/
3305
3306 static void spoolss_notify_job_status_string(int snum,
3307                                              struct spoolss_Notify *data,
3308                                              print_queue_struct *queue,
3309                                              NT_PRINTER_INFO_LEVEL *printer,
3310                                              TALLOC_CTX *mem_ctx)
3311 {
3312         /*
3313          * Now we're returning job status codes we just return a "" here. JRA.
3314          */
3315
3316         const char *p = "";
3317
3318 #if 0 /* NO LONGER NEEDED - JRA. 02/22/2001 */
3319         p = "unknown";
3320
3321         switch (queue->status) {
3322         case LPQ_QUEUED:
3323                 p = "Queued";
3324                 break;
3325         case LPQ_PAUSED:
3326                 p = "";    /* NT provides the paused string */
3327                 break;
3328         case LPQ_SPOOLING:
3329                 p = "Spooling";
3330                 break;
3331         case LPQ_PRINTING:
3332                 p = "Printing";
3333                 break;
3334         }
3335 #endif /* NO LONGER NEEDED. */
3336
3337         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, p);
3338 }
3339
3340 /*******************************************************************
3341  * fill a notify_info_data with job time
3342  ********************************************************************/
3343
3344 static void spoolss_notify_job_time(int snum,
3345                                     struct spoolss_Notify *data,
3346                                     print_queue_struct *queue,
3347                                     NT_PRINTER_INFO_LEVEL *printer,
3348                                     TALLOC_CTX *mem_ctx)
3349 {
3350         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, 0);
3351 }
3352
3353 /*******************************************************************
3354  * fill a notify_info_data with job size
3355  ********************************************************************/
3356
3357 static void spoolss_notify_job_size(int snum,
3358                                     struct spoolss_Notify *data,
3359                                     print_queue_struct *queue,
3360                                     NT_PRINTER_INFO_LEVEL *printer,
3361                                     TALLOC_CTX *mem_ctx)
3362 {
3363         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, queue->size);
3364 }
3365
3366 /*******************************************************************
3367  * fill a notify_info_data with page info
3368  ********************************************************************/
3369 static void spoolss_notify_total_pages(int snum,
3370                                 struct spoolss_Notify *data,
3371                                 print_queue_struct *queue,
3372                                 NT_PRINTER_INFO_LEVEL *printer,
3373                                 TALLOC_CTX *mem_ctx)
3374 {
3375         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, queue->page_count);
3376 }
3377
3378 /*******************************************************************
3379  * fill a notify_info_data with pages printed info.
3380  ********************************************************************/
3381 static void spoolss_notify_pages_printed(int snum,
3382                                 struct spoolss_Notify *data,
3383                                 print_queue_struct *queue,
3384                                 NT_PRINTER_INFO_LEVEL *printer,
3385                                 TALLOC_CTX *mem_ctx)
3386 {
3387         /* Add code when back-end tracks this */
3388         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, 0);
3389 }
3390
3391 /*******************************************************************
3392  Fill a notify_info_data with job position.
3393  ********************************************************************/
3394
3395 static void spoolss_notify_job_position(int snum,
3396                                         struct spoolss_Notify *data,
3397                                         print_queue_struct *queue,
3398                                         NT_PRINTER_INFO_LEVEL *printer,
3399                                         TALLOC_CTX *mem_ctx)
3400 {
3401         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, queue->job);
3402 }
3403
3404 /*******************************************************************
3405  Fill a notify_info_data with submitted time.
3406  ********************************************************************/
3407
3408 static void spoolss_notify_submitted_time(int snum,
3409                                           struct spoolss_Notify *data,
3410                                           print_queue_struct *queue,
3411                                           NT_PRINTER_INFO_LEVEL *printer,
3412                                           TALLOC_CTX *mem_ctx)
3413 {
3414         data->data.string.string = NULL;
3415         data->data.string.size = 0;
3416
3417         init_systemtime_buffer(mem_ctx, gmtime(&queue->time),
3418                                &data->data.string.string,
3419                                &data->data.string.size);
3420
3421 }
3422
3423 struct s_notify_info_data_table
3424 {
3425         enum spoolss_NotifyType type;
3426         enum spoolss_Field field;
3427         const char *name;
3428         enum spoolss_NotifyTable variable_type;
3429         void (*fn) (int snum, struct spoolss_Notify *data,
3430                     print_queue_struct *queue,
3431                     NT_PRINTER_INFO_LEVEL *printer, TALLOC_CTX *mem_ctx);
3432 };
3433
3434 /* A table describing the various print notification constants and
3435    whether the notification data is a pointer to a variable sized
3436    buffer, a one value uint32 or a two value uint32. */
3437
3438 static const struct s_notify_info_data_table notify_info_data_table[] =
3439 {
3440 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SERVER_NAME,         "PRINTER_NOTIFY_SERVER_NAME",         NOTIFY_TABLE_STRING,   spoolss_notify_server_name },
3441 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PRINTER_NAME,        "PRINTER_NOTIFY_PRINTER_NAME",        NOTIFY_TABLE_STRING,   spoolss_notify_printer_name },
3442 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SHARE_NAME,          "PRINTER_NOTIFY_SHARE_NAME",          NOTIFY_TABLE_STRING,   spoolss_notify_share_name },
3443 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PORT_NAME,           "PRINTER_NOTIFY_PORT_NAME",           NOTIFY_TABLE_STRING,   spoolss_notify_port_name },
3444 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DRIVER_NAME,         "PRINTER_NOTIFY_DRIVER_NAME",         NOTIFY_TABLE_STRING,   spoolss_notify_driver_name },
3445 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_COMMENT,             "PRINTER_NOTIFY_COMMENT",             NOTIFY_TABLE_STRING,   spoolss_notify_comment },
3446 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_LOCATION,            "PRINTER_NOTIFY_LOCATION",            NOTIFY_TABLE_STRING,   spoolss_notify_location },
3447 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DEVMODE,             "PRINTER_NOTIFY_DEVMODE",             NOTIFY_TABLE_DEVMODE,  spoolss_notify_devmode },
3448 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SEPFILE,             "PRINTER_NOTIFY_SEPFILE",             NOTIFY_TABLE_STRING,   spoolss_notify_sepfile },
3449 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PRINT_PROCESSOR,     "PRINTER_NOTIFY_PRINT_PROCESSOR",     NOTIFY_TABLE_STRING,   spoolss_notify_print_processor },
3450 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PARAMETERS,          "PRINTER_NOTIFY_PARAMETERS",          NOTIFY_TABLE_STRING,   spoolss_notify_parameters },
3451 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DATATYPE,            "PRINTER_NOTIFY_DATATYPE",            NOTIFY_TABLE_STRING,   spoolss_notify_datatype },
3452 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SECURITY_DESCRIPTOR, "PRINTER_NOTIFY_SECURITY_DESCRIPTOR", NOTIFY_TABLE_SECURITYDESCRIPTOR,   spoolss_notify_security_desc },
3453 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_ATTRIBUTES,          "PRINTER_NOTIFY_ATTRIBUTES",          NOTIFY_TABLE_DWORD,    spoolss_notify_attributes },
3454 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PRIORITY,            "PRINTER_NOTIFY_PRIORITY",            NOTIFY_TABLE_DWORD,    spoolss_notify_priority },
3455 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DEFAULT_PRIORITY,    "PRINTER_NOTIFY_DEFAULT_PRIORITY",    NOTIFY_TABLE_DWORD,    spoolss_notify_default_priority },
3456 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_START_TIME,          "PRINTER_NOTIFY_START_TIME",          NOTIFY_TABLE_DWORD,    spoolss_notify_start_time },
3457 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_UNTIL_TIME,          "PRINTER_NOTIFY_UNTIL_TIME",          NOTIFY_TABLE_DWORD,    spoolss_notify_until_time },
3458 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_STATUS,              "PRINTER_NOTIFY_STATUS",              NOTIFY_TABLE_DWORD,    spoolss_notify_status },
3459 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_STATUS_STRING,       "PRINTER_NOTIFY_STATUS_STRING",       NOTIFY_TABLE_STRING,   NULL },
3460 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_CJOBS,               "PRINTER_NOTIFY_CJOBS",               NOTIFY_TABLE_DWORD,    spoolss_notify_cjobs },
3461 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_AVERAGE_PPM,         "PRINTER_NOTIFY_AVERAGE_PPM",         NOTIFY_TABLE_DWORD,    spoolss_notify_average_ppm },
3462 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_TOTAL_PAGES,         "PRINTER_NOTIFY_TOTAL_PAGES",         NOTIFY_TABLE_DWORD,    NULL },
3463 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PAGES_PRINTED,       "PRINTER_NOTIFY_PAGES_PRINTED",       NOTIFY_TABLE_DWORD,    NULL },
3464 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_TOTAL_BYTES,         "PRINTER_NOTIFY_TOTAL_BYTES",         NOTIFY_TABLE_DWORD,    NULL },
3465 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_BYTES_PRINTED,       "PRINTER_NOTIFY_BYTES_PRINTED",       NOTIFY_TABLE_DWORD,    NULL },
3466 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_PRINTER_NAME,            "JOB_NOTIFY_PRINTER_NAME",            NOTIFY_TABLE_STRING,   spoolss_notify_printer_name },
3467 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_MACHINE_NAME,            "JOB_NOTIFY_MACHINE_NAME",            NOTIFY_TABLE_STRING,   spoolss_notify_server_name },
3468 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_PORT_NAME,               "JOB_NOTIFY_PORT_NAME",               NOTIFY_TABLE_STRING,   spoolss_notify_port_name },
3469 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_USER_NAME,               "JOB_NOTIFY_USER_NAME",               NOTIFY_TABLE_STRING,   spoolss_notify_username },
3470 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_NOTIFY_NAME,             "JOB_NOTIFY_NOTIFY_NAME",             NOTIFY_TABLE_STRING,   spoolss_notify_username },
3471 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_DATATYPE,                "JOB_NOTIFY_DATATYPE",                NOTIFY_TABLE_STRING,   spoolss_notify_datatype },
3472 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_PRINT_PROCESSOR,         "JOB_NOTIFY_PRINT_PROCESSOR",         NOTIFY_TABLE_STRING,   spoolss_notify_print_processor },
3473 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_PARAMETERS,              "JOB_NOTIFY_PARAMETERS",              NOTIFY_TABLE_STRING,   spoolss_notify_parameters },
3474 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_DRIVER_NAME,             "JOB_NOTIFY_DRIVER_NAME",             NOTIFY_TABLE_STRING,   spoolss_notify_driver_name },
3475 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_DEVMODE,                 "JOB_NOTIFY_DEVMODE",                 NOTIFY_TABLE_DEVMODE,  spoolss_notify_devmode },
3476 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_STATUS,                  "JOB_NOTIFY_STATUS",                  NOTIFY_TABLE_DWORD,    spoolss_notify_job_status },
3477 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_STATUS_STRING,           "JOB_NOTIFY_STATUS_STRING",           NOTIFY_TABLE_STRING,   spoolss_notify_job_status_string },
3478 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_SECURITY_DESCRIPTOR,     "JOB_NOTIFY_SECURITY_DESCRIPTOR",     NOTIFY_TABLE_SECURITYDESCRIPTOR,   NULL },
3479 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_DOCUMENT,                "JOB_NOTIFY_DOCUMENT",                NOTIFY_TABLE_STRING,   spoolss_notify_job_name },
3480 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_PRIORITY,                "JOB_NOTIFY_PRIORITY",                NOTIFY_TABLE_DWORD,    spoolss_notify_priority },
3481 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_POSITION,                "JOB_NOTIFY_POSITION",                NOTIFY_TABLE_DWORD,    spoolss_notify_job_position },
3482 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_SUBMITTED,               "JOB_NOTIFY_SUBMITTED",               NOTIFY_TABLE_TIME,     spoolss_notify_submitted_time },
3483 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_START_TIME,              "JOB_NOTIFY_START_TIME",              NOTIFY_TABLE_DWORD,    spoolss_notify_start_time },
3484 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_UNTIL_TIME,              "JOB_NOTIFY_UNTIL_TIME",              NOTIFY_TABLE_DWORD,    spoolss_notify_until_time },
3485 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_TIME,                    "JOB_NOTIFY_TIME",                    NOTIFY_TABLE_DWORD,    spoolss_notify_job_time },
3486 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_TOTAL_PAGES,             "JOB_NOTIFY_TOTAL_PAGES",             NOTIFY_TABLE_DWORD,    spoolss_notify_total_pages },
3487 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_PAGES_PRINTED,           "JOB_NOTIFY_PAGES_PRINTED",           NOTIFY_TABLE_DWORD,    spoolss_notify_pages_printed },
3488 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_TOTAL_BYTES,             "JOB_NOTIFY_TOTAL_BYTES",             NOTIFY_TABLE_DWORD,    spoolss_notify_job_size },
3489 };
3490
3491 /*******************************************************************
3492  Return the variable_type of info_data structure.
3493 ********************************************************************/
3494
3495 static uint32_t variable_type_of_notify_info_data(enum spoolss_NotifyType type,
3496                                                   enum spoolss_Field field)
3497 {
3498         int i=0;
3499
3500         for (i = 0; i < ARRAY_SIZE(notify_info_data_table); i++) {
3501                 if ( (notify_info_data_table[i].type == type) &&
3502                      (notify_info_data_table[i].field == field) ) {
3503                         return notify_info_data_table[i].variable_type;
3504                 }
3505         }
3506
3507         DEBUG(5, ("invalid notify data type %d/%d\n", type, field));
3508
3509         return 0;
3510 }
3511
3512 /****************************************************************************
3513 ****************************************************************************/
3514
3515 static bool search_notify(enum spoolss_NotifyType type,
3516                           enum spoolss_Field field,
3517                           int *value)
3518 {
3519         int i;
3520
3521         for (i = 0; i < ARRAY_SIZE(notify_info_data_table); i++) {
3522                 if (notify_info_data_table[i].type == type &&
3523                     notify_info_data_table[i].field == field &&
3524                     notify_info_data_table[i].fn != NULL) {
3525                         *value = i;
3526                         return True;
3527                 }
3528         }
3529
3530         return False;
3531 }
3532
3533 /****************************************************************************
3534 ****************************************************************************/
3535
3536 void construct_info_data(struct spoolss_Notify *info_data,
3537                          enum spoolss_NotifyType type,
3538                          enum spoolss_Field field,
3539                          int id)
3540 {
3541         info_data->type                 = type;
3542         info_data->field                = field;
3543         info_data->variable_type        = variable_type_of_notify_info_data(type, field);
3544         info_data->job_id               = id;
3545 }
3546
3547 /*******************************************************************
3548  *
3549  * fill a notify_info struct with info asked
3550  *
3551  ********************************************************************/
3552
3553 static bool construct_notify_printer_info(Printer_entry *print_hnd,
3554                                           struct spoolss_NotifyInfo *info,
3555                                           int snum,
3556                                           const struct spoolss_NotifyOptionType *option_type,
3557                                           uint32_t id,
3558                                           TALLOC_CTX *mem_ctx)
3559 {
3560         int field_num,j;
3561         enum spoolss_NotifyType type;
3562         enum spoolss_Field field;
3563
3564         struct spoolss_Notify *current_data;
3565         NT_PRINTER_INFO_LEVEL *printer = NULL;
3566         print_queue_struct *queue=NULL;
3567
3568         type = option_type->type;
3569
3570         DEBUG(4,("construct_notify_printer_info: Notify type: [%s], number of notify info: [%d] on printer: [%s]\n",
3571                 (type == PRINTER_NOTIFY_TYPE ? "PRINTER_NOTIFY_TYPE" : "JOB_NOTIFY_TYPE"),
3572                 option_type->count, lp_servicename(snum)));
3573
3574         if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &printer, 2, lp_const_servicename(snum))))
3575                 return False;
3576
3577         for(field_num=0; field_num < option_type->count; field_num++) {
3578                 field = option_type->fields[field_num];
3579
3580                 DEBUG(4,("construct_notify_printer_info: notify [%d]: type [%x], field [%x]\n", field_num, type, field));
3581
3582                 if (!search_notify(type, field, &j) )
3583                         continue;
3584
3585                 info->notifies = TALLOC_REALLOC_ARRAY(info, info->notifies,
3586                                                       struct spoolss_Notify,
3587                                                       info->count + 1);
3588                 if (info->notifies == NULL) {
3589                         DEBUG(2,("construct_notify_printer_info: failed to enlarge buffer info->data!\n"));
3590                         free_a_printer(&printer, 2);
3591                         return False;
3592                 }
3593
3594                 current_data = &info->notifies[info->count];
3595
3596                 construct_info_data(current_data, type, field, id);
3597
3598                 DEBUG(10,("construct_notify_printer_info: calling [%s]  snum=%d  printername=[%s])\n",
3599                                 notify_info_data_table[j].name, snum, printer->info_2->printername ));
3600
3601                 notify_info_data_table[j].fn(snum, current_data, queue,
3602                                              printer, mem_ctx);
3603
3604                 info->count++;
3605         }
3606
3607         free_a_printer(&printer, 2);
3608         return True;
3609 }
3610
3611 /*******************************************************************
3612  *
3613  * fill a notify_info struct with info asked
3614  *
3615  ********************************************************************/
3616
3617 static bool construct_notify_jobs_info(print_queue_struct *queue,
3618                                        struct spoolss_NotifyInfo *info,
3619                                        NT_PRINTER_INFO_LEVEL *printer,
3620                                        int snum,
3621                                        const struct spoolss_NotifyOptionType *option_type,
3622                                        uint32_t id,
3623                                        TALLOC_CTX *mem_ctx)
3624 {
3625         int field_num,j;
3626         enum spoolss_NotifyType type;
3627         enum spoolss_Field field;
3628         struct spoolss_Notify *current_data;
3629
3630         DEBUG(4,("construct_notify_jobs_info\n"));
3631
3632         type = option_type->type;
3633
3634         DEBUGADD(4,("Notify type: [%s], number of notify info: [%d]\n",
3635                 (type == PRINTER_NOTIFY_TYPE ? "PRINTER_NOTIFY_TYPE" : "JOB_NOTIFY_TYPE"),
3636                 option_type->count));
3637
3638         for(field_num=0; field_num<option_type->count; field_num++) {
3639                 field = option_type->fields[field_num];
3640
3641                 if (!search_notify(type, field, &j) )
3642                         continue;
3643
3644                 info->notifies = TALLOC_REALLOC_ARRAY(info, info->notifies,
3645                                                       struct spoolss_Notify,
3646                                                       info->count + 1);
3647                 if (info->notifies == NULL) {
3648                         DEBUG(2,("construct_notify_jobs_info: failed to enlarg buffer info->data!\n"));
3649                         return False;
3650                 }
3651
3652                 current_data=&(info->notifies[info->count]);
3653
3654                 construct_info_data(current_data, type, field, id);
3655                 notify_info_data_table[j].fn(snum, current_data, queue,
3656                                              printer, mem_ctx);
3657                 info->count++;
3658         }
3659
3660         return True;
3661 }
3662
3663 /*
3664  * JFM: The enumeration is not that simple, it's even non obvious.
3665  *
3666  * let's take an example: I want to monitor the PRINTER SERVER for
3667  * the printer's name and the number of jobs currently queued.
3668  * So in the NOTIFY_OPTION, I have one NOTIFY_OPTION_TYPE structure.
3669  * Its type is PRINTER_NOTIFY_TYPE and it has 2 fields NAME and CJOBS.
3670  *
3671  * I have 3 printers on the back of my server.
3672  *
3673  * Now the response is a NOTIFY_INFO structure, with 6 NOTIFY_INFO_DATA
3674  * structures.
3675  *   Number     Data                    Id
3676  *      1       printer 1 name          1
3677  *      2       printer 1 cjob          1
3678  *      3       printer 2 name          2
3679  *      4       printer 2 cjob          2
3680  *      5       printer 3 name          3
3681  *      6       printer 3 name          3
3682  *
3683  * that's the print server case, the printer case is even worse.
3684  */
3685
3686 /*******************************************************************
3687  *
3688  * enumerate all printers on the printserver
3689  * fill a notify_info struct with info asked
3690  *
3691  ********************************************************************/
3692
3693 static WERROR printserver_notify_info(pipes_struct *p, POLICY_HND *hnd,
3694                                       struct spoolss_NotifyInfo *info,
3695                                       TALLOC_CTX *mem_ctx)
3696 {
3697         int snum;
3698         Printer_entry *Printer=find_printer_index_by_hnd(p, hnd);
3699         int n_services=lp_numservices();
3700         int i;
3701         struct spoolss_NotifyOption *option;
3702         struct spoolss_NotifyOptionType option_type;
3703
3704         DEBUG(4,("printserver_notify_info\n"));
3705
3706         if (!Printer)
3707                 return WERR_BADFID;
3708
3709         option = Printer->notify.option;
3710
3711         info->version   = 2;
3712         info->notifies  = NULL;
3713         info->count     = 0;
3714
3715         /* a bug in xp sp2 rc2 causes it to send a fnpcn request without
3716            sending a ffpcn() request first */
3717
3718         if ( !option )
3719                 return WERR_BADFID;
3720
3721         for (i=0; i<option->count; i++) {
3722                 option_type = option->types[i];
3723
3724                 if (option_type.type != PRINTER_NOTIFY_TYPE)
3725                         continue;
3726
3727                 for (snum=0; snum<n_services; snum++)
3728                 {
3729                         if ( lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) )
3730                                 construct_notify_printer_info ( Printer, info, snum, &option_type, snum, mem_ctx );
3731                 }
3732         }
3733
3734 #if 0
3735         /*
3736          * Debugging information, don't delete.
3737          */
3738
3739         DEBUG(1,("dumping the NOTIFY_INFO\n"));
3740         DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
3741         DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3742
3743         for (i=0; i<info->count; i++) {
3744                 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3745                 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
3746                 info->data[i].id, info->data[i].size, info->data[i].enc_type));
3747         }
3748 #endif
3749
3750         return WERR_OK;
3751 }
3752
3753 /*******************************************************************
3754  *
3755  * fill a notify_info struct with info asked
3756  *
3757  ********************************************************************/
3758
3759 static WERROR printer_notify_info(pipes_struct *p, POLICY_HND *hnd, struct spoolss_NotifyInfo *info,
3760                                   TALLOC_CTX *mem_ctx)
3761 {
3762         int snum;
3763         Printer_entry *Printer=find_printer_index_by_hnd(p, hnd);
3764         int i;
3765         uint32 id;
3766         struct spoolss_NotifyOption *option;
3767         struct spoolss_NotifyOptionType option_type;
3768         int count,j;
3769         print_queue_struct *queue=NULL;
3770         print_status_struct status;
3771
3772         DEBUG(4,("printer_notify_info\n"));
3773
3774         if (!Printer)
3775                 return WERR_BADFID;
3776
3777         option = Printer->notify.option;
3778         id = 0x0;
3779
3780         info->version   = 2;
3781         info->notifies  = NULL;
3782         info->count     = 0;
3783
3784         /* a bug in xp sp2 rc2 causes it to send a fnpcn request without
3785            sending a ffpcn() request first */
3786
3787         if ( !option )
3788                 return WERR_BADFID;
3789
3790         get_printer_snum(p, hnd, &snum, NULL);
3791
3792         for (i=0; i<option->count; i++) {
3793                 option_type = option->types[i];
3794
3795                 switch (option_type.type) {
3796                 case PRINTER_NOTIFY_TYPE:
3797                         if(construct_notify_printer_info(Printer, info, snum,
3798                                                          &option_type, id,
3799                                                          mem_ctx))
3800                                 id--;
3801                         break;
3802
3803                 case JOB_NOTIFY_TYPE: {
3804                         NT_PRINTER_INFO_LEVEL *printer = NULL;
3805
3806                         count = print_queue_status(snum, &queue, &status);
3807
3808                         if (!W_ERROR_IS_OK(get_a_printer(Printer, &printer, 2, lp_const_servicename(snum))))
3809                                 goto done;
3810
3811                         for (j=0; j<count; j++) {
3812                                 construct_notify_jobs_info(&queue[j], info,
3813                                                            printer, snum,
3814                                                            &option_type,
3815                                                            queue[j].job,
3816                                                            mem_ctx);
3817                         }
3818
3819                         free_a_printer(&printer, 2);
3820
3821                 done:
3822                         SAFE_FREE(queue);
3823                         break;
3824                 }
3825                 }
3826         }
3827
3828         /*
3829          * Debugging information, don't delete.
3830          */
3831         /*
3832         DEBUG(1,("dumping the NOTIFY_INFO\n"));
3833         DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
3834         DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3835
3836         for (i=0; i<info->count; i++) {
3837                 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3838                 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
3839                 info->data[i].id, info->data[i].size, info->data[i].enc_type));
3840         }
3841         */
3842         return WERR_OK;
3843 }
3844
3845 /****************************************************************
3846  _spoolss_RouterRefreshPrinterChangeNotify
3847 ****************************************************************/
3848
3849 WERROR _spoolss_RouterRefreshPrinterChangeNotify(pipes_struct *p,
3850                                                  struct spoolss_RouterRefreshPrinterChangeNotify *r)
3851 {
3852         POLICY_HND *handle = r->in.handle;
3853         struct spoolss_NotifyInfo *info;
3854
3855         Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
3856         WERROR result = WERR_BADFID;
3857
3858         /* we always have a spoolss_NotifyInfo struct */
3859         info = talloc_zero(p->mem_ctx, struct spoolss_NotifyInfo);
3860         if (!info) {
3861                 result = WERR_NOMEM;
3862                 goto done;
3863         }
3864
3865         *r->out.info = info;
3866
3867         if (!Printer) {
3868                 DEBUG(2,("_spoolss_RouterRefreshPrinterChangeNotify: "
3869                         "Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
3870                 goto done;
3871         }
3872
3873         DEBUG(4,("Printer type %x\n",Printer->printer_type));
3874
3875         /*
3876          *      We are now using the change value, and
3877          *      I should check for PRINTER_NOTIFY_OPTIONS_REFRESH but as
3878          *      I don't have a global notification system, I'm sending back all the
3879          *      informations even when _NOTHING_ has changed.
3880          */
3881
3882         /* We need to keep track of the change value to send back in
3883            RRPCN replies otherwise our updates are ignored. */
3884
3885         Printer->notify.fnpcn = True;
3886
3887         if (Printer->notify.client_connected) {
3888                 DEBUG(10,("_spoolss_RouterRefreshPrinterChangeNotify: "
3889                         "Saving change value in request [%x]\n",
3890                         r->in.change_low));
3891                 Printer->notify.change = r->in.change_low;
3892         }
3893
3894         /* just ignore the spoolss_NotifyOption */
3895
3896         switch (Printer->printer_type) {
3897                 case SPLHND_SERVER:
3898                         result = printserver_notify_info(p, handle, info, p->mem_ctx);
3899                         break;
3900
3901                 case SPLHND_PRINTER:
3902                         result = printer_notify_info(p, handle, info, p->mem_ctx);
3903                         break;
3904         }
3905
3906         Printer->notify.fnpcn = False;
3907
3908 done:
3909         return result;
3910 }
3911
3912 /********************************************************************
3913  * construct_printer_info_0
3914  * fill a printer_info_0 struct
3915  ********************************************************************/
3916
3917 static bool construct_printer_info_0(Printer_entry *print_hnd, PRINTER_INFO_0 *printer, int snum)
3918 {
3919         char *chaine = NULL;
3920         int count;
3921         NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
3922         counter_printer_0 *session_counter;
3923         uint32 global_counter;
3924         struct tm *t;
3925         time_t setuptime;
3926         print_status_struct status;
3927         TALLOC_CTX *ctx = talloc_tos();
3928
3929         if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
3930                 return False;
3931
3932         init_unistr(&printer->printername, ntprinter->info_2->printername);
3933
3934         chaine = talloc_asprintf(ctx, "\\\\%s", get_server_name(print_hnd));
3935         if (!chaine) {
3936                 free_a_printer(&ntprinter,2);
3937                 return false;
3938         }
3939
3940         count = print_queue_length(snum, &status);
3941
3942         /* check if we already have a counter for this printer */
3943         for(session_counter = counter_list; session_counter; session_counter = session_counter->next) {
3944                 if (session_counter->snum == snum)
3945                         break;
3946         }
3947
3948         init_unistr(&printer->servername, chaine);
3949
3950         /* it's the first time, add it to the list */
3951         if (session_counter==NULL) {
3952                 if((session_counter=SMB_MALLOC_P(counter_printer_0)) == NULL) {
3953                         free_a_printer(&ntprinter, 2);
3954                         return False;
3955                 }
3956                 ZERO_STRUCTP(session_counter);
3957                 session_counter->snum=snum;
3958                 session_counter->counter=0;
3959                 DLIST_ADD(counter_list, session_counter);
3960         }
3961
3962         /* increment it */
3963         session_counter->counter++;
3964
3965         /* JFM:
3966          * the global_counter should be stored in a TDB as it's common to all the clients
3967          * and should be zeroed on samba startup
3968          */
3969         global_counter=session_counter->counter;
3970         printer->cjobs = count;
3971         printer->total_jobs = 0;
3972         printer->total_bytes = 0;
3973
3974         setuptime = (time_t)ntprinter->info_2->setuptime;
3975         t=gmtime(&setuptime);
3976
3977         printer->year = t->tm_year+1900;
3978         printer->month = t->tm_mon+1;
3979         printer->dayofweek = t->tm_wday;
3980         printer->day = t->tm_mday;
3981         printer->hour = t->tm_hour;
3982         printer->minute = t->tm_min;
3983         printer->second = t->tm_sec;
3984         printer->milliseconds = 0;
3985
3986         printer->global_counter = global_counter;
3987         printer->total_pages = 0;
3988
3989         /* in 2.2 we reported ourselves as 0x0004 and 0x0565 */
3990         printer->major_version = 0x0005;        /* NT 5 */
3991         printer->build_version = 0x0893;        /* build 2195 */
3992
3993         printer->unknown7 = 0x1;
3994         printer->unknown8 = 0x0;
3995         printer->unknown9 = 0x0;
3996         printer->session_counter = session_counter->counter;
3997         printer->unknown11 = 0x0;
3998         printer->printer_errors = 0x0;          /* number of print failure */
3999         printer->unknown13 = 0x0;
4000         printer->unknown14 = 0x1;
4001         printer->unknown15 = 0x024a;            /* 586 Pentium ? */
4002         printer->unknown16 =  0x0;
4003         printer->change_id = ntprinter->info_2->changeid; /* ChangeID in milliseconds*/
4004         printer->unknown18 =  0x0;
4005         printer->status = nt_printq_status(status.status);
4006         printer->unknown20 =  0x0;
4007         printer->c_setprinter = get_c_setprinter(); /* monotonically increasing sum of delta printer counts */
4008         printer->unknown22 = 0x0;
4009         printer->unknown23 = 0x6;               /* 6  ???*/
4010         printer->unknown24 = 0;                 /* unknown 24 to 26 are always 0 */
4011         printer->unknown25 = 0;
4012         printer->unknown26 = 0;
4013         printer->unknown27 = 0;
4014         printer->unknown28 = 0;
4015         printer->unknown29 = 0;
4016
4017         free_a_printer(&ntprinter,2);
4018         return (True);
4019 }
4020
4021 /********************************************************************
4022  * construct_printer_info_1
4023  * fill a printer_info_1 struct
4024  ********************************************************************/
4025 static bool construct_printer_info_1(Printer_entry *print_hnd, uint32 flags, PRINTER_INFO_1 *printer, int snum)
4026 {
4027         char *chaine = NULL;
4028         NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4029         TALLOC_CTX *ctx = talloc_tos();
4030
4031         if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
4032                 return false;
4033
4034         printer->flags=flags;
4035
4036         if (*ntprinter->info_2->comment == '\0') {
4037                 init_unistr(&printer->comment, lp_comment(snum));
4038                 chaine = talloc_asprintf(ctx,
4039                                 "%s,%s,%s", ntprinter->info_2->printername,
4040                                 ntprinter->info_2->drivername, lp_comment(snum));
4041         }
4042         else {
4043                 init_unistr(&printer->comment, ntprinter->info_2->comment); /* saved comment. */
4044                 chaine = talloc_asprintf(ctx,
4045                                 "%s,%s,%s", ntprinter->info_2->printername,
4046                                 ntprinter->info_2->drivername, ntprinter->info_2->comment);
4047         }
4048
4049         if (!chaine) {
4050                 free_a_printer(&ntprinter,2);
4051                 return false;
4052         }
4053
4054         init_unistr(&printer->description, chaine);
4055         init_unistr(&printer->name, ntprinter->info_2->printername);
4056
4057         free_a_printer(&ntprinter,2);
4058
4059         return True;
4060 }
4061
4062 /****************************************************************************
4063  Free a DEVMODE struct.
4064 ****************************************************************************/
4065
4066 static void free_dev_mode(DEVICEMODE *dev)
4067 {
4068         if (dev == NULL)
4069                 return;
4070
4071         SAFE_FREE(dev->dev_private);
4072         SAFE_FREE(dev);
4073 }
4074
4075
4076 /****************************************************************************
4077  Convert an NT_DEVICEMODE to a DEVICEMODE structure.  Both pointers
4078  should be valid upon entry
4079 ****************************************************************************/
4080
4081 static bool convert_nt_devicemode( DEVICEMODE *devmode, NT_DEVICEMODE *ntdevmode )
4082 {
4083         if ( !devmode || !ntdevmode )
4084                 return False;
4085
4086         init_unistr(&devmode->devicename, ntdevmode->devicename);
4087
4088         init_unistr(&devmode->formname, ntdevmode->formname);
4089
4090         devmode->specversion      = ntdevmode->specversion;
4091         devmode->driverversion    = ntdevmode->driverversion;
4092         devmode->size             = ntdevmode->size;
4093         devmode->driverextra      = ntdevmode->driverextra;
4094         devmode->fields           = ntdevmode->fields;
4095
4096         devmode->orientation      = ntdevmode->orientation;
4097         devmode->papersize        = ntdevmode->papersize;
4098         devmode->paperlength      = ntdevmode->paperlength;
4099         devmode->paperwidth       = ntdevmode->paperwidth;
4100         devmode->scale            = ntdevmode->scale;
4101         devmode->copies           = ntdevmode->copies;
4102         devmode->defaultsource    = ntdevmode->defaultsource;
4103         devmode->printquality     = ntdevmode->printquality;
4104         devmode->color            = ntdevmode->color;
4105         devmode->duplex           = ntdevmode->duplex;
4106         devmode->yresolution      = ntdevmode->yresolution;
4107         devmode->ttoption         = ntdevmode->ttoption;
4108         devmode->collate          = ntdevmode->collate;
4109         devmode->icmmethod        = ntdevmode->icmmethod;
4110         devmode->icmintent        = ntdevmode->icmintent;
4111         devmode->mediatype        = ntdevmode->mediatype;
4112         devmode->dithertype       = ntdevmode->dithertype;
4113
4114         if (ntdevmode->nt_dev_private != NULL) {
4115                 if ((devmode->dev_private=(uint8 *)memdup(ntdevmode->nt_dev_private, ntdevmode->driverextra)) == NULL)
4116                         return False;
4117         }
4118
4119         return True;
4120 }
4121
4122 /****************************************************************************
4123  Create a DEVMODE struct. Returns malloced memory.
4124 ****************************************************************************/
4125
4126 DEVICEMODE *construct_dev_mode(const char *servicename)
4127 {
4128         NT_PRINTER_INFO_LEVEL   *printer = NULL;
4129         DEVICEMODE              *devmode = NULL;
4130
4131         DEBUG(7,("construct_dev_mode\n"));
4132
4133         DEBUGADD(8,("getting printer characteristics\n"));
4134
4135         if (!W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, servicename)))
4136                 return NULL;
4137
4138         if ( !printer->info_2->devmode ) {
4139                 DEBUG(5, ("BONG! There was no device mode!\n"));
4140                 goto done;
4141         }
4142
4143         if ((devmode = SMB_MALLOC_P(DEVICEMODE)) == NULL) {
4144                 DEBUG(2,("construct_dev_mode: malloc fail.\n"));
4145                 goto done;
4146         }
4147
4148         ZERO_STRUCTP(devmode);
4149
4150         DEBUGADD(8,("loading DEVICEMODE\n"));
4151
4152         if ( !convert_nt_devicemode( devmode, printer->info_2->devmode ) ) {
4153                 free_dev_mode( devmode );
4154                 devmode = NULL;
4155         }
4156
4157 done:
4158         free_a_printer(&printer,2);
4159
4160         return devmode;
4161 }
4162
4163 /********************************************************************
4164  * construct_printer_info_2
4165  * fill a printer_info_2 struct
4166  ********************************************************************/
4167
4168 static bool construct_printer_info_2(Printer_entry *print_hnd, PRINTER_INFO_2 *printer, int snum)
4169 {
4170         int count;
4171         NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4172
4173         print_status_struct status;
4174
4175         if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
4176                 return False;
4177
4178         count = print_queue_length(snum, &status);
4179
4180         init_unistr(&printer->servername, ntprinter->info_2->servername); /* servername*/
4181         init_unistr(&printer->printername, ntprinter->info_2->printername);                             /* printername*/
4182         init_unistr(&printer->sharename, lp_servicename(snum));                 /* sharename */
4183         init_unistr(&printer->portname, ntprinter->info_2->portname);                   /* port */
4184         init_unistr(&printer->drivername, ntprinter->info_2->drivername);       /* drivername */
4185
4186         if (*ntprinter->info_2->comment == '\0')
4187                 init_unistr(&printer->comment, lp_comment(snum));                       /* comment */
4188         else
4189                 init_unistr(&printer->comment, ntprinter->info_2->comment); /* saved comment. */
4190
4191         init_unistr(&printer->location, ntprinter->info_2->location);           /* location */
4192         init_unistr(&printer->sepfile, ntprinter->info_2->sepfile);             /* separator file */
4193         init_unistr(&printer->printprocessor, ntprinter->info_2->printprocessor);/* print processor */
4194         init_unistr(&printer->datatype, ntprinter->info_2->datatype);           /* datatype */
4195         init_unistr(&printer->parameters, ntprinter->info_2->parameters);       /* parameters (of print processor) */
4196
4197         printer->attributes = ntprinter->info_2->attributes;
4198
4199         printer->priority = ntprinter->info_2->priority;                                /* priority */
4200         printer->defaultpriority = ntprinter->info_2->default_priority;         /* default priority */
4201         printer->starttime = ntprinter->info_2->starttime;                      /* starttime */
4202         printer->untiltime = ntprinter->info_2->untiltime;                      /* untiltime */
4203         printer->status = nt_printq_status(status.status);                      /* status */
4204         printer->cjobs = count;                                                 /* jobs */
4205         printer->averageppm = ntprinter->info_2->averageppm;                    /* average pages per minute */
4206
4207         if ( !(printer->devmode = construct_dev_mode(
4208                        lp_const_servicename(snum))) )
4209                 DEBUG(8, ("Returning NULL Devicemode!\n"));
4210
4211         printer->secdesc = NULL;
4212
4213         if ( ntprinter->info_2->secdesc_buf
4214                 && ntprinter->info_2->secdesc_buf->sd_size != 0 )
4215         {
4216                 /* don't use talloc_steal() here unless you do a deep steal of all
4217                    the SEC_DESC members */
4218
4219                 printer->secdesc = dup_sec_desc( talloc_tos(),
4220                         ntprinter->info_2->secdesc_buf->sd );
4221         }
4222
4223         free_a_printer(&ntprinter, 2);
4224
4225         return True;
4226 }
4227
4228 /********************************************************************
4229  * construct_printer_info_3
4230  * fill a printer_info_3 struct
4231  ********************************************************************/
4232
4233 static bool construct_printer_info_3(Printer_entry *print_hnd, PRINTER_INFO_3 **pp_printer, int snum)
4234 {
4235         NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4236         PRINTER_INFO_3 *printer = NULL;
4237
4238         if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
4239                 return False;
4240
4241         *pp_printer = NULL;
4242         if ((printer = SMB_MALLOC_P(PRINTER_INFO_3)) == NULL) {
4243                 DEBUG(2,("construct_printer_info_3: malloc fail.\n"));
4244                 free_a_printer(&ntprinter, 2);
4245                 return False;
4246         }
4247
4248         ZERO_STRUCTP(printer);
4249
4250         /* These are the components of the SD we are returning. */
4251
4252         if (ntprinter->info_2->secdesc_buf && ntprinter->info_2->secdesc_buf->sd_size != 0) {
4253                 /* don't use talloc_steal() here unless you do a deep steal of all
4254                    the SEC_DESC members */
4255
4256                 printer->secdesc = dup_sec_desc( talloc_tos(),
4257                         ntprinter->info_2->secdesc_buf->sd );
4258         }
4259
4260         free_a_printer(&ntprinter, 2);
4261
4262         *pp_printer = printer;
4263         return True;
4264 }
4265
4266 /********************************************************************
4267  * construct_printer_info_4
4268  * fill a printer_info_4 struct
4269  ********************************************************************/
4270
4271 static bool construct_printer_info_4(Printer_entry *print_hnd, PRINTER_INFO_4 *printer, int snum)
4272 {
4273         NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4274
4275         if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
4276                 return False;
4277
4278         init_unistr(&printer->printername, ntprinter->info_2->printername);                             /* printername*/
4279         init_unistr(&printer->servername, ntprinter->info_2->servername); /* servername*/
4280         printer->attributes = ntprinter->info_2->attributes;
4281
4282         free_a_printer(&ntprinter, 2);
4283         return True;
4284 }
4285
4286 /********************************************************************
4287  * construct_printer_info_5
4288  * fill a printer_info_5 struct
4289  ********************************************************************/
4290
4291 static bool construct_printer_info_5(Printer_entry *print_hnd, PRINTER_INFO_5 *printer, int snum)
4292 {
4293         NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4294
4295         if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
4296                 return False;
4297
4298         init_unistr(&printer->printername, ntprinter->info_2->printername);
4299         init_unistr(&printer->portname, ntprinter->info_2->portname);
4300         printer->attributes = ntprinter->info_2->attributes;
4301
4302         /* these two are not used by NT+ according to MSDN */
4303
4304         printer->device_not_selected_timeout = 0x0;  /* have seen 0x3a98 */
4305         printer->transmission_retry_timeout  = 0x0;  /* have seen 0xafc8 */
4306
4307         free_a_printer(&ntprinter, 2);
4308
4309         return True;
4310 }
4311
4312 /********************************************************************
4313  * construct_printer_info_6
4314  * fill a printer_info_6 struct
4315  ********************************************************************/
4316
4317 static bool construct_printer_info_6(Printer_entry *print_hnd,
4318                                      PRINTER_INFO_6 *printer,
4319                                      int snum)
4320 {
4321         NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4322         int count;
4323         print_status_struct status;
4324
4325         if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2,
4326                                          lp_const_servicename(snum))))
4327                 return False;
4328
4329         count = print_queue_length(snum, &status);
4330
4331         printer->status = nt_printq_status(status.status);
4332
4333         free_a_printer(&ntprinter, 2);
4334
4335         return True;
4336 }
4337
4338 /********************************************************************
4339  * construct_printer_info_7
4340  * fill a printer_info_7 struct
4341  ********************************************************************/
4342
4343 static bool construct_printer_info_7(Printer_entry *print_hnd, PRINTER_INFO_7 *printer, int snum)
4344 {
4345         char *guid_str = NULL;
4346         struct GUID guid;
4347
4348         if (is_printer_published(print_hnd, snum, &guid)) {
4349                 if (asprintf(&guid_str, "{%s}",
4350                              GUID_string(talloc_tos(), &guid)) == -1) {
4351                         return false;
4352                 }
4353                 strupper_m(guid_str);
4354                 init_unistr(&printer->guid, guid_str);
4355                 SAFE_FREE(guid_str);
4356                 printer->action = DSPRINT_PUBLISH;
4357         } else {
4358                 init_unistr(&printer->guid, "");
4359                 printer->action = DSPRINT_UNPUBLISH;
4360         }
4361
4362         return True;
4363 }
4364
4365 /********************************************************************
4366  Spoolss_enumprinters.
4367 ********************************************************************/
4368
4369 static WERROR enum_all_printers_info_1(uint32 flags, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4370 {
4371         int snum;
4372         int i;
4373         int n_services=lp_numservices();
4374         PRINTER_INFO_1 *printers=NULL;
4375         PRINTER_INFO_1 current_prt;
4376         WERROR result = WERR_OK;
4377
4378         DEBUG(4,("enum_all_printers_info_1\n"));
4379
4380         for (snum=0; snum<n_services; snum++) {
4381                 if (lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) ) {
4382                         DEBUG(4,("Found a printer in smb.conf: %s[%x]\n", lp_servicename(snum), snum));
4383
4384                         if (construct_printer_info_1(NULL, flags, &current_prt, snum)) {
4385                                 if((printers=SMB_REALLOC_ARRAY(printers, PRINTER_INFO_1, *returned +1)) == NULL) {
4386                                         DEBUG(2,("enum_all_printers_info_1: failed to enlarge printers buffer!\n"));
4387                                         *returned=0;
4388                                         return WERR_NOMEM;
4389                                 }
4390                                 DEBUG(4,("ReAlloced memory for [%d] PRINTER_INFO_1\n", *returned));
4391
4392                                 memcpy(&printers[*returned], &current_prt, sizeof(PRINTER_INFO_1));
4393                                 (*returned)++;
4394                         }
4395                 }
4396         }
4397
4398         /* check the required size. */
4399         for (i=0; i<*returned; i++)
4400                 (*needed) += spoolss_size_printer_info_1(&printers[i]);
4401
4402         if (*needed > offered) {
4403                 result = WERR_INSUFFICIENT_BUFFER;
4404                 goto out;
4405         }
4406
4407         if (!rpcbuf_alloc_size(buffer, *needed)) {
4408                 result = WERR_NOMEM;
4409                 goto out;
4410         }
4411
4412         /* fill the buffer with the structures */
4413         for (i=0; i<*returned; i++)
4414                 smb_io_printer_info_1("", buffer, &printers[i], 0);
4415
4416 out:
4417         /* clear memory */
4418
4419         SAFE_FREE(printers);
4420
4421         if ( !W_ERROR_IS_OK(result) )
4422                 *returned = 0;
4423
4424         return result;
4425 }
4426
4427 /********************************************************************
4428  enum_all_printers_info_1_local.
4429 *********************************************************************/
4430
4431 static WERROR enum_all_printers_info_1_local(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4432 {
4433         DEBUG(4,("enum_all_printers_info_1_local\n"));
4434
4435         return enum_all_printers_info_1(PRINTER_ENUM_ICON8, buffer, offered, needed, returned);
4436 }
4437
4438 /********************************************************************
4439  enum_all_printers_info_1_name.
4440 *********************************************************************/
4441
4442 static WERROR enum_all_printers_info_1_name(fstring name, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4443 {
4444         char *s = name;
4445
4446         DEBUG(4,("enum_all_printers_info_1_name\n"));
4447
4448         if ((name[0] == '\\') && (name[1] == '\\'))
4449                 s = name + 2;
4450
4451         if (is_myname_or_ipaddr(s)) {
4452                 return enum_all_printers_info_1(PRINTER_ENUM_ICON8, buffer, offered, needed, returned);
4453         }
4454         else
4455                 return WERR_INVALID_NAME;
4456 }
4457
4458 #if 0   /* JERRY -- disabled for now.  Don't think this is used, tested, or correct */
4459 /********************************************************************
4460  enum_all_printers_info_1_remote.
4461 *********************************************************************/
4462
4463 static WERROR enum_all_printers_info_1_remote(fstring name, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4464 {
4465         PRINTER_INFO_1 *printer;
4466         fstring printername;
4467         fstring desc;
4468         fstring comment;
4469         DEBUG(4,("enum_all_printers_info_1_remote\n"));
4470         WERROR result = WERR_OK;
4471
4472         /* JFM: currently it's more a place holder than anything else.
4473          * In the spooler world there is a notion of server registration.
4474          * the print servers are registered on the PDC (in the same domain)
4475          *
4476          * We should have a TDB here. The registration is done thru an
4477          * undocumented RPC call.
4478          */
4479
4480         if((printer=SMB_MALLOC_P(PRINTER_INFO_1)) == NULL)
4481                 return WERR_NOMEM;
4482
4483         *returned=1;
4484
4485         slprintf(printername, sizeof(printername)-1,"Windows NT Remote Printers!!\\\\%s", name);
4486         slprintf(desc, sizeof(desc)-1,"%s", name);
4487         slprintf(comment, sizeof(comment)-1, "Logged on Domain");
4488
4489         init_unistr(&printer->description, desc);
4490         init_unistr(&printer->name, printername);
4491         init_unistr(&printer->comment, comment);
4492         printer->flags=PRINTER_ENUM_ICON3|PRINTER_ENUM_CONTAINER;
4493
4494         /* check the required size. */
4495         *needed += spoolss_size_printer_info_1(printer);
4496
4497         if (*needed > offered) {
4498                 result = WERR_INSUFFICIENT_BUFFER;
4499                 goto out;
4500         }
4501
4502         if (!rpcbuf_alloc_size(buffer, *needed)) {
4503                 result = WERR_NOMEM;
4504                 goto out;
4505         }
4506
4507         /* fill the buffer with the structures */
4508         smb_io_printer_info_1("", buffer, printer, 0);
4509
4510 out:
4511         /* clear memory */
4512         SAFE_FREE(printer);
4513
4514         if ( !W_ERROR_IS_OK(result) )
4515                 *returned = 0;
4516
4517         return result;
4518 }
4519
4520 #endif
4521
4522 /********************************************************************
4523  enum_all_printers_info_1_network.
4524 *********************************************************************/
4525
4526 static WERROR enum_all_printers_info_1_network(fstring name, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4527 {
4528         char *s = name;
4529
4530         DEBUG(4,("enum_all_printers_info_1_network\n"));
4531
4532         /* If we respond to a enum_printers level 1 on our name with flags
4533            set to PRINTER_ENUM_REMOTE with a list of printers then these
4534            printers incorrectly appear in the APW browse list.
4535            Specifically the printers for the server appear at the workgroup
4536            level where all the other servers in the domain are
4537            listed. Windows responds to this call with a
4538            WERR_CAN_NOT_COMPLETE so we should do the same. */
4539
4540         if (name[0] == '\\' && name[1] == '\\')
4541                  s = name + 2;
4542
4543         if (is_myname_or_ipaddr(s))
4544                  return WERR_CAN_NOT_COMPLETE;
4545
4546         return enum_all_printers_info_1(PRINTER_ENUM_NAME, buffer, offered, needed, returned);
4547 }
4548
4549 /********************************************************************
4550  * api_spoolss_enumprinters
4551  *
4552  * called from api_spoolss_enumprinters (see this to understand)
4553  ********************************************************************/
4554
4555 static WERROR enum_all_printers_info_2(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4556 {
4557         int snum;
4558         int i;
4559         int n_services=lp_numservices();
4560         PRINTER_INFO_2 *printers=NULL;
4561         PRINTER_INFO_2 current_prt;
4562         WERROR result = WERR_OK;
4563
4564         *returned = 0;
4565
4566         for (snum=0; snum<n_services; snum++) {
4567                 if (lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) ) {
4568                         DEBUG(4,("Found a printer in smb.conf: %s[%x]\n", lp_servicename(snum), snum));
4569
4570                         if (construct_printer_info_2(NULL, &current_prt, snum)) {
4571                                 if ( !(printers=SMB_REALLOC_ARRAY(printers, PRINTER_INFO_2, *returned +1)) ) {
4572                                         DEBUG(2,("enum_all_printers_info_2: failed to enlarge printers buffer!\n"));
4573                                         *returned = 0;
4574                                         return WERR_NOMEM;
4575                                 }
4576
4577                                 DEBUG(4,("ReAlloced memory for [%d] PRINTER_INFO_2\n", *returned + 1));
4578
4579                                 memcpy(&printers[*returned], &current_prt, sizeof(PRINTER_INFO_2));
4580
4581                                 (*returned)++;
4582                         }
4583                 }
4584         }
4585
4586         /* check the required size. */
4587         for (i=0; i<*returned; i++)
4588                 (*needed) += spoolss_size_printer_info_2(&printers[i]);
4589
4590         if (*needed > offered) {
4591                 result = WERR_INSUFFICIENT_BUFFER;
4592                 goto out;
4593         }
4594
4595         if (!rpcbuf_alloc_size(buffer, *needed)) {
4596                 result = WERR_NOMEM;
4597                 goto out;
4598         }
4599
4600         /* fill the buffer with the structures */
4601         for (i=0; i<*returned; i++)
4602                 smb_io_printer_info_2("", buffer, &(printers[i]), 0);
4603
4604 out:
4605         /* clear memory */
4606
4607         for (i=0; i<*returned; i++)
4608                 free_devmode(printers[i].devmode);
4609
4610         SAFE_FREE(printers);
4611
4612         if ( !W_ERROR_IS_OK(result) )
4613                 *returned = 0;
4614
4615         return result;
4616 }
4617
4618 /********************************************************************
4619  * handle enumeration of printers at level 1
4620  ********************************************************************/
4621
4622 static WERROR enumprinters_level1( uint32 flags, fstring name,
4623                                  RPC_BUFFER *buffer, uint32 offered,
4624                                  uint32 *needed, uint32 *returned)
4625 {
4626         /* Not all the flags are equals */
4627
4628         if (flags & PRINTER_ENUM_LOCAL)
4629                 return enum_all_printers_info_1_local(buffer, offered, needed, returned);
4630
4631         if (flags & PRINTER_ENUM_NAME)
4632                 return enum_all_printers_info_1_name(name, buffer, offered, needed, returned);
4633
4634 #if 0   /* JERRY - disabled for now */
4635         if (flags & PRINTER_ENUM_REMOTE)
4636                 return enum_all_printers_info_1_remote(name, buffer, offered, needed, returned);
4637 #endif
4638
4639         if (flags & PRINTER_ENUM_NETWORK)
4640                 return enum_all_printers_info_1_network(name, buffer, offered, needed, returned);
4641
4642         return WERR_OK; /* NT4sp5 does that */
4643 }
4644
4645 /********************************************************************
4646  * handle enumeration of printers at level 2
4647  ********************************************************************/
4648
4649 static WERROR enumprinters_level2( uint32 flags, const char *servername,
4650                                  RPC_BUFFER *buffer, uint32 offered,
4651                                  uint32 *needed, uint32 *returned)
4652 {
4653         if (flags & PRINTER_ENUM_LOCAL) {
4654                         return enum_all_printers_info_2(buffer, offered, needed, returned);
4655         }
4656
4657         if (flags & PRINTER_ENUM_NAME) {
4658                 if (is_myname_or_ipaddr(canon_servername(servername)))
4659                         return enum_all_printers_info_2(buffer, offered, needed, returned);
4660                 else
4661                         return WERR_INVALID_NAME;
4662         }
4663
4664         if (flags & PRINTER_ENUM_REMOTE)
4665                 return WERR_UNKNOWN_LEVEL;
4666
4667         return WERR_OK;
4668 }
4669
4670 /********************************************************************
4671  * handle enumeration of printers at level 5
4672  ********************************************************************/
4673
4674 static WERROR enumprinters_level5( uint32 flags, const char *servername,
4675                                  RPC_BUFFER *buffer, uint32 offered,
4676                                  uint32 *needed, uint32 *returned)
4677 {
4678 /*      return enum_all_printers_info_5(buffer, offered, needed, returned);*/
4679         return WERR_OK;
4680 }
4681
4682 /********************************************************************
4683  * api_spoolss_enumprinters
4684  *
4685  * called from api_spoolss_enumprinters (see this to understand)
4686  ********************************************************************/
4687
4688 WERROR _spoolss_enumprinters( pipes_struct *p, SPOOL_Q_ENUMPRINTERS *q_u, SPOOL_R_ENUMPRINTERS *r_u)
4689 {
4690         uint32 flags = q_u->flags;
4691         UNISTR2 *servername = &q_u->servername;
4692         uint32 level = q_u->level;
4693         RPC_BUFFER *buffer = NULL;
4694         uint32 offered = q_u->offered;
4695         uint32 *needed = &r_u->needed;
4696         uint32 *returned = &r_u->returned;
4697
4698         fstring name;
4699
4700         /* that's an [in out] buffer */
4701
4702         if (!q_u->buffer && (offered!=0)) {
4703                 return WERR_INVALID_PARAM;
4704         }
4705
4706         if (offered > MAX_RPC_DATA_SIZE) {
4707                 return WERR_INVALID_PARAM;
4708         }
4709
4710         rpcbuf_move(q_u->buffer, &r_u->buffer);
4711         buffer = r_u->buffer;
4712
4713         DEBUG(4,("_spoolss_enumprinters\n"));
4714
4715         *needed=0;
4716         *returned=0;
4717
4718         /*
4719          * Level 1:
4720          *          flags==PRINTER_ENUM_NAME
4721          *           if name=="" then enumerates all printers
4722          *           if name!="" then enumerate the printer
4723          *          flags==PRINTER_ENUM_REMOTE
4724          *          name is NULL, enumerate printers
4725          * Level 2: name!="" enumerates printers, name can't be NULL
4726          * Level 3: doesn't exist
4727          * Level 4: does a local registry lookup
4728          * Level 5: same as Level 2
4729          */
4730
4731         unistr2_to_ascii(name, servername, sizeof(name));
4732         strupper_m(name);
4733
4734         switch (level) {
4735         case 1:
4736                 return enumprinters_level1(flags, name, buffer, offered, needed, returned);
4737         case 2:
4738                 return enumprinters_level2(flags, name, buffer, offered, needed, returned);
4739         case 5:
4740                 return enumprinters_level5(flags, name, buffer, offered, needed, returned);
4741         case 3:
4742         case 4:
4743                 break;
4744         }
4745         return WERR_UNKNOWN_LEVEL;
4746 }
4747
4748 /****************************************************************************
4749 ****************************************************************************/
4750
4751 static WERROR getprinter_level_0(Printer_entry *print_hnd, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
4752 {
4753         PRINTER_INFO_0 *printer=NULL;
4754         WERROR result = WERR_OK;
4755
4756         if((printer=SMB_MALLOC_P(PRINTER_INFO_0)) == NULL)
4757                 return WERR_NOMEM;
4758
4759         construct_printer_info_0(print_hnd, printer, snum);
4760
4761         /* check the required size. */
4762         *needed += spoolss_size_printer_info_0(printer);
4763
4764         if (*needed > offered) {
4765                 result = WERR_INSUFFICIENT_BUFFER;
4766                 goto out;
4767         }
4768
4769         if (!rpcbuf_alloc_size(buffer, *needed)) {
4770                 result = WERR_NOMEM;
4771                 goto out;
4772         }
4773
4774         /* fill the buffer with the structures */
4775         smb_io_printer_info_0("", buffer, printer, 0);
4776
4777 out:
4778         /* clear memory */
4779
4780         SAFE_FREE(printer);
4781
4782         return result;
4783 }
4784
4785 /****************************************************************************
4786 ****************************************************************************/
4787
4788 static WERROR getprinter_level_1(Printer_entry *print_hnd, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
4789 {
4790         PRINTER_INFO_1 *printer=NULL;
4791         WERROR result = WERR_OK;
4792
4793         if((printer=SMB_MALLOC_P(PRINTER_INFO_1)) == NULL)
4794                 return WERR_NOMEM;
4795
4796         construct_printer_info_1(print_hnd, PRINTER_ENUM_ICON8, printer, snum);
4797
4798         /* check the required size. */
4799         *needed += spoolss_size_printer_info_1(printer);
4800
4801         if (*needed > offered) {
4802                 result = WERR_INSUFFICIENT_BUFFER;
4803                 goto out;
4804         }
4805
4806         if (!rpcbuf_alloc_size(buffer, *needed)) {
4807                 result = WERR_NOMEM;
4808                 goto out;
4809         }
4810
4811         /* fill the buffer with the structures */
4812         smb_io_printer_info_1("", buffer, printer, 0);
4813
4814 out:
4815         /* clear memory */
4816         SAFE_FREE(printer);
4817
4818         return result;
4819 }
4820
4821 /****************************************************************************
4822 ****************************************************************************/
4823
4824 static WERROR getprinter_level_2(Printer_entry *print_hnd, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
4825 {
4826         PRINTER_INFO_2 *printer=NULL;
4827         WERROR result = WERR_OK;
4828
4829         if((printer=SMB_MALLOC_P(PRINTER_INFO_2))==NULL)
4830                 return WERR_NOMEM;
4831
4832         construct_printer_info_2(print_hnd, printer, snum);
4833
4834         /* check the required size. */
4835         *needed += spoolss_size_printer_info_2(printer);
4836
4837         if (*needed > offered) {
4838                 result = WERR_INSUFFICIENT_BUFFER;
4839                 goto out;
4840         }
4841
4842         if (!rpcbuf_alloc_size(buffer, *needed)) {
4843                 result = WERR_NOMEM;
4844                 goto out;
4845         }
4846
4847         /* fill the buffer with the structures */
4848         if (!smb_io_printer_info_2("", buffer, printer, 0))
4849                 result = WERR_NOMEM;
4850
4851 out:
4852         /* clear memory */
4853         free_printer_info_2(printer);
4854
4855         return result;
4856 }
4857
4858 /****************************************************************************
4859 ****************************************************************************/
4860
4861 static WERROR getprinter_level_3(Printer_entry *print_hnd, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
4862 {
4863         PRINTER_INFO_3 *printer=NULL;
4864         WERROR result = WERR_OK;
4865
4866         if (!construct_printer_info_3(print_hnd, &printer, snum))
4867                 return WERR_NOMEM;
4868
4869         /* check the required size. */
4870         *needed += spoolss_size_printer_info_3(printer);
4871
4872         if (*needed > offered) {
4873                 result = WERR_INSUFFICIENT_BUFFER;
4874                 goto out;
4875         }
4876
4877         if (!rpcbuf_alloc_size(buffer, *needed)) {
4878                 result = WERR_NOMEM;
4879                 goto out;
4880         }
4881
4882         /* fill the buffer with the structures */
4883         smb_io_printer_info_3("", buffer, printer, 0);
4884
4885 out:
4886         /* clear memory */
4887         free_printer_info_3(printer);
4888
4889         return result;
4890 }
4891
4892 /****************************************************************************
4893 ****************************************************************************/
4894
4895 static WERROR getprinter_level_4(Printer_entry *print_hnd, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
4896 {
4897         PRINTER_INFO_4 *printer=NULL;
4898         WERROR result = WERR_OK;
4899
4900         if((printer=SMB_MALLOC_P(PRINTER_INFO_4))==NULL)
4901                 return WERR_NOMEM;
4902
4903         if (!construct_printer_info_4(print_hnd, printer, snum)) {
4904                 SAFE_FREE(printer);
4905                 return WERR_NOMEM;
4906         }
4907
4908         /* check the required size. */
4909         *needed += spoolss_size_printer_info_4(printer);
4910
4911         if (*needed > offered) {
4912                 result = WERR_INSUFFICIENT_BUFFER;
4913                 goto out;
4914         }
4915
4916         if (!rpcbuf_alloc_size(buffer, *needed)) {
4917                 result = WERR_NOMEM;
4918                 goto out;
4919         }
4920
4921         /* fill the buffer with the structures */
4922         smb_io_printer_info_4("", buffer, printer, 0);
4923
4924 out:
4925         /* clear memory */
4926         free_printer_info_4(printer);
4927
4928         return result;
4929 }
4930
4931 /****************************************************************************
4932 ****************************************************************************/
4933
4934 static WERROR getprinter_level_5(Printer_entry *print_hnd, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
4935 {
4936         PRINTER_INFO_5 *printer=NULL;
4937         WERROR result = WERR_OK;
4938
4939         if((printer=SMB_MALLOC_P(PRINTER_INFO_5))==NULL)
4940                 return WERR_NOMEM;
4941
4942         if (!construct_printer_info_5(print_hnd, printer, snum)) {
4943                 free_printer_info_5(printer);
4944                 return WERR_NOMEM;
4945         }
4946
4947         /* check the required size. */
4948         *needed += spoolss_size_printer_info_5(printer);
4949
4950         if (*needed > offered) {
4951                 result = WERR_INSUFFICIENT_BUFFER;
4952                 goto out;
4953         }
4954
4955         if (!rpcbuf_alloc_size(buffer, *needed)) {
4956                 result = WERR_NOMEM;
4957                 goto out;
4958         }
4959
4960         /* fill the buffer with the structures */
4961         smb_io_printer_info_5("", buffer, printer, 0);
4962
4963 out:
4964         /* clear memory */
4965         free_printer_info_5(printer);
4966
4967         return result;
4968 }
4969
4970 static WERROR getprinter_level_6(Printer_entry *print_hnd,
4971                                  int snum,
4972                                  RPC_BUFFER *buffer, uint32 offered,
4973                                  uint32 *needed)
4974 {
4975         PRINTER_INFO_6 *printer;
4976         WERROR result = WERR_OK;
4977
4978         if ((printer = SMB_MALLOC_P(PRINTER_INFO_6)) == NULL) {
4979                 return WERR_NOMEM;
4980         }
4981
4982         if (!construct_printer_info_6(print_hnd, printer, snum)) {
4983                 free_printer_info_6(printer);
4984                 return WERR_NOMEM;
4985         }
4986
4987         /* check the required size. */
4988         *needed += spoolss_size_printer_info_6(printer);
4989
4990         if (*needed > offered) {
4991                 result = WERR_INSUFFICIENT_BUFFER;
4992                 goto out;
4993         }
4994
4995         if (!rpcbuf_alloc_size(buffer, *needed)) {
4996                 result = WERR_NOMEM;
4997                 goto out;
4998         }
4999
5000         /* fill the buffer with the structures */
5001         smb_io_printer_info_6("", buffer, printer, 0);
5002
5003 out:
5004         /* clear memory */
5005         free_printer_info_6(printer);
5006
5007         return result;
5008 }
5009
5010 static WERROR getprinter_level_7(Printer_entry *print_hnd, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
5011 {
5012         PRINTER_INFO_7 *printer=NULL;
5013         WERROR result = WERR_OK;
5014
5015         if((printer=SMB_MALLOC_P(PRINTER_INFO_7))==NULL)
5016                 return WERR_NOMEM;
5017
5018         if (!construct_printer_info_7(print_hnd, printer, snum)) {
5019                 result = WERR_NOMEM;
5020                 goto out;
5021         }
5022
5023         /* check the required size. */
5024         *needed += spoolss_size_printer_info_7(printer);
5025
5026         if (*needed > offered) {
5027                 result = WERR_INSUFFICIENT_BUFFER;
5028                 goto out;
5029         }
5030
5031         if (!rpcbuf_alloc_size(buffer, *needed)) {
5032                 result = WERR_NOMEM;
5033                 goto out;
5034
5035         }
5036
5037         /* fill the buffer with the structures */
5038         smb_io_printer_info_7("", buffer, printer, 0);
5039
5040 out:
5041         /* clear memory */
5042         free_printer_info_7(printer);
5043
5044         return result;
5045 }
5046
5047 /****************************************************************************
5048 ****************************************************************************/
5049
5050 WERROR _spoolss_getprinter(pipes_struct *p, SPOOL_Q_GETPRINTER *q_u, SPOOL_R_GETPRINTER *r_u)
5051 {
5052         POLICY_HND *handle = &q_u->handle;
5053         uint32 level = q_u->level;
5054         RPC_BUFFER *buffer = NULL;
5055         uint32 offered = q_u->offered;
5056         uint32 *needed = &r_u->needed;
5057         Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
5058
5059         int snum;
5060
5061         /* that's an [in out] buffer */
5062
5063         if (!q_u->buffer && (offered!=0)) {
5064                 return WERR_INVALID_PARAM;
5065         }
5066
5067         if (offered > MAX_RPC_DATA_SIZE) {
5068                 return WERR_INVALID_PARAM;
5069         }
5070
5071         rpcbuf_move(q_u->buffer, &r_u->buffer);
5072         buffer = r_u->buffer;
5073
5074         *needed=0;
5075
5076         if (!get_printer_snum(p, handle, &snum, NULL))
5077                 return WERR_BADFID;
5078
5079         switch (level) {
5080         case 0:
5081                 return getprinter_level_0(Printer, snum, buffer, offered, needed);
5082         case 1:
5083                 return getprinter_level_1(Printer, snum, buffer, offered, needed);
5084         case 2:
5085                 return getprinter_level_2(Printer, snum, buffer, offered, needed);
5086         case 3:
5087                 return getprinter_level_3(Printer, snum, buffer, offered, needed);
5088         case 4:
5089                 return getprinter_level_4(Printer, snum, buffer, offered, needed);
5090         case 5:
5091                 return getprinter_level_5(Printer, snum, buffer, offered, needed);
5092         case 6:
5093                 return getprinter_level_6(Printer, snum, buffer, offered, needed);
5094         case 7:
5095                 return getprinter_level_7(Printer, snum, buffer, offered, needed);
5096         }
5097         return WERR_UNKNOWN_LEVEL;
5098 }
5099
5100 /********************************************************************
5101  * fill a DRIVER_INFO_1 struct
5102  ********************************************************************/
5103
5104 static void fill_printer_driver_info_1(DRIVER_INFO_1 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, const char *servername, fstring architecture)
5105 {
5106         init_unistr( &info->name, driver.info_3->name);
5107 }
5108
5109 /********************************************************************
5110  * construct_printer_driver_info_1
5111  ********************************************************************/
5112
5113 static WERROR construct_printer_driver_info_1(DRIVER_INFO_1 *info, int snum, const char *servername, fstring architecture, uint32 version)
5114 {
5115         NT_PRINTER_INFO_LEVEL *printer = NULL;
5116         NT_PRINTER_DRIVER_INFO_LEVEL driver;
5117
5118         ZERO_STRUCT(driver);
5119
5120         if (!W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, lp_const_servicename(snum))))
5121                 return WERR_INVALID_PRINTER_NAME;
5122
5123         if (!W_ERROR_IS_OK(get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version))) {
5124                 free_a_printer(&printer, 2);
5125                 return WERR_UNKNOWN_PRINTER_DRIVER;
5126         }
5127
5128         fill_printer_driver_info_1(info, driver, servername, architecture);
5129
5130         free_a_printer(&printer,2);
5131
5132         return WERR_OK;
5133 }
5134
5135 /********************************************************************
5136  * construct_printer_driver_info_2
5137  * fill a printer_info_2 struct
5138  ********************************************************************/
5139
5140 static void fill_printer_driver_info_2(DRIVER_INFO_2 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, const char *servername)
5141 {
5142         TALLOC_CTX *ctx = talloc_tos();
5143         char *temp = NULL;
5144         const char *cservername = canon_servername(servername);
5145
5146         info->version=driver.info_3->cversion;
5147
5148         init_unistr( &info->name, driver.info_3->name );
5149         init_unistr( &info->architecture, driver.info_3->environment );
5150
5151         if (strlen(driver.info_3->driverpath)) {
5152                 temp = talloc_asprintf(ctx,
5153                                 "\\\\%s%s",
5154                                 cservername,
5155                                 driver.info_3->driverpath);
5156                 init_unistr( &info->driverpath, temp );
5157         } else {
5158                 init_unistr( &info->driverpath, "" );
5159         }
5160
5161         TALLOC_FREE(temp);
5162         if (strlen(driver.info_3->datafile)) {
5163                 temp = talloc_asprintf(ctx,
5164                                 "\\\\%s%s",
5165                                 cservername,
5166                                 driver.info_3->datafile);
5167                 init_unistr( &info->datafile, temp );
5168         } else
5169                 init_unistr( &info->datafile, "" );
5170
5171         TALLOC_FREE(temp);
5172         if (strlen(driver.info_3->configfile)) {
5173                 temp = talloc_asprintf(ctx,
5174                                 "\\\\%s%s",
5175                                 cservername,
5176                                 driver.info_3->configfile);
5177                 init_unistr( &info->configfile, temp );
5178         } else
5179                 init_unistr( &info->configfile, "" );
5180 }
5181
5182 /********************************************************************
5183  * construct_printer_driver_info_2
5184  * fill a printer_info_2 struct
5185  ********************************************************************/
5186
5187 static WERROR construct_printer_driver_info_2(DRIVER_INFO_2 *info, int snum, const char *servername, fstring architecture, uint32 version)
5188 {
5189         NT_PRINTER_INFO_LEVEL *printer = NULL;
5190         NT_PRINTER_DRIVER_INFO_LEVEL driver;
5191
5192         ZERO_STRUCT(printer);
5193         ZERO_STRUCT(driver);
5194
5195         if (!W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, lp_const_servicename(snum))))
5196                 return WERR_INVALID_PRINTER_NAME;
5197
5198         if (!W_ERROR_IS_OK(get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version))) {
5199                 free_a_printer(&printer, 2);
5200                 return WERR_UNKNOWN_PRINTER_DRIVER;
5201         }
5202
5203         fill_printer_driver_info_2(info, driver, servername);
5204
5205         free_a_printer(&printer,2);
5206
5207         return WERR_OK;
5208 }
5209
5210 /********************************************************************
5211  * copy a strings array and convert to UNICODE
5212  *
5213  * convert an array of ascii string to a UNICODE string
5214  ********************************************************************/
5215
5216 static uint32 init_unistr_array(uint16 **uni_array, fstring *char_array, const char *servername)
5217 {
5218         int i=0;
5219         int j=0;
5220         const char *v;
5221         char *line = NULL;
5222         TALLOC_CTX *ctx = talloc_tos();
5223
5224         DEBUG(6,("init_unistr_array\n"));
5225         *uni_array=NULL;
5226
5227         while (true) {
5228                 if ( !char_array ) {
5229                         v = "";
5230                 } else {
5231                         v = char_array[i];
5232                         if (!v)
5233                                 v = ""; /* hack to handle null lists */
5234                 }
5235
5236                 /* hack to allow this to be used in places other than when generating
5237                    the list of dependent files */
5238
5239                 TALLOC_FREE(line);
5240                 if ( servername ) {
5241                         line = talloc_asprintf(ctx,
5242                                         "\\\\%s%s",
5243                                         canon_servername(servername),
5244                                         v);
5245                 } else {
5246                         line = talloc_strdup(ctx, v);
5247                 }
5248
5249                 if (!line) {
5250                         SAFE_FREE(*uni_array);
5251                         return 0;
5252                 }
5253                 DEBUGADD(6,("%d:%s:%lu\n", i, line, (unsigned long)strlen(line)));
5254
5255                 /* add one extra unit16 for the second terminating NULL */
5256
5257                 if ( (*uni_array=SMB_REALLOC_ARRAY(*uni_array, uint16, j+1+strlen(line)+2)) == NULL ) {
5258                         DEBUG(2,("init_unistr_array: Realloc error\n" ));
5259                         return 0;
5260                 }
5261
5262                 if ( !strlen(v) )
5263                         break;
5264
5265                 j += (rpcstr_push((*uni_array+j), line, sizeof(uint16)*strlen(line)+2, STR_TERMINATE) / sizeof(uint16));
5266                 i++;
5267         }
5268
5269         if (*uni_array) {
5270                 /* special case for ""; we need to add both NULL's here */
5271                 if (!j)
5272                         (*uni_array)[j++]=0x0000;
5273                 (*uni_array)[j]=0x0000;
5274         }
5275
5276         DEBUGADD(6,("last one:done\n"));
5277
5278         /* return size of array in uint16's */
5279
5280         return j+1;
5281 }
5282
5283 /********************************************************************
5284  * construct_printer_info_3
5285  * fill a printer_info_3 struct
5286  ********************************************************************/
5287
5288 static void fill_printer_driver_info_3(DRIVER_INFO_3 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, const char *servername)
5289 {
5290         char *temp = NULL;
5291         TALLOC_CTX *ctx = talloc_tos();
5292         const char *cservername = canon_servername(servername);
5293
5294         ZERO_STRUCTP(info);
5295
5296         info->version=driver.info_3->cversion;
5297
5298         init_unistr( &info->name, driver.info_3->name );
5299         init_unistr( &info->architecture, driver.info_3->environment );
5300
5301         if (strlen(driver.info_3->driverpath)) {
5302                 temp = talloc_asprintf(ctx,
5303                                 "\\\\%s%s",
5304                                 cservername,
5305                                 driver.info_3->driverpath);
5306                 init_unistr( &info->driverpath, temp );
5307         } else
5308                 init_unistr( &info->driverpath, "" );
5309
5310         TALLOC_FREE(temp);
5311         if (strlen(driver.info_3->datafile)) {
5312                 temp = talloc_asprintf(ctx,
5313                                 "\\\\%s%s",
5314                                 cservername,
5315                                 driver.info_3->datafile);
5316                 init_unistr( &info->datafile, temp );
5317         } else
5318                 init_unistr( &info->datafile, "" );
5319
5320         TALLOC_FREE(temp);
5321         if (strlen(driver.info_3->configfile)) {
5322                 temp = talloc_asprintf(ctx,
5323                                 "\\\\%s%s",
5324                                 cservername,
5325                                 driver.info_3->configfile);
5326                 init_unistr( &info->configfile, temp );
5327         } else
5328                 init_unistr( &info->configfile, "" );
5329
5330         TALLOC_FREE(temp);
5331         if (strlen(driver.info_3->helpfile)) {
5332                 temp = talloc_asprintf(ctx,
5333                                 "\\\\%s%s",
5334                                 cservername,
5335                                 driver.info_3->helpfile);
5336                 init_unistr( &info->helpfile, temp );
5337         } else
5338                 init_unistr( &info->helpfile, "" );
5339
5340         TALLOC_FREE(temp);
5341         init_unistr( &info->monitorname, driver.info_3->monitorname );
5342         init_unistr( &info->defaultdatatype, driver.info_3->defaultdatatype );
5343
5344         info->dependentfiles=NULL;
5345         init_unistr_array(&info->dependentfiles, driver.info_3->dependentfiles, cservername);
5346 }
5347
5348 /********************************************************************
5349  * construct_printer_info_3
5350  * fill a printer_info_3 struct
5351  ********************************************************************/
5352
5353 static WERROR construct_printer_driver_info_3(DRIVER_INFO_3 *info, int snum, const char *servername, fstring architecture, uint32 version)
5354 {
5355         NT_PRINTER_INFO_LEVEL *printer = NULL;
5356         NT_PRINTER_DRIVER_INFO_LEVEL driver;
5357         WERROR status;
5358         ZERO_STRUCT(driver);
5359
5360         status=get_a_printer(NULL, &printer, 2, lp_const_servicename(snum) );
5361         DEBUG(8,("construct_printer_driver_info_3: status: %s\n", win_errstr(status)));
5362         if (!W_ERROR_IS_OK(status))
5363                 return WERR_INVALID_PRINTER_NAME;
5364
5365         status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
5366         DEBUG(8,("construct_printer_driver_info_3: status: %s\n", win_errstr(status)));
5367
5368 #if 0   /* JERRY */
5369
5370         /*
5371          * I put this code in during testing.  Helpful when commenting out the
5372          * support for DRIVER_INFO_6 in regards to win2k.  Not needed in general
5373          * as win2k always queries the driver using an infor level of 6.
5374          * I've left it in (but ifdef'd out) because I'll probably
5375          * use it in experimentation again in the future.   --jerry 22/01/2002
5376          */
5377
5378         if (!W_ERROR_IS_OK(status)) {
5379                 /*
5380                  * Is this a W2k client ?
5381                  */
5382                 if (version == 3) {
5383                         /* Yes - try again with a WinNT driver. */
5384                         version = 2;
5385                         status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
5386                         DEBUG(8,("construct_printer_driver_info_3: status: %s\n", win_errstr(status)));
5387                 }
5388 #endif
5389
5390                 if (!W_ERROR_IS_OK(status)) {
5391                         free_a_printer(&printer,2);
5392                         return WERR_UNKNOWN_PRINTER_DRIVER;
5393                 }
5394
5395 #if 0   /* JERRY */
5396         }
5397 #endif
5398
5399
5400         fill_printer_driver_info_3(info, driver, servername);
5401
5402         free_a_printer(&printer,2);
5403
5404         return WERR_OK;
5405 }
5406
5407 /********************************************************************
5408  * construct_printer_info_6
5409  * fill a printer_info_6 struct - we know that driver is really level 3. This sucks. JRA.
5410  ********************************************************************/
5411
5412 static void fill_printer_driver_info_6(DRIVER_INFO_6 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, const char *servername)
5413 {
5414         char *temp = NULL;
5415         fstring nullstr;
5416         TALLOC_CTX *ctx = talloc_tos();
5417         const char *cservername = canon_servername(servername);
5418
5419         ZERO_STRUCTP(info);
5420         memset(&nullstr, '\0', sizeof(fstring));
5421
5422         info->version=driver.info_3->cversion;
5423
5424         init_unistr( &info->name, driver.info_3->name );
5425         init_unistr( &info->architecture, driver.info_3->environment );
5426
5427         if (strlen(driver.info_3->driverpath)) {
5428                 temp = talloc_asprintf(ctx,
5429                                 "\\\\%s%s",
5430                                 cservername,
5431                                 driver.info_3->driverpath);
5432                 init_unistr( &info->driverpath, temp );
5433         } else
5434                 init_unistr( &info->driverpath, "" );
5435
5436         TALLOC_FREE(temp);
5437         if (strlen(driver.info_3->datafile)) {
5438                 temp = talloc_asprintf(ctx,
5439                                 "\\\\%s%s",
5440                                 cservername,
5441                                 driver.info_3->datafile);
5442                 init_unistr( &info->datafile, temp );
5443         } else
5444                 init_unistr( &info->datafile, "" );
5445
5446         TALLOC_FREE(temp);
5447         if (strlen(driver.info_3->configfile)) {
5448                 temp = talloc_asprintf(ctx,
5449                                 "\\\\%s%s",
5450                                 cservername,
5451                                 driver.info_3->configfile);
5452                 init_unistr( &info->configfile, temp );
5453         } else
5454                 init_unistr( &info->configfile, "" );
5455
5456         TALLOC_FREE(temp);
5457         if (strlen(driver.info_3->helpfile)) {
5458                 temp = talloc_asprintf(ctx,
5459                                 "\\\\%s%s",
5460                                 cservername,
5461                                 driver.info_3->helpfile);
5462                 init_unistr( &info->helpfile, temp );
5463         } else
5464                 init_unistr( &info->helpfile, "" );
5465
5466         TALLOC_FREE(temp);
5467         init_unistr( &info->monitorname, driver.info_3->monitorname );
5468         init_unistr( &info->defaultdatatype, driver.info_3->defaultdatatype );
5469
5470         info->dependentfiles = NULL;
5471         init_unistr_array( &info->dependentfiles, driver.info_3->dependentfiles, servername );
5472
5473         info->previousdrivernames=NULL;
5474         init_unistr_array(&info->previousdrivernames, &nullstr, servername);
5475
5476         info->driver_date=0;
5477
5478         info->padding=0;
5479         info->driver_version_low=0;
5480         info->driver_version_high=0;
5481
5482         init_unistr( &info->mfgname, "");
5483         init_unistr( &info->oem_url, "");
5484         init_unistr( &info->hardware_id, "");
5485         init_unistr( &info->provider, "");
5486 }
5487
5488 /********************************************************************
5489  * construct_printer_info_6
5490  * fill a printer_info_6 struct
5491  ********************************************************************/
5492
5493 static WERROR construct_printer_driver_info_6(DRIVER_INFO_6 *info, int snum,
5494               const char *servername, fstring architecture, uint32 version)
5495 {
5496         NT_PRINTER_INFO_LEVEL           *printer = NULL;
5497         NT_PRINTER_DRIVER_INFO_LEVEL    driver;
5498         WERROR                          status;
5499
5500         ZERO_STRUCT(driver);
5501
5502         status=get_a_printer(NULL, &printer, 2, lp_const_servicename(snum) );
5503
5504         DEBUG(8,("construct_printer_driver_info_6: status: %s\n", win_errstr(status)));
5505
5506         if (!W_ERROR_IS_OK(status))
5507                 return WERR_INVALID_PRINTER_NAME;
5508
5509         status = get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
5510
5511         DEBUG(8,("construct_printer_driver_info_6: status: %s\n", win_errstr(status)));
5512
5513         if (!W_ERROR_IS_OK(status))
5514         {
5515                 /*
5516                  * Is this a W2k client ?
5517                  */
5518
5519                 if (version < 3) {
5520                         free_a_printer(&printer,2);
5521                         return WERR_UNKNOWN_PRINTER_DRIVER;
5522                 }
5523
5524                 /* Yes - try again with a WinNT driver. */
5525                 version = 2;
5526                 status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
5527                 DEBUG(8,("construct_printer_driver_info_6: status: %s\n", win_errstr(status)));
5528                 if (!W_ERROR_IS_OK(status)) {
5529                         free_a_printer(&printer,2);
5530                         return WERR_UNKNOWN_PRINTER_DRIVER;
5531                 }
5532         }
5533
5534         fill_printer_driver_info_6(info, driver, servername);
5535
5536         free_a_printer(&printer,2);
5537         free_a_printer_driver(driver, 3);
5538
5539         return WERR_OK;
5540 }
5541
5542 /****************************************************************************
5543 ****************************************************************************/
5544
5545 static void free_printer_driver_info_3(DRIVER_INFO_3 *info)
5546 {
5547         SAFE_FREE(info->dependentfiles);
5548 }
5549
5550 /****************************************************************************
5551 ****************************************************************************/
5552
5553 static void free_printer_driver_info_6(DRIVER_INFO_6 *info)
5554 {
5555         SAFE_FREE(info->dependentfiles);
5556 }
5557
5558 /****************************************************************************
5559 ****************************************************************************/
5560
5561 static WERROR getprinterdriver2_level1(const char *servername, fstring architecture, uint32 version, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
5562 {
5563         DRIVER_INFO_1 *info=NULL;
5564         WERROR result;
5565
5566         if((info=SMB_MALLOC_P(DRIVER_INFO_1)) == NULL)
5567                 return WERR_NOMEM;
5568
5569         result = construct_printer_driver_info_1(info, snum, servername, architecture, version);
5570         if (!W_ERROR_IS_OK(result))
5571                 goto out;
5572
5573         /* check the required size. */
5574         *needed += spoolss_size_printer_driver_info_1(info);
5575
5576         if (*needed > offered) {
5577                 result = WERR_INSUFFICIENT_BUFFER;
5578                 goto out;
5579         }
5580
5581         if (!rpcbuf_alloc_size(buffer, *needed)) {
5582                 result = WERR_NOMEM;
5583                 goto out;
5584         }
5585
5586         /* fill the buffer with the structures */
5587         smb_io_printer_driver_info_1("", buffer, info, 0);
5588
5589 out:
5590         /* clear memory */
5591         SAFE_FREE(info);
5592
5593         return result;
5594 }
5595
5596 /****************************************************************************
5597 ****************************************************************************/
5598
5599 static WERROR getprinterdriver2_level2(const char *servername, fstring architecture, uint32 version, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
5600 {
5601         DRIVER_INFO_2 *info=NULL;
5602         WERROR result;
5603
5604         if((info=SMB_MALLOC_P(DRIVER_INFO_2)) == NULL)
5605                 return WERR_NOMEM;
5606
5607         result = construct_printer_driver_info_2(info, snum, servername, architecture, version);
5608         if (!W_ERROR_IS_OK(result))
5609                 goto out;
5610
5611         /* check the required size. */
5612         *needed += spoolss_size_printer_driver_info_2(info);
5613
5614         if (*needed > offered) {
5615                 result = WERR_INSUFFICIENT_BUFFER;
5616                 goto out;
5617         }
5618
5619         if (!rpcbuf_alloc_size(buffer, *needed)) {
5620                 result = WERR_NOMEM;
5621                 goto out;
5622         }
5623
5624         /* fill the buffer with the structures */
5625         smb_io_printer_driver_info_2("", buffer, info, 0);
5626
5627 out:
5628         /* clear memory */
5629         SAFE_FREE(info);
5630
5631         return result;
5632 }
5633
5634 /****************************************************************************
5635 ****************************************************************************/
5636
5637 static WERROR getprinterdriver2_level3(const char *servername, fstring architecture, uint32 version, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
5638 {
5639         DRIVER_INFO_3 info;
5640         WERROR result;
5641
5642         ZERO_STRUCT(info);
5643
5644         result = construct_printer_driver_info_3(&info, snum, servername, architecture, version);
5645         if (!W_ERROR_IS_OK(result))
5646                 goto out;
5647
5648         /* check the required size. */
5649         *needed += spoolss_size_printer_driver_info_3(&info);
5650
5651         if (*needed > offered) {
5652                 result = WERR_INSUFFICIENT_BUFFER;
5653                 goto out;
5654         }
5655
5656         if (!rpcbuf_alloc_size(buffer, *needed)) {
5657                 result = WERR_NOMEM;
5658                 goto out;
5659         }
5660
5661         /* fill the buffer with the structures */
5662         smb_io_printer_driver_info_3("", buffer, &info, 0);
5663
5664 out:
5665         free_printer_driver_info_3(&info);
5666
5667         return result;
5668 }
5669
5670 /****************************************************************************
5671 ****************************************************************************/
5672
5673 static WERROR getprinterdriver2_level6(const char *servername, fstring architecture, uint32 version, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
5674 {
5675         DRIVER_INFO_6 info;
5676         WERROR result;
5677
5678         ZERO_STRUCT(info);
5679
5680         result = construct_printer_driver_info_6(&info, snum, servername, architecture, version);
5681         if (!W_ERROR_IS_OK(result))
5682                 goto out;
5683
5684         /* check the required size. */
5685         *needed += spoolss_size_printer_driver_info_6(&info);
5686
5687         if (*needed > offered) {
5688                 result = WERR_INSUFFICIENT_BUFFER;
5689                 goto out;
5690         }
5691
5692         if (!rpcbuf_alloc_size(buffer, *needed)) {
5693                 result = WERR_NOMEM;
5694                 goto out;
5695         }
5696
5697         /* fill the buffer with the structures */
5698         smb_io_printer_driver_info_6("", buffer, &info, 0);
5699
5700 out:
5701         free_printer_driver_info_6(&info);
5702
5703         return result;
5704 }
5705
5706 /****************************************************************************
5707 ****************************************************************************/
5708
5709 WERROR _spoolss_getprinterdriver2(pipes_struct *p, SPOOL_Q_GETPRINTERDRIVER2 *q_u, SPOOL_R_GETPRINTERDRIVER2 *r_u)
5710 {
5711         POLICY_HND *handle = &q_u->handle;
5712         UNISTR2 *uni_arch = &q_u->architecture;
5713         uint32 level = q_u->level;
5714         uint32 clientmajorversion = q_u->clientmajorversion;
5715         RPC_BUFFER *buffer = NULL;
5716         uint32 offered = q_u->offered;
5717         uint32 *needed = &r_u->needed;
5718         uint32 *servermajorversion = &r_u->servermajorversion;
5719         uint32 *serverminorversion = &r_u->serverminorversion;
5720         Printer_entry *printer;
5721
5722         fstring servername;
5723         fstring architecture;
5724         int snum;
5725
5726         /* that's an [in out] buffer */
5727
5728         if (!q_u->buffer && (offered!=0)) {
5729                 return WERR_INVALID_PARAM;
5730         }
5731
5732         if (offered > MAX_RPC_DATA_SIZE) {
5733                 return WERR_INVALID_PARAM;
5734         }
5735
5736         rpcbuf_move(q_u->buffer, &r_u->buffer);
5737         buffer = r_u->buffer;
5738
5739         DEBUG(4,("_spoolss_getprinterdriver2\n"));
5740
5741         if ( !(printer = find_printer_index_by_hnd( p, handle )) ) {
5742                 DEBUG(0,("_spoolss_getprinterdriver2: invalid printer handle!\n"));
5743                 return WERR_INVALID_PRINTER_NAME;
5744         }
5745
5746         *needed = 0;
5747         *servermajorversion = 0;
5748         *serverminorversion = 0;
5749
5750         fstrcpy(servername, get_server_name( printer ));
5751         unistr2_to_ascii(architecture, uni_arch, sizeof(architecture));
5752
5753         if (!get_printer_snum(p, handle, &snum, NULL))
5754                 return WERR_BADFID;
5755
5756         switch (level) {
5757         case 1:
5758                 return getprinterdriver2_level1(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
5759         case 2:
5760                 return getprinterdriver2_level2(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
5761         case 3:
5762                 return getprinterdriver2_level3(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
5763         case 6:
5764                 return getprinterdriver2_level6(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
5765 #if 0   /* JERRY */
5766         case 101:
5767                 /* apparently this call is the equivalent of
5768                    EnumPrinterDataEx() for the DsDriver key */
5769                 break;
5770 #endif
5771         }
5772
5773         return WERR_UNKNOWN_LEVEL;
5774 }
5775
5776
5777 /****************************************************************
5778  _spoolss_StartPagePrinter
5779 ****************************************************************/
5780
5781 WERROR _spoolss_StartPagePrinter(pipes_struct *p,
5782                                  struct spoolss_StartPagePrinter *r)
5783 {
5784         POLICY_HND *handle = r->in.handle;
5785
5786         Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5787
5788         if (!Printer) {
5789                 DEBUG(3,("_spoolss_StartPagePrinter: "
5790                         "Error in startpageprinter printer handle\n"));
5791                 return WERR_BADFID;
5792         }
5793
5794         Printer->page_started=True;
5795         return WERR_OK;
5796 }
5797
5798 /****************************************************************
5799  _spoolss_EndPagePrinter
5800 ****************************************************************/
5801
5802 WERROR _spoolss_EndPagePrinter(pipes_struct *p,
5803                                struct spoolss_EndPagePrinter *r)
5804 {
5805         POLICY_HND *handle = r->in.handle;
5806         int snum;
5807
5808         Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5809
5810         if (!Printer) {
5811                 DEBUG(2,("_spoolss_EndPagePrinter: Invalid handle (%s:%u:%u).\n",
5812                         OUR_HANDLE(handle)));
5813                 return WERR_BADFID;
5814         }
5815
5816         if (!get_printer_snum(p, handle, &snum, NULL))
5817                 return WERR_BADFID;
5818
5819         Printer->page_started=False;
5820         print_job_endpage(snum, Printer->jobid);
5821
5822         return WERR_OK;
5823 }
5824
5825 /****************************************************************
5826  _spoolss_StartDocPrinter
5827 ****************************************************************/
5828
5829 WERROR _spoolss_StartDocPrinter(pipes_struct *p,
5830                                 struct spoolss_StartDocPrinter *r)
5831 {
5832         POLICY_HND *handle = r->in.handle;
5833         uint32_t *jobid = r->out.job_id;
5834         struct spoolss_DocumentInfo1 *info_1;
5835         int snum;
5836         Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5837
5838         if (!Printer) {
5839                 DEBUG(2,("_spoolss_StartDocPrinter: "
5840                         "Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
5841                 return WERR_BADFID;
5842         }
5843
5844         if (r->in.level != 1) {
5845                 return WERR_UNKNOWN_LEVEL;
5846         }
5847
5848         info_1 = r->in.info.info1;
5849
5850         /*
5851          * a nice thing with NT is it doesn't listen to what you tell it.
5852          * when asked to send _only_ RAW datas, it tries to send datas
5853          * in EMF format.
5854          *
5855          * So I add checks like in NT Server ...
5856          */
5857
5858         if (info_1->datatype) {
5859                 if (strcmp(info_1->datatype, "RAW") != 0) {
5860                         (*jobid)=0;
5861                         return WERR_INVALID_DATATYPE;
5862                 }
5863         }
5864
5865         /* get the share number of the printer */
5866         if (!get_printer_snum(p, handle, &snum, NULL)) {
5867                 return WERR_BADFID;
5868         }
5869
5870         Printer->jobid = print_job_start(p->server_info, snum,
5871                                          CONST_DISCARD(char *,info_1->document_name),
5872                                          Printer->nt_devmode);
5873
5874         /* An error occured in print_job_start() so return an appropriate
5875            NT error code. */
5876
5877         if (Printer->jobid == -1) {
5878                 return map_werror_from_unix(errno);
5879         }
5880
5881         Printer->document_started=True;
5882         (*jobid) = Printer->jobid;
5883
5884         return WERR_OK;
5885 }
5886
5887 /****************************************************************
5888  _spoolss_EndDocPrinter
5889 ****************************************************************/
5890
5891 WERROR _spoolss_EndDocPrinter(pipes_struct *p,
5892                               struct spoolss_EndDocPrinter *r)
5893 {
5894         POLICY_HND *handle = r->in.handle;
5895
5896         return _spoolss_enddocprinter_internal(p, handle);
5897 }
5898
5899 /****************************************************************
5900  _spoolss_WritePrinter
5901 ****************************************************************/
5902
5903 WERROR _spoolss_WritePrinter(pipes_struct *p,
5904                              struct spoolss_WritePrinter *r)
5905 {
5906         POLICY_HND *handle = r->in.handle;
5907         uint32 buffer_size = r->in._data_size;
5908         uint8 *buffer = r->in.data.data;
5909         uint32 *buffer_written = &r->in._data_size;
5910         int snum;
5911         Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5912
5913         if (!Printer) {
5914                 DEBUG(2,("_spoolss_WritePrinter: Invalid handle (%s:%u:%u)\n",
5915                         OUR_HANDLE(handle)));
5916                 *r->out.num_written = r->in._data_size;
5917                 return WERR_BADFID;
5918         }
5919
5920         if (!get_printer_snum(p, handle, &snum, NULL))
5921                 return WERR_BADFID;
5922
5923         (*buffer_written) = (uint32)print_job_write(snum, Printer->jobid, (const char *)buffer,
5924                                         (SMB_OFF_T)-1, (size_t)buffer_size);
5925         if (*buffer_written == (uint32)-1) {
5926                 *r->out.num_written = 0;
5927                 if (errno == ENOSPC)
5928                         return WERR_NO_SPOOL_SPACE;
5929                 else
5930                         return WERR_ACCESS_DENIED;
5931         }
5932
5933         *r->out.num_written = r->in._data_size;
5934
5935         return WERR_OK;
5936 }
5937
5938 /********************************************************************
5939  * api_spoolss_getprinter
5940  * called from the spoolss dispatcher
5941  *
5942  ********************************************************************/
5943
5944 static WERROR control_printer(POLICY_HND *handle, uint32 command,
5945                               pipes_struct *p)
5946 {
5947         int snum;
5948         WERROR errcode = WERR_BADFUNC;
5949         Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5950
5951         if (!Printer) {
5952                 DEBUG(2,("control_printer: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
5953                 return WERR_BADFID;
5954         }
5955
5956         if (!get_printer_snum(p, handle, &snum, NULL))
5957                 return WERR_BADFID;
5958
5959         switch (command) {
5960         case SPOOLSS_PRINTER_CONTROL_PAUSE:
5961                 if (print_queue_pause(p->server_info, snum, &errcode)) {
5962                         errcode = WERR_OK;
5963                 }
5964                 break;
5965         case SPOOLSS_PRINTER_CONTROL_RESUME:
5966         case SPOOLSS_PRINTER_CONTROL_UNPAUSE:
5967                 if (print_queue_resume(p->server_info, snum, &errcode)) {
5968                         errcode = WERR_OK;
5969                 }
5970                 break;
5971         case SPOOLSS_PRINTER_CONTROL_PURGE:
5972                 if (print_queue_purge(p->server_info, snum, &errcode)) {
5973                         errcode = WERR_OK;
5974                 }
5975                 break;
5976         default:
5977                 return WERR_UNKNOWN_LEVEL;
5978         }
5979
5980         return errcode;
5981 }
5982
5983
5984 /****************************************************************
5985  _spoolss_AbortPrinter
5986  * From MSDN: "Deletes printer's spool file if printer is configured
5987  * for spooling"
5988 ****************************************************************/
5989
5990 WERROR _spoolss_AbortPrinter(pipes_struct *p,
5991                              struct spoolss_AbortPrinter *r)
5992 {
5993         POLICY_HND      *handle = r->in.handle;
5994         Printer_entry   *Printer = find_printer_index_by_hnd(p, handle);
5995         int             snum;
5996         WERROR          errcode = WERR_OK;
5997
5998         if (!Printer) {
5999                 DEBUG(2,("_spoolss_AbortPrinter: Invalid handle (%s:%u:%u)\n",
6000                         OUR_HANDLE(handle)));
6001                 return WERR_BADFID;
6002         }
6003
6004         if (!get_printer_snum(p, handle, &snum, NULL))
6005                 return WERR_BADFID;
6006
6007         print_job_delete(p->server_info, snum, Printer->jobid, &errcode );
6008
6009         return errcode;
6010 }
6011
6012 /********************************************************************
6013  * called by spoolss_api_setprinter
6014  * when updating a printer description
6015  ********************************************************************/
6016
6017 static WERROR update_printer_sec(POLICY_HND *handle,
6018                                  pipes_struct *p, SEC_DESC_BUF *secdesc_ctr)
6019 {
6020         SEC_DESC_BUF *new_secdesc_ctr = NULL, *old_secdesc_ctr = NULL;
6021         WERROR result;
6022         int snum;
6023
6024         Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
6025
6026         if (!Printer || !get_printer_snum(p, handle, &snum, NULL)) {
6027                 DEBUG(2,("update_printer_sec: Invalid handle (%s:%u:%u)\n",
6028                          OUR_HANDLE(handle)));
6029
6030                 result = WERR_BADFID;
6031                 goto done;
6032         }
6033
6034         if (!secdesc_ctr) {
6035                 DEBUG(10,("update_printer_sec: secdesc_ctr is NULL !\n"));
6036                 result = WERR_INVALID_PARAM;
6037                 goto done;
6038         }
6039
6040         /* Check the user has permissions to change the security
6041            descriptor.  By experimentation with two NT machines, the user
6042            requires Full Access to the printer to change security
6043            information. */
6044
6045         if ( Printer->access_granted != PRINTER_ACCESS_ADMINISTER ) {
6046                 DEBUG(4,("update_printer_sec: updated denied by printer permissions\n"));
6047                 result = WERR_ACCESS_DENIED;
6048                 goto done;
6049         }
6050
6051         /* NT seems to like setting the security descriptor even though
6052            nothing may have actually changed. */
6053
6054         if ( !nt_printing_getsec(p->mem_ctx, Printer->sharename, &old_secdesc_ctr)) {
6055                 DEBUG(2,("update_printer_sec: nt_printing_getsec() failed\n"));
6056                 result = WERR_BADFID;
6057                 goto done;
6058         }
6059
6060         if (DEBUGLEVEL >= 10) {
6061                 SEC_ACL *the_acl;
6062                 int i;
6063
6064                 the_acl = old_secdesc_ctr->sd->dacl;
6065                 DEBUG(10, ("old_secdesc_ctr for %s has %d aces:\n",
6066                            PRINTERNAME(snum), the_acl->num_aces));
6067
6068                 for (i = 0; i < the_acl->num_aces; i++) {
6069                         DEBUG(10, ("%s 0x%08x\n", sid_string_dbg(
6070                                            &the_acl->aces[i].trustee),
6071                                   the_acl->aces[i].access_mask));
6072                 }
6073
6074                 the_acl = secdesc_ctr->sd->dacl;
6075
6076                 if (the_acl) {
6077                         DEBUG(10, ("secdesc_ctr for %s has %d aces:\n",
6078                                    PRINTERNAME(snum), the_acl->num_aces));
6079
6080                         for (i = 0; i < the_acl->num_aces; i++) {
6081                                 DEBUG(10, ("%s 0x%08x\n", sid_string_dbg(
6082                                                    &the_acl->aces[i].trustee),
6083                                            the_acl->aces[i].access_mask));
6084                         }
6085                 } else {
6086                         DEBUG(10, ("dacl for secdesc_ctr is NULL\n"));
6087                 }
6088         }
6089
6090         new_secdesc_ctr = sec_desc_merge(p->mem_ctx, secdesc_ctr, old_secdesc_ctr);
6091         if (!new_secdesc_ctr) {
6092                 result = WERR_NOMEM;
6093                 goto done;
6094         }
6095
6096         if (sec_desc_equal(new_secdesc_ctr->sd, old_secdesc_ctr->sd)) {
6097                 result = WERR_OK;
6098                 goto done;
6099         }
6100
6101         result = nt_printing_setsec(Printer->sharename, new_secdesc_ctr);
6102
6103  done:
6104
6105         return result;
6106 }
6107
6108 /********************************************************************
6109  Canonicalize printer info from a client
6110
6111  ATTN: It does not matter what we set the servername to hear
6112  since we do the necessary work in get_a_printer() to set it to
6113  the correct value based on what the client sent in the
6114  _spoolss_open_printer_ex().
6115  ********************************************************************/
6116
6117 static bool check_printer_ok(NT_PRINTER_INFO_LEVEL_2 *info, int snum)
6118 {
6119         fstring printername;
6120         const char *p;
6121
6122         DEBUG(5,("check_printer_ok: servername=%s printername=%s sharename=%s "
6123                 "portname=%s drivername=%s comment=%s location=%s\n",
6124                 info->servername, info->printername, info->sharename,
6125                 info->portname, info->drivername, info->comment, info->location));
6126
6127         /* we force some elements to "correct" values */
6128         slprintf(info->servername, sizeof(info->servername)-1, "\\\\%s", global_myname());
6129         fstrcpy(info->sharename, lp_servicename(snum));
6130
6131         /* check to see if we allow printername != sharename */
6132
6133         if ( lp_force_printername(snum) ) {
6134                 slprintf(info->printername, sizeof(info->printername)-1, "\\\\%s\\%s",
6135                         global_myname(), info->sharename );
6136         } else {
6137
6138                 /* make sure printername is in \\server\printername format */
6139
6140                 fstrcpy( printername, info->printername );
6141                 p = printername;
6142                 if ( printername[0] == '\\' && printername[1] == '\\' ) {
6143                         if ( (p = strchr_m( &printername[2], '\\' )) != NULL )
6144                                 p++;
6145                 }
6146
6147                 slprintf(info->printername, sizeof(info->printername)-1, "\\\\%s\\%s",
6148                          global_myname(), p );
6149         }
6150
6151         info->attributes |= PRINTER_ATTRIBUTE_SAMBA;
6152         info->attributes &= ~PRINTER_ATTRIBUTE_NOT_SAMBA;
6153
6154
6155
6156         return True;
6157 }
6158
6159 /****************************************************************************
6160 ****************************************************************************/
6161
6162 WERROR add_port_hook(TALLOC_CTX *ctx, NT_USER_TOKEN *token, const char *portname, const char *uri )
6163 {
6164         char *cmd = lp_addport_cmd();
6165         char *command = NULL;
6166         int ret;
6167         SE_PRIV se_printop = SE_PRINT_OPERATOR;
6168         bool is_print_op = False;
6169
6170         if ( !*cmd ) {
6171                 return WERR_ACCESS_DENIED;
6172         }
6173
6174         command = talloc_asprintf(ctx,
6175                         "%s \"%s\" \"%s\"", cmd, portname, uri );
6176         if (!command) {
6177                 return WERR_NOMEM;
6178         }
6179
6180         if ( token )
6181                 is_print_op = user_has_privileges( token, &se_printop );
6182
6183         DEBUG(10,("Running [%s]\n", command));
6184
6185         /********* BEGIN SePrintOperatorPrivilege **********/
6186
6187         if ( is_print_op )
6188                 become_root();
6189
6190         ret = smbrun(command, NULL);
6191
6192         if ( is_print_op )
6193                 unbecome_root();
6194
6195         /********* END SePrintOperatorPrivilege **********/
6196
6197         DEBUGADD(10,("returned [%d]\n", ret));
6198
6199         TALLOC_FREE(command);
6200
6201         if ( ret != 0 ) {
6202                 return WERR_ACCESS_DENIED;
6203         }
6204
6205         return WERR_OK;
6206 }
6207
6208 /****************************************************************************
6209 ****************************************************************************/
6210
6211 bool add_printer_hook(TALLOC_CTX *ctx, NT_USER_TOKEN *token, NT_PRINTER_INFO_LEVEL *printer)
6212 {
6213         char *cmd = lp_addprinter_cmd();
6214         char **qlines;
6215         char *command = NULL;
6216         int numlines;
6217         int ret;
6218         int fd;
6219         SE_PRIV se_printop = SE_PRINT_OPERATOR;
6220         bool is_print_op = False;
6221         char *remote_machine = talloc_strdup(ctx, "%m");
6222
6223         if (!remote_machine) {
6224                 return false;
6225         }
6226         remote_machine = talloc_sub_basic(ctx,
6227                                 current_user_info.smb_name,
6228                                 current_user_info.domain,
6229                                 remote_machine);
6230         if (!remote_machine) {
6231                 return false;
6232         }
6233
6234         command = talloc_asprintf(ctx,
6235                         "%s \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\"",
6236                         cmd, printer->info_2->printername, printer->info_2->sharename,
6237                         printer->info_2->portname, printer->info_2->drivername,
6238                         printer->info_2->location, printer->info_2->comment, remote_machine);
6239         if (!command) {
6240                 return false;
6241         }
6242
6243         if ( token )
6244                 is_print_op = user_has_privileges( token, &se_printop );
6245
6246         DEBUG(10,("Running [%s]\n", command));
6247
6248         /********* BEGIN SePrintOperatorPrivilege **********/
6249
6250         if ( is_print_op )
6251                 become_root();
6252
6253         if ( (ret = smbrun(command, &fd)) == 0 ) {
6254                 /* Tell everyone we updated smb.conf. */
6255                 message_send_all(smbd_messaging_context(),
6256                                  MSG_SMB_CONF_UPDATED, NULL, 0, NULL);
6257         }
6258
6259         if ( is_print_op )
6260                 unbecome_root();
6261
6262         /********* END SePrintOperatorPrivilege **********/
6263
6264         DEBUGADD(10,("returned [%d]\n", ret));
6265
6266         TALLOC_FREE(command);
6267         TALLOC_FREE(remote_machine);
6268
6269         if ( ret != 0 ) {
6270                 if (fd != -1)
6271                         close(fd);
6272                 return False;
6273         }
6274
6275         /* reload our services immediately */
6276         reload_services( False );
6277
6278         numlines = 0;
6279         /* Get lines and convert them back to dos-codepage */
6280         qlines = fd_lines_load(fd, &numlines, 0, NULL);
6281         DEBUGADD(10,("Lines returned = [%d]\n", numlines));
6282         close(fd);
6283
6284         /* Set the portname to what the script says the portname should be. */
6285         /* but don't require anything to be return from the script exit a good error code */
6286
6287         if (numlines) {
6288                 /* Set the portname to what the script says the portname should be. */
6289                 strncpy(printer->info_2->portname, qlines[0], sizeof(printer->info_2->portname));
6290                 DEBUGADD(6,("Line[0] = [%s]\n", qlines[0]));
6291         }
6292
6293         TALLOC_FREE(qlines);
6294         return True;
6295 }
6296
6297
6298 /********************************************************************
6299  * Called by spoolss_api_setprinter
6300  * when updating a printer description.
6301  ********************************************************************/
6302
6303 static WERROR update_printer(pipes_struct *p, POLICY_HND *handle,
6304                              struct spoolss_SetPrinterInfoCtr *info_ctr,
6305                              struct spoolss_DeviceMode *devmode)
6306 {
6307         int snum;
6308         NT_PRINTER_INFO_LEVEL *printer = NULL, *old_printer = NULL;
6309         Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
6310         WERROR result;
6311         UNISTR2 buffer;
6312         fstring asc_buffer;
6313
6314         DEBUG(8,("update_printer\n"));
6315
6316         result = WERR_OK;
6317
6318         if (!Printer) {
6319                 result = WERR_BADFID;
6320                 goto done;
6321         }
6322
6323         if (!get_printer_snum(p, handle, &snum, NULL)) {
6324                 result = WERR_BADFID;
6325                 goto done;
6326         }
6327
6328         if (!W_ERROR_IS_OK(get_a_printer(Printer, &printer, 2, lp_const_servicename(snum))) ||
6329             (!W_ERROR_IS_OK(get_a_printer(Printer, &old_printer, 2, lp_const_servicename(snum))))) {
6330                 result = WERR_BADFID;
6331                 goto done;
6332         }
6333
6334         DEBUGADD(8,("Converting info_2 struct\n"));
6335
6336         /*
6337          * convert_printer_info converts the incoming
6338          * info from the client and overwrites the info
6339          * just read from the tdb in the pointer 'printer'.
6340          */
6341
6342         if (!convert_printer_info_new(info_ctr, printer)) {
6343                 result =  WERR_NOMEM;
6344                 goto done;
6345         }
6346
6347         if (devmode) {
6348                 /* we have a valid devmode
6349                    convert it and link it*/
6350
6351                 DEBUGADD(8,("update_printer: Converting the devicemode struct\n"));
6352                 if (!convert_devicemode_new(printer->info_2->printername,
6353                                             devmode,
6354                                             &printer->info_2->devmode)) {
6355                         result =  WERR_NOMEM;
6356                         goto done;
6357                 }
6358         }
6359
6360         /* Do sanity check on the requested changes for Samba */
6361
6362         if (!check_printer_ok(printer->info_2, snum)) {
6363                 result = WERR_INVALID_PARAM;
6364                 goto done;
6365         }
6366
6367         /* FIXME!!! If the driver has changed we really should verify that
6368            it is installed before doing much else   --jerry */
6369
6370         /* Check calling user has permission to update printer description */
6371
6372         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
6373                 DEBUG(3, ("update_printer: printer property change denied by handle\n"));
6374                 result = WERR_ACCESS_DENIED;
6375                 goto done;
6376         }
6377
6378         /* Call addprinter hook */
6379         /* Check changes to see if this is really needed */
6380
6381         if ( *lp_addprinter_cmd()
6382                 && (!strequal(printer->info_2->drivername, old_printer->info_2->drivername)
6383                         || !strequal(printer->info_2->comment, old_printer->info_2->comment)
6384                         || !strequal(printer->info_2->portname, old_printer->info_2->portname)
6385                         || !strequal(printer->info_2->location, old_printer->info_2->location)) )
6386         {
6387                 /* add_printer_hook() will call reload_services() */
6388
6389                 if ( !add_printer_hook(p->mem_ctx, p->server_info->ptok,
6390                                        printer) ) {
6391                         result = WERR_ACCESS_DENIED;
6392                         goto done;
6393                 }
6394         }
6395
6396         /*
6397          * When a *new* driver is bound to a printer, the drivername is used to
6398          * lookup previously saved driver initialization info, which is then
6399          * bound to the printer, simulating what happens in the Windows arch.
6400          */
6401         if (!strequal(printer->info_2->drivername, old_printer->info_2->drivername))
6402         {
6403                 if (!set_driver_init(printer, 2))
6404                 {
6405                         DEBUG(5,("update_printer: Error restoring driver initialization data for driver [%s]!\n",
6406                                 printer->info_2->drivername));
6407                 }
6408
6409                 DEBUG(10,("update_printer: changing driver [%s]!  Sending event!\n",
6410                         printer->info_2->drivername));
6411
6412                 notify_printer_driver(snum, printer->info_2->drivername);
6413         }
6414
6415         /*
6416          * flag which changes actually occured.  This is a small subset of
6417          * all the possible changes.  We also have to update things in the
6418          * DsSpooler key.
6419          */
6420
6421         if (!strequal(printer->info_2->comment, old_printer->info_2->comment)) {
6422                 init_unistr2( &buffer, printer->info_2->comment, UNI_STR_TERMINATE);
6423                 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "description",
6424                         REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6425
6426                 notify_printer_comment(snum, printer->info_2->comment);
6427         }
6428
6429         if (!strequal(printer->info_2->sharename, old_printer->info_2->sharename)) {
6430                 init_unistr2( &buffer, printer->info_2->sharename, UNI_STR_TERMINATE);
6431                 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "shareName",
6432                         REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6433
6434                 notify_printer_sharename(snum, printer->info_2->sharename);
6435         }
6436
6437         if (!strequal(printer->info_2->printername, old_printer->info_2->printername)) {
6438                 char *pname;
6439
6440                 if ( (pname = strchr_m( printer->info_2->printername+2, '\\' )) != NULL )
6441                         pname++;
6442                 else
6443                         pname = printer->info_2->printername;
6444
6445
6446                 init_unistr2( &buffer, pname, UNI_STR_TERMINATE);
6447                 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "printerName",
6448                         REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6449
6450                 notify_printer_printername( snum, pname );
6451         }
6452
6453         if (!strequal(printer->info_2->portname, old_printer->info_2->portname)) {
6454                 init_unistr2( &buffer, printer->info_2->portname, UNI_STR_TERMINATE);
6455                 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "portName",
6456                         REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6457
6458                 notify_printer_port(snum, printer->info_2->portname);
6459         }
6460
6461         if (!strequal(printer->info_2->location, old_printer->info_2->location)) {
6462                 init_unistr2( &buffer, printer->info_2->location, UNI_STR_TERMINATE);
6463                 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "location",
6464                         REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6465
6466                 notify_printer_location(snum, printer->info_2->location);
6467         }
6468
6469         /* here we need to update some more DsSpooler keys */
6470         /* uNCName, serverName, shortServerName */
6471
6472         init_unistr2( &buffer, global_myname(), UNI_STR_TERMINATE);
6473         set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "serverName",
6474                 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6475         set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "shortServerName",
6476                 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6477
6478         slprintf( asc_buffer, sizeof(asc_buffer)-1, "\\\\%s\\%s",
6479                  global_myname(), printer->info_2->sharename );
6480         init_unistr2( &buffer, asc_buffer, UNI_STR_TERMINATE);
6481         set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "uNCName",
6482                 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6483
6484         /* Update printer info */
6485         result = mod_a_printer(printer, 2);
6486
6487 done:
6488         free_a_printer(&printer, 2);
6489         free_a_printer(&old_printer, 2);
6490
6491
6492         return result;
6493 }
6494
6495 /****************************************************************************
6496 ****************************************************************************/
6497 static WERROR publish_or_unpublish_printer(pipes_struct *p, POLICY_HND *handle,
6498                                            struct spoolss_SetPrinterInfo7 *info7)
6499 {
6500 #ifdef HAVE_ADS
6501         int snum;
6502         Printer_entry *Printer;
6503
6504         if ( lp_security() != SEC_ADS ) {
6505                 return WERR_UNKNOWN_LEVEL;
6506         }
6507
6508         Printer = find_printer_index_by_hnd(p, handle);
6509
6510         DEBUG(5,("publish_or_unpublish_printer, action = %d\n",info7->action));
6511
6512         if (!Printer)
6513                 return WERR_BADFID;
6514
6515         if (!get_printer_snum(p, handle, &snum, NULL))
6516                 return WERR_BADFID;
6517
6518         nt_printer_publish(Printer, snum, info7->action);
6519
6520         return WERR_OK;
6521 #else
6522         return WERR_UNKNOWN_LEVEL;
6523 #endif
6524 }
6525
6526 /****************************************************************
6527  _spoolss_SetPrinter
6528 ****************************************************************/
6529
6530 WERROR _spoolss_SetPrinter(pipes_struct *p,
6531                            struct spoolss_SetPrinter *r)
6532 {
6533         POLICY_HND *handle = r->in.handle;
6534         WERROR result;
6535
6536         Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
6537
6538         if (!Printer) {
6539                 DEBUG(2,("_spoolss_SetPrinter: Invalid handle (%s:%u:%u)\n",
6540                         OUR_HANDLE(handle)));
6541                 return WERR_BADFID;
6542         }
6543
6544         /* check the level */
6545         switch (r->in.info_ctr->level) {
6546                 case 0:
6547                         return control_printer(handle, r->in.command, p);
6548                 case 2:
6549                         result = update_printer(p, handle,
6550                                                 r->in.info_ctr,
6551                                                 r->in.devmode_ctr->devmode);
6552                         if (!W_ERROR_IS_OK(result))
6553                                 return result;
6554                         if (r->in.secdesc_ctr->sd)
6555                                 result = update_printer_sec(handle, p,
6556                                                             r->in.secdesc_ctr);
6557                         return result;
6558                 case 3:
6559                         return update_printer_sec(handle, p,
6560                                                   r->in.secdesc_ctr);
6561                 case 7:
6562                         return publish_or_unpublish_printer(p, handle,
6563                                                             r->in.info_ctr->info.info7);
6564                 default:
6565                         return WERR_UNKNOWN_LEVEL;
6566         }
6567 }
6568
6569 /****************************************************************
6570  _spoolss_FindClosePrinterNotify
6571 ****************************************************************/
6572
6573 WERROR _spoolss_FindClosePrinterNotify(pipes_struct *p,
6574                                        struct spoolss_FindClosePrinterNotify *r)
6575 {
6576         POLICY_HND *handle = r->in.handle;
6577         Printer_entry *Printer= find_printer_index_by_hnd(p, handle);
6578
6579         if (!Printer) {
6580                 DEBUG(2,("_spoolss_FindClosePrinterNotify: "
6581                         "Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
6582                 return WERR_BADFID;
6583         }
6584
6585         if (Printer->notify.client_connected==True) {
6586                 int snum = -1;
6587
6588                 if ( Printer->printer_type == SPLHND_SERVER)
6589                         snum = -1;
6590                 else if ( (Printer->printer_type == SPLHND_PRINTER) &&
6591                                 !get_printer_snum(p, handle, &snum, NULL) )
6592                         return WERR_BADFID;
6593
6594                 srv_spoolss_replycloseprinter(snum, &Printer->notify.client_hnd);
6595         }
6596
6597         Printer->notify.flags=0;
6598         Printer->notify.options=0;
6599         Printer->notify.localmachine[0]='\0';
6600         Printer->notify.printerlocal=0;
6601         TALLOC_FREE(Printer->notify.option);
6602         Printer->notify.client_connected=False;
6603
6604         return WERR_OK;
6605 }
6606
6607 /****************************************************************
6608  _spoolss_AddJob
6609 ****************************************************************/
6610
6611 WERROR _spoolss_AddJob(pipes_struct *p,
6612                        struct spoolss_AddJob *r)
6613 {
6614         if (!r->in.buffer && (r->in.offered != 0)) {
6615                 return WERR_INVALID_PARAM;
6616         }
6617
6618         /* this is what a NT server returns for AddJob. AddJob must fail on
6619          * non-local printers */
6620
6621         if (r->in.level != 1) {
6622                 return WERR_UNKNOWN_LEVEL;
6623         }
6624
6625         return WERR_INVALID_PARAM;
6626 }
6627
6628 /****************************************************************************
6629 ****************************************************************************/
6630
6631 static void fill_job_info_1(JOB_INFO_1 *job_info, const print_queue_struct *queue,
6632                             int position, int snum,
6633                             const NT_PRINTER_INFO_LEVEL *ntprinter)
6634 {
6635         struct tm *t;
6636
6637         t=gmtime(&queue->time);
6638
6639         job_info->jobid=queue->job;
6640         init_unistr(&job_info->printername, lp_servicename(snum));
6641         init_unistr(&job_info->machinename, ntprinter->info_2->servername);
6642         init_unistr(&job_info->username, queue->fs_user);
6643         init_unistr(&job_info->document, queue->fs_file);
6644         init_unistr(&job_info->datatype, "RAW");
6645         init_unistr(&job_info->text_status, "");
6646         job_info->status=nt_printj_status(queue->status);
6647         job_info->priority=queue->priority;
6648         job_info->position=position;
6649         job_info->totalpages=queue->page_count;
6650         job_info->pagesprinted=0;
6651
6652         make_systemtime(&job_info->submitted, t);
6653 }
6654
6655 /****************************************************************************
6656 ****************************************************************************/
6657
6658 static bool fill_job_info_2(JOB_INFO_2 *job_info, const print_queue_struct *queue,
6659                             int position, int snum,
6660                             const NT_PRINTER_INFO_LEVEL *ntprinter,
6661                             DEVICEMODE *devmode)
6662 {
6663         struct tm *t;
6664
6665         t=gmtime(&queue->time);
6666
6667         job_info->jobid=queue->job;
6668
6669         init_unistr(&job_info->printername, ntprinter->info_2->printername);
6670
6671         init_unistr(&job_info->machinename, ntprinter->info_2->servername);
6672         init_unistr(&job_info->username, queue->fs_user);
6673         init_unistr(&job_info->document, queue->fs_file);
6674         init_unistr(&job_info->notifyname, queue->fs_user);
6675         init_unistr(&job_info->datatype, "RAW");
6676         init_unistr(&job_info->printprocessor, "winprint");
6677         init_unistr(&job_info->parameters, "");
6678         init_unistr(&job_info->drivername, ntprinter->info_2->drivername);
6679         init_unistr(&job_info->text_status, "");
6680
6681 /* and here the security descriptor */
6682
6683         job_info->status=nt_printj_status(queue->status);
6684         job_info->priority=queue->priority;
6685         job_info->position=position;
6686         job_info->starttime=0;
6687         job_info->untiltime=0;
6688         job_info->totalpages=queue->page_count;
6689         job_info->size=queue->size;
6690         make_systemtime(&(job_info->submitted), t);
6691         job_info->timeelapsed=0;
6692         job_info->pagesprinted=0;
6693
6694         job_info->devmode = devmode;
6695
6696         return (True);
6697 }
6698
6699 /****************************************************************************
6700  Enumjobs at level 1.
6701 ****************************************************************************/
6702
6703 static WERROR enumjobs_level1(const print_queue_struct *queue, int snum,
6704                               const NT_PRINTER_INFO_LEVEL *ntprinter,
6705                               RPC_BUFFER *buffer, uint32 offered,
6706                               uint32 *needed, uint32 *returned)
6707 {
6708         JOB_INFO_1 *info;
6709         int i;
6710         WERROR result = WERR_OK;
6711
6712         info=SMB_MALLOC_ARRAY(JOB_INFO_1,*returned);
6713         if (info==NULL) {
6714                 *returned=0;
6715                 return WERR_NOMEM;
6716         }
6717
6718         for (i=0; i<*returned; i++)
6719                 fill_job_info_1( &info[i], &queue[i], i, snum, ntprinter );
6720
6721         /* check the required size. */
6722         for (i=0; i<*returned; i++)
6723                 (*needed) += spoolss_size_job_info_1(&info[i]);
6724
6725         if (*needed > offered) {
6726                 result = WERR_INSUFFICIENT_BUFFER;
6727                 goto out;
6728         }
6729
6730         if (!rpcbuf_alloc_size(buffer, *needed)) {
6731                 result = WERR_NOMEM;
6732                 goto out;
6733         }
6734
6735         /* fill the buffer with the structures */
6736         for (i=0; i<*returned; i++)
6737                 smb_io_job_info_1("", buffer, &info[i], 0);
6738
6739 out:
6740         /* clear memory */
6741         SAFE_FREE(info);
6742
6743         if ( !W_ERROR_IS_OK(result) )
6744                 *returned = 0;
6745
6746         return result;
6747 }
6748
6749 /****************************************************************************
6750  Enumjobs at level 2.
6751 ****************************************************************************/
6752
6753 static WERROR enumjobs_level2(const print_queue_struct *queue, int snum,
6754                               const NT_PRINTER_INFO_LEVEL *ntprinter,
6755                               RPC_BUFFER *buffer, uint32 offered,
6756                               uint32 *needed, uint32 *returned)
6757 {
6758         JOB_INFO_2 *info = NULL;
6759         int i;
6760         WERROR result = WERR_OK;
6761         DEVICEMODE *devmode = NULL;
6762
6763         if ( !(info = SMB_MALLOC_ARRAY(JOB_INFO_2,*returned)) ) {
6764                 *returned=0;
6765                 return WERR_NOMEM;
6766         }
6767
6768         /* this should not be a failure condition if the devmode is NULL */
6769
6770         devmode = construct_dev_mode(lp_const_servicename(snum));
6771
6772         for (i=0; i<*returned; i++)
6773                 fill_job_info_2(&(info[i]), &queue[i], i, snum, ntprinter, devmode);
6774
6775         /* check the required size. */
6776         for (i=0; i<*returned; i++)
6777                 (*needed) += spoolss_size_job_info_2(&info[i]);
6778
6779         if (*needed > offered) {
6780                 result = WERR_INSUFFICIENT_BUFFER;
6781                 goto out;
6782         }
6783
6784         if (!rpcbuf_alloc_size(buffer, *needed)) {
6785                 result = WERR_NOMEM;
6786                 goto out;
6787         }
6788
6789         /* fill the buffer with the structures */
6790         for (i=0; i<*returned; i++)
6791                 smb_io_job_info_2("", buffer, &info[i], 0);
6792
6793 out:
6794         free_devmode(devmode);
6795         SAFE_FREE(info);
6796
6797         if ( !W_ERROR_IS_OK(result) )
6798                 *returned = 0;
6799
6800         return result;
6801
6802 }
6803
6804 /****************************************************************************
6805  Enumjobs.
6806 ****************************************************************************/
6807
6808 WERROR _spoolss_enumjobs( pipes_struct *p, SPOOL_Q_ENUMJOBS *q_u, SPOOL_R_ENUMJOBS *r_u)
6809 {
6810         POLICY_HND *handle = &q_u->handle;
6811         uint32 level = q_u->level;
6812         RPC_BUFFER *buffer = NULL;
6813         uint32 offered = q_u->offered;
6814         uint32 *needed = &r_u->needed;
6815         uint32 *returned = &r_u->returned;
6816         WERROR wret;
6817         NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
6818         int snum;
6819         print_status_struct prt_status;
6820         print_queue_struct *queue=NULL;
6821
6822         /* that's an [in out] buffer */
6823
6824         if (!q_u->buffer && (offered!=0)) {
6825                 return WERR_INVALID_PARAM;
6826         }
6827
6828         if (offered > MAX_RPC_DATA_SIZE) {
6829                 return WERR_INVALID_PARAM;
6830         }
6831
6832         rpcbuf_move(q_u->buffer, &r_u->buffer);
6833         buffer = r_u->buffer;
6834
6835         DEBUG(4,("_spoolss_enumjobs\n"));
6836
6837         *needed=0;
6838         *returned=0;
6839
6840         /* lookup the printer snum and tdb entry */
6841
6842         if (!get_printer_snum(p, handle, &snum, NULL))
6843                 return WERR_BADFID;
6844
6845         wret = get_a_printer(NULL, &ntprinter, 2, lp_servicename(snum));
6846         if ( !W_ERROR_IS_OK(wret) )
6847                 return wret;
6848
6849         *returned = print_queue_status(snum, &queue, &prt_status);
6850         DEBUGADD(4,("count:[%d], status:[%d], [%s]\n", *returned, prt_status.status, prt_status.message));
6851
6852         if (*returned == 0) {
6853                 SAFE_FREE(queue);
6854                 free_a_printer(&ntprinter, 2);
6855                 return WERR_OK;
6856         }
6857
6858         switch (level) {
6859         case 1:
6860                 wret = enumjobs_level1(queue, snum, ntprinter, buffer, offered, needed, returned);
6861                 break;
6862         case 2:
6863                 wret = enumjobs_level2(queue, snum, ntprinter, buffer, offered, needed, returned);
6864                 break;
6865         default:
6866                 *returned=0;
6867                 wret = WERR_UNKNOWN_LEVEL;
6868                 break;
6869         }
6870
6871         SAFE_FREE(queue);
6872         free_a_printer( &ntprinter, 2 );
6873         return wret;
6874 }
6875
6876 /****************************************************************
6877  _spoolss_ScheduleJob
6878 ****************************************************************/
6879
6880 WERROR _spoolss_ScheduleJob(pipes_struct *p,
6881                             struct spoolss_ScheduleJob *r)
6882 {
6883         return WERR_OK;
6884 }
6885
6886 /****************************************************************
6887  _spoolss_SetJob
6888 ****************************************************************/
6889
6890 WERROR _spoolss_SetJob(pipes_struct *p,
6891                        struct spoolss_SetJob *r)
6892 {
6893         POLICY_HND *handle = r->in.handle;
6894         uint32 jobid = r->in.job_id;
6895         uint32 command = r->in.command;
6896
6897         int snum;
6898         WERROR errcode = WERR_BADFUNC;
6899
6900         if (!get_printer_snum(p, handle, &snum, NULL)) {
6901                 return WERR_BADFID;
6902         }
6903
6904         if (!print_job_exists(lp_const_servicename(snum), jobid)) {
6905                 return WERR_INVALID_PRINTER_NAME;
6906         }
6907
6908         switch (command) {
6909         case SPOOLSS_JOB_CONTROL_CANCEL:
6910         case SPOOLSS_JOB_CONTROL_DELETE:
6911                 if (print_job_delete(p->server_info, snum, jobid, &errcode)) {
6912                         errcode = WERR_OK;
6913                 }
6914                 break;
6915         case SPOOLSS_JOB_CONTROL_PAUSE:
6916                 if (print_job_pause(p->server_info, snum, jobid, &errcode)) {
6917                         errcode = WERR_OK;
6918                 }
6919                 break;
6920         case SPOOLSS_JOB_CONTROL_RESTART:
6921         case SPOOLSS_JOB_CONTROL_RESUME:
6922                 if (print_job_resume(p->server_info, snum, jobid, &errcode)) {
6923                         errcode = WERR_OK;
6924                 }
6925                 break;
6926         default:
6927                 return WERR_UNKNOWN_LEVEL;
6928         }
6929
6930         return errcode;
6931 }
6932
6933 /****************************************************************************
6934  Enumerates all printer drivers at level 1.
6935 ****************************************************************************/
6936
6937 static WERROR enumprinterdrivers_level1(const char *servername, fstring architecture, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
6938 {
6939         int i;
6940         int ndrivers;
6941         uint32 version;
6942         fstring *list = NULL;
6943         NT_PRINTER_DRIVER_INFO_LEVEL driver;
6944         DRIVER_INFO_1 *driver_info_1=NULL;
6945         WERROR result = WERR_OK;
6946
6947         *returned=0;
6948
6949         for (version=0; version<DRIVER_MAX_VERSION; version++) {
6950                 list=NULL;
6951                 ndrivers=get_ntdrivers(&list, architecture, version);
6952                 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
6953
6954                 if(ndrivers == -1) {
6955                         SAFE_FREE(driver_info_1);
6956                         return WERR_NOMEM;
6957                 }
6958
6959                 if(ndrivers != 0) {
6960                         if((driver_info_1=SMB_REALLOC_ARRAY(driver_info_1, DRIVER_INFO_1, *returned+ndrivers )) == NULL) {
6961                                 DEBUG(0,("enumprinterdrivers_level1: failed to enlarge driver info buffer!\n"));
6962                                 SAFE_FREE(list);
6963                                 return WERR_NOMEM;
6964                         }
6965                 }
6966
6967                 for (i=0; i<ndrivers; i++) {
6968                         WERROR status;
6969                         DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
6970                         ZERO_STRUCT(driver);
6971                         status = get_a_printer_driver(&driver, 3, list[i],
6972                                                       architecture, version);
6973                         if (!W_ERROR_IS_OK(status)) {
6974                                 SAFE_FREE(list);
6975                                 SAFE_FREE(driver_info_1);
6976                                 return status;
6977                         }
6978                         fill_printer_driver_info_1(&driver_info_1[*returned+i], driver, servername, architecture );
6979                         free_a_printer_driver(driver, 3);
6980                 }
6981
6982                 *returned+=ndrivers;
6983                 SAFE_FREE(list);
6984         }
6985
6986         /* check the required size. */
6987         for (i=0; i<*returned; i++) {
6988                 DEBUGADD(6,("adding driver [%d]'s size\n",i));
6989                 *needed += spoolss_size_printer_driver_info_1(&driver_info_1[i]);
6990         }
6991
6992         if (*needed > offered) {
6993                 result = WERR_INSUFFICIENT_BUFFER;
6994                 goto out;
6995         }
6996
6997         if (!rpcbuf_alloc_size(buffer, *needed)) {
6998                 result = WERR_NOMEM;
6999                 goto out;
7000         }
7001
7002         /* fill the buffer with the driver structures */
7003         for (i=0; i<*returned; i++) {
7004                 DEBUGADD(6,("adding driver [%d] to buffer\n",i));
7005                 smb_io_printer_driver_info_1("", buffer, &driver_info_1[i], 0);
7006         }
7007
7008 out:
7009         SAFE_FREE(driver_info_1);
7010
7011         if ( !W_ERROR_IS_OK(result) )
7012                 *returned = 0;
7013
7014         return result;
7015 }
7016
7017 /****************************************************************************
7018  Enumerates all printer drivers at level 2.
7019 ****************************************************************************/
7020
7021 static WERROR enumprinterdrivers_level2(const char *servername, fstring architecture, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
7022 {
7023         int i;
7024         int ndrivers;
7025         uint32 version;
7026         fstring *list = NULL;
7027         NT_PRINTER_DRIVER_INFO_LEVEL driver;
7028         DRIVER_INFO_2 *driver_info_2=NULL;
7029         WERROR result = WERR_OK;
7030
7031         *returned=0;
7032
7033         for (version=0; version<DRIVER_MAX_VERSION; version++) {
7034                 list=NULL;
7035                 ndrivers=get_ntdrivers(&list, architecture, version);
7036                 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
7037
7038                 if(ndrivers == -1) {
7039                         SAFE_FREE(driver_info_2);
7040                         return WERR_NOMEM;
7041                 }
7042
7043                 if(ndrivers != 0) {
7044                         if((driver_info_2=SMB_REALLOC_ARRAY(driver_info_2, DRIVER_INFO_2, *returned+ndrivers )) == NULL) {
7045                                 DEBUG(0,("enumprinterdrivers_level2: failed to enlarge driver info buffer!\n"));
7046                                 SAFE_FREE(list);
7047                                 return WERR_NOMEM;
7048                         }
7049                 }
7050
7051                 for (i=0; i<ndrivers; i++) {
7052                         WERROR status;
7053
7054                         DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
7055                         ZERO_STRUCT(driver);
7056                         status = get_a_printer_driver(&driver, 3, list[i],
7057                                                       architecture, version);
7058                         if (!W_ERROR_IS_OK(status)) {
7059                                 SAFE_FREE(list);
7060                                 SAFE_FREE(driver_info_2);
7061                                 return status;
7062                         }
7063                         fill_printer_driver_info_2(&driver_info_2[*returned+i], driver, servername);
7064                         free_a_printer_driver(driver, 3);
7065                 }
7066
7067                 *returned+=ndrivers;
7068                 SAFE_FREE(list);
7069         }
7070
7071         /* check the required size. */
7072         for (i=0; i<*returned; i++) {
7073                 DEBUGADD(6,("adding driver [%d]'s size\n",i));
7074                 *needed += spoolss_size_printer_driver_info_2(&(driver_info_2[i]));
7075         }
7076
7077         if (*needed > offered) {
7078                 result = WERR_INSUFFICIENT_BUFFER;
7079                 goto out;
7080         }
7081
7082         if (!rpcbuf_alloc_size(buffer, *needed)) {
7083                 result = WERR_NOMEM;
7084                 goto out;
7085         }
7086
7087         /* fill the buffer with the form structures */
7088         for (i=0; i<*returned; i++) {
7089                 DEBUGADD(6,("adding driver [%d] to buffer\n",i));
7090                 smb_io_printer_driver_info_2("", buffer, &(driver_info_2[i]), 0);
7091         }
7092
7093 out:
7094         SAFE_FREE(driver_info_2);
7095
7096         if ( !W_ERROR_IS_OK(result) )
7097                 *returned = 0;
7098
7099         return result;
7100 }
7101
7102 /****************************************************************************
7103  Enumerates all printer drivers at level 3.
7104 ****************************************************************************/
7105
7106 static WERROR enumprinterdrivers_level3(const char *servername, fstring architecture, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
7107 {
7108         int i;
7109         int ndrivers;
7110         uint32 version;
7111         fstring *list = NULL;
7112         DRIVER_INFO_3 *driver_info_3=NULL;
7113         NT_PRINTER_DRIVER_INFO_LEVEL driver;
7114         WERROR result = WERR_OK;
7115
7116         *returned=0;
7117
7118         for (version=0; version<DRIVER_MAX_VERSION; version++) {
7119                 list=NULL;
7120                 ndrivers=get_ntdrivers(&list, architecture, version);
7121                 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
7122
7123                 if(ndrivers == -1) {
7124                         SAFE_FREE(driver_info_3);
7125                         return WERR_NOMEM;
7126                 }
7127
7128                 if(ndrivers != 0) {
7129                         if((driver_info_3=SMB_REALLOC_ARRAY(driver_info_3, DRIVER_INFO_3, *returned+ndrivers )) == NULL) {
7130                                 DEBUG(0,("enumprinterdrivers_level3: failed to enlarge driver info buffer!\n"));
7131                                 SAFE_FREE(list);
7132                                 return WERR_NOMEM;
7133                         }
7134                 }
7135
7136                 for (i=0; i<ndrivers; i++) {
7137                         WERROR status;
7138
7139                         DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
7140                         ZERO_STRUCT(driver);
7141                         status = get_a_printer_driver(&driver, 3, list[i],
7142                                                       architecture, version);
7143                         if (!W_ERROR_IS_OK(status)) {
7144                                 SAFE_FREE(list);
7145                                 SAFE_FREE(driver_info_3);
7146                                 return status;
7147                         }
7148                         fill_printer_driver_info_3(&driver_info_3[*returned+i], driver, servername);
7149                         free_a_printer_driver(driver, 3);
7150                 }
7151
7152                 *returned+=ndrivers;
7153                 SAFE_FREE(list);
7154         }
7155
7156         /* check the required size. */
7157         for (i=0; i<*returned; i++) {
7158                 DEBUGADD(6,("adding driver [%d]'s size\n",i));
7159                 *needed += spoolss_size_printer_driver_info_3(&driver_info_3[i]);
7160         }
7161
7162         if (*needed > offered) {
7163                 result = WERR_INSUFFICIENT_BUFFER;
7164                 goto out;
7165         }
7166
7167         if (!rpcbuf_alloc_size(buffer, *needed)) {
7168                 result = WERR_NOMEM;
7169                 goto out;
7170         }
7171
7172         /* fill the buffer with the driver structures */
7173         for (i=0; i<*returned; i++) {
7174                 DEBUGADD(6,("adding driver [%d] to buffer\n",i));
7175                 smb_io_printer_driver_info_3("", buffer, &driver_info_3[i], 0);
7176         }
7177
7178 out:
7179         for (i=0; i<*returned; i++) {
7180                 SAFE_FREE(driver_info_3[i].dependentfiles);
7181         }
7182
7183         SAFE_FREE(driver_info_3);
7184
7185         if ( !W_ERROR_IS_OK(result) )
7186                 *returned = 0;
7187
7188         return result;
7189 }
7190
7191 /****************************************************************************
7192  Enumerates all printer drivers.
7193 ****************************************************************************/
7194
7195 WERROR _spoolss_enumprinterdrivers( pipes_struct *p, SPOOL_Q_ENUMPRINTERDRIVERS *q_u, SPOOL_R_ENUMPRINTERDRIVERS *r_u)
7196 {
7197         uint32 level = q_u->level;
7198         RPC_BUFFER *buffer = NULL;
7199         uint32 offered = q_u->offered;
7200         uint32 *needed = &r_u->needed;
7201         uint32 *returned = &r_u->returned;
7202         const char *cservername;
7203         fstring servername;
7204         fstring architecture;
7205
7206         /* that's an [in out] buffer */
7207
7208         if (!q_u->buffer && (offered!=0)) {
7209                 return WERR_INVALID_PARAM;
7210         }
7211
7212         if (offered > MAX_RPC_DATA_SIZE) {
7213                 return WERR_INVALID_PARAM;
7214         }
7215
7216         rpcbuf_move(q_u->buffer, &r_u->buffer);
7217         buffer = r_u->buffer;
7218
7219         DEBUG(4,("_spoolss_enumprinterdrivers\n"));
7220
7221         *needed   = 0;
7222         *returned = 0;
7223
7224         unistr2_to_ascii(architecture, &q_u->environment, sizeof(architecture));
7225         unistr2_to_ascii(servername, &q_u->name, sizeof(servername));
7226
7227         cservername = canon_servername(servername);
7228
7229         if (!is_myname_or_ipaddr(cservername))
7230                 return WERR_UNKNOWN_PRINTER_DRIVER;
7231
7232         switch (level) {
7233         case 1:
7234                 return enumprinterdrivers_level1(cservername, architecture, buffer, offered, needed, returned);
7235         case 2:
7236                 return enumprinterdrivers_level2(cservername, architecture, buffer, offered, needed, returned);
7237         case 3:
7238                 return enumprinterdrivers_level3(cservername, architecture, buffer, offered, needed, returned);
7239         default:
7240                 return WERR_UNKNOWN_LEVEL;
7241         }
7242 }
7243
7244 /****************************************************************************
7245 ****************************************************************************/
7246
7247 static WERROR fill_form_info_1(TALLOC_CTX *mem_ctx,
7248                                struct spoolss_FormInfo1 *form,
7249                                nt_forms_struct *list)
7250 {
7251         form->form_name         = talloc_strdup(mem_ctx, list->name);
7252         W_ERROR_HAVE_NO_MEMORY(form->form_name);
7253
7254         form->flags             = list->flag;
7255         form->size.width        = list->width;
7256         form->size.height       = list->length;
7257         form->area.left         = list->left;
7258         form->area.top          = list->top;
7259         form->area.right        = list->right;
7260         form->area.bottom       = list->bottom;
7261
7262         return WERR_OK;
7263 }
7264
7265 /****************************************************************
7266  _spoolss_EnumForms
7267 ****************************************************************/
7268
7269 WERROR _spoolss_EnumForms(pipes_struct *p,
7270                           struct spoolss_EnumForms *r)
7271 {
7272         nt_forms_struct *list=NULL;
7273         nt_forms_struct *builtinlist=NULL;
7274         union spoolss_FormInfo *info;
7275         uint32_t count;
7276         uint32_t numbuiltinforms;
7277         size_t buffer_size = 0;
7278         int i;
7279
7280         *r->out.count = 0;
7281
7282         /* that's an [in out] buffer */
7283
7284         if (!r->in.buffer && (r->in.offered != 0) ) {
7285                 return WERR_INVALID_PARAM;
7286         }
7287
7288         DEBUG(4,("_spoolss_EnumForms\n"));
7289         DEBUGADD(5,("Offered buffer size [%d]\n", r->in.offered));
7290         DEBUGADD(5,("Info level [%d]\n",          r->in.level));
7291
7292         numbuiltinforms = get_builtin_ntforms(&builtinlist);
7293         DEBUGADD(5,("Number of builtin forms [%d]\n",     numbuiltinforms));
7294         count = get_ntforms(&list);
7295         DEBUGADD(5,("Number of user forms [%d]\n",     count));
7296         count += numbuiltinforms;
7297
7298         if (count == 0) {
7299                 SAFE_FREE(builtinlist);
7300                 SAFE_FREE(list);
7301                 return WERR_NO_MORE_ITEMS;
7302         }
7303
7304         info = TALLOC_ARRAY(p->mem_ctx, union spoolss_FormInfo, count);
7305         if (!info) {
7306                 SAFE_FREE(builtinlist);
7307                 SAFE_FREE(list);
7308                 return WERR_NOMEM;
7309         }
7310
7311         switch (r->in.level) {
7312         case 1:
7313                 /* construct the list of form structures */
7314                 for (i=0; i<numbuiltinforms; i++) {
7315                         DEBUGADD(6,("Filling form number [%d]\n",i));
7316                         fill_form_info_1(info, &info[i].info1, &builtinlist[i]);
7317                 }
7318
7319                 SAFE_FREE(builtinlist);
7320
7321                 for (; i<count; i++) {
7322                         DEBUGADD(6,("Filling form number [%d]\n",i));
7323                         fill_form_info_1(info, &info[i].info1, &list[i-numbuiltinforms]);
7324                 }
7325
7326                 SAFE_FREE(list);
7327
7328                 /* check the required size. */
7329                 for (i=0; i<numbuiltinforms; i++) {
7330                         DEBUGADD(6,("adding form [%d]'s size\n",i));
7331                         buffer_size += ndr_size_spoolss_FormInfo1(&info[i].info1, NULL, 0);
7332                 }
7333                 for (; i<count; i++) {
7334                         DEBUGADD(6,("adding form [%d]'s size\n",i));
7335                         buffer_size += ndr_size_spoolss_FormInfo1(&info[i].info1, NULL, 0);
7336                 }
7337
7338                 *r->out.needed = buffer_size;
7339
7340                 if (*r->out.needed > r->in.offered) {
7341                         TALLOC_FREE(info);
7342                         return WERR_INSUFFICIENT_BUFFER;
7343                 }
7344
7345                 *r->out.count = count;
7346                 *r->out.info = info;
7347
7348                 return WERR_OK;
7349
7350         default:
7351                 SAFE_FREE(list);
7352                 SAFE_FREE(builtinlist);
7353                 return WERR_UNKNOWN_LEVEL;
7354         }
7355 }
7356
7357 /****************************************************************
7358  _spoolss_GetForm
7359 ****************************************************************/
7360
7361 WERROR _spoolss_GetForm(pipes_struct *p,
7362                         struct spoolss_GetForm *r)
7363 {
7364         uint32 level = r->in.level;
7365         uint32 offered = r->in.offered;
7366         uint32 *needed = r->out.needed;
7367
7368         nt_forms_struct *list=NULL;
7369         nt_forms_struct builtin_form;
7370         bool foundBuiltin;
7371         union spoolss_FormInfo info;
7372         struct spoolss_FormInfo1 form_1;
7373         int numofforms=0, i=0;
7374
7375         /* that's an [in out] buffer */
7376
7377         if (!r->in.buffer && (offered!=0)) {
7378                 return WERR_INVALID_PARAM;
7379         }
7380
7381         DEBUG(4,("_spoolss_GetForm\n"));
7382         DEBUGADD(5,("Offered buffer size [%d]\n", offered));
7383         DEBUGADD(5,("Info level [%d]\n",          level));
7384
7385         foundBuiltin = get_a_builtin_ntform_by_string(r->in.form_name, &builtin_form);
7386         if (!foundBuiltin) {
7387                 numofforms = get_ntforms(&list);
7388                 DEBUGADD(5,("Number of forms [%d]\n",     numofforms));
7389
7390                 if (numofforms == 0)
7391                         return WERR_BADFID;
7392         }
7393
7394         ZERO_STRUCT(form_1);
7395
7396         switch (level) {
7397         case 1:
7398                 if (foundBuiltin) {
7399                         fill_form_info_1(p->mem_ctx, &form_1, &builtin_form);
7400                 } else {
7401
7402                         /* Check if the requested name is in the list of form structures */
7403                         for (i=0; i<numofforms; i++) {
7404
7405                                 DEBUG(4,("_spoolss_GetForm: checking form %s (want %s)\n",
7406                                         list[i].name, r->in.form_name));
7407
7408                                 if (strequal(r->in.form_name, list[i].name)) {
7409                                         DEBUGADD(6,("Found form %s number [%d]\n",
7410                                                 r->in.form_name, i));
7411                                         fill_form_info_1(p->mem_ctx, &form_1, &list[i]);
7412                                         break;
7413                                 }
7414                         }
7415
7416                         SAFE_FREE(list);
7417                         if (i == numofforms) {
7418                                 return WERR_BADFID;
7419                         }
7420                 }
7421                 /* check the required size. */
7422
7423                 info.info1 = form_1;
7424
7425                 *needed = ndr_size_spoolss_FormInfo(&info, 1, NULL, 0);
7426
7427                 if (*needed > offered) {
7428                         r->out.info = NULL;
7429                         return WERR_INSUFFICIENT_BUFFER;
7430                 }
7431
7432                 r->out.info->info1 = form_1;
7433
7434                 /* fill the buffer with the form structures */
7435                 DEBUGADD(6,("adding form %s [%d] to buffer\n",
7436                         r->in.form_name, i));
7437
7438                 return WERR_OK;
7439
7440         default:
7441                 SAFE_FREE(list);
7442                 return WERR_UNKNOWN_LEVEL;
7443         }
7444 }
7445
7446 /****************************************************************************
7447 ****************************************************************************/
7448
7449 static void fill_port_1(PORT_INFO_1 *port, const char *name)
7450 {
7451         init_unistr(&port->port_name, name);
7452 }
7453
7454 /****************************************************************************
7455  TODO: This probably needs distinguish between TCP/IP and Local ports
7456  somehow.
7457 ****************************************************************************/
7458
7459 static void fill_port_2(PORT_INFO_2 *port, const char *name)
7460 {
7461         init_unistr(&port->port_name, name);
7462         init_unistr(&port->monitor_name, "Local Monitor");
7463         init_unistr(&port->description, SPL_LOCAL_PORT );
7464         port->port_type=PORT_TYPE_WRITE;
7465         port->reserved=0x0;
7466 }
7467
7468
7469 /****************************************************************************
7470  wrapper around the enumer ports command
7471 ****************************************************************************/
7472
7473 WERROR enumports_hook(TALLOC_CTX *ctx, int *count, char ***lines )
7474 {
7475         char *cmd = lp_enumports_cmd();
7476         char **qlines = NULL;
7477         char *command = NULL;
7478         int numlines;
7479         int ret;
7480         int fd;
7481
7482         *count = 0;
7483         *lines = NULL;
7484
7485         /* if no hook then just fill in the default port */
7486
7487         if ( !*cmd ) {
7488                 if (!(qlines = TALLOC_ARRAY( NULL, char*, 2 ))) {
7489                         return WERR_NOMEM;
7490                 }
7491                 if (!(qlines[0] = talloc_strdup(qlines, SAMBA_PRINTER_PORT_NAME ))) {
7492                         TALLOC_FREE(qlines);
7493                         return WERR_NOMEM;
7494                 }
7495                 qlines[1] = NULL;
7496                 numlines = 1;
7497         }
7498         else {
7499                 /* we have a valid enumport command */
7500
7501                 command = talloc_asprintf(ctx, "%s \"%d\"", cmd, 1);
7502                 if (!command) {
7503                         return WERR_NOMEM;
7504                 }
7505
7506                 DEBUG(10,("Running [%s]\n", command));
7507                 ret = smbrun(command, &fd);
7508                 DEBUG(10,("Returned [%d]\n", ret));
7509                 TALLOC_FREE(command);
7510                 if (ret != 0) {
7511                         if (fd != -1) {
7512                                 close(fd);
7513                         }
7514                         return WERR_ACCESS_DENIED;
7515                 }
7516
7517                 numlines = 0;
7518                 qlines = fd_lines_load(fd, &numlines, 0, NULL);
7519                 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
7520                 close(fd);
7521         }
7522
7523         *count = numlines;
7524         *lines = qlines;
7525
7526         return WERR_OK;
7527 }
7528
7529 /****************************************************************************
7530  enumports level 1.
7531 ****************************************************************************/
7532
7533 static WERROR enumports_level_1(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
7534 {
7535         PORT_INFO_1 *ports=NULL;
7536         int i=0;
7537         WERROR result = WERR_OK;
7538         char **qlines = NULL;
7539         int numlines = 0;
7540
7541         result = enumports_hook(talloc_tos(), &numlines, &qlines );
7542         if (!W_ERROR_IS_OK(result)) {
7543                 TALLOC_FREE(qlines);
7544                 return result;
7545         }
7546
7547         if(numlines) {
7548                 if((ports=SMB_MALLOC_ARRAY( PORT_INFO_1, numlines )) == NULL) {
7549                         DEBUG(10,("Returning WERR_NOMEM [%s]\n",
7550                                   win_errstr(WERR_NOMEM)));
7551                         TALLOC_FREE(qlines);
7552                         return WERR_NOMEM;
7553                 }
7554
7555                 for (i=0; i<numlines; i++) {
7556                         DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
7557                         fill_port_1(&ports[i], qlines[i]);
7558                 }
7559         }
7560         TALLOC_FREE(qlines);
7561
7562         *returned = numlines;
7563
7564         /* check the required size. */
7565         for (i=0; i<*returned; i++) {
7566                 DEBUGADD(6,("adding port [%d]'s size\n", i));
7567                 *needed += spoolss_size_port_info_1(&ports[i]);
7568         }
7569
7570         if (*needed > offered) {
7571                 result = WERR_INSUFFICIENT_BUFFER;
7572                 goto out;
7573         }
7574
7575         if (!rpcbuf_alloc_size(buffer, *needed)) {
7576                 result = WERR_NOMEM;
7577                 goto out;
7578         }
7579
7580         /* fill the buffer with the ports structures */
7581         for (i=0; i<*returned; i++) {
7582                 DEBUGADD(6,("adding port [%d] to buffer\n", i));
7583                 smb_io_port_1("", buffer, &ports[i], 0);
7584         }
7585
7586 out:
7587         SAFE_FREE(ports);
7588
7589         if ( !W_ERROR_IS_OK(result) )
7590                 *returned = 0;
7591
7592         return result;
7593 }
7594
7595 /****************************************************************************
7596  enumports level 2.
7597 ****************************************************************************/
7598
7599 static WERROR enumports_level_2(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
7600 {
7601         PORT_INFO_2 *ports=NULL;
7602         int i=0;
7603         WERROR result = WERR_OK;
7604         char **qlines = NULL;
7605         int numlines = 0;
7606
7607         result = enumports_hook(talloc_tos(), &numlines, &qlines );
7608         if ( !W_ERROR_IS_OK(result)) {
7609                 TALLOC_FREE(qlines);
7610                 return result;
7611         }
7612
7613         if(numlines) {
7614                 if((ports=SMB_MALLOC_ARRAY( PORT_INFO_2, numlines)) == NULL) {
7615                         TALLOC_FREE(qlines);
7616                         return WERR_NOMEM;
7617                 }
7618
7619                 for (i=0; i<numlines; i++) {
7620                         DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
7621                         fill_port_2(&(ports[i]), qlines[i]);
7622                 }
7623         }
7624
7625         TALLOC_FREE(qlines);
7626
7627         *returned = numlines;
7628
7629         /* check the required size. */
7630         for (i=0; i<*returned; i++) {
7631                 DEBUGADD(6,("adding port [%d]'s size\n", i));
7632                 *needed += spoolss_size_port_info_2(&ports[i]);
7633         }
7634
7635         if (*needed > offered) {
7636                 result = WERR_INSUFFICIENT_BUFFER;
7637                 goto out;
7638         }
7639
7640         if (!rpcbuf_alloc_size(buffer, *needed)) {
7641                 result = WERR_NOMEM;
7642                 goto out;
7643         }
7644
7645         /* fill the buffer with the ports structures */
7646         for (i=0; i<*returned; i++) {
7647                 DEBUGADD(6,("adding port [%d] to buffer\n", i));
7648                 smb_io_port_2("", buffer, &ports[i], 0);
7649         }
7650
7651 out:
7652         SAFE_FREE(ports);
7653
7654         if ( !W_ERROR_IS_OK(result) )
7655                 *returned = 0;
7656
7657         return result;
7658 }
7659
7660 /****************************************************************************
7661  enumports.
7662 ****************************************************************************/
7663
7664 WERROR _spoolss_enumports( pipes_struct *p, SPOOL_Q_ENUMPORTS *q_u, SPOOL_R_ENUMPORTS *r_u)
7665 {
7666         uint32 level = q_u->level;
7667         RPC_BUFFER *buffer = NULL;
7668         uint32 offered = q_u->offered;
7669         uint32 *needed = &r_u->needed;
7670         uint32 *returned = &r_u->returned;
7671
7672         /* that's an [in out] buffer */
7673
7674         if (!q_u->buffer && (offered!=0)) {
7675                 return WERR_INVALID_PARAM;
7676         }
7677
7678         if (offered > MAX_RPC_DATA_SIZE) {
7679                 return WERR_INVALID_PARAM;
7680         }
7681
7682         rpcbuf_move(q_u->buffer, &r_u->buffer);
7683         buffer = r_u->buffer;
7684
7685         DEBUG(4,("_spoolss_enumports\n"));
7686
7687         *returned=0;
7688         *needed=0;
7689
7690         switch (level) {
7691         case 1:
7692                 return enumports_level_1(buffer, offered, needed, returned);
7693         case 2:
7694                 return enumports_level_2(buffer, offered, needed, returned);
7695         default:
7696                 return WERR_UNKNOWN_LEVEL;
7697         }
7698 }
7699
7700 /****************************************************************************
7701 ****************************************************************************/
7702
7703 static WERROR spoolss_addprinterex_level_2(pipes_struct *p,
7704                                            const char *server,
7705                                            struct spoolss_SetPrinterInfoCtr *info_ctr,
7706                                            struct spoolss_DeviceMode *devmode,
7707                                            struct security_descriptor *sec_desc,
7708                                            struct spoolss_UserLevelCtr *user_ctr,
7709                                            POLICY_HND *handle)
7710 {
7711         NT_PRINTER_INFO_LEVEL *printer = NULL;
7712         fstring name;
7713         int     snum;
7714         WERROR err = WERR_OK;
7715
7716         if ( !(printer = TALLOC_ZERO_P(NULL, NT_PRINTER_INFO_LEVEL)) ) {
7717                 DEBUG(0,("spoolss_addprinterex_level_2: malloc fail.\n"));
7718                 return WERR_NOMEM;
7719         }
7720
7721         /* convert from UNICODE to ASCII - this allocates the info_2 struct inside *printer.*/
7722         if (!convert_printer_info_new(info_ctr, printer)) {
7723                 free_a_printer(&printer, 2);
7724                 return WERR_NOMEM;
7725         }
7726
7727         /* check to see if the printer already exists */
7728
7729         if ((snum = print_queue_snum(printer->info_2->sharename)) != -1) {
7730                 DEBUG(5, ("spoolss_addprinterex_level_2: Attempted to add a printer named [%s] when one already existed!\n",
7731                         printer->info_2->sharename));
7732                 free_a_printer(&printer, 2);
7733                 return WERR_PRINTER_ALREADY_EXISTS;
7734         }
7735
7736         /* FIXME!!!  smbd should check to see if the driver is installed before
7737            trying to add a printer like this  --jerry */
7738
7739         if (*lp_addprinter_cmd() ) {
7740                 if ( !add_printer_hook(p->mem_ctx, p->server_info->ptok,
7741                                        printer) ) {
7742                         free_a_printer(&printer,2);
7743                         return WERR_ACCESS_DENIED;
7744                 }
7745         } else {
7746                 DEBUG(0,("spoolss_addprinterex_level_2: add printer for printer %s called and no"
7747                         "smb.conf parameter \"addprinter command\" is defined. This"
7748                         "parameter must exist for this call to succeed\n",
7749                         printer->info_2->sharename ));
7750         }
7751
7752         /* use our primary netbios name since get_a_printer() will convert
7753            it to what the client expects on a case by case basis */
7754
7755         slprintf(name, sizeof(name)-1, "\\\\%s\\%s", global_myname(),
7756              printer->info_2->sharename);
7757
7758
7759         if ((snum = print_queue_snum(printer->info_2->sharename)) == -1) {
7760                 free_a_printer(&printer,2);
7761                 return WERR_ACCESS_DENIED;
7762         }
7763
7764         /* you must be a printer admin to add a new printer */
7765         if (!print_access_check(NULL, snum, PRINTER_ACCESS_ADMINISTER)) {
7766                 free_a_printer(&printer,2);
7767                 return WERR_ACCESS_DENIED;
7768         }
7769
7770         /*
7771          * Do sanity check on the requested changes for Samba.
7772          */
7773
7774         if (!check_printer_ok(printer->info_2, snum)) {
7775                 free_a_printer(&printer,2);
7776                 return WERR_INVALID_PARAM;
7777         }
7778
7779         /*
7780          * When a printer is created, the drivername bound to the printer is used
7781          * to lookup previously saved driver initialization info, which is then
7782          * bound to the new printer, simulating what happens in the Windows arch.
7783          */
7784
7785         if (!devmode)
7786         {
7787                 set_driver_init(printer, 2);
7788         }
7789         else
7790         {
7791                 /* A valid devmode was included, convert and link it
7792                 */
7793                 DEBUGADD(10, ("spoolss_addprinterex_level_2: devmode included, converting\n"));
7794
7795                 if (!convert_devicemode_new(printer->info_2->printername,
7796                                             devmode,
7797                                             &printer->info_2->devmode))
7798                         return  WERR_NOMEM;
7799         }
7800
7801         /* write the ASCII on disk */
7802         err = mod_a_printer(printer, 2);
7803         if (!W_ERROR_IS_OK(err)) {
7804                 free_a_printer(&printer,2);
7805                 return err;
7806         }
7807
7808         if (!open_printer_hnd(p, handle, name, PRINTER_ACCESS_ADMINISTER)) {
7809                 /* Handle open failed - remove addition. */
7810                 del_a_printer(printer->info_2->sharename);
7811                 free_a_printer(&printer,2);
7812                 ZERO_STRUCTP(handle);
7813                 return WERR_ACCESS_DENIED;
7814         }
7815
7816         update_c_setprinter(False);
7817         free_a_printer(&printer,2);
7818
7819         return WERR_OK;
7820 }
7821
7822 /****************************************************************
7823  _spoolss_AddPrinterEx
7824 ****************************************************************/
7825
7826 WERROR _spoolss_AddPrinterEx(pipes_struct *p,
7827                              struct spoolss_AddPrinterEx *r)
7828 {
7829         switch (r->in.info_ctr->level) {
7830         case 1:
7831                 /* we don't handle yet */
7832                 /* but I know what to do ... */
7833                 return WERR_UNKNOWN_LEVEL;
7834         case 2:
7835                 return spoolss_addprinterex_level_2(p, r->in.server,
7836                                                     r->in.info_ctr,
7837                                                     r->in.devmode_ctr->devmode,
7838                                                     r->in.secdesc_ctr->sd,
7839                                                     r->in.userlevel_ctr,
7840                                                     r->out.handle);
7841         default:
7842                 return WERR_UNKNOWN_LEVEL;
7843         }
7844 }
7845
7846 /****************************************************************
7847  _spoolss_AddPrinterDriver
7848 ****************************************************************/
7849
7850 WERROR _spoolss_AddPrinterDriver(pipes_struct *p,
7851                                  struct spoolss_AddPrinterDriver *r)
7852 {
7853         uint32_t level = r->in.info_ctr->level;
7854         struct spoolss_AddDriverInfoCtr *info = r->in.info_ctr;
7855         WERROR err = WERR_OK;
7856         NT_PRINTER_DRIVER_INFO_LEVEL driver;
7857         fstring driver_name;
7858         uint32 version;
7859         const char *fn;
7860
7861         switch (p->hdr_req.opnum) {
7862                 case NDR_SPOOLSS_ADDPRINTERDRIVER:
7863                         fn = "_spoolss_AddPrinterDriver";
7864                         break;
7865                 case NDR_SPOOLSS_ADDPRINTERDRIVEREX:
7866                         fn = "_spoolss_AddPrinterDriverEx";
7867                         break;
7868                 default:
7869                         return WERR_INVALID_PARAM;
7870         }
7871
7872
7873         /* FIXME */
7874         if (level != 3 && level != 6) {
7875                 /* Clever hack from Martin Zielinski <mz@seh.de>
7876                  * to allow downgrade from level 8 (Vista).
7877                  */
7878                 DEBUG(0,("%s: level %d not yet implemented\n", fn, level));
7879                 return WERR_UNKNOWN_LEVEL;
7880         }
7881
7882         ZERO_STRUCT(driver);
7883
7884         if (!convert_printer_driver_info(info, &driver, level)) {
7885                 err = WERR_NOMEM;
7886                 goto done;
7887         }
7888
7889         DEBUG(5,("Cleaning driver's information\n"));
7890         err = clean_up_driver_struct(p, driver, level);
7891         if (!W_ERROR_IS_OK(err))
7892                 goto done;
7893
7894         DEBUG(5,("Moving driver to final destination\n"));
7895         if( !W_ERROR_IS_OK(err = move_driver_to_download_area(p, driver, level,
7896                                                               &err)) ) {
7897                 goto done;
7898         }
7899
7900         if (add_a_printer_driver(driver, level)!=0) {
7901                 err = WERR_ACCESS_DENIED;
7902                 goto done;
7903         }
7904
7905         switch(level) {
7906         case 3:
7907                 fstrcpy(driver_name,
7908                         driver.info_3->name ? driver.info_3->name : "");
7909                 break;
7910         case 6:
7911                 fstrcpy(driver_name,
7912                         driver.info_6->name ?  driver.info_6->name : "");
7913                 break;
7914         }
7915
7916         /*
7917          * I think this is where he DrvUpgradePrinter() hook would be
7918          * be called in a driver's interface DLL on a Windows NT 4.0/2k
7919          * server.  Right now, we just need to send ourselves a message
7920          * to update each printer bound to this driver.   --jerry
7921          */
7922
7923         if (!srv_spoolss_drv_upgrade_printer(driver_name)) {
7924                 DEBUG(0,("%s: Failed to send message about upgrading driver [%s]!\n",
7925                         fn, driver_name));
7926         }
7927
7928         /*
7929          * Based on the version (e.g. driver destination dir: 0=9x,2=Nt/2k,3=2k/Xp),
7930          * decide if the driver init data should be deleted. The rules are:
7931          *  1) never delete init data if it is a 9x driver, they don't use it anyway
7932          *  2) delete init data only if there is no 2k/Xp driver
7933          *  3) always delete init data
7934          * The generalized rule is always use init data from the highest order driver.
7935          * It is necessary to follow the driver install by an initialization step to
7936          * finish off this process.
7937         */
7938         if (level == 3)
7939                 version = driver.info_3->cversion;
7940         else if (level == 6)
7941                 version = driver.info_6->version;
7942         else
7943                 version = -1;
7944         switch (version) {
7945                 /*
7946                  * 9x printer driver - never delete init data
7947                 */
7948                 case 0:
7949                         DEBUG(10,("%s: init data not deleted for 9x driver [%s]\n",
7950                                 fn, driver_name));
7951                         break;
7952
7953                 /*
7954                  * Nt or 2k (compatiblity mode) printer driver - only delete init data if
7955                  * there is no 2k/Xp driver init data for this driver name.
7956                 */
7957                 case 2:
7958                 {
7959                         NT_PRINTER_DRIVER_INFO_LEVEL driver1;
7960
7961                         if (!W_ERROR_IS_OK(get_a_printer_driver(&driver1, 3, driver_name, "Windows NT x86", 3))) {
7962                                 /*
7963                                  * No 2k/Xp driver found, delete init data (if any) for the new Nt driver.
7964                                 */
7965                                 if (!del_driver_init(driver_name))
7966                                         DEBUG(6,("%s: del_driver_init(%s) Nt failed!\n",
7967                                                 fn, driver_name));
7968                         } else {
7969                                 /*
7970                                  * a 2k/Xp driver was found, don't delete init data because Nt driver will use it.
7971                                 */
7972                                 free_a_printer_driver(driver1,3);
7973                                 DEBUG(10,("%s: init data not deleted for Nt driver [%s]\n",
7974                                         fn, driver_name));
7975                         }
7976                 }
7977                 break;
7978
7979                 /*
7980                  * 2k or Xp printer driver - always delete init data
7981                 */
7982                 case 3:
7983                         if (!del_driver_init(driver_name))
7984                                 DEBUG(6,("%s: del_driver_init(%s) 2k/Xp failed!\n",
7985                                         fn, driver_name));
7986                         break;
7987
7988                 default:
7989                         DEBUG(0,("%s: invalid level=%d\n", fn, level));
7990                         break;
7991         }
7992
7993
7994 done:
7995         free_a_printer_driver(driver, level);
7996         return err;
7997 }
7998
7999 /****************************************************************
8000  _spoolss_AddPrinterDriverEx
8001 ****************************************************************/
8002
8003 WERROR _spoolss_AddPrinterDriverEx(pipes_struct *p,
8004                                    struct spoolss_AddPrinterDriverEx *r)
8005 {
8006         struct spoolss_AddPrinterDriver a;
8007
8008         /*
8009          * we only support the semantics of AddPrinterDriver()
8010          * i.e. only copy files that are newer than existing ones
8011          */
8012
8013         if (r->in.flags != APD_COPY_NEW_FILES) {
8014                 return WERR_ACCESS_DENIED;
8015         }
8016
8017         a.in.servername         = r->in.servername;
8018         a.in.info_ctr           = r->in.info_ctr;
8019
8020         return _spoolss_AddPrinterDriver(p, &a);
8021 }
8022
8023 /****************************************************************************
8024 ****************************************************************************/
8025
8026 struct _spoolss_paths {
8027         int type;
8028         const char *share;
8029         const char *dir;
8030 };
8031
8032 enum { SPOOLSS_DRIVER_PATH, SPOOLSS_PRTPROCS_PATH };
8033
8034 static const struct _spoolss_paths spoolss_paths[]= {
8035         { SPOOLSS_DRIVER_PATH,          "print$",       "DRIVERS" },
8036         { SPOOLSS_PRTPROCS_PATH,        "prnproc$",     "PRTPROCS" }
8037 };
8038
8039 static WERROR compose_spoolss_server_path(TALLOC_CTX *mem_ctx,
8040                                           const char *servername,
8041                                           const char *environment,
8042                                           int component,
8043                                           char **path)
8044 {
8045         const char *pservername = NULL;
8046         const char *long_archi = SPOOLSS_ARCHITECTURE_NT_X86;
8047         const char *short_archi;
8048
8049         *path = NULL;
8050
8051         /* environment may be empty */
8052         if (environment && strlen(environment)) {
8053                 long_archi = environment;
8054         }
8055
8056         /* servername may be empty */
8057         if (servername && strlen(servername)) {
8058                 pservername = canon_servername(servername);
8059
8060                 if (!is_myname_or_ipaddr(pservername)) {
8061                         return WERR_INVALID_PARAM;
8062                 }
8063         }
8064
8065         if (!(short_archi = get_short_archi(long_archi))) {
8066                 return WERR_INVALID_ENVIRONMENT;
8067         }
8068
8069         switch (component) {
8070         case SPOOLSS_PRTPROCS_PATH:
8071         case SPOOLSS_DRIVER_PATH:
8072                 if (pservername) {
8073                         *path = talloc_asprintf(mem_ctx,
8074                                         "\\\\%s\\%s\\%s",
8075                                         pservername,
8076                                         spoolss_paths[component].share,
8077                                         short_archi);
8078                 } else {
8079                         *path = talloc_asprintf(mem_ctx, "%s\\%s\\%s",
8080                                         SPOOLSS_DEFAULT_SERVER_PATH,
8081                                         spoolss_paths[component].dir,
8082                                         short_archi);
8083                 }
8084                 break;
8085         default:
8086                 return WERR_INVALID_PARAM;
8087         }
8088
8089         if (!*path) {
8090                 return WERR_NOMEM;
8091         }
8092
8093         return WERR_OK;
8094 }
8095
8096 /****************************************************************************
8097 ****************************************************************************/
8098
8099 static WERROR getprinterdriverdir_level_1(TALLOC_CTX *mem_ctx,
8100                                           const char *servername,
8101                                           const char *environment,
8102                                           struct spoolss_DriverDirectoryInfo1 *r,
8103                                           uint32_t offered,
8104                                           uint32_t *needed)
8105 {
8106         WERROR werr;
8107         char *path = NULL;
8108
8109         werr = compose_spoolss_server_path(mem_ctx,
8110                                            servername,
8111                                            environment,
8112                                            SPOOLSS_DRIVER_PATH,
8113                                            &path);
8114         if (!W_ERROR_IS_OK(werr)) {
8115                 return werr;
8116         }
8117
8118         DEBUG(4,("printer driver directory: [%s]\n", path));
8119
8120         r->directory_name = path;
8121
8122         *needed += ndr_size_spoolss_DriverDirectoryInfo1(r, NULL, 0);
8123
8124         if (*needed > offered) {
8125                 talloc_free(path);
8126                 return WERR_INSUFFICIENT_BUFFER;
8127         }
8128
8129         return WERR_OK;
8130 }
8131
8132 /****************************************************************
8133  _spoolss_GetPrinterDriverDirectory
8134 ****************************************************************/
8135
8136 WERROR _spoolss_GetPrinterDriverDirectory(pipes_struct *p,
8137                                           struct spoolss_GetPrinterDriverDirectory *r)
8138 {
8139         WERROR werror;
8140
8141         /* that's an [in out] buffer */
8142
8143         if (!r->in.buffer && (r->in.offered != 0)) {
8144                 return WERR_INVALID_PARAM;
8145         }
8146
8147         DEBUG(5,("_spoolss_GetPrinterDriverDirectory: level %d\n",
8148                 r->in.level));
8149
8150         *r->out.needed = 0;
8151
8152         /* r->in.level is ignored */
8153
8154         werror = getprinterdriverdir_level_1(p->mem_ctx,
8155                                              r->in.server,
8156                                              r->in.environment,
8157                                              &r->out.info->info1,
8158                                              r->in.offered,
8159                                              r->out.needed);
8160         if (!W_ERROR_IS_OK(werror)) {
8161                 TALLOC_FREE(r->out.info);
8162         }
8163
8164         return werror;
8165 }
8166
8167 /****************************************************************************
8168 ****************************************************************************/
8169
8170 WERROR _spoolss_enumprinterdata(pipes_struct *p, SPOOL_Q_ENUMPRINTERDATA *q_u, SPOOL_R_ENUMPRINTERDATA *r_u)
8171 {
8172         POLICY_HND *handle = &q_u->handle;
8173         uint32 idx               = q_u->index;
8174         uint32 in_value_len      = q_u->valuesize;
8175         uint32 in_data_len       = q_u->datasize;
8176         uint32 *out_max_value_len = &r_u->valuesize;
8177         uint16 **out_value       = &r_u->value;
8178         uint32 *out_value_len    = &r_u->realvaluesize;
8179         uint32 *out_type         = &r_u->type;
8180         uint32 *out_max_data_len = &r_u->datasize;
8181         uint8  **data_out        = &r_u->data;
8182         uint32 *out_data_len     = &r_u->realdatasize;
8183
8184         NT_PRINTER_INFO_LEVEL *printer = NULL;
8185
8186         uint32          biggest_valuesize;
8187         uint32          biggest_datasize;
8188         uint32          data_len;
8189         Printer_entry   *Printer = find_printer_index_by_hnd(p, handle);
8190         int             snum;
8191         WERROR          result;
8192         REGISTRY_VALUE  *val = NULL;
8193         NT_PRINTER_DATA *p_data;
8194         int             i, key_index, num_values;
8195         int             name_length;
8196
8197         *out_type = 0;
8198
8199         *out_max_data_len = 0;
8200         *data_out         = NULL;
8201         *out_data_len     = 0;
8202
8203         DEBUG(5,("spoolss_enumprinterdata\n"));
8204
8205         if (!Printer) {
8206                 DEBUG(2,("_spoolss_enumprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8207                 return WERR_BADFID;
8208         }
8209
8210         if (!get_printer_snum(p,handle, &snum, NULL))
8211                 return WERR_BADFID;
8212
8213         result = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8214         if (!W_ERROR_IS_OK(result))
8215                 return result;
8216
8217         p_data = printer->info_2->data;
8218         key_index = lookup_printerkey( p_data, SPOOL_PRINTERDATA_KEY );
8219
8220         result = WERR_OK;
8221
8222         /*
8223          * The NT machine wants to know the biggest size of value and data
8224          *
8225          * cf: MSDN EnumPrinterData remark section
8226          */
8227
8228         if ( !in_value_len && !in_data_len && (key_index != -1) )
8229         {
8230                 DEBUGADD(6,("Activating NT mega-hack to find sizes\n"));
8231
8232                 biggest_valuesize = 0;
8233                 biggest_datasize  = 0;
8234
8235                 num_values = regval_ctr_numvals( p_data->keys[key_index].values );
8236
8237                 for ( i=0; i<num_values; i++ )
8238                 {
8239                         val = regval_ctr_specific_value( p_data->keys[key_index].values, i );
8240
8241                         name_length = strlen(val->valuename);
8242                         if ( strlen(val->valuename) > biggest_valuesize )
8243                                 biggest_valuesize = name_length;
8244
8245                         if ( val->size > biggest_datasize )
8246                                 biggest_datasize = val->size;
8247
8248                         DEBUG(6,("current values: [%d], [%d]\n", biggest_valuesize,
8249                                 biggest_datasize));
8250                 }
8251
8252                 /* the value is an UNICODE string but real_value_size is the length
8253                    in bytes including the trailing 0 */
8254
8255                 *out_value_len = 2 * (1+biggest_valuesize);
8256                 *out_data_len  = biggest_datasize;
8257
8258                 DEBUG(6,("final values: [%d], [%d]\n", *out_value_len, *out_data_len));
8259
8260                 goto done;
8261         }
8262
8263         /*
8264          * the value len is wrong in NT sp3
8265          * that's the number of bytes not the number of unicode chars
8266          */
8267
8268         if ( key_index != -1 )
8269                 val = regval_ctr_specific_value( p_data->keys[key_index].values, idx );
8270
8271         if ( !val )
8272         {
8273
8274                 /* out_value should default to "" or else NT4 has
8275                    problems unmarshalling the response */
8276
8277                 *out_max_value_len=(in_value_len/sizeof(uint16));
8278
8279                 if (in_value_len) {
8280                         if((*out_value=(uint16 *)TALLOC_ZERO(p->mem_ctx, in_value_len*sizeof(uint8))) == NULL)
8281                         {
8282                                 result = WERR_NOMEM;
8283                                 goto done;
8284                         }
8285                         *out_value_len = (uint32)rpcstr_push((char *)*out_value, "", in_value_len, 0);
8286                 } else {
8287                         *out_value=NULL;
8288                         *out_value_len = 0;
8289                 }
8290
8291                 /* the data is counted in bytes */
8292
8293                 *out_max_data_len = in_data_len;
8294                 *out_data_len     = in_data_len;
8295
8296                 /* only allocate when given a non-zero data_len */
8297
8298                 if ( in_data_len && ((*data_out=(uint8 *)TALLOC_ZERO(p->mem_ctx, in_data_len*sizeof(uint8))) == NULL) )
8299                 {
8300                         result = WERR_NOMEM;
8301                         goto done;
8302                 }
8303
8304                 result = WERR_NO_MORE_ITEMS;
8305         }
8306         else
8307         {
8308                 /*
8309                  * the value is:
8310                  * - counted in bytes in the request
8311                  * - counted in UNICODE chars in the max reply
8312                  * - counted in bytes in the real size
8313                  *
8314                  * take a pause *before* coding not *during* coding
8315                  */
8316
8317                 /* name */
8318                 *out_max_value_len=(in_value_len/sizeof(uint16));
8319                 if (in_value_len) {
8320                         if ( (*out_value = (uint16 *)TALLOC_ZERO(p->mem_ctx, in_value_len*sizeof(uint8))) == NULL )
8321                         {
8322                                 result = WERR_NOMEM;
8323                                 goto done;
8324                         }
8325
8326                         *out_value_len = (uint32)rpcstr_push((char *)*out_value, regval_name(val), (size_t)in_value_len, 0);
8327                 } else {
8328                         *out_value = NULL;
8329                         *out_value_len = 0;
8330                 }
8331
8332                 /* type */
8333
8334                 *out_type = regval_type( val );
8335
8336                 /* data - counted in bytes */
8337
8338                 *out_max_data_len = in_data_len;
8339                 if ( in_data_len && (*data_out = (uint8 *)TALLOC_ZERO(p->mem_ctx, in_data_len*sizeof(uint8))) == NULL)
8340                 {
8341                         result = WERR_NOMEM;
8342                         goto done;
8343                 }
8344                 data_len = regval_size(val);
8345                 if ( *data_out && data_len )
8346                         memcpy( *data_out, regval_data_p(val), data_len );
8347                 *out_data_len = data_len;
8348         }
8349
8350 done:
8351         free_a_printer(&printer, 2);
8352         return result;
8353 }
8354
8355 /****************************************************************************
8356 ****************************************************************************/
8357
8358 WERROR _spoolss_setprinterdata( pipes_struct *p, SPOOL_Q_SETPRINTERDATA *q_u, SPOOL_R_SETPRINTERDATA *r_u)
8359 {
8360         POLICY_HND              *handle = &q_u->handle;
8361         UNISTR2                 *value = &q_u->value;
8362         uint32                  type = q_u->type;
8363         uint8                   *data = q_u->data;
8364         uint32                  real_len = q_u->real_len;
8365
8366         NT_PRINTER_INFO_LEVEL   *printer = NULL;
8367         int                     snum=0;
8368         WERROR                  status = WERR_OK;
8369         Printer_entry           *Printer=find_printer_index_by_hnd(p, handle);
8370         fstring                 valuename;
8371
8372         DEBUG(5,("spoolss_setprinterdata\n"));
8373
8374         if (!Printer) {
8375                 DEBUG(2,("_spoolss_setprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8376                 return WERR_BADFID;
8377         }
8378
8379         if ( Printer->printer_type == SPLHND_SERVER ) {
8380                 DEBUG(10,("_spoolss_setprinterdata: Not implemented for server handles yet\n"));
8381                 return WERR_INVALID_PARAM;
8382         }
8383
8384         if (!get_printer_snum(p,handle, &snum, NULL))
8385                 return WERR_BADFID;
8386
8387         /*
8388          * Access check : NT returns "access denied" if you make a
8389          * SetPrinterData call without the necessary privildge.
8390          * we were originally returning OK if nothing changed
8391          * which made Win2k issue **a lot** of SetPrinterData
8392          * when connecting to a printer  --jerry
8393          */
8394
8395         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER)
8396         {
8397                 DEBUG(3, ("_spoolss_setprinterdata: change denied by handle access permissions\n"));
8398                 status = WERR_ACCESS_DENIED;
8399                 goto done;
8400         }
8401
8402         status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8403         if (!W_ERROR_IS_OK(status))
8404                 return status;
8405
8406         unistr2_to_ascii(valuename, value, sizeof(valuename));
8407
8408         /*
8409          * When client side code sets a magic printer data key, detect it and save
8410          * the current printer data and the magic key's data (its the DEVMODE) for
8411          * future printer/driver initializations.
8412          */
8413         if ( (type == REG_BINARY) && strequal( valuename, PHANTOM_DEVMODE_KEY))
8414         {
8415                 /* Set devmode and printer initialization info */
8416                 status = save_driver_init( printer, 2, data, real_len );
8417
8418                 srv_spoolss_reset_printerdata( printer->info_2->drivername );
8419         }
8420         else
8421         {
8422         status = set_printer_dataex( printer, SPOOL_PRINTERDATA_KEY, valuename,
8423                                         type, data, real_len );
8424                 if ( W_ERROR_IS_OK(status) )
8425                         status = mod_a_printer(printer, 2);
8426         }
8427
8428 done:
8429         free_a_printer(&printer, 2);
8430
8431         return status;
8432 }
8433
8434 /****************************************************************
8435  _spoolss_ResetPrinter
8436 ****************************************************************/
8437
8438 WERROR _spoolss_ResetPrinter(pipes_struct *p,
8439                              struct spoolss_ResetPrinter *r)
8440 {
8441         POLICY_HND      *handle = r->in.handle;
8442         Printer_entry   *Printer=find_printer_index_by_hnd(p, handle);
8443         int             snum;
8444
8445         DEBUG(5,("_spoolss_ResetPrinter\n"));
8446
8447         /*
8448          * All we do is to check to see if the handle and queue is valid.
8449          * This call really doesn't mean anything to us because we only
8450          * support RAW printing.   --jerry
8451          */
8452
8453         if (!Printer) {
8454                 DEBUG(2,("_spoolss_ResetPrinter: Invalid handle (%s:%u:%u).\n",
8455                         OUR_HANDLE(handle)));
8456                 return WERR_BADFID;
8457         }
8458
8459         if (!get_printer_snum(p,handle, &snum, NULL))
8460                 return WERR_BADFID;
8461
8462
8463         /* blindly return success */
8464         return WERR_OK;
8465 }
8466
8467 /****************************************************************
8468  _spoolss_DeletePrinterData
8469 ****************************************************************/
8470
8471 WERROR _spoolss_DeletePrinterData(pipes_struct *p,
8472                                   struct spoolss_DeletePrinterData *r)
8473 {
8474         POLICY_HND      *handle = r->in.handle;
8475         NT_PRINTER_INFO_LEVEL   *printer = NULL;
8476         int             snum=0;
8477         WERROR          status = WERR_OK;
8478         Printer_entry   *Printer=find_printer_index_by_hnd(p, handle);
8479
8480         DEBUG(5,("_spoolss_DeletePrinterData\n"));
8481
8482         if (!Printer) {
8483                 DEBUG(2,("_spoolss_DeletePrinterData: Invalid handle (%s:%u:%u).\n",
8484                         OUR_HANDLE(handle)));
8485                 return WERR_BADFID;
8486         }
8487
8488         if (!get_printer_snum(p, handle, &snum, NULL))
8489                 return WERR_BADFID;
8490
8491         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
8492                 DEBUG(3, ("_spoolss_DeletePrinterData: "
8493                         "printer properties change denied by handle\n"));
8494                 return WERR_ACCESS_DENIED;
8495         }
8496
8497         status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8498         if (!W_ERROR_IS_OK(status))
8499                 return status;
8500
8501         if (!r->in.value_name) {
8502                 free_a_printer(&printer, 2);
8503                 return WERR_NOMEM;
8504         }
8505
8506         status = delete_printer_dataex( printer, SPOOL_PRINTERDATA_KEY,
8507                                         r->in.value_name );
8508
8509         if ( W_ERROR_IS_OK(status) )
8510                 mod_a_printer( printer, 2 );
8511
8512         free_a_printer(&printer, 2);
8513
8514         return status;
8515 }
8516
8517 /****************************************************************
8518  _spoolss_AddForm
8519 ****************************************************************/
8520
8521 WERROR _spoolss_AddForm(pipes_struct *p,
8522                         struct spoolss_AddForm *r)
8523 {
8524         POLICY_HND *handle = r->in.handle;
8525         struct spoolss_AddFormInfo1 *form = r->in.info.info1;
8526         nt_forms_struct tmpForm;
8527         int snum;
8528         WERROR status = WERR_OK;
8529         NT_PRINTER_INFO_LEVEL *printer = NULL;
8530
8531         int count=0;
8532         nt_forms_struct *list=NULL;
8533         Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8534
8535         DEBUG(5,("_spoolss_AddForm\n"));
8536
8537         if (!Printer) {
8538                 DEBUG(2,("_spoolss_AddForm: Invalid handle (%s:%u:%u).\n",
8539                         OUR_HANDLE(handle)));
8540                 return WERR_BADFID;
8541         }
8542
8543
8544         /* forms can be added on printer of on the print server handle */
8545
8546         if ( Printer->printer_type == SPLHND_PRINTER )
8547         {
8548                 if (!get_printer_snum(p,handle, &snum, NULL))
8549                         return WERR_BADFID;
8550
8551                 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8552                 if (!W_ERROR_IS_OK(status))
8553                         goto done;
8554         }
8555
8556         if ( !(Printer->access_granted & (PRINTER_ACCESS_ADMINISTER|SERVER_ACCESS_ADMINISTER)) ) {
8557                 DEBUG(2,("_spoolss_addform: denied by handle permissions.\n"));
8558                 status = WERR_ACCESS_DENIED;
8559                 goto done;
8560         }
8561
8562         /* can't add if builtin */
8563
8564         if (get_a_builtin_ntform_by_string(form->form_name, &tmpForm)) {
8565                 status = WERR_FILE_EXISTS;
8566                 goto done;
8567         }
8568
8569         count = get_ntforms(&list);
8570
8571         if(!add_a_form(&list, form, &count)) {
8572                 status =  WERR_NOMEM;
8573                 goto done;
8574         }
8575
8576         write_ntforms(&list, count);
8577
8578         /*
8579          * ChangeID must always be set if this is a printer
8580          */
8581
8582         if ( Printer->printer_type == SPLHND_PRINTER )
8583                 status = mod_a_printer(printer, 2);
8584
8585 done:
8586         if ( printer )
8587                 free_a_printer(&printer, 2);
8588         SAFE_FREE(list);
8589
8590         return status;
8591 }
8592
8593 /****************************************************************
8594  _spoolss_DeleteForm
8595 ****************************************************************/
8596
8597 WERROR _spoolss_DeleteForm(pipes_struct *p,
8598                            struct spoolss_DeleteForm *r)
8599 {
8600         POLICY_HND *handle = r->in.handle;
8601         const char *form_name = r->in.form_name;
8602         nt_forms_struct tmpForm;
8603         int count=0;
8604         nt_forms_struct *list=NULL;
8605         Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8606         int snum;
8607         WERROR status = WERR_OK;
8608         NT_PRINTER_INFO_LEVEL *printer = NULL;
8609
8610         DEBUG(5,("_spoolss_DeleteForm\n"));
8611
8612         if (!Printer) {
8613                 DEBUG(2,("_spoolss_DeleteForm: Invalid handle (%s:%u:%u).\n",
8614                         OUR_HANDLE(handle)));
8615                 return WERR_BADFID;
8616         }
8617
8618         /* forms can be deleted on printer of on the print server handle */
8619
8620         if ( Printer->printer_type == SPLHND_PRINTER )
8621         {
8622                 if (!get_printer_snum(p,handle, &snum, NULL))
8623                         return WERR_BADFID;
8624
8625                 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8626                 if (!W_ERROR_IS_OK(status))
8627                         goto done;
8628         }
8629
8630         if ( !(Printer->access_granted & (PRINTER_ACCESS_ADMINISTER|SERVER_ACCESS_ADMINISTER)) ) {
8631                 DEBUG(2,("_spoolss_DeleteForm: denied by handle permissions.\n"));
8632                 status = WERR_ACCESS_DENIED;
8633                 goto done;
8634         }
8635
8636         /* can't delete if builtin */
8637
8638         if (get_a_builtin_ntform_by_string(form_name,&tmpForm)) {
8639                 status = WERR_INVALID_PARAM;
8640                 goto done;
8641         }
8642
8643         count = get_ntforms(&list);
8644
8645         if ( !delete_a_form(&list, form_name, &count, &status ))
8646                 goto done;
8647
8648         /*
8649          * ChangeID must always be set if this is a printer
8650          */
8651
8652         if ( Printer->printer_type == SPLHND_PRINTER )
8653                 status = mod_a_printer(printer, 2);
8654
8655 done:
8656         if ( printer )
8657                 free_a_printer(&printer, 2);
8658         SAFE_FREE(list);
8659
8660         return status;
8661 }
8662
8663 /****************************************************************
8664  _spoolss_SetForm
8665 ****************************************************************/
8666
8667 WERROR _spoolss_SetForm(pipes_struct *p,
8668                         struct spoolss_SetForm *r)
8669 {
8670         POLICY_HND *handle = r->in.handle;
8671         struct spoolss_AddFormInfo1 *form = r->in.info.info1;
8672         nt_forms_struct tmpForm;
8673         int snum;
8674         WERROR status = WERR_OK;
8675         NT_PRINTER_INFO_LEVEL *printer = NULL;
8676
8677         int count=0;
8678         nt_forms_struct *list=NULL;
8679         Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8680
8681         DEBUG(5,("_spoolss_SetForm\n"));
8682
8683         if (!Printer) {
8684                 DEBUG(2,("_spoolss_SetForm: Invalid handle (%s:%u:%u).\n",
8685                         OUR_HANDLE(handle)));
8686                 return WERR_BADFID;
8687         }
8688
8689         /* forms can be modified on printer of on the print server handle */
8690
8691         if ( Printer->printer_type == SPLHND_PRINTER )
8692         {
8693                 if (!get_printer_snum(p,handle, &snum, NULL))
8694                         return WERR_BADFID;
8695
8696                 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8697                 if (!W_ERROR_IS_OK(status))
8698                         goto done;
8699         }
8700
8701         if ( !(Printer->access_granted & (PRINTER_ACCESS_ADMINISTER|SERVER_ACCESS_ADMINISTER)) ) {
8702                 DEBUG(2,("_spoolss_SetForm: denied by handle permissions\n"));
8703                 status = WERR_ACCESS_DENIED;
8704                 goto done;
8705         }
8706
8707         /* can't set if builtin */
8708         if (get_a_builtin_ntform_by_string(form->form_name, &tmpForm)) {
8709                 status = WERR_INVALID_PARAM;
8710                 goto done;
8711         }
8712
8713         count = get_ntforms(&list);
8714         update_a_form(&list, form, count);
8715         write_ntforms(&list, count);
8716
8717         /*
8718          * ChangeID must always be set if this is a printer
8719          */
8720
8721         if ( Printer->printer_type == SPLHND_PRINTER )
8722                 status = mod_a_printer(printer, 2);
8723
8724
8725 done:
8726         if ( printer )
8727                 free_a_printer(&printer, 2);
8728         SAFE_FREE(list);
8729
8730         return status;
8731 }
8732
8733 /****************************************************************************
8734  enumprintprocessors level 1.
8735 ****************************************************************************/
8736
8737 static WERROR enumprintprocessors_level_1(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
8738 {
8739         PRINTPROCESSOR_1 *info_1=NULL;
8740         WERROR result = WERR_OK;
8741
8742         if((info_1 = SMB_MALLOC_P(PRINTPROCESSOR_1)) == NULL)
8743                 return WERR_NOMEM;
8744
8745         (*returned) = 0x1;
8746
8747         init_unistr(&info_1->name, "winprint");
8748
8749         *needed += spoolss_size_printprocessor_info_1(info_1);
8750
8751         if (*needed > offered) {
8752                 result = WERR_INSUFFICIENT_BUFFER;
8753                 goto out;
8754         }
8755
8756         if (!rpcbuf_alloc_size(buffer, *needed)) {
8757                 result = WERR_NOMEM;
8758                 goto out;
8759         }
8760
8761         smb_io_printprocessor_info_1("", buffer, info_1, 0);
8762
8763 out:
8764         SAFE_FREE(info_1);
8765
8766         if ( !W_ERROR_IS_OK(result) )
8767                 *returned = 0;
8768
8769         return result;
8770 }
8771
8772 /****************************************************************************
8773 ****************************************************************************/
8774
8775 WERROR _spoolss_enumprintprocessors(pipes_struct *p, SPOOL_Q_ENUMPRINTPROCESSORS *q_u, SPOOL_R_ENUMPRINTPROCESSORS *r_u)
8776 {
8777         uint32 level = q_u->level;
8778         RPC_BUFFER *buffer = NULL;
8779         uint32 offered = q_u->offered;
8780         uint32 *needed = &r_u->needed;
8781         uint32 *returned = &r_u->returned;
8782
8783         /* that's an [in out] buffer */
8784
8785         if (!q_u->buffer && (offered!=0)) {
8786                 return WERR_INVALID_PARAM;
8787         }
8788
8789         if (offered > MAX_RPC_DATA_SIZE) {
8790                 return WERR_INVALID_PARAM;
8791         }
8792
8793         rpcbuf_move(q_u->buffer, &r_u->buffer);
8794         buffer = r_u->buffer;
8795
8796         DEBUG(5,("spoolss_enumprintprocessors\n"));
8797
8798         /*
8799          * Enumerate the print processors ...
8800          *
8801          * Just reply with "winprint", to keep NT happy
8802          * and I can use my nice printer checker.
8803          */
8804
8805         *returned=0;
8806         *needed=0;
8807
8808         switch (level) {
8809         case 1:
8810                 return enumprintprocessors_level_1(buffer, offered, needed, returned);
8811         default:
8812                 return WERR_UNKNOWN_LEVEL;
8813         }
8814 }
8815
8816 /****************************************************************************
8817  enumprintprocdatatypes level 1.
8818 ****************************************************************************/
8819
8820 static WERROR enumprintprocdatatypes_level_1(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
8821 {
8822         PRINTPROCDATATYPE_1 *info_1=NULL;
8823         WERROR result = WERR_OK;
8824
8825         if((info_1 = SMB_MALLOC_P(PRINTPROCDATATYPE_1)) == NULL)
8826                 return WERR_NOMEM;
8827
8828         (*returned) = 0x1;
8829
8830         init_unistr(&info_1->name, "RAW");
8831
8832         *needed += spoolss_size_printprocdatatype_info_1(info_1);
8833
8834         if (*needed > offered) {
8835                 result = WERR_INSUFFICIENT_BUFFER;
8836                 goto out;
8837         }
8838
8839         if (!rpcbuf_alloc_size(buffer, *needed)) {
8840                 result = WERR_NOMEM;
8841                 goto out;
8842         }
8843
8844         smb_io_printprocdatatype_info_1("", buffer, info_1, 0);
8845
8846 out:
8847         SAFE_FREE(info_1);
8848
8849         if ( !W_ERROR_IS_OK(result) )
8850                 *returned = 0;
8851
8852         return result;
8853 }
8854
8855 /****************************************************************************
8856 ****************************************************************************/
8857
8858 WERROR _spoolss_enumprintprocdatatypes(pipes_struct *p, SPOOL_Q_ENUMPRINTPROCDATATYPES *q_u, SPOOL_R_ENUMPRINTPROCDATATYPES *r_u)
8859 {
8860         uint32 level = q_u->level;
8861         RPC_BUFFER *buffer = NULL;
8862         uint32 offered = q_u->offered;
8863         uint32 *needed = &r_u->needed;
8864         uint32 *returned = &r_u->returned;
8865
8866         /* that's an [in out] buffer */
8867
8868         if (!q_u->buffer && (offered!=0)) {
8869                 return WERR_INVALID_PARAM;
8870         }
8871
8872         if (offered > MAX_RPC_DATA_SIZE) {
8873                 return WERR_INVALID_PARAM;
8874         }
8875
8876         rpcbuf_move(q_u->buffer, &r_u->buffer);
8877         buffer = r_u->buffer;
8878
8879         DEBUG(5,("_spoolss_enumprintprocdatatypes\n"));
8880
8881         *returned=0;
8882         *needed=0;
8883
8884         switch (level) {
8885         case 1:
8886                 return enumprintprocdatatypes_level_1(buffer, offered, needed, returned);
8887         default:
8888                 return WERR_UNKNOWN_LEVEL;
8889         }
8890 }
8891
8892 /****************************************************************************
8893  enumprintmonitors level 1.
8894 ****************************************************************************/
8895
8896 static WERROR enumprintmonitors_level_1(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
8897 {
8898         PRINTMONITOR_1 *info_1;
8899         WERROR result = WERR_OK;
8900         int i;
8901
8902         if((info_1 = SMB_MALLOC_ARRAY(PRINTMONITOR_1, 2)) == NULL)
8903                 return WERR_NOMEM;
8904
8905         *returned = 2;
8906
8907         init_unistr(&(info_1[0].name), SPL_LOCAL_PORT );
8908         init_unistr(&(info_1[1].name), SPL_TCPIP_PORT );
8909
8910         for ( i=0; i<*returned; i++ ) {
8911                 *needed += spoolss_size_printmonitor_info_1(&info_1[i]);
8912         }
8913
8914         if (*needed > offered) {
8915                 result = WERR_INSUFFICIENT_BUFFER;
8916                 goto out;
8917         }
8918
8919         if (!rpcbuf_alloc_size(buffer, *needed)) {
8920                 result = WERR_NOMEM;
8921                 goto out;
8922         }
8923
8924         for ( i=0; i<*returned; i++ ) {
8925                 smb_io_printmonitor_info_1("", buffer, &info_1[i], 0);
8926         }
8927
8928 out:
8929         SAFE_FREE(info_1);
8930
8931         if ( !W_ERROR_IS_OK(result) )
8932                 *returned = 0;
8933
8934         return result;
8935 }
8936
8937 /****************************************************************************
8938  enumprintmonitors level 2.
8939 ****************************************************************************/
8940
8941 static WERROR enumprintmonitors_level_2(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
8942 {
8943         PRINTMONITOR_2 *info_2;
8944         WERROR result = WERR_OK;
8945         int i;
8946
8947         if((info_2 = SMB_MALLOC_ARRAY(PRINTMONITOR_2, 2)) == NULL)
8948                 return WERR_NOMEM;
8949
8950         *returned = 2;
8951
8952         init_unistr( &(info_2[0].name), SPL_LOCAL_PORT );
8953         init_unistr( &(info_2[0].environment), "Windows NT X86" );
8954         init_unistr( &(info_2[0].dll_name), "localmon.dll" );
8955
8956         init_unistr( &(info_2[1].name), SPL_TCPIP_PORT );
8957         init_unistr( &(info_2[1].environment), "Windows NT X86" );
8958         init_unistr( &(info_2[1].dll_name), "tcpmon.dll" );
8959
8960         for ( i=0; i<*returned; i++ ) {
8961                 *needed += spoolss_size_printmonitor_info_2(&info_2[i]);
8962         }
8963
8964         if (*needed > offered) {
8965                 result = WERR_INSUFFICIENT_BUFFER;
8966                 goto out;
8967         }
8968
8969         if (!rpcbuf_alloc_size(buffer, *needed)) {
8970                 result = WERR_NOMEM;
8971                 goto out;
8972         }
8973
8974         for ( i=0; i<*returned; i++ ) {
8975                 smb_io_printmonitor_info_2("", buffer, &info_2[i], 0);
8976         }
8977
8978 out:
8979         SAFE_FREE(info_2);
8980
8981         if ( !W_ERROR_IS_OK(result) )
8982                 *returned = 0;
8983
8984         return result;
8985 }
8986
8987 /****************************************************************************
8988 ****************************************************************************/
8989
8990 WERROR _spoolss_enumprintmonitors(pipes_struct *p, SPOOL_Q_ENUMPRINTMONITORS *q_u, SPOOL_R_ENUMPRINTMONITORS *r_u)
8991 {
8992         uint32 level = q_u->level;
8993         RPC_BUFFER *buffer = NULL;
8994         uint32 offered = q_u->offered;
8995         uint32 *needed = &r_u->needed;
8996         uint32 *returned = &r_u->returned;
8997
8998         /* that's an [in out] buffer */
8999
9000         if (!q_u->buffer && (offered!=0)) {
9001                 return WERR_INVALID_PARAM;
9002         }
9003
9004         if (offered > MAX_RPC_DATA_SIZE) {
9005                 return WERR_INVALID_PARAM;
9006         }
9007
9008         rpcbuf_move(q_u->buffer, &r_u->buffer);
9009         buffer = r_u->buffer;
9010
9011         DEBUG(5,("spoolss_enumprintmonitors\n"));
9012
9013         /*
9014          * Enumerate the print monitors ...
9015          *
9016          * Just reply with "Local Port", to keep NT happy
9017          * and I can use my nice printer checker.
9018          */
9019
9020         *returned=0;
9021         *needed=0;
9022
9023         switch (level) {
9024         case 1:
9025                 return enumprintmonitors_level_1(buffer, offered, needed, returned);
9026         case 2:
9027                 return enumprintmonitors_level_2(buffer, offered, needed, returned);
9028         default:
9029                 return WERR_UNKNOWN_LEVEL;
9030         }
9031 }
9032
9033 /****************************************************************************
9034 ****************************************************************************/
9035
9036 static WERROR getjob_level_1(print_queue_struct **queue, int count, int snum,
9037                              NT_PRINTER_INFO_LEVEL *ntprinter,
9038                              uint32 jobid, RPC_BUFFER *buffer, uint32 offered,
9039                              uint32 *needed)
9040 {
9041         int i=0;
9042         bool found=False;
9043         JOB_INFO_1 *info_1=NULL;
9044         WERROR result = WERR_OK;
9045
9046         info_1=SMB_MALLOC_P(JOB_INFO_1);
9047
9048         if (info_1 == NULL) {
9049                 return WERR_NOMEM;
9050         }
9051
9052         for (i=0; i<count && found==False; i++) {
9053                 if ((*queue)[i].job==(int)jobid)
9054                         found=True;
9055         }
9056
9057         if (found==False) {
9058                 SAFE_FREE(info_1);
9059                 /* NT treats not found as bad param... yet another bad choice */
9060                 return WERR_INVALID_PARAM;
9061         }
9062
9063         fill_job_info_1( info_1, &((*queue)[i-1]), i, snum, ntprinter );
9064
9065         *needed += spoolss_size_job_info_1(info_1);
9066
9067         if (*needed > offered) {
9068                 result = WERR_INSUFFICIENT_BUFFER;
9069                 goto out;
9070         }
9071
9072         if (!rpcbuf_alloc_size(buffer, *needed)) {
9073                 result = WERR_NOMEM;
9074                 goto out;
9075         }
9076
9077         smb_io_job_info_1("", buffer, info_1, 0);
9078
9079 out:
9080         SAFE_FREE(info_1);
9081
9082         return result;
9083 }
9084
9085 /****************************************************************************
9086 ****************************************************************************/
9087
9088 static WERROR getjob_level_2(print_queue_struct **queue, int count, int snum,
9089                              NT_PRINTER_INFO_LEVEL *ntprinter,
9090                              uint32 jobid, RPC_BUFFER *buffer, uint32 offered,
9091                              uint32 *needed)
9092 {
9093         int             i = 0;
9094         bool            found = False;
9095         JOB_INFO_2      *info_2;
9096         WERROR          result;
9097         DEVICEMODE      *devmode = NULL;
9098         NT_DEVICEMODE   *nt_devmode = NULL;
9099
9100         if ( !(info_2=SMB_MALLOC_P(JOB_INFO_2)) )
9101                 return WERR_NOMEM;
9102
9103         ZERO_STRUCTP(info_2);
9104
9105         for ( i=0; i<count && found==False; i++ )
9106         {
9107                 if ((*queue)[i].job == (int)jobid)
9108                         found = True;
9109         }
9110
9111         if ( !found ) {
9112                 /* NT treats not found as bad param... yet another bad
9113                    choice */
9114                 result = WERR_INVALID_PARAM;
9115                 goto done;
9116         }
9117
9118         /*
9119          * if the print job does not have a DEVMODE associated with it,
9120          * just use the one for the printer. A NULL devicemode is not
9121          *  a failure condition
9122          */
9123
9124         if ( !(nt_devmode=print_job_devmode( lp_const_servicename(snum), jobid )) )
9125                 devmode = construct_dev_mode(lp_const_servicename(snum));
9126         else {
9127                 if ((devmode = SMB_MALLOC_P(DEVICEMODE)) != NULL) {
9128                         ZERO_STRUCTP( devmode );
9129                         convert_nt_devicemode( devmode, nt_devmode );
9130                 }
9131         }
9132
9133         fill_job_info_2(info_2, &((*queue)[i-1]), i, snum, ntprinter, devmode);
9134
9135         *needed += spoolss_size_job_info_2(info_2);
9136
9137         if (*needed > offered) {
9138                 result = WERR_INSUFFICIENT_BUFFER;
9139                 goto done;
9140         }
9141
9142         if (!rpcbuf_alloc_size(buffer, *needed)) {
9143                 result = WERR_NOMEM;
9144                 goto done;
9145         }
9146
9147         smb_io_job_info_2("", buffer, info_2, 0);
9148
9149         result = WERR_OK;
9150
9151  done:
9152         /* Cleanup allocated memory */
9153
9154         free_job_info_2(info_2);        /* Also frees devmode */
9155         SAFE_FREE(info_2);
9156
9157         return result;
9158 }
9159
9160 /****************************************************************************
9161 ****************************************************************************/
9162
9163 WERROR _spoolss_getjob( pipes_struct *p, SPOOL_Q_GETJOB *q_u, SPOOL_R_GETJOB *r_u)
9164 {
9165         POLICY_HND *handle = &q_u->handle;
9166         uint32 jobid = q_u->jobid;
9167         uint32 level = q_u->level;
9168         RPC_BUFFER *buffer = NULL;
9169         uint32 offered = q_u->offered;
9170         uint32 *needed = &r_u->needed;
9171         WERROR          wstatus = WERR_OK;
9172         NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
9173         int snum;
9174         int count;
9175         print_queue_struct      *queue = NULL;
9176         print_status_struct prt_status;
9177
9178         /* that's an [in out] buffer */
9179
9180         if (!q_u->buffer && (offered!=0)) {
9181                 return WERR_INVALID_PARAM;
9182         }
9183
9184         if (offered > MAX_RPC_DATA_SIZE) {
9185                 return WERR_INVALID_PARAM;
9186         }
9187
9188         rpcbuf_move(q_u->buffer, &r_u->buffer);
9189         buffer = r_u->buffer;
9190
9191         DEBUG(5,("spoolss_getjob\n"));
9192
9193         *needed = 0;
9194
9195         if (!get_printer_snum(p, handle, &snum, NULL))
9196                 return WERR_BADFID;
9197
9198         wstatus = get_a_printer(NULL, &ntprinter, 2, lp_servicename(snum));
9199         if ( !W_ERROR_IS_OK(wstatus) )
9200                 return wstatus;
9201
9202         count = print_queue_status(snum, &queue, &prt_status);
9203
9204         DEBUGADD(4,("count:[%d], prt_status:[%d], [%s]\n",
9205                      count, prt_status.status, prt_status.message));
9206
9207         switch ( level ) {
9208         case 1:
9209                         wstatus = getjob_level_1(&queue, count, snum, ntprinter, jobid,
9210                                 buffer, offered, needed);
9211                         break;
9212         case 2:
9213                         wstatus = getjob_level_2(&queue, count, snum, ntprinter, jobid,
9214                                 buffer, offered, needed);
9215                         break;
9216         default:
9217                         wstatus = WERR_UNKNOWN_LEVEL;
9218                         break;
9219         }
9220
9221         SAFE_FREE(queue);
9222         free_a_printer( &ntprinter, 2 );
9223
9224         return wstatus;
9225 }
9226
9227 /****************************************************************
9228  _spoolss_GetPrinterDataEx
9229
9230  From MSDN documentation of GetPrinterDataEx: pass request
9231  to GetPrinterData if key is "PrinterDriverData".
9232 ****************************************************************/
9233
9234 WERROR _spoolss_GetPrinterDataEx(pipes_struct *p,
9235                                  struct spoolss_GetPrinterDataEx *r)
9236 {
9237         POLICY_HND      *handle = r->in.handle;
9238         uint8           *data = NULL;
9239         const char      *keyname = r->in.key_name;
9240         const char      *valuename = r->in.value_name;
9241
9242         Printer_entry   *Printer = find_printer_index_by_hnd(p, handle);
9243
9244         NT_PRINTER_INFO_LEVEL   *printer = NULL;
9245         int                     snum = 0;
9246         WERROR                  status = WERR_OK;
9247
9248         DEBUG(4,("_spoolss_GetPrinterDataEx\n"));
9249
9250         DEBUG(10, ("_spoolss_GetPrinterDataEx: key => [%s], value => [%s]\n",
9251                 keyname, valuename));
9252
9253         /* in case of problem, return some default values */
9254
9255         *r->out.needed  = 0;
9256         *r->out.type    = 0;
9257
9258         if (!Printer) {
9259                 DEBUG(2,("_spoolss_GetPrinterDataEx: "
9260                         "Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
9261                 status = WERR_BADFID;
9262                 goto done;
9263         }
9264
9265         /* Is the handle to a printer or to the server? */
9266
9267         if (Printer->printer_type == SPLHND_SERVER) {
9268                 DEBUG(10,("_spoolss_GetPrinterDataEx: "
9269                         "Not implemented for server handles yet\n"));
9270                 status = WERR_INVALID_PARAM;
9271                 goto done;
9272         }
9273
9274         if ( !get_printer_snum(p,handle, &snum, NULL) )
9275                 return WERR_BADFID;
9276
9277         status = get_a_printer(Printer, &printer, 2, lp_servicename(snum));
9278         if ( !W_ERROR_IS_OK(status) )
9279                 goto done;
9280
9281         /* check to see if the keyname is valid */
9282         if ( !strlen(keyname) ) {
9283                 status = WERR_INVALID_PARAM;
9284                 goto done;
9285         }
9286
9287         if ( lookup_printerkey( printer->info_2->data, keyname ) == -1 ) {
9288                 DEBUG(4,("_spoolss_GetPrinterDataEx: "
9289                         "Invalid keyname [%s]\n", keyname ));
9290                 free_a_printer( &printer, 2 );
9291                 status = WERR_BADFILE;
9292                 goto done;
9293         }
9294
9295         /* When given a new keyname, we should just create it */
9296
9297         status = get_printer_dataex( p->mem_ctx, printer, keyname, valuename,
9298                                      r->out.type, &data, r->out.needed,
9299                                      r->in.offered );
9300
9301         if (*r->out.needed > r->in.offered) {
9302                 status = WERR_MORE_DATA;
9303         }
9304
9305         if (W_ERROR_IS_OK(status)) {
9306                 memcpy(r->out.buffer, data, r->in.offered);
9307         }
9308
9309 done:
9310         if ( printer )
9311         free_a_printer( &printer, 2 );
9312
9313         return status;
9314 }
9315
9316 /****************************************************************
9317  _spoolss_SetPrinterDataEx
9318 ****************************************************************/
9319
9320 WERROR _spoolss_SetPrinterDataEx(pipes_struct *p,
9321                                  struct spoolss_SetPrinterDataEx *r)
9322 {
9323         POLICY_HND              *handle = r->in.handle;
9324         NT_PRINTER_INFO_LEVEL   *printer = NULL;
9325         int                     snum = 0;
9326         WERROR                  status = WERR_OK;
9327         Printer_entry           *Printer = find_printer_index_by_hnd(p, handle);
9328         char                    *oid_string;
9329
9330         DEBUG(4,("_spoolss_SetPrinterDataEx\n"));
9331
9332         /* From MSDN documentation of SetPrinterDataEx: pass request to
9333            SetPrinterData if key is "PrinterDriverData" */
9334
9335         if (!Printer) {
9336                 DEBUG(2,("_spoolss_SetPrinterDataEx: "
9337                         "Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
9338                 return WERR_BADFID;
9339         }
9340
9341         if ( Printer->printer_type == SPLHND_SERVER ) {
9342                 DEBUG(10,("_spoolss_SetPrinterDataEx: "
9343                         "Not implemented for server handles yet\n"));
9344                 return WERR_INVALID_PARAM;
9345         }
9346
9347         if ( !get_printer_snum(p,handle, &snum, NULL) )
9348                 return WERR_BADFID;
9349
9350         /*
9351          * Access check : NT returns "access denied" if you make a
9352          * SetPrinterData call without the necessary privildge.
9353          * we were originally returning OK if nothing changed
9354          * which made Win2k issue **a lot** of SetPrinterData
9355          * when connecting to a printer  --jerry
9356          */
9357
9358         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER)
9359         {
9360                 DEBUG(3, ("_spoolss_SetPrinterDataEx: "
9361                         "change denied by handle access permissions\n"));
9362                 return WERR_ACCESS_DENIED;
9363         }
9364
9365         status = get_a_printer(Printer, &printer, 2, lp_servicename(snum));
9366         if (!W_ERROR_IS_OK(status))
9367                 return status;
9368
9369         /* check for OID in valuename */
9370
9371         if ( (oid_string = strchr( r->in.value_name, ',' )) != NULL )
9372         {
9373                 *oid_string = '\0';
9374                 oid_string++;
9375         }
9376
9377         /* save the registry data */
9378
9379         status = set_printer_dataex( printer, r->in.key_name, r->in.value_name,
9380                                      r->in.type, r->in.buffer, r->in.offered );
9381
9382         if ( W_ERROR_IS_OK(status) )
9383         {
9384                 /* save the OID if one was specified */
9385                 if ( oid_string ) {
9386                         char *str = talloc_asprintf(p->mem_ctx, "%s\\%s",
9387                                 r->in.key_name, SPOOL_OID_KEY);
9388                         if (!str) {
9389                                 return WERR_NOMEM;
9390                         }
9391
9392                         /*
9393                          * I'm not checking the status here on purpose.  Don't know
9394                          * if this is right, but I'm returning the status from the
9395                          * previous set_printer_dataex() call.  I have no idea if
9396                          * this is right.    --jerry
9397                          */
9398
9399                         set_printer_dataex( printer, str, r->in.value_name,
9400                                             REG_SZ, (uint8 *)oid_string,
9401                                             strlen(oid_string)+1 );
9402                 }
9403
9404                 status = mod_a_printer(printer, 2);
9405         }
9406
9407         free_a_printer(&printer, 2);
9408
9409         return status;
9410 }
9411
9412 /****************************************************************
9413  _spoolss_DeletePrinterDataEx
9414 ****************************************************************/
9415
9416 WERROR _spoolss_DeletePrinterDataEx(pipes_struct *p,
9417                                     struct spoolss_DeletePrinterDataEx *r)
9418 {
9419         POLICY_HND      *handle = r->in.handle;
9420         NT_PRINTER_INFO_LEVEL   *printer = NULL;
9421         int             snum=0;
9422         WERROR          status = WERR_OK;
9423         Printer_entry   *Printer=find_printer_index_by_hnd(p, handle);
9424
9425         DEBUG(5,("_spoolss_DeletePrinterDataEx\n"));
9426
9427         if (!Printer) {
9428                 DEBUG(2,("_spoolss_DeletePrinterDataEx: "
9429                         "Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
9430                 return WERR_BADFID;
9431         }
9432
9433         if (!get_printer_snum(p, handle, &snum, NULL))
9434                 return WERR_BADFID;
9435
9436         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
9437                 DEBUG(3, ("_spoolss_DeletePrinterDataEx: "
9438                         "printer properties change denied by handle\n"));
9439                 return WERR_ACCESS_DENIED;
9440         }
9441
9442         if (!r->in.value_name || !r->in.key_name) {
9443                 return WERR_NOMEM;
9444         }
9445
9446         status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
9447         if (!W_ERROR_IS_OK(status))
9448                 return status;
9449
9450         status = delete_printer_dataex( printer, r->in.key_name, r->in.value_name );
9451
9452         if ( W_ERROR_IS_OK(status) )
9453                 mod_a_printer( printer, 2 );
9454
9455         free_a_printer(&printer, 2);
9456
9457         return status;
9458 }
9459
9460 /********************************************************************
9461  * spoolss_enumprinterkey
9462  ********************************************************************/
9463
9464
9465 WERROR _spoolss_enumprinterkey(pipes_struct *p, SPOOL_Q_ENUMPRINTERKEY *q_u, SPOOL_R_ENUMPRINTERKEY *r_u)
9466 {
9467         fstring         key;
9468         fstring         *keynames = NULL;
9469         uint16          *enumkeys = NULL;
9470         int             num_keys;
9471         int             printerkey_len;
9472         POLICY_HND      *handle = &q_u->handle;
9473         Printer_entry   *Printer = find_printer_index_by_hnd(p, handle);
9474         NT_PRINTER_DATA *data;
9475         NT_PRINTER_INFO_LEVEL   *printer = NULL;
9476         int             snum = 0;
9477         WERROR          status = WERR_BADFILE;
9478
9479
9480         DEBUG(4,("_spoolss_enumprinterkey\n"));
9481
9482         if (!Printer) {
9483                 DEBUG(2,("_spoolss_enumprinterkey: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
9484                 return WERR_BADFID;
9485         }
9486
9487         if ( !get_printer_snum(p,handle, &snum, NULL) )
9488                 return WERR_BADFID;
9489
9490         status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
9491         if (!W_ERROR_IS_OK(status))
9492                 return status;
9493
9494         /* get the list of subkey names */
9495
9496         unistr2_to_ascii(key, &q_u->key, sizeof(key));
9497         data = printer->info_2->data;
9498
9499         num_keys = get_printer_subkeys( data, key, &keynames );
9500
9501         if ( num_keys == -1 ) {
9502                 status = WERR_BADFILE;
9503                 goto done;
9504         }
9505
9506         printerkey_len = init_unistr_array( &enumkeys,  keynames, NULL );
9507
9508         r_u->needed = printerkey_len*2;
9509
9510         if ( q_u->size < r_u->needed ) {
9511                 status = WERR_MORE_DATA;
9512                 goto done;
9513         }
9514
9515         if (!make_spoolss_buffer5(p->mem_ctx, &r_u->keys, printerkey_len, enumkeys)) {
9516                 status = WERR_NOMEM;
9517                 goto done;
9518         }
9519
9520         status = WERR_OK;
9521
9522         if ( q_u->size < r_u->needed )
9523                 status = WERR_MORE_DATA;
9524
9525 done:
9526         free_a_printer( &printer, 2 );
9527         SAFE_FREE( keynames );
9528
9529         return status;
9530 }
9531
9532 /****************************************************************
9533  _spoolss_DeletePrinterKey
9534 ****************************************************************/
9535
9536 WERROR _spoolss_DeletePrinterKey(pipes_struct *p,
9537                                  struct spoolss_DeletePrinterKey *r)
9538 {
9539         POLICY_HND              *handle = r->in.handle;
9540         Printer_entry           *Printer = find_printer_index_by_hnd(p, handle);
9541         NT_PRINTER_INFO_LEVEL   *printer = NULL;
9542         int                     snum=0;
9543         WERROR                  status;
9544
9545         DEBUG(5,("_spoolss_DeletePrinterKey\n"));
9546
9547         if (!Printer) {
9548                 DEBUG(2,("_spoolss_DeletePrinterKey: Invalid handle (%s:%u:%u).\n",
9549                         OUR_HANDLE(handle)));
9550                 return WERR_BADFID;
9551         }
9552
9553         /* if keyname == NULL, return error */
9554
9555         if ( !r->in.key_name )
9556                 return WERR_INVALID_PARAM;
9557
9558         if (!get_printer_snum(p, handle, &snum, NULL))
9559                 return WERR_BADFID;
9560
9561         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
9562                 DEBUG(3, ("_spoolss_DeletePrinterKey: "
9563                         "printer properties change denied by handle\n"));
9564                 return WERR_ACCESS_DENIED;
9565         }
9566
9567         status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
9568         if (!W_ERROR_IS_OK(status))
9569                 return status;
9570
9571         /* delete the key and all subneys */
9572
9573         status = delete_all_printer_data( printer->info_2, r->in.key_name );
9574
9575         if ( W_ERROR_IS_OK(status) )
9576                 status = mod_a_printer(printer, 2);
9577
9578         free_a_printer( &printer, 2 );
9579
9580         return status;
9581 }
9582
9583
9584 /********************************************************************
9585  * spoolss_enumprinterdataex
9586  ********************************************************************/
9587
9588 WERROR _spoolss_enumprinterdataex(pipes_struct *p, SPOOL_Q_ENUMPRINTERDATAEX *q_u, SPOOL_R_ENUMPRINTERDATAEX *r_u)
9589 {
9590         POLICY_HND      *handle = &q_u->handle;
9591         uint32          in_size = q_u->size;
9592         uint32          num_entries,
9593                         needed;
9594         NT_PRINTER_INFO_LEVEL   *printer = NULL;
9595         PRINTER_ENUM_VALUES     *enum_values = NULL;
9596         NT_PRINTER_DATA         *p_data;
9597         fstring         key;
9598         Printer_entry   *Printer = find_printer_index_by_hnd(p, handle);
9599         int             snum;
9600         WERROR          result;
9601         int             key_index;
9602         int             i;
9603         REGISTRY_VALUE  *val;
9604         char            *value_name;
9605         uint32          data_len;
9606
9607
9608         DEBUG(4,("_spoolss_enumprinterdataex\n"));
9609
9610         if (!Printer) {
9611                 DEBUG(2,("_spoolss_enumprinterdataex: Invalid handle (%s:%u:%u1<).\n", OUR_HANDLE(handle)));
9612                 return WERR_BADFID;
9613         }
9614
9615         /*
9616          * first check for a keyname of NULL or "".  Win2k seems to send
9617          * this a lot and we should send back WERR_INVALID_PARAM
9618          * no need to spend time looking up the printer in this case.
9619          * --jerry
9620          */
9621
9622         unistr2_to_ascii(key, &q_u->key, sizeof(key));
9623         if ( !strlen(key) ) {
9624                 result = WERR_INVALID_PARAM;
9625                 goto done;
9626         }
9627
9628         /* get the printer off of disk */
9629
9630         if (!get_printer_snum(p,handle, &snum, NULL))
9631                 return WERR_BADFID;
9632
9633         ZERO_STRUCT(printer);
9634         result = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
9635         if (!W_ERROR_IS_OK(result))
9636                 return result;
9637
9638         /* now look for a match on the key name */
9639
9640         p_data = printer->info_2->data;
9641
9642         unistr2_to_ascii(key, &q_u->key, sizeof(key));
9643         if ( (key_index = lookup_printerkey( p_data, key)) == -1  )
9644         {
9645                 DEBUG(10,("_spoolss_enumprinterdataex: Unknown keyname [%s]\n", key));
9646                 result = WERR_INVALID_PARAM;
9647                 goto done;
9648         }
9649
9650         result = WERR_OK;
9651         needed = 0;
9652
9653         /* allocate the memory for the array of pointers -- if necessary */
9654
9655         num_entries = regval_ctr_numvals( p_data->keys[key_index].values );
9656         if ( num_entries )
9657         {
9658                 if ( (enum_values=TALLOC_ARRAY(p->mem_ctx, PRINTER_ENUM_VALUES, num_entries)) == NULL )
9659                 {
9660                         DEBUG(0,("_spoolss_enumprinterdataex: talloc() failed to allocate memory for [%lu] bytes!\n",
9661                                 (unsigned long)num_entries*sizeof(PRINTER_ENUM_VALUES)));
9662                         result = WERR_NOMEM;
9663                         goto done;
9664                 }
9665
9666                 memset( enum_values, 0x0, num_entries*sizeof(PRINTER_ENUM_VALUES) );
9667         }
9668
9669         /*
9670          * loop through all params and build the array to pass
9671          * back to the  client
9672          */
9673
9674         for ( i=0; i<num_entries; i++ )
9675         {
9676                 /* lookup the registry value */
9677
9678                 val = regval_ctr_specific_value( p_data->keys[key_index].values, i );
9679                 DEBUG(10,("retrieved value number [%d] [%s]\n", i, regval_name(val) ));
9680
9681                 /* copy the data */
9682
9683                 value_name = regval_name( val );
9684                 init_unistr( &enum_values[i].valuename, value_name );
9685                 enum_values[i].value_len = (strlen(value_name)+1) * 2;
9686                 enum_values[i].type      = regval_type( val );
9687
9688                 data_len = regval_size( val );
9689                 if ( data_len ) {
9690                         if ( !(enum_values[i].data = (uint8 *)TALLOC_MEMDUP(p->mem_ctx, regval_data_p(val), data_len)) )
9691                         {
9692                                 DEBUG(0,("TALLOC_MEMDUP failed to allocate memory [data_len=%d] for data!\n",
9693                                         data_len ));
9694                                 result = WERR_NOMEM;
9695                                 goto done;
9696                         }
9697                 }
9698                 enum_values[i].data_len = data_len;
9699
9700                 /* keep track of the size of the array in bytes */
9701
9702                 needed += spoolss_size_printer_enum_values(&enum_values[i]);
9703         }
9704
9705         /* housekeeping information in the reply */
9706
9707         /* Fix from Martin Zielinski <mz@seh.de> - ensure
9708          * the hand marshalled container size is a multiple
9709          * of 4 bytes for RPC alignment.
9710          */
9711
9712         if (needed % 4) {
9713                 needed += 4-(needed % 4);
9714         }
9715
9716         r_u->needed     = needed;
9717         r_u->returned   = num_entries;
9718
9719         if (needed > in_size) {
9720                 result = WERR_MORE_DATA;
9721                 goto done;
9722         }
9723
9724         /* copy data into the reply */
9725
9726         /* mz: Vista x64 returns 0x6f7 (The stub received bad data), if the
9727            response buffer size is != the offered buffer size
9728
9729                 r_u->ctr.size           = r_u->needed;
9730         */
9731         r_u->ctr.size           = in_size;
9732
9733         r_u->ctr.size_of_array  = r_u->returned;
9734         r_u->ctr.values         = enum_values;
9735
9736 done:
9737         if ( printer )
9738         free_a_printer(&printer, 2);
9739
9740         return result;
9741 }
9742
9743 /****************************************************************************
9744 ****************************************************************************/
9745
9746 static WERROR getprintprocessordirectory_level_1(TALLOC_CTX *mem_ctx,
9747                                                  const char *servername,
9748                                                  const char *environment,
9749                                                  struct spoolss_PrintProcessorDirectoryInfo1 *r,
9750                                                  uint32_t offered,
9751                                                  uint32_t *needed)
9752 {
9753         WERROR werr;
9754         char *path = NULL;
9755
9756         werr = compose_spoolss_server_path(mem_ctx,
9757                                            servername,
9758                                            environment,
9759                                            SPOOLSS_PRTPROCS_PATH,
9760                                            &path);
9761         if (!W_ERROR_IS_OK(werr)) {
9762                 return werr;
9763         }
9764
9765         DEBUG(4,("print processor directory: [%s]\n", path));
9766
9767         r->directory_name = path;
9768
9769         *needed += ndr_size_spoolss_PrintProcessorDirectoryInfo1(r, NULL, 0);
9770
9771         if (*needed > offered) {
9772                 talloc_free(path);
9773                 return WERR_INSUFFICIENT_BUFFER;
9774         }
9775
9776         return WERR_OK;
9777 }
9778
9779 /****************************************************************
9780  _spoolss_GetPrintProcessorDirectory
9781 ****************************************************************/
9782
9783 WERROR _spoolss_GetPrintProcessorDirectory(pipes_struct *p,
9784                                            struct spoolss_GetPrintProcessorDirectory *r)
9785 {
9786         WERROR result;
9787
9788         /* that's an [in out] buffer */
9789
9790         if (!r->in.buffer && (r->in.offered != 0)) {
9791                 return WERR_INVALID_PARAM;
9792         }
9793
9794         DEBUG(5,("_spoolss_GetPrintProcessorDirectory: level %d\n",
9795                 r->in.level));
9796
9797         *r->out.needed = 0;
9798
9799         /* r->in.level is ignored */
9800
9801         result = getprintprocessordirectory_level_1(p->mem_ctx,
9802                                                     r->in.server,
9803                                                     r->in.environment,
9804                                                     &r->out.info->info1,
9805                                                     r->in.offered,
9806                                                     r->out.needed);
9807         if (!W_ERROR_IS_OK(result)) {
9808                 TALLOC_FREE(r->out.info);
9809         }
9810
9811         return result;
9812 }
9813
9814 /*******************************************************************
9815  ********************************************************************/
9816
9817 static bool push_monitorui_buf(TALLOC_CTX *mem_ctx, DATA_BLOB *buf,
9818                                const char *dllname)
9819 {
9820         enum ndr_err_code ndr_err;
9821         struct spoolss_MonitorUi ui;
9822
9823         ui.dll_name = dllname;
9824
9825         ndr_err = ndr_push_struct_blob(buf, mem_ctx, NULL, &ui,
9826                        (ndr_push_flags_fn_t)ndr_push_spoolss_MonitorUi);
9827         if (NDR_ERR_CODE_IS_SUCCESS(ndr_err) && (DEBUGLEVEL >= 10)) {
9828                 NDR_PRINT_DEBUG(spoolss_MonitorUi, &ui);
9829         }
9830         return NDR_ERR_CODE_IS_SUCCESS(ndr_err);
9831 }
9832
9833 /*******************************************************************
9834  Streams the monitor UI DLL name in UNICODE
9835 *******************************************************************/
9836
9837 static WERROR xcvtcp_monitorui(TALLOC_CTX *mem_ctx,
9838                                NT_USER_TOKEN *token, DATA_BLOB *in,
9839                                DATA_BLOB *out, uint32_t *needed)
9840 {
9841         const char *dllname = "tcpmonui.dll";
9842
9843         *needed = (strlen(dllname)+1) * 2;
9844
9845         if (out->length < *needed) {
9846                 return WERR_INSUFFICIENT_BUFFER;
9847         }
9848
9849         if (!push_monitorui_buf(mem_ctx, out, dllname)) {
9850                 return WERR_NOMEM;
9851         }
9852
9853         return WERR_OK;
9854 }
9855
9856 /*******************************************************************
9857  ********************************************************************/
9858
9859 static bool pull_port_data_1(TALLOC_CTX *mem_ctx,
9860                              struct spoolss_PortData1 *port1,
9861                              const DATA_BLOB *buf)
9862 {
9863         enum ndr_err_code ndr_err;
9864         ndr_err = ndr_pull_struct_blob(buf, mem_ctx, NULL, port1,
9865                        (ndr_pull_flags_fn_t)ndr_pull_spoolss_PortData1);
9866         if (NDR_ERR_CODE_IS_SUCCESS(ndr_err) && (DEBUGLEVEL >= 10)) {
9867                 NDR_PRINT_DEBUG(spoolss_PortData1, port1);
9868         }
9869         return NDR_ERR_CODE_IS_SUCCESS(ndr_err);
9870 }
9871
9872 /*******************************************************************
9873  ********************************************************************/
9874
9875 static bool pull_port_data_2(TALLOC_CTX *mem_ctx,
9876                              struct spoolss_PortData2 *port2,
9877                              const DATA_BLOB *buf)
9878 {
9879         enum ndr_err_code ndr_err;
9880         ndr_err = ndr_pull_struct_blob(buf, mem_ctx, NULL, port2,
9881                        (ndr_pull_flags_fn_t)ndr_pull_spoolss_PortData2);
9882         if (NDR_ERR_CODE_IS_SUCCESS(ndr_err) && (DEBUGLEVEL >= 10)) {
9883                 NDR_PRINT_DEBUG(spoolss_PortData2, port2);
9884         }
9885         return NDR_ERR_CODE_IS_SUCCESS(ndr_err);
9886 }
9887
9888 /*******************************************************************
9889  Create a new TCP/IP port
9890 *******************************************************************/
9891
9892 static WERROR xcvtcp_addport(TALLOC_CTX *mem_ctx,
9893                              NT_USER_TOKEN *token, DATA_BLOB *in,
9894                              DATA_BLOB *out, uint32_t *needed)
9895 {
9896         struct spoolss_PortData1 port1;
9897         struct spoolss_PortData2 port2;
9898         char *device_uri = NULL;
9899         uint32_t version;
9900
9901         const char *portname;
9902         const char *hostaddress;
9903         const char *queue;
9904         uint32_t port_number;
9905         uint32_t protocol;
9906
9907         /* peek for spoolss_PortData version */
9908
9909         if (!in || (in->length < (128 + 4))) {
9910                 return WERR_GENERAL_FAILURE;
9911         }
9912
9913         version = IVAL(in->data, 128);
9914
9915         switch (version) {
9916                 case 1:
9917                         ZERO_STRUCT(port1);
9918
9919                         if (!pull_port_data_1(mem_ctx, &port1, in)) {
9920                                 return WERR_NOMEM;
9921                         }
9922
9923                         portname        = port1.portname;
9924                         hostaddress     = port1.hostaddress;
9925                         queue           = port1.queue;
9926                         protocol        = port1.protocol;
9927                         port_number     = port1.port_number;
9928
9929                         break;
9930                 case 2:
9931                         ZERO_STRUCT(port2);
9932
9933                         if (!pull_port_data_2(mem_ctx, &port2, in)) {
9934                                 return WERR_NOMEM;
9935                         }
9936
9937                         portname        = port2.portname;
9938                         hostaddress     = port2.hostaddress;
9939                         queue           = port2.queue;
9940                         protocol        = port2.protocol;
9941                         port_number     = port2.port_number;
9942
9943                         break;
9944                 default:
9945                         DEBUG(1,("xcvtcp_addport: "
9946                                 "unknown version of port_data: %d\n", version));
9947                         return WERR_UNKNOWN_PORT;
9948         }
9949
9950         /* create the device URI and call the add_port_hook() */
9951
9952         switch (protocol) {
9953         case PROTOCOL_RAWTCP_TYPE:
9954                 device_uri = talloc_asprintf(mem_ctx,
9955                                 "socket://%s:%d/", hostaddress,
9956                                 port_number);
9957                 break;
9958
9959         case PROTOCOL_LPR_TYPE:
9960                 device_uri = talloc_asprintf(mem_ctx,
9961                         "lpr://%s/%s", hostaddress, queue );
9962                 break;
9963
9964         default:
9965                 return WERR_UNKNOWN_PORT;
9966         }
9967
9968         if (!device_uri) {
9969                 return WERR_NOMEM;
9970         }
9971
9972         return add_port_hook(mem_ctx, token, portname, device_uri);
9973 }
9974
9975 /*******************************************************************
9976 *******************************************************************/
9977
9978 struct xcv_api_table xcvtcp_cmds[] = {
9979         { "MonitorUI",  xcvtcp_monitorui },
9980         { "AddPort",    xcvtcp_addport},
9981         { NULL,         NULL }
9982 };
9983
9984 static WERROR process_xcvtcp_command(TALLOC_CTX *mem_ctx,
9985                                      NT_USER_TOKEN *token, const char *command,
9986                                      DATA_BLOB *inbuf,
9987                                      DATA_BLOB *outbuf,
9988                                      uint32_t *needed )
9989 {
9990         int i;
9991
9992         DEBUG(10,("process_xcvtcp_command: Received command \"%s\"\n", command));
9993
9994         for ( i=0; xcvtcp_cmds[i].name; i++ ) {
9995                 if ( strcmp( command, xcvtcp_cmds[i].name ) == 0 )
9996                         return xcvtcp_cmds[i].fn(mem_ctx, token, inbuf, outbuf, needed);
9997         }
9998
9999         return WERR_BADFUNC;
10000 }
10001
10002 /*******************************************************************
10003 *******************************************************************/
10004 #if 0   /* don't support management using the "Local Port" monitor */
10005
10006 static WERROR xcvlocal_monitorui(TALLOC_CTX *mem_ctx,
10007                                  NT_USER_TOKEN *token, DATA_BLOB *in,
10008                                  DATA_BLOB *out, uint32_t *needed)
10009 {
10010         const char *dllname = "localui.dll";
10011
10012         *needed = (strlen(dllname)+1) * 2;
10013
10014         if (out->length < *needed) {
10015                 return WERR_INSUFFICIENT_BUFFER;
10016         }
10017
10018         if (!push_monitorui_buf(mem_ctx, out, dllname)) {
10019                 return WERR_NOMEM;
10020         }
10021
10022         return WERR_OK;
10023 }
10024
10025 /*******************************************************************
10026 *******************************************************************/
10027
10028 struct xcv_api_table xcvlocal_cmds[] = {
10029         { "MonitorUI",  xcvlocal_monitorui },
10030         { NULL,         NULL }
10031 };
10032 #else
10033 struct xcv_api_table xcvlocal_cmds[] = {
10034         { NULL,         NULL }
10035 };
10036 #endif
10037
10038
10039
10040 /*******************************************************************
10041 *******************************************************************/
10042
10043 static WERROR process_xcvlocal_command(TALLOC_CTX *mem_ctx,
10044                                        NT_USER_TOKEN *token, const char *command,
10045                                        DATA_BLOB *inbuf, DATA_BLOB *outbuf,
10046                                        uint32_t *needed)
10047 {
10048         int i;
10049
10050         DEBUG(10,("process_xcvlocal_command: Received command \"%s\"\n", command));
10051
10052         for ( i=0; xcvlocal_cmds[i].name; i++ ) {
10053                 if ( strcmp( command, xcvlocal_cmds[i].name ) == 0 )
10054                         return xcvlocal_cmds[i].fn(mem_ctx, token, inbuf, outbuf, needed);
10055         }
10056         return WERR_BADFUNC;
10057 }
10058
10059 /****************************************************************
10060  _spoolss_XcvData
10061 ****************************************************************/
10062
10063 WERROR _spoolss_XcvData(pipes_struct *p,
10064                         struct spoolss_XcvData *r)
10065 {
10066         Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
10067         DATA_BLOB out_data = data_blob_null;
10068         WERROR werror;
10069
10070         if (!Printer) {
10071                 DEBUG(2,("_spoolss_XcvData: Invalid handle (%s:%u:%u).\n",
10072                         OUR_HANDLE(r->in.handle)));
10073                 return WERR_BADFID;
10074         }
10075
10076         /* Has to be a handle to the TCP/IP port monitor */
10077
10078         if ( !(Printer->printer_type & (SPLHND_PORTMON_LOCAL|SPLHND_PORTMON_TCP)) ) {
10079                 DEBUG(2,("_spoolss_XcvData: Call only valid for Port Monitors\n"));
10080                 return WERR_BADFID;
10081         }
10082
10083         /* requires administrative access to the server */
10084
10085         if ( !(Printer->access_granted & SERVER_ACCESS_ADMINISTER) ) {
10086                 DEBUG(2,("_spoolss_XcvData: denied by handle permissions.\n"));
10087                 return WERR_ACCESS_DENIED;
10088         }
10089
10090         /* Allocate the outgoing buffer */
10091
10092         if (r->in.out_data_size) {
10093                 out_data = data_blob_talloc_zero(p->mem_ctx, r->in.out_data_size);
10094                 if (out_data.data == NULL) {
10095                         return WERR_NOMEM;
10096                 }
10097         }
10098
10099         switch ( Printer->printer_type ) {
10100         case SPLHND_PORTMON_TCP:
10101                 werror = process_xcvtcp_command(p->mem_ctx,
10102                                                 p->server_info->ptok,
10103                                                 r->in.function_name,
10104                                                 &r->in.in_data, &out_data,
10105                                                 r->out.needed);
10106                 break;
10107         case SPLHND_PORTMON_LOCAL:
10108                 werror = process_xcvlocal_command(p->mem_ctx,
10109                                                   p->server_info->ptok,
10110                                                   r->in.function_name,
10111                                                   &r->in.in_data, &out_data,
10112                                                   r->out.needed);
10113                 break;
10114         default:
10115                 werror = WERR_INVALID_PRINT_MONITOR;
10116         }
10117
10118         if (!W_ERROR_IS_OK(werror)) {
10119                 return werror;
10120         }
10121
10122         *r->out.status_code = 0;
10123
10124         memcpy(r->out.out_data, out_data.data, out_data.length);
10125
10126         return WERR_OK;
10127 }
10128
10129 /****************************************************************
10130  _spoolss_AddPrintProcessor
10131 ****************************************************************/
10132
10133 WERROR _spoolss_AddPrintProcessor(pipes_struct *p,
10134                                   struct spoolss_AddPrintProcessor *r)
10135 {
10136         /* for now, just indicate success and ignore the add.  We'll
10137            automatically set the winprint processor for printer
10138            entries later.  Used to debug the LexMark Optra S 1855 PCL
10139            driver --jerry */
10140
10141         return WERR_OK;
10142 }
10143
10144 /****************************************************************
10145  _spoolss_EnumPrinters
10146 ****************************************************************/
10147
10148 WERROR _spoolss_EnumPrinters(pipes_struct *p,
10149                              struct spoolss_EnumPrinters *r)
10150 {
10151         p->rng_fault_state = true;
10152         return WERR_NOT_SUPPORTED;
10153 }
10154
10155 /****************************************************************
10156  _spoolss_GetJob
10157 ****************************************************************/
10158
10159 WERROR _spoolss_GetJob(pipes_struct *p,
10160                        struct spoolss_GetJob *r)
10161 {
10162         p->rng_fault_state = true;
10163         return WERR_NOT_SUPPORTED;
10164 }
10165
10166 /****************************************************************
10167  _spoolss_EnumJobs
10168 ****************************************************************/
10169
10170 WERROR _spoolss_EnumJobs(pipes_struct *p,
10171                          struct spoolss_EnumJobs *r)
10172 {
10173         p->rng_fault_state = true;
10174         return WERR_NOT_SUPPORTED;
10175 }
10176
10177 /****************************************************************
10178  _spoolss_AddPrinter
10179 ****************************************************************/
10180
10181 WERROR _spoolss_AddPrinter(pipes_struct *p,
10182                            struct spoolss_AddPrinter *r)
10183 {
10184         p->rng_fault_state = true;
10185         return WERR_NOT_SUPPORTED;
10186 }
10187
10188 /****************************************************************
10189  _spoolss_GetPrinter
10190 ****************************************************************/
10191
10192 WERROR _spoolss_GetPrinter(pipes_struct *p,
10193                            struct spoolss_GetPrinter *r)
10194 {
10195         p->rng_fault_state = true;
10196         return WERR_NOT_SUPPORTED;
10197 }
10198
10199 /****************************************************************
10200  _spoolss_EnumPrinterDrivers
10201 ****************************************************************/
10202
10203 WERROR _spoolss_EnumPrinterDrivers(pipes_struct *p,
10204                                    struct spoolss_EnumPrinterDrivers *r)
10205 {
10206         p->rng_fault_state = true;
10207         return WERR_NOT_SUPPORTED;
10208 }
10209
10210 /****************************************************************
10211  _spoolss_GetPrinterDriver
10212 ****************************************************************/
10213
10214 WERROR _spoolss_GetPrinterDriver(pipes_struct *p,
10215                                  struct spoolss_GetPrinterDriver *r)
10216 {
10217         p->rng_fault_state = true;
10218         return WERR_NOT_SUPPORTED;
10219 }
10220
10221 /****************************************************************
10222  _spoolss_EnumPrintProcessors
10223 ****************************************************************/
10224
10225 WERROR _spoolss_EnumPrintProcessors(pipes_struct *p,
10226                                     struct spoolss_EnumPrintProcessors *r)
10227 {
10228         p->rng_fault_state = true;
10229         return WERR_NOT_SUPPORTED;
10230 }
10231
10232 /****************************************************************
10233  _spoolss_ReadPrinter
10234 ****************************************************************/
10235
10236 WERROR _spoolss_ReadPrinter(pipes_struct *p,
10237                             struct spoolss_ReadPrinter *r)
10238 {
10239         p->rng_fault_state = true;
10240         return WERR_NOT_SUPPORTED;
10241 }
10242
10243 /****************************************************************
10244  _spoolss_GetPrinterData
10245 ****************************************************************/
10246
10247 WERROR _spoolss_GetPrinterData(pipes_struct *p,
10248                                struct spoolss_GetPrinterData *r)
10249 {
10250         p->rng_fault_state = true;
10251         return WERR_NOT_SUPPORTED;
10252 }
10253
10254 /****************************************************************
10255  _spoolss_SetPrinterData
10256 ****************************************************************/
10257
10258 WERROR _spoolss_SetPrinterData(pipes_struct *p,
10259                                struct spoolss_SetPrinterData *r)
10260 {
10261         p->rng_fault_state = true;
10262         return WERR_NOT_SUPPORTED;
10263 }
10264
10265 /****************************************************************
10266  _spoolss_WaitForPrinterChange
10267 ****************************************************************/
10268
10269 WERROR _spoolss_WaitForPrinterChange(pipes_struct *p,
10270                                      struct spoolss_WaitForPrinterChange *r)
10271 {
10272         p->rng_fault_state = true;
10273         return WERR_NOT_SUPPORTED;
10274 }
10275
10276 /****************************************************************
10277  _spoolss_EnumPorts
10278 ****************************************************************/
10279
10280 WERROR _spoolss_EnumPorts(pipes_struct *p,
10281                           struct spoolss_EnumPorts *r)
10282 {
10283         p->rng_fault_state = true;
10284         return WERR_NOT_SUPPORTED;
10285 }
10286
10287 /****************************************************************
10288  _spoolss_EnumMonitors
10289 ****************************************************************/
10290
10291 WERROR _spoolss_EnumMonitors(pipes_struct *p,
10292                              struct spoolss_EnumMonitors *r)
10293 {
10294         p->rng_fault_state = true;
10295         return WERR_NOT_SUPPORTED;
10296 }
10297
10298 /****************************************************************
10299  _spoolss_AddPort
10300 ****************************************************************/
10301
10302 WERROR _spoolss_AddPort(pipes_struct *p,
10303                         struct spoolss_AddPort *r)
10304 {
10305         p->rng_fault_state = true;
10306         return WERR_NOT_SUPPORTED;
10307 }
10308
10309 /****************************************************************
10310  _spoolss_ConfigurePort
10311 ****************************************************************/
10312
10313 WERROR _spoolss_ConfigurePort(pipes_struct *p,
10314                               struct spoolss_ConfigurePort *r)
10315 {
10316         p->rng_fault_state = true;
10317         return WERR_NOT_SUPPORTED;
10318 }
10319
10320 /****************************************************************
10321  _spoolss_DeletePort
10322 ****************************************************************/
10323
10324 WERROR _spoolss_DeletePort(pipes_struct *p,
10325                            struct spoolss_DeletePort *r)
10326 {
10327         p->rng_fault_state = true;
10328         return WERR_NOT_SUPPORTED;
10329 }
10330
10331 /****************************************************************
10332  _spoolss_CreatePrinterIC
10333 ****************************************************************/
10334
10335 WERROR _spoolss_CreatePrinterIC(pipes_struct *p,
10336                                 struct spoolss_CreatePrinterIC *r)
10337 {
10338         p->rng_fault_state = true;
10339         return WERR_NOT_SUPPORTED;
10340 }
10341
10342 /****************************************************************
10343  _spoolss_PlayGDIScriptOnPrinterIC
10344 ****************************************************************/
10345
10346 WERROR _spoolss_PlayGDIScriptOnPrinterIC(pipes_struct *p,
10347                                          struct spoolss_PlayGDIScriptOnPrinterIC *r)
10348 {
10349         p->rng_fault_state = true;
10350         return WERR_NOT_SUPPORTED;
10351 }
10352
10353 /****************************************************************
10354  _spoolss_DeletePrinterIC
10355 ****************************************************************/
10356
10357 WERROR _spoolss_DeletePrinterIC(pipes_struct *p,
10358                                 struct spoolss_DeletePrinterIC *r)
10359 {
10360         p->rng_fault_state = true;
10361         return WERR_NOT_SUPPORTED;
10362 }
10363
10364 /****************************************************************
10365  _spoolss_AddPrinterConnection
10366 ****************************************************************/
10367
10368 WERROR _spoolss_AddPrinterConnection(pipes_struct *p,
10369                                      struct spoolss_AddPrinterConnection *r)
10370 {
10371         p->rng_fault_state = true;
10372         return WERR_NOT_SUPPORTED;
10373 }
10374
10375 /****************************************************************
10376  _spoolss_DeletePrinterConnection
10377 ****************************************************************/
10378
10379 WERROR _spoolss_DeletePrinterConnection(pipes_struct *p,
10380                                         struct spoolss_DeletePrinterConnection *r)
10381 {
10382         p->rng_fault_state = true;
10383         return WERR_NOT_SUPPORTED;
10384 }
10385
10386 /****************************************************************
10387  _spoolss_PrinterMessageBox
10388 ****************************************************************/
10389
10390 WERROR _spoolss_PrinterMessageBox(pipes_struct *p,
10391                                   struct spoolss_PrinterMessageBox *r)
10392 {
10393         p->rng_fault_state = true;
10394         return WERR_NOT_SUPPORTED;
10395 }
10396
10397 /****************************************************************
10398  _spoolss_AddMonitor
10399 ****************************************************************/
10400
10401 WERROR _spoolss_AddMonitor(pipes_struct *p,
10402                            struct spoolss_AddMonitor *r)
10403 {
10404         p->rng_fault_state = true;
10405         return WERR_NOT_SUPPORTED;
10406 }
10407
10408 /****************************************************************
10409  _spoolss_DeleteMonitor
10410 ****************************************************************/
10411
10412 WERROR _spoolss_DeleteMonitor(pipes_struct *p,
10413                               struct spoolss_DeleteMonitor *r)
10414 {
10415         p->rng_fault_state = true;
10416         return WERR_NOT_SUPPORTED;
10417 }
10418
10419 /****************************************************************
10420  _spoolss_DeletePrintProcessor
10421 ****************************************************************/
10422
10423 WERROR _spoolss_DeletePrintProcessor(pipes_struct *p,
10424                                      struct spoolss_DeletePrintProcessor *r)
10425 {
10426         p->rng_fault_state = true;
10427         return WERR_NOT_SUPPORTED;
10428 }
10429
10430 /****************************************************************
10431  _spoolss_AddPrintProvidor
10432 ****************************************************************/
10433
10434 WERROR _spoolss_AddPrintProvidor(pipes_struct *p,
10435                                  struct spoolss_AddPrintProvidor *r)
10436 {
10437         p->rng_fault_state = true;
10438         return WERR_NOT_SUPPORTED;
10439 }
10440
10441 /****************************************************************
10442  _spoolss_DeletePrintProvidor
10443 ****************************************************************/
10444
10445 WERROR _spoolss_DeletePrintProvidor(pipes_struct *p,
10446                                     struct spoolss_DeletePrintProvidor *r)
10447 {
10448         p->rng_fault_state = true;
10449         return WERR_NOT_SUPPORTED;
10450 }
10451
10452 /****************************************************************
10453  _spoolss_EnumPrintProcDataTypes
10454 ****************************************************************/
10455
10456 WERROR _spoolss_EnumPrintProcDataTypes(pipes_struct *p,
10457                                        struct spoolss_EnumPrintProcDataTypes *r)
10458 {
10459         p->rng_fault_state = true;
10460         return WERR_NOT_SUPPORTED;
10461 }
10462
10463 /****************************************************************
10464  _spoolss_GetPrinterDriver2
10465 ****************************************************************/
10466
10467 WERROR _spoolss_GetPrinterDriver2(pipes_struct *p,
10468                                   struct spoolss_GetPrinterDriver2 *r)
10469 {
10470         p->rng_fault_state = true;
10471         return WERR_NOT_SUPPORTED;
10472 }
10473
10474 /****************************************************************
10475  _spoolss_FindFirstPrinterChangeNotification
10476 ****************************************************************/
10477
10478 WERROR _spoolss_FindFirstPrinterChangeNotification(pipes_struct *p,
10479                                                    struct spoolss_FindFirstPrinterChangeNotification *r)
10480 {
10481         p->rng_fault_state = true;
10482         return WERR_NOT_SUPPORTED;
10483 }
10484
10485 /****************************************************************
10486  _spoolss_FindNextPrinterChangeNotification
10487 ****************************************************************/
10488
10489 WERROR _spoolss_FindNextPrinterChangeNotification(pipes_struct *p,
10490                                                   struct spoolss_FindNextPrinterChangeNotification *r)
10491 {
10492         p->rng_fault_state = true;
10493         return WERR_NOT_SUPPORTED;
10494 }
10495
10496 /****************************************************************
10497  _spoolss_RouterFindFirstPrinterChangeNotificationOld
10498 ****************************************************************/
10499
10500 WERROR _spoolss_RouterFindFirstPrinterChangeNotificationOld(pipes_struct *p,
10501                                                             struct spoolss_RouterFindFirstPrinterChangeNotificationOld *r)
10502 {
10503         p->rng_fault_state = true;
10504         return WERR_NOT_SUPPORTED;
10505 }
10506
10507 /****************************************************************
10508  _spoolss_ReplyOpenPrinter
10509 ****************************************************************/
10510
10511 WERROR _spoolss_ReplyOpenPrinter(pipes_struct *p,
10512                                  struct spoolss_ReplyOpenPrinter *r)
10513 {
10514         p->rng_fault_state = true;
10515         return WERR_NOT_SUPPORTED;
10516 }
10517
10518 /****************************************************************
10519  _spoolss_RouterReplyPrinter
10520 ****************************************************************/
10521
10522 WERROR _spoolss_RouterReplyPrinter(pipes_struct *p,
10523                                    struct spoolss_RouterReplyPrinter *r)
10524 {
10525         p->rng_fault_state = true;
10526         return WERR_NOT_SUPPORTED;
10527 }
10528
10529 /****************************************************************
10530  _spoolss_ReplyClosePrinter
10531 ****************************************************************/
10532
10533 WERROR _spoolss_ReplyClosePrinter(pipes_struct *p,
10534                                   struct spoolss_ReplyClosePrinter *r)
10535 {
10536         p->rng_fault_state = true;
10537         return WERR_NOT_SUPPORTED;
10538 }
10539
10540 /****************************************************************
10541  _spoolss_AddPortEx
10542 ****************************************************************/
10543
10544 WERROR _spoolss_AddPortEx(pipes_struct *p,
10545                           struct spoolss_AddPortEx *r)
10546 {
10547         p->rng_fault_state = true;
10548         return WERR_NOT_SUPPORTED;
10549 }
10550
10551 /****************************************************************
10552  _spoolss_RouterFindFirstPrinterChangeNotification
10553 ****************************************************************/
10554
10555 WERROR _spoolss_RouterFindFirstPrinterChangeNotification(pipes_struct *p,
10556                                                          struct spoolss_RouterFindFirstPrinterChangeNotification *r)
10557 {
10558         p->rng_fault_state = true;
10559         return WERR_NOT_SUPPORTED;
10560 }
10561
10562 /****************************************************************
10563  _spoolss_SpoolerInit
10564 ****************************************************************/
10565
10566 WERROR _spoolss_SpoolerInit(pipes_struct *p,
10567                             struct spoolss_SpoolerInit *r)
10568 {
10569         p->rng_fault_state = true;
10570         return WERR_NOT_SUPPORTED;
10571 }
10572
10573 /****************************************************************
10574  _spoolss_ResetPrinterEx
10575 ****************************************************************/
10576
10577 WERROR _spoolss_ResetPrinterEx(pipes_struct *p,
10578                                struct spoolss_ResetPrinterEx *r)
10579 {
10580         p->rng_fault_state = true;
10581         return WERR_NOT_SUPPORTED;
10582 }
10583
10584 /****************************************************************
10585  _spoolss_RouterReplyPrinterEx
10586 ****************************************************************/
10587
10588 WERROR _spoolss_RouterReplyPrinterEx(pipes_struct *p,
10589                                      struct spoolss_RouterReplyPrinterEx *r)
10590 {
10591         p->rng_fault_state = true;
10592         return WERR_NOT_SUPPORTED;
10593 }
10594
10595 /****************************************************************
10596  _spoolss_44
10597 ****************************************************************/
10598
10599 WERROR _spoolss_44(pipes_struct *p,
10600                    struct spoolss_44 *r)
10601 {
10602         p->rng_fault_state = true;
10603         return WERR_NOT_SUPPORTED;
10604 }
10605
10606 /****************************************************************
10607  _spoolss_47
10608 ****************************************************************/
10609
10610 WERROR _spoolss_47(pipes_struct *p,
10611                    struct spoolss_47 *r)
10612 {
10613         p->rng_fault_state = true;
10614         return WERR_NOT_SUPPORTED;
10615 }
10616
10617 /****************************************************************
10618  _spoolss_EnumPrinterData
10619 ****************************************************************/
10620
10621 WERROR _spoolss_EnumPrinterData(pipes_struct *p,
10622                                 struct spoolss_EnumPrinterData *r)
10623 {
10624         p->rng_fault_state = true;
10625         return WERR_NOT_SUPPORTED;
10626 }
10627
10628 /****************************************************************
10629  _spoolss_4a
10630 ****************************************************************/
10631
10632 WERROR _spoolss_4a(pipes_struct *p,
10633                    struct spoolss_4a *r)
10634 {
10635         p->rng_fault_state = true;
10636         return WERR_NOT_SUPPORTED;
10637 }
10638
10639 /****************************************************************
10640  _spoolss_4b
10641 ****************************************************************/
10642
10643 WERROR _spoolss_4b(pipes_struct *p,
10644                    struct spoolss_4b *r)
10645 {
10646         p->rng_fault_state = true;
10647         return WERR_NOT_SUPPORTED;
10648 }
10649
10650 /****************************************************************
10651  _spoolss_4c
10652 ****************************************************************/
10653
10654 WERROR _spoolss_4c(pipes_struct *p,
10655                    struct spoolss_4c *r)
10656 {
10657         p->rng_fault_state = true;
10658         return WERR_NOT_SUPPORTED;
10659 }
10660
10661 /****************************************************************
10662  _spoolss_EnumPrinterDataEx
10663 ****************************************************************/
10664
10665 WERROR _spoolss_EnumPrinterDataEx(pipes_struct *p,
10666                                   struct spoolss_EnumPrinterDataEx *r)
10667 {
10668         p->rng_fault_state = true;
10669         return WERR_NOT_SUPPORTED;
10670 }
10671
10672 /****************************************************************
10673  _spoolss_EnumPrinterKey
10674 ****************************************************************/
10675
10676 WERROR _spoolss_EnumPrinterKey(pipes_struct *p,
10677                                struct spoolss_EnumPrinterKey *r)
10678 {
10679         p->rng_fault_state = true;
10680         return WERR_NOT_SUPPORTED;
10681 }
10682
10683 /****************************************************************
10684  _spoolss_53
10685 ****************************************************************/
10686
10687 WERROR _spoolss_53(pipes_struct *p,
10688                    struct spoolss_53 *r)
10689 {
10690         p->rng_fault_state = true;
10691         return WERR_NOT_SUPPORTED;
10692 }
10693
10694 /****************************************************************
10695  _spoolss_55
10696 ****************************************************************/
10697
10698 WERROR _spoolss_55(pipes_struct *p,
10699                    struct spoolss_55 *r)
10700 {
10701         p->rng_fault_state = true;
10702         return WERR_NOT_SUPPORTED;
10703 }
10704
10705 /****************************************************************
10706  _spoolss_56
10707 ****************************************************************/
10708
10709 WERROR _spoolss_56(pipes_struct *p,
10710                    struct spoolss_56 *r)
10711 {
10712         p->rng_fault_state = true;
10713         return WERR_NOT_SUPPORTED;
10714 }
10715
10716 /****************************************************************
10717  _spoolss_57
10718 ****************************************************************/
10719
10720 WERROR _spoolss_57(pipes_struct *p,
10721                    struct spoolss_57 *r)
10722 {
10723         p->rng_fault_state = true;
10724         return WERR_NOT_SUPPORTED;
10725 }
10726
10727 /****************************************************************
10728  _spoolss_5a
10729 ****************************************************************/
10730
10731 WERROR _spoolss_5a(pipes_struct *p,
10732                    struct spoolss_5a *r)
10733 {
10734         p->rng_fault_state = true;
10735         return WERR_NOT_SUPPORTED;
10736 }
10737
10738 /****************************************************************
10739  _spoolss_5b
10740 ****************************************************************/
10741
10742 WERROR _spoolss_5b(pipes_struct *p,
10743                    struct spoolss_5b *r)
10744 {
10745         p->rng_fault_state = true;
10746         return WERR_NOT_SUPPORTED;
10747 }
10748
10749 /****************************************************************
10750  _spoolss_5c
10751 ****************************************************************/
10752
10753 WERROR _spoolss_5c(pipes_struct *p,
10754                    struct spoolss_5c *r)
10755 {
10756         p->rng_fault_state = true;
10757         return WERR_NOT_SUPPORTED;
10758 }
10759
10760 /****************************************************************
10761  _spoolss_5d
10762 ****************************************************************/
10763
10764 WERROR _spoolss_5d(pipes_struct *p,
10765                    struct spoolss_5d *r)
10766 {
10767         p->rng_fault_state = true;
10768         return WERR_NOT_SUPPORTED;
10769 }
10770
10771 /****************************************************************
10772  _spoolss_5e
10773 ****************************************************************/
10774
10775 WERROR _spoolss_5e(pipes_struct *p,
10776                    struct spoolss_5e *r)
10777 {
10778         p->rng_fault_state = true;
10779         return WERR_NOT_SUPPORTED;
10780 }
10781
10782 /****************************************************************
10783  _spoolss_5f
10784 ****************************************************************/
10785
10786 WERROR _spoolss_5f(pipes_struct *p,
10787                    struct spoolss_5f *r)
10788 {
10789         p->rng_fault_state = true;
10790         return WERR_NOT_SUPPORTED;
10791 }
10792