s3-spoolss: use pidl for _spoolss_EnumForms.
[jra/samba/.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 void fill_form_1(FORM_1 *form, nt_forms_struct *list)
7248 {
7249         form->flag=list->flag;
7250         init_unistr(&form->name, list->name);
7251         form->width=list->width;
7252         form->length=list->length;
7253         form->left=list->left;
7254         form->top=list->top;
7255         form->right=list->right;
7256         form->bottom=list->bottom;
7257 }
7258
7259 /****************************************************************************
7260 ****************************************************************************/
7261
7262 static WERROR fill_form_info_1(TALLOC_CTX *mem_ctx,
7263                                struct spoolss_FormInfo1 *form,
7264                                nt_forms_struct *list)
7265 {
7266         form->form_name         = talloc_strdup(mem_ctx, list->name);
7267         W_ERROR_HAVE_NO_MEMORY(form->form_name);
7268
7269         form->flags             = list->flag;
7270         form->size.width        = list->width;
7271         form->size.height       = list->length;
7272         form->area.left         = list->left;
7273         form->area.top          = list->top;
7274         form->area.right        = list->right;
7275         form->area.bottom       = list->bottom;
7276
7277         return WERR_OK;
7278 }
7279
7280 /****************************************************************
7281  _spoolss_EnumForms
7282 ****************************************************************/
7283
7284 WERROR _spoolss_EnumForms(pipes_struct *p,
7285                           struct spoolss_EnumForms *r)
7286 {
7287         nt_forms_struct *list=NULL;
7288         nt_forms_struct *builtinlist=NULL;
7289         union spoolss_FormInfo *info;
7290         uint32_t count;
7291         uint32_t numbuiltinforms;
7292         size_t buffer_size = 0;
7293         int i;
7294
7295         *r->out.count = 0;
7296
7297         /* that's an [in out] buffer */
7298
7299         if (!r->in.buffer && (r->in.offered != 0) ) {
7300                 return WERR_INVALID_PARAM;
7301         }
7302
7303         DEBUG(4,("_spoolss_EnumForms\n"));
7304         DEBUGADD(5,("Offered buffer size [%d]\n", r->in.offered));
7305         DEBUGADD(5,("Info level [%d]\n",          r->in.level));
7306
7307         numbuiltinforms = get_builtin_ntforms(&builtinlist);
7308         DEBUGADD(5,("Number of builtin forms [%d]\n",     numbuiltinforms));
7309         count = get_ntforms(&list);
7310         DEBUGADD(5,("Number of user forms [%d]\n",     count));
7311         count += numbuiltinforms;
7312
7313         if (count == 0) {
7314                 SAFE_FREE(builtinlist);
7315                 SAFE_FREE(list);
7316                 return WERR_NO_MORE_ITEMS;
7317         }
7318
7319         info = TALLOC_ARRAY(p->mem_ctx, union spoolss_FormInfo, count);
7320         if (!info) {
7321                 SAFE_FREE(builtinlist);
7322                 SAFE_FREE(list);
7323                 return WERR_NOMEM;
7324         }
7325
7326         switch (r->in.level) {
7327         case 1:
7328                 /* construct the list of form structures */
7329                 for (i=0; i<numbuiltinforms; i++) {
7330                         DEBUGADD(6,("Filling form number [%d]\n",i));
7331                         fill_form_info_1(info, &info[i].info1, &builtinlist[i]);
7332                 }
7333
7334                 SAFE_FREE(builtinlist);
7335
7336                 for (; i<count; i++) {
7337                         DEBUGADD(6,("Filling form number [%d]\n",i));
7338                         fill_form_info_1(info, &info[i].info1, &list[i-numbuiltinforms]);
7339                 }
7340
7341                 SAFE_FREE(list);
7342
7343                 /* check the required size. */
7344                 for (i=0; i<numbuiltinforms; i++) {
7345                         DEBUGADD(6,("adding form [%d]'s size\n",i));
7346                         buffer_size += ndr_size_spoolss_FormInfo1(&info[i].info1, NULL, 0);
7347                 }
7348                 for (; i<count; i++) {
7349                         DEBUGADD(6,("adding form [%d]'s size\n",i));
7350                         buffer_size += ndr_size_spoolss_FormInfo1(&info[i].info1, NULL, 0);
7351                 }
7352
7353                 *r->out.needed = buffer_size;
7354
7355                 if (*r->out.needed > r->in.offered) {
7356                         TALLOC_FREE(info);
7357                         return WERR_INSUFFICIENT_BUFFER;
7358                 }
7359
7360                 *r->out.count = count;
7361                 *r->out.info = info;
7362
7363                 return WERR_OK;
7364
7365         default:
7366                 SAFE_FREE(list);
7367                 SAFE_FREE(builtinlist);
7368                 return WERR_UNKNOWN_LEVEL;
7369         }
7370 }
7371
7372 /****************************************************************
7373  _spoolss_GetForm
7374 ****************************************************************/
7375
7376 WERROR _spoolss_GetForm(pipes_struct *p,
7377                         struct spoolss_GetForm *r)
7378 {
7379         uint32 level = r->in.level;
7380         uint32 offered = r->in.offered;
7381         uint32 *needed = r->out.needed;
7382
7383         nt_forms_struct *list=NULL;
7384         nt_forms_struct builtin_form;
7385         bool foundBuiltin;
7386         union spoolss_FormInfo info;
7387         struct spoolss_FormInfo1 form_1;
7388         int numofforms=0, i=0;
7389
7390         /* that's an [in out] buffer */
7391
7392         if (!r->in.buffer && (offered!=0)) {
7393                 return WERR_INVALID_PARAM;
7394         }
7395
7396         DEBUG(4,("_spoolss_GetForm\n"));
7397         DEBUGADD(5,("Offered buffer size [%d]\n", offered));
7398         DEBUGADD(5,("Info level [%d]\n",          level));
7399
7400         foundBuiltin = get_a_builtin_ntform_by_string(r->in.form_name, &builtin_form);
7401         if (!foundBuiltin) {
7402                 numofforms = get_ntforms(&list);
7403                 DEBUGADD(5,("Number of forms [%d]\n",     numofforms));
7404
7405                 if (numofforms == 0)
7406                         return WERR_BADFID;
7407         }
7408
7409         ZERO_STRUCT(form_1);
7410
7411         switch (level) {
7412         case 1:
7413                 if (foundBuiltin) {
7414                         fill_form_info_1(p->mem_ctx, &form_1, &builtin_form);
7415                 } else {
7416
7417                         /* Check if the requested name is in the list of form structures */
7418                         for (i=0; i<numofforms; i++) {
7419
7420                                 DEBUG(4,("_spoolss_GetForm: checking form %s (want %s)\n",
7421                                         list[i].name, r->in.form_name));
7422
7423                                 if (strequal(r->in.form_name, list[i].name)) {
7424                                         DEBUGADD(6,("Found form %s number [%d]\n",
7425                                                 r->in.form_name, i));
7426                                         fill_form_info_1(p->mem_ctx, &form_1, &list[i]);
7427                                         break;
7428                                 }
7429                         }
7430
7431                         SAFE_FREE(list);
7432                         if (i == numofforms) {
7433                                 return WERR_BADFID;
7434                         }
7435                 }
7436                 /* check the required size. */
7437
7438                 info.info1 = form_1;
7439
7440                 *needed = ndr_size_spoolss_FormInfo(&info, 1, NULL, 0);
7441
7442                 if (*needed > offered) {
7443                         r->out.info = NULL;
7444                         return WERR_INSUFFICIENT_BUFFER;
7445                 }
7446
7447                 r->out.info->info1 = form_1;
7448
7449                 /* fill the buffer with the form structures */
7450                 DEBUGADD(6,("adding form %s [%d] to buffer\n",
7451                         r->in.form_name, i));
7452
7453                 return WERR_OK;
7454
7455         default:
7456                 SAFE_FREE(list);
7457                 return WERR_UNKNOWN_LEVEL;
7458         }
7459 }
7460
7461 /****************************************************************************
7462 ****************************************************************************/
7463
7464 static void fill_port_1(PORT_INFO_1 *port, const char *name)
7465 {
7466         init_unistr(&port->port_name, name);
7467 }
7468
7469 /****************************************************************************
7470  TODO: This probably needs distinguish between TCP/IP and Local ports
7471  somehow.
7472 ****************************************************************************/
7473
7474 static void fill_port_2(PORT_INFO_2 *port, const char *name)
7475 {
7476         init_unistr(&port->port_name, name);
7477         init_unistr(&port->monitor_name, "Local Monitor");
7478         init_unistr(&port->description, SPL_LOCAL_PORT );
7479         port->port_type=PORT_TYPE_WRITE;
7480         port->reserved=0x0;
7481 }
7482
7483
7484 /****************************************************************************
7485  wrapper around the enumer ports command
7486 ****************************************************************************/
7487
7488 WERROR enumports_hook(TALLOC_CTX *ctx, int *count, char ***lines )
7489 {
7490         char *cmd = lp_enumports_cmd();
7491         char **qlines = NULL;
7492         char *command = NULL;
7493         int numlines;
7494         int ret;
7495         int fd;
7496
7497         *count = 0;
7498         *lines = NULL;
7499
7500         /* if no hook then just fill in the default port */
7501
7502         if ( !*cmd ) {
7503                 if (!(qlines = TALLOC_ARRAY( NULL, char*, 2 ))) {
7504                         return WERR_NOMEM;
7505                 }
7506                 if (!(qlines[0] = talloc_strdup(qlines, SAMBA_PRINTER_PORT_NAME ))) {
7507                         TALLOC_FREE(qlines);
7508                         return WERR_NOMEM;
7509                 }
7510                 qlines[1] = NULL;
7511                 numlines = 1;
7512         }
7513         else {
7514                 /* we have a valid enumport command */
7515
7516                 command = talloc_asprintf(ctx, "%s \"%d\"", cmd, 1);
7517                 if (!command) {
7518                         return WERR_NOMEM;
7519                 }
7520
7521                 DEBUG(10,("Running [%s]\n", command));
7522                 ret = smbrun(command, &fd);
7523                 DEBUG(10,("Returned [%d]\n", ret));
7524                 TALLOC_FREE(command);
7525                 if (ret != 0) {
7526                         if (fd != -1) {
7527                                 close(fd);
7528                         }
7529                         return WERR_ACCESS_DENIED;
7530                 }
7531
7532                 numlines = 0;
7533                 qlines = fd_lines_load(fd, &numlines, 0, NULL);
7534                 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
7535                 close(fd);
7536         }
7537
7538         *count = numlines;
7539         *lines = qlines;
7540
7541         return WERR_OK;
7542 }
7543
7544 /****************************************************************************
7545  enumports level 1.
7546 ****************************************************************************/
7547
7548 static WERROR enumports_level_1(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
7549 {
7550         PORT_INFO_1 *ports=NULL;
7551         int i=0;
7552         WERROR result = WERR_OK;
7553         char **qlines = NULL;
7554         int numlines = 0;
7555
7556         result = enumports_hook(talloc_tos(), &numlines, &qlines );
7557         if (!W_ERROR_IS_OK(result)) {
7558                 TALLOC_FREE(qlines);
7559                 return result;
7560         }
7561
7562         if(numlines) {
7563                 if((ports=SMB_MALLOC_ARRAY( PORT_INFO_1, numlines )) == NULL) {
7564                         DEBUG(10,("Returning WERR_NOMEM [%s]\n",
7565                                   win_errstr(WERR_NOMEM)));
7566                         TALLOC_FREE(qlines);
7567                         return WERR_NOMEM;
7568                 }
7569
7570                 for (i=0; i<numlines; i++) {
7571                         DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
7572                         fill_port_1(&ports[i], qlines[i]);
7573                 }
7574         }
7575         TALLOC_FREE(qlines);
7576
7577         *returned = numlines;
7578
7579         /* check the required size. */
7580         for (i=0; i<*returned; i++) {
7581                 DEBUGADD(6,("adding port [%d]'s size\n", i));
7582                 *needed += spoolss_size_port_info_1(&ports[i]);
7583         }
7584
7585         if (*needed > offered) {
7586                 result = WERR_INSUFFICIENT_BUFFER;
7587                 goto out;
7588         }
7589
7590         if (!rpcbuf_alloc_size(buffer, *needed)) {
7591                 result = WERR_NOMEM;
7592                 goto out;
7593         }
7594
7595         /* fill the buffer with the ports structures */
7596         for (i=0; i<*returned; i++) {
7597                 DEBUGADD(6,("adding port [%d] to buffer\n", i));
7598                 smb_io_port_1("", buffer, &ports[i], 0);
7599         }
7600
7601 out:
7602         SAFE_FREE(ports);
7603
7604         if ( !W_ERROR_IS_OK(result) )
7605                 *returned = 0;
7606
7607         return result;
7608 }
7609
7610 /****************************************************************************
7611  enumports level 2.
7612 ****************************************************************************/
7613
7614 static WERROR enumports_level_2(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
7615 {
7616         PORT_INFO_2 *ports=NULL;
7617         int i=0;
7618         WERROR result = WERR_OK;
7619         char **qlines = NULL;
7620         int numlines = 0;
7621
7622         result = enumports_hook(talloc_tos(), &numlines, &qlines );
7623         if ( !W_ERROR_IS_OK(result)) {
7624                 TALLOC_FREE(qlines);
7625                 return result;
7626         }
7627
7628         if(numlines) {
7629                 if((ports=SMB_MALLOC_ARRAY( PORT_INFO_2, numlines)) == NULL) {
7630                         TALLOC_FREE(qlines);
7631                         return WERR_NOMEM;
7632                 }
7633
7634                 for (i=0; i<numlines; i++) {
7635                         DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
7636                         fill_port_2(&(ports[i]), qlines[i]);
7637                 }
7638         }
7639
7640         TALLOC_FREE(qlines);
7641
7642         *returned = numlines;
7643
7644         /* check the required size. */
7645         for (i=0; i<*returned; i++) {
7646                 DEBUGADD(6,("adding port [%d]'s size\n", i));
7647                 *needed += spoolss_size_port_info_2(&ports[i]);
7648         }
7649
7650         if (*needed > offered) {
7651                 result = WERR_INSUFFICIENT_BUFFER;
7652                 goto out;
7653         }
7654
7655         if (!rpcbuf_alloc_size(buffer, *needed)) {
7656                 result = WERR_NOMEM;
7657                 goto out;
7658         }
7659
7660         /* fill the buffer with the ports structures */
7661         for (i=0; i<*returned; i++) {
7662                 DEBUGADD(6,("adding port [%d] to buffer\n", i));
7663                 smb_io_port_2("", buffer, &ports[i], 0);
7664         }
7665
7666 out:
7667         SAFE_FREE(ports);
7668
7669         if ( !W_ERROR_IS_OK(result) )
7670                 *returned = 0;
7671
7672         return result;
7673 }
7674
7675 /****************************************************************************
7676  enumports.
7677 ****************************************************************************/
7678
7679 WERROR _spoolss_enumports( pipes_struct *p, SPOOL_Q_ENUMPORTS *q_u, SPOOL_R_ENUMPORTS *r_u)
7680 {
7681         uint32 level = q_u->level;
7682         RPC_BUFFER *buffer = NULL;
7683         uint32 offered = q_u->offered;
7684         uint32 *needed = &r_u->needed;
7685         uint32 *returned = &r_u->returned;
7686
7687         /* that's an [in out] buffer */
7688
7689         if (!q_u->buffer && (offered!=0)) {
7690                 return WERR_INVALID_PARAM;
7691         }
7692
7693         if (offered > MAX_RPC_DATA_SIZE) {
7694                 return WERR_INVALID_PARAM;
7695         }
7696
7697         rpcbuf_move(q_u->buffer, &r_u->buffer);
7698         buffer = r_u->buffer;
7699
7700         DEBUG(4,("_spoolss_enumports\n"));
7701
7702         *returned=0;
7703         *needed=0;
7704
7705         switch (level) {
7706         case 1:
7707                 return enumports_level_1(buffer, offered, needed, returned);
7708         case 2:
7709                 return enumports_level_2(buffer, offered, needed, returned);
7710         default:
7711                 return WERR_UNKNOWN_LEVEL;
7712         }
7713 }
7714
7715 /****************************************************************************
7716 ****************************************************************************/
7717
7718 static WERROR spoolss_addprinterex_level_2(pipes_struct *p,
7719                                            const char *server,
7720                                            struct spoolss_SetPrinterInfoCtr *info_ctr,
7721                                            struct spoolss_DeviceMode *devmode,
7722                                            struct security_descriptor *sec_desc,
7723                                            struct spoolss_UserLevelCtr *user_ctr,
7724                                            POLICY_HND *handle)
7725 {
7726         NT_PRINTER_INFO_LEVEL *printer = NULL;
7727         fstring name;
7728         int     snum;
7729         WERROR err = WERR_OK;
7730
7731         if ( !(printer = TALLOC_ZERO_P(NULL, NT_PRINTER_INFO_LEVEL)) ) {
7732                 DEBUG(0,("spoolss_addprinterex_level_2: malloc fail.\n"));
7733                 return WERR_NOMEM;
7734         }
7735
7736         /* convert from UNICODE to ASCII - this allocates the info_2 struct inside *printer.*/
7737         if (!convert_printer_info_new(info_ctr, printer)) {
7738                 free_a_printer(&printer, 2);
7739                 return WERR_NOMEM;
7740         }
7741
7742         /* check to see if the printer already exists */
7743
7744         if ((snum = print_queue_snum(printer->info_2->sharename)) != -1) {
7745                 DEBUG(5, ("spoolss_addprinterex_level_2: Attempted to add a printer named [%s] when one already existed!\n",
7746                         printer->info_2->sharename));
7747                 free_a_printer(&printer, 2);
7748                 return WERR_PRINTER_ALREADY_EXISTS;
7749         }
7750
7751         /* FIXME!!!  smbd should check to see if the driver is installed before
7752            trying to add a printer like this  --jerry */
7753
7754         if (*lp_addprinter_cmd() ) {
7755                 if ( !add_printer_hook(p->mem_ctx, p->server_info->ptok,
7756                                        printer) ) {
7757                         free_a_printer(&printer,2);
7758                         return WERR_ACCESS_DENIED;
7759                 }
7760         } else {
7761                 DEBUG(0,("spoolss_addprinterex_level_2: add printer for printer %s called and no"
7762                         "smb.conf parameter \"addprinter command\" is defined. This"
7763                         "parameter must exist for this call to succeed\n",
7764                         printer->info_2->sharename ));
7765         }
7766
7767         /* use our primary netbios name since get_a_printer() will convert
7768            it to what the client expects on a case by case basis */
7769
7770         slprintf(name, sizeof(name)-1, "\\\\%s\\%s", global_myname(),
7771              printer->info_2->sharename);
7772
7773
7774         if ((snum = print_queue_snum(printer->info_2->sharename)) == -1) {
7775                 free_a_printer(&printer,2);
7776                 return WERR_ACCESS_DENIED;
7777         }
7778
7779         /* you must be a printer admin to add a new printer */
7780         if (!print_access_check(NULL, snum, PRINTER_ACCESS_ADMINISTER)) {
7781                 free_a_printer(&printer,2);
7782                 return WERR_ACCESS_DENIED;
7783         }
7784
7785         /*
7786          * Do sanity check on the requested changes for Samba.
7787          */
7788
7789         if (!check_printer_ok(printer->info_2, snum)) {
7790                 free_a_printer(&printer,2);
7791                 return WERR_INVALID_PARAM;
7792         }
7793
7794         /*
7795          * When a printer is created, the drivername bound to the printer is used
7796          * to lookup previously saved driver initialization info, which is then
7797          * bound to the new printer, simulating what happens in the Windows arch.
7798          */
7799
7800         if (!devmode)
7801         {
7802                 set_driver_init(printer, 2);
7803         }
7804         else
7805         {
7806                 /* A valid devmode was included, convert and link it
7807                 */
7808                 DEBUGADD(10, ("spoolss_addprinterex_level_2: devmode included, converting\n"));
7809
7810                 if (!convert_devicemode_new(printer->info_2->printername,
7811                                             devmode,
7812                                             &printer->info_2->devmode))
7813                         return  WERR_NOMEM;
7814         }
7815
7816         /* write the ASCII on disk */
7817         err = mod_a_printer(printer, 2);
7818         if (!W_ERROR_IS_OK(err)) {
7819                 free_a_printer(&printer,2);
7820                 return err;
7821         }
7822
7823         if (!open_printer_hnd(p, handle, name, PRINTER_ACCESS_ADMINISTER)) {
7824                 /* Handle open failed - remove addition. */
7825                 del_a_printer(printer->info_2->sharename);
7826                 free_a_printer(&printer,2);
7827                 ZERO_STRUCTP(handle);
7828                 return WERR_ACCESS_DENIED;
7829         }
7830
7831         update_c_setprinter(False);
7832         free_a_printer(&printer,2);
7833
7834         return WERR_OK;
7835 }
7836
7837 /****************************************************************
7838  _spoolss_AddPrinterEx
7839 ****************************************************************/
7840
7841 WERROR _spoolss_AddPrinterEx(pipes_struct *p,
7842                              struct spoolss_AddPrinterEx *r)
7843 {
7844         switch (r->in.info_ctr->level) {
7845         case 1:
7846                 /* we don't handle yet */
7847                 /* but I know what to do ... */
7848                 return WERR_UNKNOWN_LEVEL;
7849         case 2:
7850                 return spoolss_addprinterex_level_2(p, r->in.server,
7851                                                     r->in.info_ctr,
7852                                                     r->in.devmode_ctr->devmode,
7853                                                     r->in.secdesc_ctr->sd,
7854                                                     r->in.userlevel_ctr,
7855                                                     r->out.handle);
7856         default:
7857                 return WERR_UNKNOWN_LEVEL;
7858         }
7859 }
7860
7861 /****************************************************************
7862  _spoolss_AddPrinterDriver
7863 ****************************************************************/
7864
7865 WERROR _spoolss_AddPrinterDriver(pipes_struct *p,
7866                                  struct spoolss_AddPrinterDriver *r)
7867 {
7868         uint32_t level = r->in.info_ctr->level;
7869         struct spoolss_AddDriverInfoCtr *info = r->in.info_ctr;
7870         WERROR err = WERR_OK;
7871         NT_PRINTER_DRIVER_INFO_LEVEL driver;
7872         fstring driver_name;
7873         uint32 version;
7874         const char *fn;
7875
7876         switch (p->hdr_req.opnum) {
7877                 case NDR_SPOOLSS_ADDPRINTERDRIVER:
7878                         fn = "_spoolss_AddPrinterDriver";
7879                         break;
7880                 case NDR_SPOOLSS_ADDPRINTERDRIVEREX:
7881                         fn = "_spoolss_AddPrinterDriverEx";
7882                         break;
7883                 default:
7884                         return WERR_INVALID_PARAM;
7885         }
7886
7887
7888         /* FIXME */
7889         if (level != 3 && level != 6) {
7890                 /* Clever hack from Martin Zielinski <mz@seh.de>
7891                  * to allow downgrade from level 8 (Vista).
7892                  */
7893                 DEBUG(0,("%s: level %d not yet implemented\n", fn, level));
7894                 return WERR_UNKNOWN_LEVEL;
7895         }
7896
7897         ZERO_STRUCT(driver);
7898
7899         if (!convert_printer_driver_info(info, &driver, level)) {
7900                 err = WERR_NOMEM;
7901                 goto done;
7902         }
7903
7904         DEBUG(5,("Cleaning driver's information\n"));
7905         err = clean_up_driver_struct(p, driver, level);
7906         if (!W_ERROR_IS_OK(err))
7907                 goto done;
7908
7909         DEBUG(5,("Moving driver to final destination\n"));
7910         if( !W_ERROR_IS_OK(err = move_driver_to_download_area(p, driver, level,
7911                                                               &err)) ) {
7912                 goto done;
7913         }
7914
7915         if (add_a_printer_driver(driver, level)!=0) {
7916                 err = WERR_ACCESS_DENIED;
7917                 goto done;
7918         }
7919
7920         switch(level) {
7921         case 3:
7922                 fstrcpy(driver_name,
7923                         driver.info_3->name ? driver.info_3->name : "");
7924                 break;
7925         case 6:
7926                 fstrcpy(driver_name,
7927                         driver.info_6->name ?  driver.info_6->name : "");
7928                 break;
7929         }
7930
7931         /*
7932          * I think this is where he DrvUpgradePrinter() hook would be
7933          * be called in a driver's interface DLL on a Windows NT 4.0/2k
7934          * server.  Right now, we just need to send ourselves a message
7935          * to update each printer bound to this driver.   --jerry
7936          */
7937
7938         if (!srv_spoolss_drv_upgrade_printer(driver_name)) {
7939                 DEBUG(0,("%s: Failed to send message about upgrading driver [%s]!\n",
7940                         fn, driver_name));
7941         }
7942
7943         /*
7944          * Based on the version (e.g. driver destination dir: 0=9x,2=Nt/2k,3=2k/Xp),
7945          * decide if the driver init data should be deleted. The rules are:
7946          *  1) never delete init data if it is a 9x driver, they don't use it anyway
7947          *  2) delete init data only if there is no 2k/Xp driver
7948          *  3) always delete init data
7949          * The generalized rule is always use init data from the highest order driver.
7950          * It is necessary to follow the driver install by an initialization step to
7951          * finish off this process.
7952         */
7953         if (level == 3)
7954                 version = driver.info_3->cversion;
7955         else if (level == 6)
7956                 version = driver.info_6->version;
7957         else
7958                 version = -1;
7959         switch (version) {
7960                 /*
7961                  * 9x printer driver - never delete init data
7962                 */
7963                 case 0:
7964                         DEBUG(10,("%s: init data not deleted for 9x driver [%s]\n",
7965                                 fn, driver_name));
7966                         break;
7967
7968                 /*
7969                  * Nt or 2k (compatiblity mode) printer driver - only delete init data if
7970                  * there is no 2k/Xp driver init data for this driver name.
7971                 */
7972                 case 2:
7973                 {
7974                         NT_PRINTER_DRIVER_INFO_LEVEL driver1;
7975
7976                         if (!W_ERROR_IS_OK(get_a_printer_driver(&driver1, 3, driver_name, "Windows NT x86", 3))) {
7977                                 /*
7978                                  * No 2k/Xp driver found, delete init data (if any) for the new Nt driver.
7979                                 */
7980                                 if (!del_driver_init(driver_name))
7981                                         DEBUG(6,("%s: del_driver_init(%s) Nt failed!\n",
7982                                                 fn, driver_name));
7983                         } else {
7984                                 /*
7985                                  * a 2k/Xp driver was found, don't delete init data because Nt driver will use it.
7986                                 */
7987                                 free_a_printer_driver(driver1,3);
7988                                 DEBUG(10,("%s: init data not deleted for Nt driver [%s]\n",
7989                                         fn, driver_name));
7990                         }
7991                 }
7992                 break;
7993
7994                 /*
7995                  * 2k or Xp printer driver - always delete init data
7996                 */
7997                 case 3:
7998                         if (!del_driver_init(driver_name))
7999                                 DEBUG(6,("%s: del_driver_init(%s) 2k/Xp failed!\n",
8000                                         fn, driver_name));
8001                         break;
8002
8003                 default:
8004                         DEBUG(0,("%s: invalid level=%d\n", fn, level));
8005                         break;
8006         }
8007
8008
8009 done:
8010         free_a_printer_driver(driver, level);
8011         return err;
8012 }
8013
8014 /****************************************************************
8015  _spoolss_AddPrinterDriverEx
8016 ****************************************************************/
8017
8018 WERROR _spoolss_AddPrinterDriverEx(pipes_struct *p,
8019                                    struct spoolss_AddPrinterDriverEx *r)
8020 {
8021         struct spoolss_AddPrinterDriver a;
8022
8023         /*
8024          * we only support the semantics of AddPrinterDriver()
8025          * i.e. only copy files that are newer than existing ones
8026          */
8027
8028         if (r->in.flags != APD_COPY_NEW_FILES) {
8029                 return WERR_ACCESS_DENIED;
8030         }
8031
8032         a.in.servername         = r->in.servername;
8033         a.in.info_ctr           = r->in.info_ctr;
8034
8035         return _spoolss_AddPrinterDriver(p, &a);
8036 }
8037
8038 /****************************************************************************
8039 ****************************************************************************/
8040
8041 struct _spoolss_paths {
8042         int type;
8043         const char *share;
8044         const char *dir;
8045 };
8046
8047 enum { SPOOLSS_DRIVER_PATH, SPOOLSS_PRTPROCS_PATH };
8048
8049 static const struct _spoolss_paths spoolss_paths[]= {
8050         { SPOOLSS_DRIVER_PATH,          "print$",       "DRIVERS" },
8051         { SPOOLSS_PRTPROCS_PATH,        "prnproc$",     "PRTPROCS" }
8052 };
8053
8054 static WERROR compose_spoolss_server_path(TALLOC_CTX *mem_ctx,
8055                                           const char *servername,
8056                                           const char *environment,
8057                                           int component,
8058                                           char **path)
8059 {
8060         const char *pservername = NULL;
8061         const char *long_archi = SPOOLSS_ARCHITECTURE_NT_X86;
8062         const char *short_archi;
8063
8064         *path = NULL;
8065
8066         /* environment may be empty */
8067         if (environment && strlen(environment)) {
8068                 long_archi = environment;
8069         }
8070
8071         /* servername may be empty */
8072         if (servername && strlen(servername)) {
8073                 pservername = canon_servername(servername);
8074
8075                 if (!is_myname_or_ipaddr(pservername)) {
8076                         return WERR_INVALID_PARAM;
8077                 }
8078         }
8079
8080         if (!(short_archi = get_short_archi(long_archi))) {
8081                 return WERR_INVALID_ENVIRONMENT;
8082         }
8083
8084         switch (component) {
8085         case SPOOLSS_PRTPROCS_PATH:
8086         case SPOOLSS_DRIVER_PATH:
8087                 if (pservername) {
8088                         *path = talloc_asprintf(mem_ctx,
8089                                         "\\\\%s\\%s\\%s",
8090                                         pservername,
8091                                         spoolss_paths[component].share,
8092                                         short_archi);
8093                 } else {
8094                         *path = talloc_asprintf(mem_ctx, "%s\\%s\\%s",
8095                                         SPOOLSS_DEFAULT_SERVER_PATH,
8096                                         spoolss_paths[component].dir,
8097                                         short_archi);
8098                 }
8099                 break;
8100         default:
8101                 return WERR_INVALID_PARAM;
8102         }
8103
8104         if (!*path) {
8105                 return WERR_NOMEM;
8106         }
8107
8108         return WERR_OK;
8109 }
8110
8111 /****************************************************************************
8112 ****************************************************************************/
8113
8114 static WERROR getprinterdriverdir_level_1(TALLOC_CTX *mem_ctx,
8115                                           const char *servername,
8116                                           const char *environment,
8117                                           struct spoolss_DriverDirectoryInfo1 *r,
8118                                           uint32_t offered,
8119                                           uint32_t *needed)
8120 {
8121         WERROR werr;
8122         char *path = NULL;
8123
8124         werr = compose_spoolss_server_path(mem_ctx,
8125                                            servername,
8126                                            environment,
8127                                            SPOOLSS_DRIVER_PATH,
8128                                            &path);
8129         if (!W_ERROR_IS_OK(werr)) {
8130                 return werr;
8131         }
8132
8133         DEBUG(4,("printer driver directory: [%s]\n", path));
8134
8135         r->directory_name = path;
8136
8137         *needed += ndr_size_spoolss_DriverDirectoryInfo1(r, NULL, 0);
8138
8139         if (*needed > offered) {
8140                 talloc_free(path);
8141                 return WERR_INSUFFICIENT_BUFFER;
8142         }
8143
8144         return WERR_OK;
8145 }
8146
8147 /****************************************************************
8148  _spoolss_GetPrinterDriverDirectory
8149 ****************************************************************/
8150
8151 WERROR _spoolss_GetPrinterDriverDirectory(pipes_struct *p,
8152                                           struct spoolss_GetPrinterDriverDirectory *r)
8153 {
8154         WERROR werror;
8155
8156         /* that's an [in out] buffer */
8157
8158         if (!r->in.buffer && (r->in.offered != 0)) {
8159                 return WERR_INVALID_PARAM;
8160         }
8161
8162         DEBUG(5,("_spoolss_GetPrinterDriverDirectory: level %d\n",
8163                 r->in.level));
8164
8165         *r->out.needed = 0;
8166
8167         /* r->in.level is ignored */
8168
8169         werror = getprinterdriverdir_level_1(p->mem_ctx,
8170                                              r->in.server,
8171                                              r->in.environment,
8172                                              &r->out.info->info1,
8173                                              r->in.offered,
8174                                              r->out.needed);
8175         if (!W_ERROR_IS_OK(werror)) {
8176                 TALLOC_FREE(r->out.info);
8177         }
8178
8179         return werror;
8180 }
8181
8182 /****************************************************************************
8183 ****************************************************************************/
8184
8185 WERROR _spoolss_enumprinterdata(pipes_struct *p, SPOOL_Q_ENUMPRINTERDATA *q_u, SPOOL_R_ENUMPRINTERDATA *r_u)
8186 {
8187         POLICY_HND *handle = &q_u->handle;
8188         uint32 idx               = q_u->index;
8189         uint32 in_value_len      = q_u->valuesize;
8190         uint32 in_data_len       = q_u->datasize;
8191         uint32 *out_max_value_len = &r_u->valuesize;
8192         uint16 **out_value       = &r_u->value;
8193         uint32 *out_value_len    = &r_u->realvaluesize;
8194         uint32 *out_type         = &r_u->type;
8195         uint32 *out_max_data_len = &r_u->datasize;
8196         uint8  **data_out        = &r_u->data;
8197         uint32 *out_data_len     = &r_u->realdatasize;
8198
8199         NT_PRINTER_INFO_LEVEL *printer = NULL;
8200
8201         uint32          biggest_valuesize;
8202         uint32          biggest_datasize;
8203         uint32          data_len;
8204         Printer_entry   *Printer = find_printer_index_by_hnd(p, handle);
8205         int             snum;
8206         WERROR          result;
8207         REGISTRY_VALUE  *val = NULL;
8208         NT_PRINTER_DATA *p_data;
8209         int             i, key_index, num_values;
8210         int             name_length;
8211
8212         *out_type = 0;
8213
8214         *out_max_data_len = 0;
8215         *data_out         = NULL;
8216         *out_data_len     = 0;
8217
8218         DEBUG(5,("spoolss_enumprinterdata\n"));
8219
8220         if (!Printer) {
8221                 DEBUG(2,("_spoolss_enumprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8222                 return WERR_BADFID;
8223         }
8224
8225         if (!get_printer_snum(p,handle, &snum, NULL))
8226                 return WERR_BADFID;
8227
8228         result = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8229         if (!W_ERROR_IS_OK(result))
8230                 return result;
8231
8232         p_data = printer->info_2->data;
8233         key_index = lookup_printerkey( p_data, SPOOL_PRINTERDATA_KEY );
8234
8235         result = WERR_OK;
8236
8237         /*
8238          * The NT machine wants to know the biggest size of value and data
8239          *
8240          * cf: MSDN EnumPrinterData remark section
8241          */
8242
8243         if ( !in_value_len && !in_data_len && (key_index != -1) )
8244         {
8245                 DEBUGADD(6,("Activating NT mega-hack to find sizes\n"));
8246
8247                 biggest_valuesize = 0;
8248                 biggest_datasize  = 0;
8249
8250                 num_values = regval_ctr_numvals( p_data->keys[key_index].values );
8251
8252                 for ( i=0; i<num_values; i++ )
8253                 {
8254                         val = regval_ctr_specific_value( p_data->keys[key_index].values, i );
8255
8256                         name_length = strlen(val->valuename);
8257                         if ( strlen(val->valuename) > biggest_valuesize )
8258                                 biggest_valuesize = name_length;
8259
8260                         if ( val->size > biggest_datasize )
8261                                 biggest_datasize = val->size;
8262
8263                         DEBUG(6,("current values: [%d], [%d]\n", biggest_valuesize,
8264                                 biggest_datasize));
8265                 }
8266
8267                 /* the value is an UNICODE string but real_value_size is the length
8268                    in bytes including the trailing 0 */
8269
8270                 *out_value_len = 2 * (1+biggest_valuesize);
8271                 *out_data_len  = biggest_datasize;
8272
8273                 DEBUG(6,("final values: [%d], [%d]\n", *out_value_len, *out_data_len));
8274
8275                 goto done;
8276         }
8277
8278         /*
8279          * the value len is wrong in NT sp3
8280          * that's the number of bytes not the number of unicode chars
8281          */
8282
8283         if ( key_index != -1 )
8284                 val = regval_ctr_specific_value( p_data->keys[key_index].values, idx );
8285
8286         if ( !val )
8287         {
8288
8289                 /* out_value should default to "" or else NT4 has
8290                    problems unmarshalling the response */
8291
8292                 *out_max_value_len=(in_value_len/sizeof(uint16));
8293
8294                 if (in_value_len) {
8295                         if((*out_value=(uint16 *)TALLOC_ZERO(p->mem_ctx, in_value_len*sizeof(uint8))) == NULL)
8296                         {
8297                                 result = WERR_NOMEM;
8298                                 goto done;
8299                         }
8300                         *out_value_len = (uint32)rpcstr_push((char *)*out_value, "", in_value_len, 0);
8301                 } else {
8302                         *out_value=NULL;
8303                         *out_value_len = 0;
8304                 }
8305
8306                 /* the data is counted in bytes */
8307
8308                 *out_max_data_len = in_data_len;
8309                 *out_data_len     = in_data_len;
8310
8311                 /* only allocate when given a non-zero data_len */
8312
8313                 if ( in_data_len && ((*data_out=(uint8 *)TALLOC_ZERO(p->mem_ctx, in_data_len*sizeof(uint8))) == NULL) )
8314                 {
8315                         result = WERR_NOMEM;
8316                         goto done;
8317                 }
8318
8319                 result = WERR_NO_MORE_ITEMS;
8320         }
8321         else
8322         {
8323                 /*
8324                  * the value is:
8325                  * - counted in bytes in the request
8326                  * - counted in UNICODE chars in the max reply
8327                  * - counted in bytes in the real size
8328                  *
8329                  * take a pause *before* coding not *during* coding
8330                  */
8331
8332                 /* name */
8333                 *out_max_value_len=(in_value_len/sizeof(uint16));
8334                 if (in_value_len) {
8335                         if ( (*out_value = (uint16 *)TALLOC_ZERO(p->mem_ctx, in_value_len*sizeof(uint8))) == NULL )
8336                         {
8337                                 result = WERR_NOMEM;
8338                                 goto done;
8339                         }
8340
8341                         *out_value_len = (uint32)rpcstr_push((char *)*out_value, regval_name(val), (size_t)in_value_len, 0);
8342                 } else {
8343                         *out_value = NULL;
8344                         *out_value_len = 0;
8345                 }
8346
8347                 /* type */
8348
8349                 *out_type = regval_type( val );
8350
8351                 /* data - counted in bytes */
8352
8353                 *out_max_data_len = in_data_len;
8354                 if ( in_data_len && (*data_out = (uint8 *)TALLOC_ZERO(p->mem_ctx, in_data_len*sizeof(uint8))) == NULL)
8355                 {
8356                         result = WERR_NOMEM;
8357                         goto done;
8358                 }
8359                 data_len = regval_size(val);
8360                 if ( *data_out && data_len )
8361                         memcpy( *data_out, regval_data_p(val), data_len );
8362                 *out_data_len = data_len;
8363         }
8364
8365 done:
8366         free_a_printer(&printer, 2);
8367         return result;
8368 }
8369
8370 /****************************************************************************
8371 ****************************************************************************/
8372
8373 WERROR _spoolss_setprinterdata( pipes_struct *p, SPOOL_Q_SETPRINTERDATA *q_u, SPOOL_R_SETPRINTERDATA *r_u)
8374 {
8375         POLICY_HND              *handle = &q_u->handle;
8376         UNISTR2                 *value = &q_u->value;
8377         uint32                  type = q_u->type;
8378         uint8                   *data = q_u->data;
8379         uint32                  real_len = q_u->real_len;
8380
8381         NT_PRINTER_INFO_LEVEL   *printer = NULL;
8382         int                     snum=0;
8383         WERROR                  status = WERR_OK;
8384         Printer_entry           *Printer=find_printer_index_by_hnd(p, handle);
8385         fstring                 valuename;
8386
8387         DEBUG(5,("spoolss_setprinterdata\n"));
8388
8389         if (!Printer) {
8390                 DEBUG(2,("_spoolss_setprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8391                 return WERR_BADFID;
8392         }
8393
8394         if ( Printer->printer_type == SPLHND_SERVER ) {
8395                 DEBUG(10,("_spoolss_setprinterdata: Not implemented for server handles yet\n"));
8396                 return WERR_INVALID_PARAM;
8397         }
8398
8399         if (!get_printer_snum(p,handle, &snum, NULL))
8400                 return WERR_BADFID;
8401
8402         /*
8403          * Access check : NT returns "access denied" if you make a
8404          * SetPrinterData call without the necessary privildge.
8405          * we were originally returning OK if nothing changed
8406          * which made Win2k issue **a lot** of SetPrinterData
8407          * when connecting to a printer  --jerry
8408          */
8409
8410         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER)
8411         {
8412                 DEBUG(3, ("_spoolss_setprinterdata: change denied by handle access permissions\n"));
8413                 status = WERR_ACCESS_DENIED;
8414                 goto done;
8415         }
8416
8417         status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8418         if (!W_ERROR_IS_OK(status))
8419                 return status;
8420
8421         unistr2_to_ascii(valuename, value, sizeof(valuename));
8422
8423         /*
8424          * When client side code sets a magic printer data key, detect it and save
8425          * the current printer data and the magic key's data (its the DEVMODE) for
8426          * future printer/driver initializations.
8427          */
8428         if ( (type == REG_BINARY) && strequal( valuename, PHANTOM_DEVMODE_KEY))
8429         {
8430                 /* Set devmode and printer initialization info */
8431                 status = save_driver_init( printer, 2, data, real_len );
8432
8433                 srv_spoolss_reset_printerdata( printer->info_2->drivername );
8434         }
8435         else
8436         {
8437         status = set_printer_dataex( printer, SPOOL_PRINTERDATA_KEY, valuename,
8438                                         type, data, real_len );
8439                 if ( W_ERROR_IS_OK(status) )
8440                         status = mod_a_printer(printer, 2);
8441         }
8442
8443 done:
8444         free_a_printer(&printer, 2);
8445
8446         return status;
8447 }
8448
8449 /****************************************************************
8450  _spoolss_ResetPrinter
8451 ****************************************************************/
8452
8453 WERROR _spoolss_ResetPrinter(pipes_struct *p,
8454                              struct spoolss_ResetPrinter *r)
8455 {
8456         POLICY_HND      *handle = r->in.handle;
8457         Printer_entry   *Printer=find_printer_index_by_hnd(p, handle);
8458         int             snum;
8459
8460         DEBUG(5,("_spoolss_ResetPrinter\n"));
8461
8462         /*
8463          * All we do is to check to see if the handle and queue is valid.
8464          * This call really doesn't mean anything to us because we only
8465          * support RAW printing.   --jerry
8466          */
8467
8468         if (!Printer) {
8469                 DEBUG(2,("_spoolss_ResetPrinter: Invalid handle (%s:%u:%u).\n",
8470                         OUR_HANDLE(handle)));
8471                 return WERR_BADFID;
8472         }
8473
8474         if (!get_printer_snum(p,handle, &snum, NULL))
8475                 return WERR_BADFID;
8476
8477
8478         /* blindly return success */
8479         return WERR_OK;
8480 }
8481
8482 /****************************************************************
8483  _spoolss_DeletePrinterData
8484 ****************************************************************/
8485
8486 WERROR _spoolss_DeletePrinterData(pipes_struct *p,
8487                                   struct spoolss_DeletePrinterData *r)
8488 {
8489         POLICY_HND      *handle = r->in.handle;
8490         NT_PRINTER_INFO_LEVEL   *printer = NULL;
8491         int             snum=0;
8492         WERROR          status = WERR_OK;
8493         Printer_entry   *Printer=find_printer_index_by_hnd(p, handle);
8494
8495         DEBUG(5,("_spoolss_DeletePrinterData\n"));
8496
8497         if (!Printer) {
8498                 DEBUG(2,("_spoolss_DeletePrinterData: Invalid handle (%s:%u:%u).\n",
8499                         OUR_HANDLE(handle)));
8500                 return WERR_BADFID;
8501         }
8502
8503         if (!get_printer_snum(p, handle, &snum, NULL))
8504                 return WERR_BADFID;
8505
8506         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
8507                 DEBUG(3, ("_spoolss_DeletePrinterData: "
8508                         "printer properties change denied by handle\n"));
8509                 return WERR_ACCESS_DENIED;
8510         }
8511
8512         status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8513         if (!W_ERROR_IS_OK(status))
8514                 return status;
8515
8516         if (!r->in.value_name) {
8517                 free_a_printer(&printer, 2);
8518                 return WERR_NOMEM;
8519         }
8520
8521         status = delete_printer_dataex( printer, SPOOL_PRINTERDATA_KEY,
8522                                         r->in.value_name );
8523
8524         if ( W_ERROR_IS_OK(status) )
8525                 mod_a_printer( printer, 2 );
8526
8527         free_a_printer(&printer, 2);
8528
8529         return status;
8530 }
8531
8532 /****************************************************************
8533  _spoolss_AddForm
8534 ****************************************************************/
8535
8536 WERROR _spoolss_AddForm(pipes_struct *p,
8537                         struct spoolss_AddForm *r)
8538 {
8539         POLICY_HND *handle = r->in.handle;
8540         struct spoolss_AddFormInfo1 *form = r->in.info.info1;
8541         nt_forms_struct tmpForm;
8542         int snum;
8543         WERROR status = WERR_OK;
8544         NT_PRINTER_INFO_LEVEL *printer = NULL;
8545
8546         int count=0;
8547         nt_forms_struct *list=NULL;
8548         Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8549
8550         DEBUG(5,("_spoolss_AddForm\n"));
8551
8552         if (!Printer) {
8553                 DEBUG(2,("_spoolss_AddForm: Invalid handle (%s:%u:%u).\n",
8554                         OUR_HANDLE(handle)));
8555                 return WERR_BADFID;
8556         }
8557
8558
8559         /* forms can be added on printer of on the print server handle */
8560
8561         if ( Printer->printer_type == SPLHND_PRINTER )
8562         {
8563                 if (!get_printer_snum(p,handle, &snum, NULL))
8564                         return WERR_BADFID;
8565
8566                 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8567                 if (!W_ERROR_IS_OK(status))
8568                         goto done;
8569         }
8570
8571         if ( !(Printer->access_granted & (PRINTER_ACCESS_ADMINISTER|SERVER_ACCESS_ADMINISTER)) ) {
8572                 DEBUG(2,("_spoolss_addform: denied by handle permissions.\n"));
8573                 status = WERR_ACCESS_DENIED;
8574                 goto done;
8575         }
8576
8577         /* can't add if builtin */
8578
8579         if (get_a_builtin_ntform_by_string(form->form_name, &tmpForm)) {
8580                 status = WERR_FILE_EXISTS;
8581                 goto done;
8582         }
8583
8584         count = get_ntforms(&list);
8585
8586         if(!add_a_form(&list, form, &count)) {
8587                 status =  WERR_NOMEM;
8588                 goto done;
8589         }
8590
8591         write_ntforms(&list, count);
8592
8593         /*
8594          * ChangeID must always be set if this is a printer
8595          */
8596
8597         if ( Printer->printer_type == SPLHND_PRINTER )
8598                 status = mod_a_printer(printer, 2);
8599
8600 done:
8601         if ( printer )
8602                 free_a_printer(&printer, 2);
8603         SAFE_FREE(list);
8604
8605         return status;
8606 }
8607
8608 /****************************************************************
8609  _spoolss_DeleteForm
8610 ****************************************************************/
8611
8612 WERROR _spoolss_DeleteForm(pipes_struct *p,
8613                            struct spoolss_DeleteForm *r)
8614 {
8615         POLICY_HND *handle = r->in.handle;
8616         const char *form_name = r->in.form_name;
8617         nt_forms_struct tmpForm;
8618         int count=0;
8619         nt_forms_struct *list=NULL;
8620         Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8621         int snum;
8622         WERROR status = WERR_OK;
8623         NT_PRINTER_INFO_LEVEL *printer = NULL;
8624
8625         DEBUG(5,("_spoolss_DeleteForm\n"));
8626
8627         if (!Printer) {
8628                 DEBUG(2,("_spoolss_DeleteForm: Invalid handle (%s:%u:%u).\n",
8629                         OUR_HANDLE(handle)));
8630                 return WERR_BADFID;
8631         }
8632
8633         /* forms can be deleted on printer of on the print server handle */
8634
8635         if ( Printer->printer_type == SPLHND_PRINTER )
8636         {
8637                 if (!get_printer_snum(p,handle, &snum, NULL))
8638                         return WERR_BADFID;
8639
8640                 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8641                 if (!W_ERROR_IS_OK(status))
8642                         goto done;
8643         }
8644
8645         if ( !(Printer->access_granted & (PRINTER_ACCESS_ADMINISTER|SERVER_ACCESS_ADMINISTER)) ) {
8646                 DEBUG(2,("_spoolss_DeleteForm: denied by handle permissions.\n"));
8647                 status = WERR_ACCESS_DENIED;
8648                 goto done;
8649         }
8650
8651         /* can't delete if builtin */
8652
8653         if (get_a_builtin_ntform_by_string(form_name,&tmpForm)) {
8654                 status = WERR_INVALID_PARAM;
8655                 goto done;
8656         }
8657
8658         count = get_ntforms(&list);
8659
8660         if ( !delete_a_form(&list, form_name, &count, &status ))
8661                 goto done;
8662
8663         /*
8664          * ChangeID must always be set if this is a printer
8665          */
8666
8667         if ( Printer->printer_type == SPLHND_PRINTER )
8668                 status = mod_a_printer(printer, 2);
8669
8670 done:
8671         if ( printer )
8672                 free_a_printer(&printer, 2);
8673         SAFE_FREE(list);
8674
8675         return status;
8676 }
8677
8678 /****************************************************************
8679  _spoolss_SetForm
8680 ****************************************************************/
8681
8682 WERROR _spoolss_SetForm(pipes_struct *p,
8683                         struct spoolss_SetForm *r)
8684 {
8685         POLICY_HND *handle = r->in.handle;
8686         struct spoolss_AddFormInfo1 *form = r->in.info.info1;
8687         nt_forms_struct tmpForm;
8688         int snum;
8689         WERROR status = WERR_OK;
8690         NT_PRINTER_INFO_LEVEL *printer = NULL;
8691
8692         int count=0;
8693         nt_forms_struct *list=NULL;
8694         Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8695
8696         DEBUG(5,("_spoolss_SetForm\n"));
8697
8698         if (!Printer) {
8699                 DEBUG(2,("_spoolss_SetForm: Invalid handle (%s:%u:%u).\n",
8700                         OUR_HANDLE(handle)));
8701                 return WERR_BADFID;
8702         }
8703
8704         /* forms can be modified on printer of on the print server handle */
8705
8706         if ( Printer->printer_type == SPLHND_PRINTER )
8707         {
8708                 if (!get_printer_snum(p,handle, &snum, NULL))
8709                         return WERR_BADFID;
8710
8711                 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8712                 if (!W_ERROR_IS_OK(status))
8713                         goto done;
8714         }
8715
8716         if ( !(Printer->access_granted & (PRINTER_ACCESS_ADMINISTER|SERVER_ACCESS_ADMINISTER)) ) {
8717                 DEBUG(2,("_spoolss_SetForm: denied by handle permissions\n"));
8718                 status = WERR_ACCESS_DENIED;
8719                 goto done;
8720         }
8721
8722         /* can't set if builtin */
8723         if (get_a_builtin_ntform_by_string(form->form_name, &tmpForm)) {
8724                 status = WERR_INVALID_PARAM;
8725                 goto done;
8726         }
8727
8728         count = get_ntforms(&list);
8729         update_a_form(&list, form, count);
8730         write_ntforms(&list, count);
8731
8732         /*
8733          * ChangeID must always be set if this is a printer
8734          */
8735
8736         if ( Printer->printer_type == SPLHND_PRINTER )
8737                 status = mod_a_printer(printer, 2);
8738
8739
8740 done:
8741         if ( printer )
8742                 free_a_printer(&printer, 2);
8743         SAFE_FREE(list);
8744
8745         return status;
8746 }
8747
8748 /****************************************************************************
8749  enumprintprocessors level 1.
8750 ****************************************************************************/
8751
8752 static WERROR enumprintprocessors_level_1(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
8753 {
8754         PRINTPROCESSOR_1 *info_1=NULL;
8755         WERROR result = WERR_OK;
8756
8757         if((info_1 = SMB_MALLOC_P(PRINTPROCESSOR_1)) == NULL)
8758                 return WERR_NOMEM;
8759
8760         (*returned) = 0x1;
8761
8762         init_unistr(&info_1->name, "winprint");
8763
8764         *needed += spoolss_size_printprocessor_info_1(info_1);
8765
8766         if (*needed > offered) {
8767                 result = WERR_INSUFFICIENT_BUFFER;
8768                 goto out;
8769         }
8770
8771         if (!rpcbuf_alloc_size(buffer, *needed)) {
8772                 result = WERR_NOMEM;
8773                 goto out;
8774         }
8775
8776         smb_io_printprocessor_info_1("", buffer, info_1, 0);
8777
8778 out:
8779         SAFE_FREE(info_1);
8780
8781         if ( !W_ERROR_IS_OK(result) )
8782                 *returned = 0;
8783
8784         return result;
8785 }
8786
8787 /****************************************************************************
8788 ****************************************************************************/
8789
8790 WERROR _spoolss_enumprintprocessors(pipes_struct *p, SPOOL_Q_ENUMPRINTPROCESSORS *q_u, SPOOL_R_ENUMPRINTPROCESSORS *r_u)
8791 {
8792         uint32 level = q_u->level;
8793         RPC_BUFFER *buffer = NULL;
8794         uint32 offered = q_u->offered;
8795         uint32 *needed = &r_u->needed;
8796         uint32 *returned = &r_u->returned;
8797
8798         /* that's an [in out] buffer */
8799
8800         if (!q_u->buffer && (offered!=0)) {
8801                 return WERR_INVALID_PARAM;
8802         }
8803
8804         if (offered > MAX_RPC_DATA_SIZE) {
8805                 return WERR_INVALID_PARAM;
8806         }
8807
8808         rpcbuf_move(q_u->buffer, &r_u->buffer);
8809         buffer = r_u->buffer;
8810
8811         DEBUG(5,("spoolss_enumprintprocessors\n"));
8812
8813         /*
8814          * Enumerate the print processors ...
8815          *
8816          * Just reply with "winprint", to keep NT happy
8817          * and I can use my nice printer checker.
8818          */
8819
8820         *returned=0;
8821         *needed=0;
8822
8823         switch (level) {
8824         case 1:
8825                 return enumprintprocessors_level_1(buffer, offered, needed, returned);
8826         default:
8827                 return WERR_UNKNOWN_LEVEL;
8828         }
8829 }
8830
8831 /****************************************************************************
8832  enumprintprocdatatypes level 1.
8833 ****************************************************************************/
8834
8835 static WERROR enumprintprocdatatypes_level_1(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
8836 {
8837         PRINTPROCDATATYPE_1 *info_1=NULL;
8838         WERROR result = WERR_OK;
8839
8840         if((info_1 = SMB_MALLOC_P(PRINTPROCDATATYPE_1)) == NULL)
8841                 return WERR_NOMEM;
8842
8843         (*returned) = 0x1;
8844
8845         init_unistr(&info_1->name, "RAW");
8846
8847         *needed += spoolss_size_printprocdatatype_info_1(info_1);
8848
8849         if (*needed > offered) {
8850                 result = WERR_INSUFFICIENT_BUFFER;
8851                 goto out;
8852         }
8853
8854         if (!rpcbuf_alloc_size(buffer, *needed)) {
8855                 result = WERR_NOMEM;
8856                 goto out;
8857         }
8858
8859         smb_io_printprocdatatype_info_1("", buffer, info_1, 0);
8860
8861 out:
8862         SAFE_FREE(info_1);
8863
8864         if ( !W_ERROR_IS_OK(result) )
8865                 *returned = 0;
8866
8867         return result;
8868 }
8869
8870 /****************************************************************************
8871 ****************************************************************************/
8872
8873 WERROR _spoolss_enumprintprocdatatypes(pipes_struct *p, SPOOL_Q_ENUMPRINTPROCDATATYPES *q_u, SPOOL_R_ENUMPRINTPROCDATATYPES *r_u)
8874 {
8875         uint32 level = q_u->level;
8876         RPC_BUFFER *buffer = NULL;
8877         uint32 offered = q_u->offered;
8878         uint32 *needed = &r_u->needed;
8879         uint32 *returned = &r_u->returned;
8880
8881         /* that's an [in out] buffer */
8882
8883         if (!q_u->buffer && (offered!=0)) {
8884                 return WERR_INVALID_PARAM;
8885         }
8886
8887         if (offered > MAX_RPC_DATA_SIZE) {
8888                 return WERR_INVALID_PARAM;
8889         }
8890
8891         rpcbuf_move(q_u->buffer, &r_u->buffer);
8892         buffer = r_u->buffer;
8893
8894         DEBUG(5,("_spoolss_enumprintprocdatatypes\n"));
8895
8896         *returned=0;
8897         *needed=0;
8898
8899         switch (level) {
8900         case 1:
8901                 return enumprintprocdatatypes_level_1(buffer, offered, needed, returned);
8902         default:
8903                 return WERR_UNKNOWN_LEVEL;
8904         }
8905 }
8906
8907 /****************************************************************************
8908  enumprintmonitors level 1.
8909 ****************************************************************************/
8910
8911 static WERROR enumprintmonitors_level_1(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
8912 {
8913         PRINTMONITOR_1 *info_1;
8914         WERROR result = WERR_OK;
8915         int i;
8916
8917         if((info_1 = SMB_MALLOC_ARRAY(PRINTMONITOR_1, 2)) == NULL)
8918                 return WERR_NOMEM;
8919
8920         *returned = 2;
8921
8922         init_unistr(&(info_1[0].name), SPL_LOCAL_PORT );
8923         init_unistr(&(info_1[1].name), SPL_TCPIP_PORT );
8924
8925         for ( i=0; i<*returned; i++ ) {
8926                 *needed += spoolss_size_printmonitor_info_1(&info_1[i]);
8927         }
8928
8929         if (*needed > offered) {
8930                 result = WERR_INSUFFICIENT_BUFFER;
8931                 goto out;
8932         }
8933
8934         if (!rpcbuf_alloc_size(buffer, *needed)) {
8935                 result = WERR_NOMEM;
8936                 goto out;
8937         }
8938
8939         for ( i=0; i<*returned; i++ ) {
8940                 smb_io_printmonitor_info_1("", buffer, &info_1[i], 0);
8941         }
8942
8943 out:
8944         SAFE_FREE(info_1);
8945
8946         if ( !W_ERROR_IS_OK(result) )
8947                 *returned = 0;
8948
8949         return result;
8950 }
8951
8952 /****************************************************************************
8953  enumprintmonitors level 2.
8954 ****************************************************************************/
8955
8956 static WERROR enumprintmonitors_level_2(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
8957 {
8958         PRINTMONITOR_2 *info_2;
8959         WERROR result = WERR_OK;
8960         int i;
8961
8962         if((info_2 = SMB_MALLOC_ARRAY(PRINTMONITOR_2, 2)) == NULL)
8963                 return WERR_NOMEM;
8964
8965         *returned = 2;
8966
8967         init_unistr( &(info_2[0].name), SPL_LOCAL_PORT );
8968         init_unistr( &(info_2[0].environment), "Windows NT X86" );
8969         init_unistr( &(info_2[0].dll_name), "localmon.dll" );
8970
8971         init_unistr( &(info_2[1].name), SPL_TCPIP_PORT );
8972         init_unistr( &(info_2[1].environment), "Windows NT X86" );
8973         init_unistr( &(info_2[1].dll_name), "tcpmon.dll" );
8974
8975         for ( i=0; i<*returned; i++ ) {
8976                 *needed += spoolss_size_printmonitor_info_2(&info_2[i]);
8977         }
8978
8979         if (*needed > offered) {
8980                 result = WERR_INSUFFICIENT_BUFFER;
8981                 goto out;
8982         }
8983
8984         if (!rpcbuf_alloc_size(buffer, *needed)) {
8985                 result = WERR_NOMEM;
8986                 goto out;
8987         }
8988
8989         for ( i=0; i<*returned; i++ ) {
8990                 smb_io_printmonitor_info_2("", buffer, &info_2[i], 0);
8991         }
8992
8993 out:
8994         SAFE_FREE(info_2);
8995
8996         if ( !W_ERROR_IS_OK(result) )
8997                 *returned = 0;
8998
8999         return result;
9000 }
9001
9002 /****************************************************************************
9003 ****************************************************************************/
9004
9005 WERROR _spoolss_enumprintmonitors(pipes_struct *p, SPOOL_Q_ENUMPRINTMONITORS *q_u, SPOOL_R_ENUMPRINTMONITORS *r_u)
9006 {
9007         uint32 level = q_u->level;
9008         RPC_BUFFER *buffer = NULL;
9009         uint32 offered = q_u->offered;
9010         uint32 *needed = &r_u->needed;
9011         uint32 *returned = &r_u->returned;
9012
9013         /* that's an [in out] buffer */
9014
9015         if (!q_u->buffer && (offered!=0)) {
9016                 return WERR_INVALID_PARAM;
9017         }
9018
9019         if (offered > MAX_RPC_DATA_SIZE) {
9020                 return WERR_INVALID_PARAM;
9021         }
9022
9023         rpcbuf_move(q_u->buffer, &r_u->buffer);
9024         buffer = r_u->buffer;
9025
9026         DEBUG(5,("spoolss_enumprintmonitors\n"));
9027
9028         /*
9029          * Enumerate the print monitors ...
9030          *
9031          * Just reply with "Local Port", to keep NT happy
9032          * and I can use my nice printer checker.
9033          */
9034
9035         *returned=0;
9036         *needed=0;
9037
9038         switch (level) {
9039         case 1:
9040                 return enumprintmonitors_level_1(buffer, offered, needed, returned);
9041         case 2:
9042                 return enumprintmonitors_level_2(buffer, offered, needed, returned);
9043         default:
9044                 return WERR_UNKNOWN_LEVEL;
9045         }
9046 }
9047
9048 /****************************************************************************
9049 ****************************************************************************/
9050
9051 static WERROR getjob_level_1(print_queue_struct **queue, int count, int snum,
9052                              NT_PRINTER_INFO_LEVEL *ntprinter,
9053                              uint32 jobid, RPC_BUFFER *buffer, uint32 offered,
9054                              uint32 *needed)
9055 {
9056         int i=0;
9057         bool found=False;
9058         JOB_INFO_1 *info_1=NULL;
9059         WERROR result = WERR_OK;
9060
9061         info_1=SMB_MALLOC_P(JOB_INFO_1);
9062
9063         if (info_1 == NULL) {
9064                 return WERR_NOMEM;
9065         }
9066
9067         for (i=0; i<count && found==False; i++) {
9068                 if ((*queue)[i].job==(int)jobid)
9069                         found=True;
9070         }
9071
9072         if (found==False) {
9073                 SAFE_FREE(info_1);
9074                 /* NT treats not found as bad param... yet another bad choice */
9075                 return WERR_INVALID_PARAM;
9076         }
9077
9078         fill_job_info_1( info_1, &((*queue)[i-1]), i, snum, ntprinter );
9079
9080         *needed += spoolss_size_job_info_1(info_1);
9081
9082         if (*needed > offered) {
9083                 result = WERR_INSUFFICIENT_BUFFER;
9084                 goto out;
9085         }
9086
9087         if (!rpcbuf_alloc_size(buffer, *needed)) {
9088                 result = WERR_NOMEM;
9089                 goto out;
9090         }
9091
9092         smb_io_job_info_1("", buffer, info_1, 0);
9093
9094 out:
9095         SAFE_FREE(info_1);
9096
9097         return result;
9098 }
9099
9100 /****************************************************************************
9101 ****************************************************************************/
9102
9103 static WERROR getjob_level_2(print_queue_struct **queue, int count, int snum,
9104                              NT_PRINTER_INFO_LEVEL *ntprinter,
9105                              uint32 jobid, RPC_BUFFER *buffer, uint32 offered,
9106                              uint32 *needed)
9107 {
9108         int             i = 0;
9109         bool            found = False;
9110         JOB_INFO_2      *info_2;
9111         WERROR          result;
9112         DEVICEMODE      *devmode = NULL;
9113         NT_DEVICEMODE   *nt_devmode = NULL;
9114
9115         if ( !(info_2=SMB_MALLOC_P(JOB_INFO_2)) )
9116                 return WERR_NOMEM;
9117
9118         ZERO_STRUCTP(info_2);
9119
9120         for ( i=0; i<count && found==False; i++ )
9121         {
9122                 if ((*queue)[i].job == (int)jobid)
9123                         found = True;
9124         }
9125
9126         if ( !found ) {
9127                 /* NT treats not found as bad param... yet another bad
9128                    choice */
9129                 result = WERR_INVALID_PARAM;
9130                 goto done;
9131         }
9132
9133         /*
9134          * if the print job does not have a DEVMODE associated with it,
9135          * just use the one for the printer. A NULL devicemode is not
9136          *  a failure condition
9137          */
9138
9139         if ( !(nt_devmode=print_job_devmode( lp_const_servicename(snum), jobid )) )
9140                 devmode = construct_dev_mode(lp_const_servicename(snum));
9141         else {
9142                 if ((devmode = SMB_MALLOC_P(DEVICEMODE)) != NULL) {
9143                         ZERO_STRUCTP( devmode );
9144                         convert_nt_devicemode( devmode, nt_devmode );
9145                 }
9146         }
9147
9148         fill_job_info_2(info_2, &((*queue)[i-1]), i, snum, ntprinter, devmode);
9149
9150         *needed += spoolss_size_job_info_2(info_2);
9151
9152         if (*needed > offered) {
9153                 result = WERR_INSUFFICIENT_BUFFER;
9154                 goto done;
9155         }
9156
9157         if (!rpcbuf_alloc_size(buffer, *needed)) {
9158                 result = WERR_NOMEM;
9159                 goto done;
9160         }
9161
9162         smb_io_job_info_2("", buffer, info_2, 0);
9163
9164         result = WERR_OK;
9165
9166  done:
9167         /* Cleanup allocated memory */
9168
9169         free_job_info_2(info_2);        /* Also frees devmode */
9170         SAFE_FREE(info_2);
9171
9172         return result;
9173 }
9174
9175 /****************************************************************************
9176 ****************************************************************************/
9177
9178 WERROR _spoolss_getjob( pipes_struct *p, SPOOL_Q_GETJOB *q_u, SPOOL_R_GETJOB *r_u)
9179 {
9180         POLICY_HND *handle = &q_u->handle;
9181         uint32 jobid = q_u->jobid;
9182         uint32 level = q_u->level;
9183         RPC_BUFFER *buffer = NULL;
9184         uint32 offered = q_u->offered;
9185         uint32 *needed = &r_u->needed;
9186         WERROR          wstatus = WERR_OK;
9187         NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
9188         int snum;
9189         int count;
9190         print_queue_struct      *queue = NULL;
9191         print_status_struct prt_status;
9192
9193         /* that's an [in out] buffer */
9194
9195         if (!q_u->buffer && (offered!=0)) {
9196                 return WERR_INVALID_PARAM;
9197         }
9198
9199         if (offered > MAX_RPC_DATA_SIZE) {
9200                 return WERR_INVALID_PARAM;
9201         }
9202
9203         rpcbuf_move(q_u->buffer, &r_u->buffer);
9204         buffer = r_u->buffer;
9205
9206         DEBUG(5,("spoolss_getjob\n"));
9207
9208         *needed = 0;
9209
9210         if (!get_printer_snum(p, handle, &snum, NULL))
9211                 return WERR_BADFID;
9212
9213         wstatus = get_a_printer(NULL, &ntprinter, 2, lp_servicename(snum));
9214         if ( !W_ERROR_IS_OK(wstatus) )
9215                 return wstatus;
9216
9217         count = print_queue_status(snum, &queue, &prt_status);
9218
9219         DEBUGADD(4,("count:[%d], prt_status:[%d], [%s]\n",
9220                      count, prt_status.status, prt_status.message));
9221
9222         switch ( level ) {
9223         case 1:
9224                         wstatus = getjob_level_1(&queue, count, snum, ntprinter, jobid,
9225                                 buffer, offered, needed);
9226                         break;
9227         case 2:
9228                         wstatus = getjob_level_2(&queue, count, snum, ntprinter, jobid,
9229                                 buffer, offered, needed);
9230                         break;
9231         default:
9232                         wstatus = WERR_UNKNOWN_LEVEL;
9233                         break;
9234         }
9235
9236         SAFE_FREE(queue);
9237         free_a_printer( &ntprinter, 2 );
9238
9239         return wstatus;
9240 }
9241
9242 /****************************************************************
9243  _spoolss_GetPrinterDataEx
9244
9245  From MSDN documentation of GetPrinterDataEx: pass request
9246  to GetPrinterData if key is "PrinterDriverData".
9247 ****************************************************************/
9248
9249 WERROR _spoolss_GetPrinterDataEx(pipes_struct *p,
9250                                  struct spoolss_GetPrinterDataEx *r)
9251 {
9252         POLICY_HND      *handle = r->in.handle;
9253         uint8           *data = NULL;
9254         const char      *keyname = r->in.key_name;
9255         const char      *valuename = r->in.value_name;
9256
9257         Printer_entry   *Printer = find_printer_index_by_hnd(p, handle);
9258
9259         NT_PRINTER_INFO_LEVEL   *printer = NULL;
9260         int                     snum = 0;
9261         WERROR                  status = WERR_OK;
9262
9263         DEBUG(4,("_spoolss_GetPrinterDataEx\n"));
9264
9265         DEBUG(10, ("_spoolss_GetPrinterDataEx: key => [%s], value => [%s]\n",
9266                 keyname, valuename));
9267
9268         /* in case of problem, return some default values */
9269
9270         *r->out.needed  = 0;
9271         *r->out.type    = 0;
9272
9273         if (!Printer) {
9274                 DEBUG(2,("_spoolss_GetPrinterDataEx: "
9275                         "Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
9276                 status = WERR_BADFID;
9277                 goto done;
9278         }
9279
9280         /* Is the handle to a printer or to the server? */
9281
9282         if (Printer->printer_type == SPLHND_SERVER) {
9283                 DEBUG(10,("_spoolss_GetPrinterDataEx: "
9284                         "Not implemented for server handles yet\n"));
9285                 status = WERR_INVALID_PARAM;
9286                 goto done;
9287         }
9288
9289         if ( !get_printer_snum(p,handle, &snum, NULL) )
9290                 return WERR_BADFID;
9291
9292         status = get_a_printer(Printer, &printer, 2, lp_servicename(snum));
9293         if ( !W_ERROR_IS_OK(status) )
9294                 goto done;
9295
9296         /* check to see if the keyname is valid */
9297         if ( !strlen(keyname) ) {
9298                 status = WERR_INVALID_PARAM;
9299                 goto done;
9300         }
9301
9302         if ( lookup_printerkey( printer->info_2->data, keyname ) == -1 ) {
9303                 DEBUG(4,("_spoolss_GetPrinterDataEx: "
9304                         "Invalid keyname [%s]\n", keyname ));
9305                 free_a_printer( &printer, 2 );
9306                 status = WERR_BADFILE;
9307                 goto done;
9308         }
9309
9310         /* When given a new keyname, we should just create it */
9311
9312         status = get_printer_dataex( p->mem_ctx, printer, keyname, valuename,
9313                                      r->out.type, &data, r->out.needed,
9314                                      r->in.offered );
9315
9316         if (*r->out.needed > r->in.offered) {
9317                 status = WERR_MORE_DATA;
9318         }
9319
9320         if (W_ERROR_IS_OK(status)) {
9321                 memcpy(r->out.buffer, data, r->in.offered);
9322         }
9323
9324 done:
9325         if ( printer )
9326         free_a_printer( &printer, 2 );
9327
9328         return status;
9329 }
9330
9331 /****************************************************************
9332  _spoolss_SetPrinterDataEx
9333 ****************************************************************/
9334
9335 WERROR _spoolss_SetPrinterDataEx(pipes_struct *p,
9336                                  struct spoolss_SetPrinterDataEx *r)
9337 {
9338         POLICY_HND              *handle = r->in.handle;
9339         NT_PRINTER_INFO_LEVEL   *printer = NULL;
9340         int                     snum = 0;
9341         WERROR                  status = WERR_OK;
9342         Printer_entry           *Printer = find_printer_index_by_hnd(p, handle);
9343         char                    *oid_string;
9344
9345         DEBUG(4,("_spoolss_SetPrinterDataEx\n"));
9346
9347         /* From MSDN documentation of SetPrinterDataEx: pass request to
9348            SetPrinterData if key is "PrinterDriverData" */
9349
9350         if (!Printer) {
9351                 DEBUG(2,("_spoolss_SetPrinterDataEx: "
9352                         "Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
9353                 return WERR_BADFID;
9354         }
9355
9356         if ( Printer->printer_type == SPLHND_SERVER ) {
9357                 DEBUG(10,("_spoolss_SetPrinterDataEx: "
9358                         "Not implemented for server handles yet\n"));
9359                 return WERR_INVALID_PARAM;
9360         }
9361
9362         if ( !get_printer_snum(p,handle, &snum, NULL) )
9363                 return WERR_BADFID;
9364
9365         /*
9366          * Access check : NT returns "access denied" if you make a
9367          * SetPrinterData call without the necessary privildge.
9368          * we were originally returning OK if nothing changed
9369          * which made Win2k issue **a lot** of SetPrinterData
9370          * when connecting to a printer  --jerry
9371          */
9372
9373         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER)
9374         {
9375                 DEBUG(3, ("_spoolss_SetPrinterDataEx: "
9376                         "change denied by handle access permissions\n"));
9377                 return WERR_ACCESS_DENIED;
9378         }
9379
9380         status = get_a_printer(Printer, &printer, 2, lp_servicename(snum));
9381         if (!W_ERROR_IS_OK(status))
9382                 return status;
9383
9384         /* check for OID in valuename */
9385
9386         if ( (oid_string = strchr( r->in.value_name, ',' )) != NULL )
9387         {
9388                 *oid_string = '\0';
9389                 oid_string++;
9390         }
9391
9392         /* save the registry data */
9393
9394         status = set_printer_dataex( printer, r->in.key_name, r->in.value_name,
9395                                      r->in.type, r->in.buffer, r->in.offered );
9396
9397         if ( W_ERROR_IS_OK(status) )
9398         {
9399                 /* save the OID if one was specified */
9400                 if ( oid_string ) {
9401                         char *str = talloc_asprintf(p->mem_ctx, "%s\\%s",
9402                                 r->in.key_name, SPOOL_OID_KEY);
9403                         if (!str) {
9404                                 return WERR_NOMEM;
9405                         }
9406
9407                         /*
9408                          * I'm not checking the status here on purpose.  Don't know
9409                          * if this is right, but I'm returning the status from the
9410                          * previous set_printer_dataex() call.  I have no idea if
9411                          * this is right.    --jerry
9412                          */
9413
9414                         set_printer_dataex( printer, str, r->in.value_name,
9415                                             REG_SZ, (uint8 *)oid_string,
9416                                             strlen(oid_string)+1 );
9417                 }
9418
9419                 status = mod_a_printer(printer, 2);
9420         }
9421
9422         free_a_printer(&printer, 2);
9423
9424         return status;
9425 }
9426
9427 /****************************************************************
9428  _spoolss_DeletePrinterDataEx
9429 ****************************************************************/
9430
9431 WERROR _spoolss_DeletePrinterDataEx(pipes_struct *p,
9432                                     struct spoolss_DeletePrinterDataEx *r)
9433 {
9434         POLICY_HND      *handle = r->in.handle;
9435         NT_PRINTER_INFO_LEVEL   *printer = NULL;
9436         int             snum=0;
9437         WERROR          status = WERR_OK;
9438         Printer_entry   *Printer=find_printer_index_by_hnd(p, handle);
9439
9440         DEBUG(5,("_spoolss_DeletePrinterDataEx\n"));
9441
9442         if (!Printer) {
9443                 DEBUG(2,("_spoolss_DeletePrinterDataEx: "
9444                         "Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
9445                 return WERR_BADFID;
9446         }
9447
9448         if (!get_printer_snum(p, handle, &snum, NULL))
9449                 return WERR_BADFID;
9450
9451         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
9452                 DEBUG(3, ("_spoolss_DeletePrinterDataEx: "
9453                         "printer properties change denied by handle\n"));
9454                 return WERR_ACCESS_DENIED;
9455         }
9456
9457         if (!r->in.value_name || !r->in.key_name) {
9458                 return WERR_NOMEM;
9459         }
9460
9461         status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
9462         if (!W_ERROR_IS_OK(status))
9463                 return status;
9464
9465         status = delete_printer_dataex( printer, r->in.key_name, r->in.value_name );
9466
9467         if ( W_ERROR_IS_OK(status) )
9468                 mod_a_printer( printer, 2 );
9469
9470         free_a_printer(&printer, 2);
9471
9472         return status;
9473 }
9474
9475 /********************************************************************
9476  * spoolss_enumprinterkey
9477  ********************************************************************/
9478
9479
9480 WERROR _spoolss_enumprinterkey(pipes_struct *p, SPOOL_Q_ENUMPRINTERKEY *q_u, SPOOL_R_ENUMPRINTERKEY *r_u)
9481 {
9482         fstring         key;
9483         fstring         *keynames = NULL;
9484         uint16          *enumkeys = NULL;
9485         int             num_keys;
9486         int             printerkey_len;
9487         POLICY_HND      *handle = &q_u->handle;
9488         Printer_entry   *Printer = find_printer_index_by_hnd(p, handle);
9489         NT_PRINTER_DATA *data;
9490         NT_PRINTER_INFO_LEVEL   *printer = NULL;
9491         int             snum = 0;
9492         WERROR          status = WERR_BADFILE;
9493
9494
9495         DEBUG(4,("_spoolss_enumprinterkey\n"));
9496
9497         if (!Printer) {
9498                 DEBUG(2,("_spoolss_enumprinterkey: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
9499                 return WERR_BADFID;
9500         }
9501
9502         if ( !get_printer_snum(p,handle, &snum, NULL) )
9503                 return WERR_BADFID;
9504
9505         status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
9506         if (!W_ERROR_IS_OK(status))
9507                 return status;
9508
9509         /* get the list of subkey names */
9510
9511         unistr2_to_ascii(key, &q_u->key, sizeof(key));
9512         data = printer->info_2->data;
9513
9514         num_keys = get_printer_subkeys( data, key, &keynames );
9515
9516         if ( num_keys == -1 ) {
9517                 status = WERR_BADFILE;
9518                 goto done;
9519         }
9520
9521         printerkey_len = init_unistr_array( &enumkeys,  keynames, NULL );
9522
9523         r_u->needed = printerkey_len*2;
9524
9525         if ( q_u->size < r_u->needed ) {
9526                 status = WERR_MORE_DATA;
9527                 goto done;
9528         }
9529
9530         if (!make_spoolss_buffer5(p->mem_ctx, &r_u->keys, printerkey_len, enumkeys)) {
9531                 status = WERR_NOMEM;
9532                 goto done;
9533         }
9534
9535         status = WERR_OK;
9536
9537         if ( q_u->size < r_u->needed )
9538                 status = WERR_MORE_DATA;
9539
9540 done:
9541         free_a_printer( &printer, 2 );
9542         SAFE_FREE( keynames );
9543
9544         return status;
9545 }
9546
9547 /****************************************************************
9548  _spoolss_DeletePrinterKey
9549 ****************************************************************/
9550
9551 WERROR _spoolss_DeletePrinterKey(pipes_struct *p,
9552                                  struct spoolss_DeletePrinterKey *r)
9553 {
9554         POLICY_HND              *handle = r->in.handle;
9555         Printer_entry           *Printer = find_printer_index_by_hnd(p, handle);
9556         NT_PRINTER_INFO_LEVEL   *printer = NULL;
9557         int                     snum=0;
9558         WERROR                  status;
9559
9560         DEBUG(5,("_spoolss_DeletePrinterKey\n"));
9561
9562         if (!Printer) {
9563                 DEBUG(2,("_spoolss_DeletePrinterKey: Invalid handle (%s:%u:%u).\n",
9564                         OUR_HANDLE(handle)));
9565                 return WERR_BADFID;
9566         }
9567
9568         /* if keyname == NULL, return error */
9569
9570         if ( !r->in.key_name )
9571                 return WERR_INVALID_PARAM;
9572
9573         if (!get_printer_snum(p, handle, &snum, NULL))
9574                 return WERR_BADFID;
9575
9576         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
9577                 DEBUG(3, ("_spoolss_DeletePrinterKey: "
9578                         "printer properties change denied by handle\n"));
9579                 return WERR_ACCESS_DENIED;
9580         }
9581
9582         status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
9583         if (!W_ERROR_IS_OK(status))
9584                 return status;
9585
9586         /* delete the key and all subneys */
9587
9588         status = delete_all_printer_data( printer->info_2, r->in.key_name );
9589
9590         if ( W_ERROR_IS_OK(status) )
9591                 status = mod_a_printer(printer, 2);
9592
9593         free_a_printer( &printer, 2 );
9594
9595         return status;
9596 }
9597
9598
9599 /********************************************************************
9600  * spoolss_enumprinterdataex
9601  ********************************************************************/
9602
9603 WERROR _spoolss_enumprinterdataex(pipes_struct *p, SPOOL_Q_ENUMPRINTERDATAEX *q_u, SPOOL_R_ENUMPRINTERDATAEX *r_u)
9604 {
9605         POLICY_HND      *handle = &q_u->handle;
9606         uint32          in_size = q_u->size;
9607         uint32          num_entries,
9608                         needed;
9609         NT_PRINTER_INFO_LEVEL   *printer = NULL;
9610         PRINTER_ENUM_VALUES     *enum_values = NULL;
9611         NT_PRINTER_DATA         *p_data;
9612         fstring         key;
9613         Printer_entry   *Printer = find_printer_index_by_hnd(p, handle);
9614         int             snum;
9615         WERROR          result;
9616         int             key_index;
9617         int             i;
9618         REGISTRY_VALUE  *val;
9619         char            *value_name;
9620         uint32          data_len;
9621
9622
9623         DEBUG(4,("_spoolss_enumprinterdataex\n"));
9624
9625         if (!Printer) {
9626                 DEBUG(2,("_spoolss_enumprinterdataex: Invalid handle (%s:%u:%u1<).\n", OUR_HANDLE(handle)));
9627                 return WERR_BADFID;
9628         }
9629
9630         /*
9631          * first check for a keyname of NULL or "".  Win2k seems to send
9632          * this a lot and we should send back WERR_INVALID_PARAM
9633          * no need to spend time looking up the printer in this case.
9634          * --jerry
9635          */
9636
9637         unistr2_to_ascii(key, &q_u->key, sizeof(key));
9638         if ( !strlen(key) ) {
9639                 result = WERR_INVALID_PARAM;
9640                 goto done;
9641         }
9642
9643         /* get the printer off of disk */
9644
9645         if (!get_printer_snum(p,handle, &snum, NULL))
9646                 return WERR_BADFID;
9647
9648         ZERO_STRUCT(printer);
9649         result = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
9650         if (!W_ERROR_IS_OK(result))
9651                 return result;
9652
9653         /* now look for a match on the key name */
9654
9655         p_data = printer->info_2->data;
9656
9657         unistr2_to_ascii(key, &q_u->key, sizeof(key));
9658         if ( (key_index = lookup_printerkey( p_data, key)) == -1  )
9659         {
9660                 DEBUG(10,("_spoolss_enumprinterdataex: Unknown keyname [%s]\n", key));
9661                 result = WERR_INVALID_PARAM;
9662                 goto done;
9663         }
9664
9665         result = WERR_OK;
9666         needed = 0;
9667
9668         /* allocate the memory for the array of pointers -- if necessary */
9669
9670         num_entries = regval_ctr_numvals( p_data->keys[key_index].values );
9671         if ( num_entries )
9672         {
9673                 if ( (enum_values=TALLOC_ARRAY(p->mem_ctx, PRINTER_ENUM_VALUES, num_entries)) == NULL )
9674                 {
9675                         DEBUG(0,("_spoolss_enumprinterdataex: talloc() failed to allocate memory for [%lu] bytes!\n",
9676                                 (unsigned long)num_entries*sizeof(PRINTER_ENUM_VALUES)));
9677                         result = WERR_NOMEM;
9678                         goto done;
9679                 }
9680
9681                 memset( enum_values, 0x0, num_entries*sizeof(PRINTER_ENUM_VALUES) );
9682         }
9683
9684         /*
9685          * loop through all params and build the array to pass
9686          * back to the  client
9687          */
9688
9689         for ( i=0; i<num_entries; i++ )
9690         {
9691                 /* lookup the registry value */
9692
9693                 val = regval_ctr_specific_value( p_data->keys[key_index].values, i );
9694                 DEBUG(10,("retrieved value number [%d] [%s]\n", i, regval_name(val) ));
9695
9696                 /* copy the data */
9697
9698                 value_name = regval_name( val );
9699                 init_unistr( &enum_values[i].valuename, value_name );
9700                 enum_values[i].value_len = (strlen(value_name)+1) * 2;
9701                 enum_values[i].type      = regval_type( val );
9702
9703                 data_len = regval_size( val );
9704                 if ( data_len ) {
9705                         if ( !(enum_values[i].data = (uint8 *)TALLOC_MEMDUP(p->mem_ctx, regval_data_p(val), data_len)) )
9706                         {
9707                                 DEBUG(0,("TALLOC_MEMDUP failed to allocate memory [data_len=%d] for data!\n",
9708                                         data_len ));
9709                                 result = WERR_NOMEM;
9710                                 goto done;
9711                         }
9712                 }
9713                 enum_values[i].data_len = data_len;
9714
9715                 /* keep track of the size of the array in bytes */
9716
9717                 needed += spoolss_size_printer_enum_values(&enum_values[i]);
9718         }
9719
9720         /* housekeeping information in the reply */
9721
9722         /* Fix from Martin Zielinski <mz@seh.de> - ensure
9723          * the hand marshalled container size is a multiple
9724          * of 4 bytes for RPC alignment.
9725          */
9726
9727         if (needed % 4) {
9728                 needed += 4-(needed % 4);
9729         }
9730
9731         r_u->needed     = needed;
9732         r_u->returned   = num_entries;
9733
9734         if (needed > in_size) {
9735                 result = WERR_MORE_DATA;
9736                 goto done;
9737         }
9738
9739         /* copy data into the reply */
9740
9741         /* mz: Vista x64 returns 0x6f7 (The stub received bad data), if the
9742            response buffer size is != the offered buffer size
9743
9744                 r_u->ctr.size           = r_u->needed;
9745         */
9746         r_u->ctr.size           = in_size;
9747
9748         r_u->ctr.size_of_array  = r_u->returned;
9749         r_u->ctr.values         = enum_values;
9750
9751 done:
9752         if ( printer )
9753         free_a_printer(&printer, 2);
9754
9755         return result;
9756 }
9757
9758 /****************************************************************************
9759 ****************************************************************************/
9760
9761 static WERROR getprintprocessordirectory_level_1(TALLOC_CTX *mem_ctx,
9762                                                  const char *servername,
9763                                                  const char *environment,
9764                                                  struct spoolss_PrintProcessorDirectoryInfo1 *r,
9765                                                  uint32_t offered,
9766                                                  uint32_t *needed)
9767 {
9768         WERROR werr;
9769         char *path = NULL;
9770
9771         werr = compose_spoolss_server_path(mem_ctx,
9772                                            servername,
9773                                            environment,
9774                                            SPOOLSS_PRTPROCS_PATH,
9775                                            &path);
9776         if (!W_ERROR_IS_OK(werr)) {
9777                 return werr;
9778         }
9779
9780         DEBUG(4,("print processor directory: [%s]\n", path));
9781
9782         r->directory_name = path;
9783
9784         *needed += ndr_size_spoolss_PrintProcessorDirectoryInfo1(r, NULL, 0);
9785
9786         if (*needed > offered) {
9787                 talloc_free(path);
9788                 return WERR_INSUFFICIENT_BUFFER;
9789         }
9790
9791         return WERR_OK;
9792 }
9793
9794 /****************************************************************
9795  _spoolss_GetPrintProcessorDirectory
9796 ****************************************************************/
9797
9798 WERROR _spoolss_GetPrintProcessorDirectory(pipes_struct *p,
9799                                            struct spoolss_GetPrintProcessorDirectory *r)
9800 {
9801         WERROR result;
9802
9803         /* that's an [in out] buffer */
9804
9805         if (!r->in.buffer && (r->in.offered != 0)) {
9806                 return WERR_INVALID_PARAM;
9807         }
9808
9809         DEBUG(5,("_spoolss_GetPrintProcessorDirectory: level %d\n",
9810                 r->in.level));
9811
9812         *r->out.needed = 0;
9813
9814         /* r->in.level is ignored */
9815
9816         result = getprintprocessordirectory_level_1(p->mem_ctx,
9817                                                     r->in.server,
9818                                                     r->in.environment,
9819                                                     &r->out.info->info1,
9820                                                     r->in.offered,
9821                                                     r->out.needed);
9822         if (!W_ERROR_IS_OK(result)) {
9823                 TALLOC_FREE(r->out.info);
9824         }
9825
9826         return result;
9827 }
9828
9829 /*******************************************************************
9830  ********************************************************************/
9831
9832 static bool push_monitorui_buf(TALLOC_CTX *mem_ctx, DATA_BLOB *buf,
9833                                const char *dllname)
9834 {
9835         enum ndr_err_code ndr_err;
9836         struct spoolss_MonitorUi ui;
9837
9838         ui.dll_name = dllname;
9839
9840         ndr_err = ndr_push_struct_blob(buf, mem_ctx, NULL, &ui,
9841                        (ndr_push_flags_fn_t)ndr_push_spoolss_MonitorUi);
9842         if (NDR_ERR_CODE_IS_SUCCESS(ndr_err) && (DEBUGLEVEL >= 10)) {
9843                 NDR_PRINT_DEBUG(spoolss_MonitorUi, &ui);
9844         }
9845         return NDR_ERR_CODE_IS_SUCCESS(ndr_err);
9846 }
9847
9848 /*******************************************************************
9849  Streams the monitor UI DLL name in UNICODE
9850 *******************************************************************/
9851
9852 static WERROR xcvtcp_monitorui(TALLOC_CTX *mem_ctx,
9853                                NT_USER_TOKEN *token, DATA_BLOB *in,
9854                                DATA_BLOB *out, uint32_t *needed)
9855 {
9856         const char *dllname = "tcpmonui.dll";
9857
9858         *needed = (strlen(dllname)+1) * 2;
9859
9860         if (out->length < *needed) {
9861                 return WERR_INSUFFICIENT_BUFFER;
9862         }
9863
9864         if (!push_monitorui_buf(mem_ctx, out, dllname)) {
9865                 return WERR_NOMEM;
9866         }
9867
9868         return WERR_OK;
9869 }
9870
9871 /*******************************************************************
9872  ********************************************************************/
9873
9874 static bool pull_port_data_1(TALLOC_CTX *mem_ctx,
9875                              struct spoolss_PortData1 *port1,
9876                              const DATA_BLOB *buf)
9877 {
9878         enum ndr_err_code ndr_err;
9879         ndr_err = ndr_pull_struct_blob(buf, mem_ctx, NULL, port1,
9880                        (ndr_pull_flags_fn_t)ndr_pull_spoolss_PortData1);
9881         if (NDR_ERR_CODE_IS_SUCCESS(ndr_err) && (DEBUGLEVEL >= 10)) {
9882                 NDR_PRINT_DEBUG(spoolss_PortData1, port1);
9883         }
9884         return NDR_ERR_CODE_IS_SUCCESS(ndr_err);
9885 }
9886
9887 /*******************************************************************
9888  ********************************************************************/
9889
9890 static bool pull_port_data_2(TALLOC_CTX *mem_ctx,
9891                              struct spoolss_PortData2 *port2,
9892                              const DATA_BLOB *buf)
9893 {
9894         enum ndr_err_code ndr_err;
9895         ndr_err = ndr_pull_struct_blob(buf, mem_ctx, NULL, port2,
9896                        (ndr_pull_flags_fn_t)ndr_pull_spoolss_PortData2);
9897         if (NDR_ERR_CODE_IS_SUCCESS(ndr_err) && (DEBUGLEVEL >= 10)) {
9898                 NDR_PRINT_DEBUG(spoolss_PortData2, port2);
9899         }
9900         return NDR_ERR_CODE_IS_SUCCESS(ndr_err);
9901 }
9902
9903 /*******************************************************************
9904  Create a new TCP/IP port
9905 *******************************************************************/
9906
9907 static WERROR xcvtcp_addport(TALLOC_CTX *mem_ctx,
9908                              NT_USER_TOKEN *token, DATA_BLOB *in,
9909                              DATA_BLOB *out, uint32_t *needed)
9910 {
9911         struct spoolss_PortData1 port1;
9912         struct spoolss_PortData2 port2;
9913         char *device_uri = NULL;
9914         uint32_t version;
9915
9916         const char *portname;
9917         const char *hostaddress;
9918         const char *queue;
9919         uint32_t port_number;
9920         uint32_t protocol;
9921
9922         /* peek for spoolss_PortData version */
9923
9924         if (!in || (in->length < (128 + 4))) {
9925                 return WERR_GENERAL_FAILURE;
9926         }
9927
9928         version = IVAL(in->data, 128);
9929
9930         switch (version) {
9931                 case 1:
9932                         ZERO_STRUCT(port1);
9933
9934                         if (!pull_port_data_1(mem_ctx, &port1, in)) {
9935                                 return WERR_NOMEM;
9936                         }
9937
9938                         portname        = port1.portname;
9939                         hostaddress     = port1.hostaddress;
9940                         queue           = port1.queue;
9941                         protocol        = port1.protocol;
9942                         port_number     = port1.port_number;
9943
9944                         break;
9945                 case 2:
9946                         ZERO_STRUCT(port2);
9947
9948                         if (!pull_port_data_2(mem_ctx, &port2, in)) {
9949                                 return WERR_NOMEM;
9950                         }
9951
9952                         portname        = port2.portname;
9953                         hostaddress     = port2.hostaddress;
9954                         queue           = port2.queue;
9955                         protocol        = port2.protocol;
9956                         port_number     = port2.port_number;
9957
9958                         break;
9959                 default:
9960                         DEBUG(1,("xcvtcp_addport: "
9961                                 "unknown version of port_data: %d\n", version));
9962                         return WERR_UNKNOWN_PORT;
9963         }
9964
9965         /* create the device URI and call the add_port_hook() */
9966
9967         switch (protocol) {
9968         case PROTOCOL_RAWTCP_TYPE:
9969                 device_uri = talloc_asprintf(mem_ctx,
9970                                 "socket://%s:%d/", hostaddress,
9971                                 port_number);
9972                 break;
9973
9974         case PROTOCOL_LPR_TYPE:
9975                 device_uri = talloc_asprintf(mem_ctx,
9976                         "lpr://%s/%s", hostaddress, queue );
9977                 break;
9978
9979         default:
9980                 return WERR_UNKNOWN_PORT;
9981         }
9982
9983         if (!device_uri) {
9984                 return WERR_NOMEM;
9985         }
9986
9987         return add_port_hook(mem_ctx, token, portname, device_uri);
9988 }
9989
9990 /*******************************************************************
9991 *******************************************************************/
9992
9993 struct xcv_api_table xcvtcp_cmds[] = {
9994         { "MonitorUI",  xcvtcp_monitorui },
9995         { "AddPort",    xcvtcp_addport},
9996         { NULL,         NULL }
9997 };
9998
9999 static WERROR process_xcvtcp_command(TALLOC_CTX *mem_ctx,
10000                                      NT_USER_TOKEN *token, const char *command,
10001                                      DATA_BLOB *inbuf,
10002                                      DATA_BLOB *outbuf,
10003                                      uint32_t *needed )
10004 {
10005         int i;
10006
10007         DEBUG(10,("process_xcvtcp_command: Received command \"%s\"\n", command));
10008
10009         for ( i=0; xcvtcp_cmds[i].name; i++ ) {
10010                 if ( strcmp( command, xcvtcp_cmds[i].name ) == 0 )
10011                         return xcvtcp_cmds[i].fn(mem_ctx, token, inbuf, outbuf, needed);
10012         }
10013
10014         return WERR_BADFUNC;
10015 }
10016
10017 /*******************************************************************
10018 *******************************************************************/
10019 #if 0   /* don't support management using the "Local Port" monitor */
10020
10021 static WERROR xcvlocal_monitorui(TALLOC_CTX *mem_ctx,
10022                                  NT_USER_TOKEN *token, DATA_BLOB *in,
10023                                  DATA_BLOB *out, uint32_t *needed)
10024 {
10025         const char *dllname = "localui.dll";
10026
10027         *needed = (strlen(dllname)+1) * 2;
10028
10029         if (out->length < *needed) {
10030                 return WERR_INSUFFICIENT_BUFFER;
10031         }
10032
10033         if (!push_monitorui_buf(mem_ctx, out, dllname)) {
10034                 return WERR_NOMEM;
10035         }
10036
10037         return WERR_OK;
10038 }
10039
10040 /*******************************************************************
10041 *******************************************************************/
10042
10043 struct xcv_api_table xcvlocal_cmds[] = {
10044         { "MonitorUI",  xcvlocal_monitorui },
10045         { NULL,         NULL }
10046 };
10047 #else
10048 struct xcv_api_table xcvlocal_cmds[] = {
10049         { NULL,         NULL }
10050 };
10051 #endif
10052
10053
10054
10055 /*******************************************************************
10056 *******************************************************************/
10057
10058 static WERROR process_xcvlocal_command(TALLOC_CTX *mem_ctx,
10059                                        NT_USER_TOKEN *token, const char *command,
10060                                        DATA_BLOB *inbuf, DATA_BLOB *outbuf,
10061                                        uint32_t *needed)
10062 {
10063         int i;
10064
10065         DEBUG(10,("process_xcvlocal_command: Received command \"%s\"\n", command));
10066
10067         for ( i=0; xcvlocal_cmds[i].name; i++ ) {
10068                 if ( strcmp( command, xcvlocal_cmds[i].name ) == 0 )
10069                         return xcvlocal_cmds[i].fn(mem_ctx, token, inbuf, outbuf, needed);
10070         }
10071         return WERR_BADFUNC;
10072 }
10073
10074 /****************************************************************
10075  _spoolss_XcvData
10076 ****************************************************************/
10077
10078 WERROR _spoolss_XcvData(pipes_struct *p,
10079                         struct spoolss_XcvData *r)
10080 {
10081         Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
10082         DATA_BLOB out_data;
10083         WERROR werror;
10084
10085         if (!Printer) {
10086                 DEBUG(2,("_spoolss_XcvData: Invalid handle (%s:%u:%u).\n",
10087                         OUR_HANDLE(r->in.handle)));
10088                 return WERR_BADFID;
10089         }
10090
10091         /* Has to be a handle to the TCP/IP port monitor */
10092
10093         if ( !(Printer->printer_type & (SPLHND_PORTMON_LOCAL|SPLHND_PORTMON_TCP)) ) {
10094                 DEBUG(2,("_spoolss_XcvData: Call only valid for Port Monitors\n"));
10095                 return WERR_BADFID;
10096         }
10097
10098         /* requires administrative access to the server */
10099
10100         if ( !(Printer->access_granted & SERVER_ACCESS_ADMINISTER) ) {
10101                 DEBUG(2,("_spoolss_XcvData: denied by handle permissions.\n"));
10102                 return WERR_ACCESS_DENIED;
10103         }
10104
10105         /* Allocate the outgoing buffer */
10106
10107         if (r->in.out_data_size) {
10108                 out_data = data_blob_talloc_zero(p->mem_ctx, r->in.out_data_size);
10109                 if (out_data.data == NULL) {
10110                         return WERR_NOMEM;
10111                 }
10112         }
10113
10114         switch ( Printer->printer_type ) {
10115         case SPLHND_PORTMON_TCP:
10116                 werror = process_xcvtcp_command(p->mem_ctx,
10117                                                 p->server_info->ptok,
10118                                                 r->in.function_name,
10119                                                 &r->in.in_data, &out_data,
10120                                                 r->out.needed);
10121                 break;
10122         case SPLHND_PORTMON_LOCAL:
10123                 werror = process_xcvlocal_command(p->mem_ctx,
10124                                                   p->server_info->ptok,
10125                                                   r->in.function_name,
10126                                                   &r->in.in_data, &out_data,
10127                                                   r->out.needed);
10128                 break;
10129         default:
10130                 werror = WERR_INVALID_PRINT_MONITOR;
10131         }
10132
10133         if (!W_ERROR_IS_OK(werror)) {
10134                 return werror;
10135         }
10136
10137         *r->out.status_code = 0;
10138
10139         memcpy(r->out.out_data, out_data.data, out_data.length);
10140
10141         return WERR_OK;
10142 }
10143
10144 /****************************************************************
10145  _spoolss_AddPrintProcessor
10146 ****************************************************************/
10147
10148 WERROR _spoolss_AddPrintProcessor(pipes_struct *p,
10149                                   struct spoolss_AddPrintProcessor *r)
10150 {
10151         /* for now, just indicate success and ignore the add.  We'll
10152            automatically set the winprint processor for printer
10153            entries later.  Used to debug the LexMark Optra S 1855 PCL
10154            driver --jerry */
10155
10156         return WERR_OK;
10157 }
10158
10159 /****************************************************************
10160  _spoolss_EnumPrinters
10161 ****************************************************************/
10162
10163 WERROR _spoolss_EnumPrinters(pipes_struct *p,
10164                              struct spoolss_EnumPrinters *r)
10165 {
10166         p->rng_fault_state = true;
10167         return WERR_NOT_SUPPORTED;
10168 }
10169
10170 /****************************************************************
10171  _spoolss_GetJob
10172 ****************************************************************/
10173
10174 WERROR _spoolss_GetJob(pipes_struct *p,
10175                        struct spoolss_GetJob *r)
10176 {
10177         p->rng_fault_state = true;
10178         return WERR_NOT_SUPPORTED;
10179 }
10180
10181 /****************************************************************
10182  _spoolss_EnumJobs
10183 ****************************************************************/
10184
10185 WERROR _spoolss_EnumJobs(pipes_struct *p,
10186                          struct spoolss_EnumJobs *r)
10187 {
10188         p->rng_fault_state = true;
10189         return WERR_NOT_SUPPORTED;
10190 }
10191
10192 /****************************************************************
10193  _spoolss_AddPrinter
10194 ****************************************************************/
10195
10196 WERROR _spoolss_AddPrinter(pipes_struct *p,
10197                            struct spoolss_AddPrinter *r)
10198 {
10199         p->rng_fault_state = true;
10200         return WERR_NOT_SUPPORTED;
10201 }
10202
10203 /****************************************************************
10204  _spoolss_GetPrinter
10205 ****************************************************************/
10206
10207 WERROR _spoolss_GetPrinter(pipes_struct *p,
10208                            struct spoolss_GetPrinter *r)
10209 {
10210         p->rng_fault_state = true;
10211         return WERR_NOT_SUPPORTED;
10212 }
10213
10214 /****************************************************************
10215  _spoolss_EnumPrinterDrivers
10216 ****************************************************************/
10217
10218 WERROR _spoolss_EnumPrinterDrivers(pipes_struct *p,
10219                                    struct spoolss_EnumPrinterDrivers *r)
10220 {
10221         p->rng_fault_state = true;
10222         return WERR_NOT_SUPPORTED;
10223 }
10224
10225 /****************************************************************
10226  _spoolss_GetPrinterDriver
10227 ****************************************************************/
10228
10229 WERROR _spoolss_GetPrinterDriver(pipes_struct *p,
10230                                  struct spoolss_GetPrinterDriver *r)
10231 {
10232         p->rng_fault_state = true;
10233         return WERR_NOT_SUPPORTED;
10234 }
10235
10236 /****************************************************************
10237  _spoolss_EnumPrintProcessors
10238 ****************************************************************/
10239
10240 WERROR _spoolss_EnumPrintProcessors(pipes_struct *p,
10241                                     struct spoolss_EnumPrintProcessors *r)
10242 {
10243         p->rng_fault_state = true;
10244         return WERR_NOT_SUPPORTED;
10245 }
10246
10247 /****************************************************************
10248  _spoolss_ReadPrinter
10249 ****************************************************************/
10250
10251 WERROR _spoolss_ReadPrinter(pipes_struct *p,
10252                             struct spoolss_ReadPrinter *r)
10253 {
10254         p->rng_fault_state = true;
10255         return WERR_NOT_SUPPORTED;
10256 }
10257
10258 /****************************************************************
10259  _spoolss_GetPrinterData
10260 ****************************************************************/
10261
10262 WERROR _spoolss_GetPrinterData(pipes_struct *p,
10263                                struct spoolss_GetPrinterData *r)
10264 {
10265         p->rng_fault_state = true;
10266         return WERR_NOT_SUPPORTED;
10267 }
10268
10269 /****************************************************************
10270  _spoolss_SetPrinterData
10271 ****************************************************************/
10272
10273 WERROR _spoolss_SetPrinterData(pipes_struct *p,
10274                                struct spoolss_SetPrinterData *r)
10275 {
10276         p->rng_fault_state = true;
10277         return WERR_NOT_SUPPORTED;
10278 }
10279
10280 /****************************************************************
10281  _spoolss_WaitForPrinterChange
10282 ****************************************************************/
10283
10284 WERROR _spoolss_WaitForPrinterChange(pipes_struct *p,
10285                                      struct spoolss_WaitForPrinterChange *r)
10286 {
10287         p->rng_fault_state = true;
10288         return WERR_NOT_SUPPORTED;
10289 }
10290
10291 /****************************************************************
10292  _spoolss_EnumPorts
10293 ****************************************************************/
10294
10295 WERROR _spoolss_EnumPorts(pipes_struct *p,
10296                           struct spoolss_EnumPorts *r)
10297 {
10298         p->rng_fault_state = true;
10299         return WERR_NOT_SUPPORTED;
10300 }
10301
10302 /****************************************************************
10303  _spoolss_EnumMonitors
10304 ****************************************************************/
10305
10306 WERROR _spoolss_EnumMonitors(pipes_struct *p,
10307                              struct spoolss_EnumMonitors *r)
10308 {
10309         p->rng_fault_state = true;
10310         return WERR_NOT_SUPPORTED;
10311 }
10312
10313 /****************************************************************
10314  _spoolss_AddPort
10315 ****************************************************************/
10316
10317 WERROR _spoolss_AddPort(pipes_struct *p,
10318                         struct spoolss_AddPort *r)
10319 {
10320         p->rng_fault_state = true;
10321         return WERR_NOT_SUPPORTED;
10322 }
10323
10324 /****************************************************************
10325  _spoolss_ConfigurePort
10326 ****************************************************************/
10327
10328 WERROR _spoolss_ConfigurePort(pipes_struct *p,
10329                               struct spoolss_ConfigurePort *r)
10330 {
10331         p->rng_fault_state = true;
10332         return WERR_NOT_SUPPORTED;
10333 }
10334
10335 /****************************************************************
10336  _spoolss_DeletePort
10337 ****************************************************************/
10338
10339 WERROR _spoolss_DeletePort(pipes_struct *p,
10340                            struct spoolss_DeletePort *r)
10341 {
10342         p->rng_fault_state = true;
10343         return WERR_NOT_SUPPORTED;
10344 }
10345
10346 /****************************************************************
10347  _spoolss_CreatePrinterIC
10348 ****************************************************************/
10349
10350 WERROR _spoolss_CreatePrinterIC(pipes_struct *p,
10351                                 struct spoolss_CreatePrinterIC *r)
10352 {
10353         p->rng_fault_state = true;
10354         return WERR_NOT_SUPPORTED;
10355 }
10356
10357 /****************************************************************
10358  _spoolss_PlayGDIScriptOnPrinterIC
10359 ****************************************************************/
10360
10361 WERROR _spoolss_PlayGDIScriptOnPrinterIC(pipes_struct *p,
10362                                          struct spoolss_PlayGDIScriptOnPrinterIC *r)
10363 {
10364         p->rng_fault_state = true;
10365         return WERR_NOT_SUPPORTED;
10366 }
10367
10368 /****************************************************************
10369  _spoolss_DeletePrinterIC
10370 ****************************************************************/
10371
10372 WERROR _spoolss_DeletePrinterIC(pipes_struct *p,
10373                                 struct spoolss_DeletePrinterIC *r)
10374 {
10375         p->rng_fault_state = true;
10376         return WERR_NOT_SUPPORTED;
10377 }
10378
10379 /****************************************************************
10380  _spoolss_AddPrinterConnection
10381 ****************************************************************/
10382
10383 WERROR _spoolss_AddPrinterConnection(pipes_struct *p,
10384                                      struct spoolss_AddPrinterConnection *r)
10385 {
10386         p->rng_fault_state = true;
10387         return WERR_NOT_SUPPORTED;
10388 }
10389
10390 /****************************************************************
10391  _spoolss_DeletePrinterConnection
10392 ****************************************************************/
10393
10394 WERROR _spoolss_DeletePrinterConnection(pipes_struct *p,
10395                                         struct spoolss_DeletePrinterConnection *r)
10396 {
10397         p->rng_fault_state = true;
10398         return WERR_NOT_SUPPORTED;
10399 }
10400
10401 /****************************************************************
10402  _spoolss_PrinterMessageBox
10403 ****************************************************************/
10404
10405 WERROR _spoolss_PrinterMessageBox(pipes_struct *p,
10406                                   struct spoolss_PrinterMessageBox *r)
10407 {
10408         p->rng_fault_state = true;
10409         return WERR_NOT_SUPPORTED;
10410 }
10411
10412 /****************************************************************
10413  _spoolss_AddMonitor
10414 ****************************************************************/
10415
10416 WERROR _spoolss_AddMonitor(pipes_struct *p,
10417                            struct spoolss_AddMonitor *r)
10418 {
10419         p->rng_fault_state = true;
10420         return WERR_NOT_SUPPORTED;
10421 }
10422
10423 /****************************************************************
10424  _spoolss_DeleteMonitor
10425 ****************************************************************/
10426
10427 WERROR _spoolss_DeleteMonitor(pipes_struct *p,
10428                               struct spoolss_DeleteMonitor *r)
10429 {
10430         p->rng_fault_state = true;
10431         return WERR_NOT_SUPPORTED;
10432 }
10433
10434 /****************************************************************
10435  _spoolss_DeletePrintProcessor
10436 ****************************************************************/
10437
10438 WERROR _spoolss_DeletePrintProcessor(pipes_struct *p,
10439                                      struct spoolss_DeletePrintProcessor *r)
10440 {
10441         p->rng_fault_state = true;
10442         return WERR_NOT_SUPPORTED;
10443 }
10444
10445 /****************************************************************
10446  _spoolss_AddPrintProvidor
10447 ****************************************************************/
10448
10449 WERROR _spoolss_AddPrintProvidor(pipes_struct *p,
10450                                  struct spoolss_AddPrintProvidor *r)
10451 {
10452         p->rng_fault_state = true;
10453         return WERR_NOT_SUPPORTED;
10454 }
10455
10456 /****************************************************************
10457  _spoolss_DeletePrintProvidor
10458 ****************************************************************/
10459
10460 WERROR _spoolss_DeletePrintProvidor(pipes_struct *p,
10461                                     struct spoolss_DeletePrintProvidor *r)
10462 {
10463         p->rng_fault_state = true;
10464         return WERR_NOT_SUPPORTED;
10465 }
10466
10467 /****************************************************************
10468  _spoolss_EnumPrintProcDataTypes
10469 ****************************************************************/
10470
10471 WERROR _spoolss_EnumPrintProcDataTypes(pipes_struct *p,
10472                                        struct spoolss_EnumPrintProcDataTypes *r)
10473 {
10474         p->rng_fault_state = true;
10475         return WERR_NOT_SUPPORTED;
10476 }
10477
10478 /****************************************************************
10479  _spoolss_GetPrinterDriver2
10480 ****************************************************************/
10481
10482 WERROR _spoolss_GetPrinterDriver2(pipes_struct *p,
10483                                   struct spoolss_GetPrinterDriver2 *r)
10484 {
10485         p->rng_fault_state = true;
10486         return WERR_NOT_SUPPORTED;
10487 }
10488
10489 /****************************************************************
10490  _spoolss_FindFirstPrinterChangeNotification
10491 ****************************************************************/
10492
10493 WERROR _spoolss_FindFirstPrinterChangeNotification(pipes_struct *p,
10494                                                    struct spoolss_FindFirstPrinterChangeNotification *r)
10495 {
10496         p->rng_fault_state = true;
10497         return WERR_NOT_SUPPORTED;
10498 }
10499
10500 /****************************************************************
10501  _spoolss_FindNextPrinterChangeNotification
10502 ****************************************************************/
10503
10504 WERROR _spoolss_FindNextPrinterChangeNotification(pipes_struct *p,
10505                                                   struct spoolss_FindNextPrinterChangeNotification *r)
10506 {
10507         p->rng_fault_state = true;
10508         return WERR_NOT_SUPPORTED;
10509 }
10510
10511 /****************************************************************
10512  _spoolss_RouterFindFirstPrinterChangeNotificationOld
10513 ****************************************************************/
10514
10515 WERROR _spoolss_RouterFindFirstPrinterChangeNotificationOld(pipes_struct *p,
10516                                                             struct spoolss_RouterFindFirstPrinterChangeNotificationOld *r)
10517 {
10518         p->rng_fault_state = true;
10519         return WERR_NOT_SUPPORTED;
10520 }
10521
10522 /****************************************************************
10523  _spoolss_ReplyOpenPrinter
10524 ****************************************************************/
10525
10526 WERROR _spoolss_ReplyOpenPrinter(pipes_struct *p,
10527                                  struct spoolss_ReplyOpenPrinter *r)
10528 {
10529         p->rng_fault_state = true;
10530         return WERR_NOT_SUPPORTED;
10531 }
10532
10533 /****************************************************************
10534  _spoolss_RouterReplyPrinter
10535 ****************************************************************/
10536
10537 WERROR _spoolss_RouterReplyPrinter(pipes_struct *p,
10538                                    struct spoolss_RouterReplyPrinter *r)
10539 {
10540         p->rng_fault_state = true;
10541         return WERR_NOT_SUPPORTED;
10542 }
10543
10544 /****************************************************************
10545  _spoolss_ReplyClosePrinter
10546 ****************************************************************/
10547
10548 WERROR _spoolss_ReplyClosePrinter(pipes_struct *p,
10549                                   struct spoolss_ReplyClosePrinter *r)
10550 {
10551         p->rng_fault_state = true;
10552         return WERR_NOT_SUPPORTED;
10553 }
10554
10555 /****************************************************************
10556  _spoolss_AddPortEx
10557 ****************************************************************/
10558
10559 WERROR _spoolss_AddPortEx(pipes_struct *p,
10560                           struct spoolss_AddPortEx *r)
10561 {
10562         p->rng_fault_state = true;
10563         return WERR_NOT_SUPPORTED;
10564 }
10565
10566 /****************************************************************
10567  _spoolss_RouterFindFirstPrinterChangeNotification
10568 ****************************************************************/
10569
10570 WERROR _spoolss_RouterFindFirstPrinterChangeNotification(pipes_struct *p,
10571                                                          struct spoolss_RouterFindFirstPrinterChangeNotification *r)
10572 {
10573         p->rng_fault_state = true;
10574         return WERR_NOT_SUPPORTED;
10575 }
10576
10577 /****************************************************************
10578  _spoolss_SpoolerInit
10579 ****************************************************************/
10580
10581 WERROR _spoolss_SpoolerInit(pipes_struct *p,
10582                             struct spoolss_SpoolerInit *r)
10583 {
10584         p->rng_fault_state = true;
10585         return WERR_NOT_SUPPORTED;
10586 }
10587
10588 /****************************************************************
10589  _spoolss_ResetPrinterEx
10590 ****************************************************************/
10591
10592 WERROR _spoolss_ResetPrinterEx(pipes_struct *p,
10593                                struct spoolss_ResetPrinterEx *r)
10594 {
10595         p->rng_fault_state = true;
10596         return WERR_NOT_SUPPORTED;
10597 }
10598
10599 /****************************************************************
10600  _spoolss_RouterReplyPrinterEx
10601 ****************************************************************/
10602
10603 WERROR _spoolss_RouterReplyPrinterEx(pipes_struct *p,
10604                                      struct spoolss_RouterReplyPrinterEx *r)
10605 {
10606         p->rng_fault_state = true;
10607         return WERR_NOT_SUPPORTED;
10608 }
10609
10610 /****************************************************************
10611  _spoolss_44
10612 ****************************************************************/
10613
10614 WERROR _spoolss_44(pipes_struct *p,
10615                    struct spoolss_44 *r)
10616 {
10617         p->rng_fault_state = true;
10618         return WERR_NOT_SUPPORTED;
10619 }
10620
10621 /****************************************************************
10622  _spoolss_47
10623 ****************************************************************/
10624
10625 WERROR _spoolss_47(pipes_struct *p,
10626                    struct spoolss_47 *r)
10627 {
10628         p->rng_fault_state = true;
10629         return WERR_NOT_SUPPORTED;
10630 }
10631
10632 /****************************************************************
10633  _spoolss_EnumPrinterData
10634 ****************************************************************/
10635
10636 WERROR _spoolss_EnumPrinterData(pipes_struct *p,
10637                                 struct spoolss_EnumPrinterData *r)
10638 {
10639         p->rng_fault_state = true;
10640         return WERR_NOT_SUPPORTED;
10641 }
10642
10643 /****************************************************************
10644  _spoolss_4a
10645 ****************************************************************/
10646
10647 WERROR _spoolss_4a(pipes_struct *p,
10648                    struct spoolss_4a *r)
10649 {
10650         p->rng_fault_state = true;
10651         return WERR_NOT_SUPPORTED;
10652 }
10653
10654 /****************************************************************
10655  _spoolss_4b
10656 ****************************************************************/
10657
10658 WERROR _spoolss_4b(pipes_struct *p,
10659                    struct spoolss_4b *r)
10660 {
10661         p->rng_fault_state = true;
10662         return WERR_NOT_SUPPORTED;
10663 }
10664
10665 /****************************************************************
10666  _spoolss_4c
10667 ****************************************************************/
10668
10669 WERROR _spoolss_4c(pipes_struct *p,
10670                    struct spoolss_4c *r)
10671 {
10672         p->rng_fault_state = true;
10673         return WERR_NOT_SUPPORTED;
10674 }
10675
10676 /****************************************************************
10677  _spoolss_EnumPrinterDataEx
10678 ****************************************************************/
10679
10680 WERROR _spoolss_EnumPrinterDataEx(pipes_struct *p,
10681                                   struct spoolss_EnumPrinterDataEx *r)
10682 {
10683         p->rng_fault_state = true;
10684         return WERR_NOT_SUPPORTED;
10685 }
10686
10687 /****************************************************************
10688  _spoolss_EnumPrinterKey
10689 ****************************************************************/
10690
10691 WERROR _spoolss_EnumPrinterKey(pipes_struct *p,
10692                                struct spoolss_EnumPrinterKey *r)
10693 {
10694         p->rng_fault_state = true;
10695         return WERR_NOT_SUPPORTED;
10696 }
10697
10698 /****************************************************************
10699  _spoolss_53
10700 ****************************************************************/
10701
10702 WERROR _spoolss_53(pipes_struct *p,
10703                    struct spoolss_53 *r)
10704 {
10705         p->rng_fault_state = true;
10706         return WERR_NOT_SUPPORTED;
10707 }
10708
10709 /****************************************************************
10710  _spoolss_55
10711 ****************************************************************/
10712
10713 WERROR _spoolss_55(pipes_struct *p,
10714                    struct spoolss_55 *r)
10715 {
10716         p->rng_fault_state = true;
10717         return WERR_NOT_SUPPORTED;
10718 }
10719
10720 /****************************************************************
10721  _spoolss_56
10722 ****************************************************************/
10723
10724 WERROR _spoolss_56(pipes_struct *p,
10725                    struct spoolss_56 *r)
10726 {
10727         p->rng_fault_state = true;
10728         return WERR_NOT_SUPPORTED;
10729 }
10730
10731 /****************************************************************
10732  _spoolss_57
10733 ****************************************************************/
10734
10735 WERROR _spoolss_57(pipes_struct *p,
10736                    struct spoolss_57 *r)
10737 {
10738         p->rng_fault_state = true;
10739         return WERR_NOT_SUPPORTED;
10740 }
10741
10742 /****************************************************************
10743  _spoolss_5a
10744 ****************************************************************/
10745
10746 WERROR _spoolss_5a(pipes_struct *p,
10747                    struct spoolss_5a *r)
10748 {
10749         p->rng_fault_state = true;
10750         return WERR_NOT_SUPPORTED;
10751 }
10752
10753 /****************************************************************
10754  _spoolss_5b
10755 ****************************************************************/
10756
10757 WERROR _spoolss_5b(pipes_struct *p,
10758                    struct spoolss_5b *r)
10759 {
10760         p->rng_fault_state = true;
10761         return WERR_NOT_SUPPORTED;
10762 }
10763
10764 /****************************************************************
10765  _spoolss_5c
10766 ****************************************************************/
10767
10768 WERROR _spoolss_5c(pipes_struct *p,
10769                    struct spoolss_5c *r)
10770 {
10771         p->rng_fault_state = true;
10772         return WERR_NOT_SUPPORTED;
10773 }
10774
10775 /****************************************************************
10776  _spoolss_5d
10777 ****************************************************************/
10778
10779 WERROR _spoolss_5d(pipes_struct *p,
10780                    struct spoolss_5d *r)
10781 {
10782         p->rng_fault_state = true;
10783         return WERR_NOT_SUPPORTED;
10784 }
10785
10786 /****************************************************************
10787  _spoolss_5e
10788 ****************************************************************/
10789
10790 WERROR _spoolss_5e(pipes_struct *p,
10791                    struct spoolss_5e *r)
10792 {
10793         p->rng_fault_state = true;
10794         return WERR_NOT_SUPPORTED;
10795 }
10796
10797 /****************************************************************
10798  _spoolss_5f
10799 ****************************************************************/
10800
10801 WERROR _spoolss_5f(pipes_struct *p,
10802                    struct spoolss_5f *r)
10803 {
10804         p->rng_fault_state = true;
10805         return WERR_NOT_SUPPORTED;
10806 }
10807