s3-spoolss: use pidl for _spoolss_EnumMonitors.
[vlendec/samba-autobuild/.git] / source3 / rpc_server / srv_spoolss_nt.c
1 /*
2  *  Unix SMB/CIFS implementation.
3  *  RPC Pipe client / server routines
4  *  Copyright (C) Andrew Tridgell              1992-2000,
5  *  Copyright (C) Luke Kenneth Casson Leighton 1996-2000,
6  *  Copyright (C) Jean François Micouleau      1998-2000,
7  *  Copyright (C) Jeremy Allison               2001-2002,
8  *  Copyright (C) Gerald Carter                2000-2004,
9  *  Copyright (C) Tim Potter                   2001-2002.
10  *
11  *  This program is free software; you can redistribute it and/or modify
12  *  it under the terms of the GNU General Public License as published by
13  *  the Free Software Foundation; either version 3 of the License, or
14  *  (at your option) any later version.
15  *
16  *  This program is distributed in the hope that it will be useful,
17  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
18  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19  *  GNU General Public License for more details.
20  *
21  *  You should have received a copy of the GNU General Public License
22  *  along with this program; if not, see <http://www.gnu.org/licenses/>.
23  */
24
25 /* Since the SPOOLSS rpc routines are basically DOS 16-bit calls wrapped
26    up, all the errors returned are DOS errors, not NT status codes. */
27
28 #include "includes.h"
29
30 extern userdom_struct current_user_info;
31
32 #undef DBGC_CLASS
33 #define DBGC_CLASS DBGC_RPC_SRV
34
35 #ifndef MAX_OPEN_PRINTER_EXS
36 #define MAX_OPEN_PRINTER_EXS 50
37 #endif
38
39 #define MAGIC_DISPLAY_FREQUENCY 0xfade2bad
40 #define PHANTOM_DEVMODE_KEY "_p_f_a_n_t_0_m_"
41
42 struct table_node {
43         const char    *long_archi;
44         const char    *short_archi;
45         int     version;
46 };
47
48 static Printer_entry *printers_list;
49
50 typedef struct _counter_printer_0 {
51         struct _counter_printer_0 *next;
52         struct _counter_printer_0 *prev;
53
54         int snum;
55         uint32 counter;
56 } counter_printer_0;
57
58 static counter_printer_0 *counter_list;
59
60 static struct rpc_pipe_client *notify_cli_pipe; /* print notify back-channel pipe handle*/
61 static uint32 smb_connections=0;
62
63
64 /* in printing/nt_printing.c */
65
66 extern struct standard_mapping printer_std_mapping, printserver_std_mapping;
67
68 /* API table for Xcv Monitor functions */
69
70 struct xcv_api_table {
71         const char *name;
72         WERROR(*fn) (TALLOC_CTX *mem_ctx, NT_USER_TOKEN *token, DATA_BLOB *in, DATA_BLOB *out, uint32_t *needed);
73 };
74
75 /********************************************************************
76  * Canonicalize servername.
77  ********************************************************************/
78
79 static const char *canon_servername(const char *servername)
80 {
81         const char *pservername = servername;
82         while (*pservername == '\\') {
83                 pservername++;
84         }
85         return pservername;
86 }
87
88 /* translate between internal status numbers and NT status numbers */
89 static int nt_printj_status(int v)
90 {
91         switch (v) {
92         case LPQ_QUEUED:
93                 return 0;
94         case LPQ_PAUSED:
95                 return JOB_STATUS_PAUSED;
96         case LPQ_SPOOLING:
97                 return JOB_STATUS_SPOOLING;
98         case LPQ_PRINTING:
99                 return JOB_STATUS_PRINTING;
100         case LPQ_ERROR:
101                 return JOB_STATUS_ERROR;
102         case LPQ_DELETING:
103                 return JOB_STATUS_DELETING;
104         case LPQ_OFFLINE:
105                 return JOB_STATUS_OFFLINE;
106         case LPQ_PAPEROUT:
107                 return JOB_STATUS_PAPEROUT;
108         case LPQ_PRINTED:
109                 return JOB_STATUS_PRINTED;
110         case LPQ_DELETED:
111                 return JOB_STATUS_DELETED;
112         case LPQ_BLOCKED:
113                 return JOB_STATUS_BLOCKED_DEVQ;
114         case LPQ_USER_INTERVENTION:
115                 return JOB_STATUS_USER_INTERVENTION;
116         }
117         return 0;
118 }
119
120 static int nt_printq_status(int v)
121 {
122         switch (v) {
123         case LPQ_PAUSED:
124                 return PRINTER_STATUS_PAUSED;
125         case LPQ_QUEUED:
126         case LPQ_SPOOLING:
127         case LPQ_PRINTING:
128                 return 0;
129         }
130         return 0;
131 }
132
133 /***************************************************************************
134  Disconnect from the client
135 ****************************************************************************/
136
137 static void srv_spoolss_replycloseprinter(int snum, POLICY_HND *handle)
138 {
139         WERROR result;
140         NTSTATUS status;
141
142         /*
143          * Tell the specific printing tdb we no longer want messages for this printer
144          * by deregistering our PID.
145          */
146
147         if (!print_notify_deregister_pid(snum))
148                 DEBUG(0,("print_notify_register_pid: Failed to register our pid for printer %s\n", lp_const_servicename(snum) ));
149
150         /* weird if the test succeds !!! */
151         if (smb_connections==0) {
152                 DEBUG(0,("srv_spoolss_replycloseprinter:Trying to close non-existant notify backchannel !\n"));
153                 return;
154         }
155
156         status = rpccli_spoolss_ReplyClosePrinter(notify_cli_pipe, talloc_tos(),
157                                                   handle,
158                                                   &result);
159         if (!NT_STATUS_IS_OK(status) || !W_ERROR_IS_OK(result))
160                 DEBUG(0,("srv_spoolss_replycloseprinter: reply_close_printer failed [%s].\n",
161                         win_errstr(result)));
162
163         /* if it's the last connection, deconnect the IPC$ share */
164         if (smb_connections==1) {
165
166                 cli_shutdown( rpc_pipe_np_smb_conn(notify_cli_pipe) );
167                 notify_cli_pipe = NULL; /* The above call shuts downn the pipe also. */
168
169                 messaging_deregister(smbd_messaging_context(),
170                                      MSG_PRINTER_NOTIFY2, NULL);
171
172                 /* Tell the connections db we're no longer interested in
173                  * printer notify messages. */
174
175                 register_message_flags( False, FLAG_MSG_PRINT_NOTIFY );
176         }
177
178         smb_connections--;
179 }
180
181 /****************************************************************************
182  Functions to free a printer entry datastruct.
183 ****************************************************************************/
184
185 static int printer_entry_destructor(Printer_entry *Printer)
186 {
187         if (Printer->notify.client_connected==True) {
188                 int snum = -1;
189
190                 if ( Printer->printer_type == SPLHND_SERVER) {
191                         snum = -1;
192                         srv_spoolss_replycloseprinter(snum, &Printer->notify.client_hnd);
193                 } else if (Printer->printer_type == SPLHND_PRINTER) {
194                         snum = print_queue_snum(Printer->sharename);
195                         if (snum != -1)
196                                 srv_spoolss_replycloseprinter(snum,
197                                                 &Printer->notify.client_hnd);
198                 }
199         }
200
201         Printer->notify.flags=0;
202         Printer->notify.options=0;
203         Printer->notify.localmachine[0]='\0';
204         Printer->notify.printerlocal=0;
205         TALLOC_FREE(Printer->notify.option);
206         Printer->notify.client_connected=False;
207
208         free_nt_devicemode( &Printer->nt_devmode );
209         free_a_printer( &Printer->printer_info, 2 );
210
211         /* Remove from the internal list. */
212         DLIST_REMOVE(printers_list, Printer);
213         return 0;
214 }
215
216 /****************************************************************************
217   find printer index by handle
218 ****************************************************************************/
219
220 static Printer_entry *find_printer_index_by_hnd(pipes_struct *p, POLICY_HND *hnd)
221 {
222         Printer_entry *find_printer = NULL;
223
224         if(!find_policy_by_hnd(p,hnd,(void **)(void *)&find_printer)) {
225                 DEBUG(2,("find_printer_index_by_hnd: Printer handle not found: "));
226                 return NULL;
227         }
228
229         return find_printer;
230 }
231
232 /****************************************************************************
233  Close printer index by handle.
234 ****************************************************************************/
235
236 static bool close_printer_handle(pipes_struct *p, POLICY_HND *hnd)
237 {
238         Printer_entry *Printer = find_printer_index_by_hnd(p, hnd);
239
240         if (!Printer) {
241                 DEBUG(2,("close_printer_handle: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(hnd)));
242                 return False;
243         }
244
245         close_policy_hnd(p, hnd);
246
247         return True;
248 }
249
250 /****************************************************************************
251  Delete a printer given a handle.
252 ****************************************************************************/
253
254 WERROR delete_printer_hook(TALLOC_CTX *ctx, NT_USER_TOKEN *token, const char *sharename )
255 {
256         char *cmd = lp_deleteprinter_cmd();
257         char *command = NULL;
258         int ret;
259         SE_PRIV se_printop = SE_PRINT_OPERATOR;
260         bool is_print_op = False;
261
262         /* can't fail if we don't try */
263
264         if ( !*cmd )
265                 return WERR_OK;
266
267         command = talloc_asprintf(ctx,
268                         "%s \"%s\"",
269                         cmd, sharename);
270         if (!command) {
271                 return WERR_NOMEM;
272         }
273         if ( token )
274                 is_print_op = user_has_privileges( token, &se_printop );
275
276         DEBUG(10,("Running [%s]\n", command));
277
278         /********** BEGIN SePrintOperatorPrivlege BLOCK **********/
279
280         if ( is_print_op )
281                 become_root();
282
283         if ( (ret = smbrun(command, NULL)) == 0 ) {
284                 /* Tell everyone we updated smb.conf. */
285                 message_send_all(smbd_messaging_context(),
286                                  MSG_SMB_CONF_UPDATED, NULL, 0, NULL);
287         }
288
289         if ( is_print_op )
290                 unbecome_root();
291
292         /********** END SePrintOperatorPrivlege BLOCK **********/
293
294         DEBUGADD(10,("returned [%d]\n", ret));
295
296         TALLOC_FREE(command);
297
298         if (ret != 0)
299                 return WERR_BADFID; /* What to return here? */
300
301         /* go ahead and re-read the services immediately */
302         reload_services( False );
303
304         if ( lp_servicenumber( sharename )  < 0 )
305                 return WERR_ACCESS_DENIED;
306
307         return WERR_OK;
308 }
309
310 /****************************************************************************
311  Delete a printer given a handle.
312 ****************************************************************************/
313
314 static WERROR delete_printer_handle(pipes_struct *p, POLICY_HND *hnd)
315 {
316         Printer_entry *Printer = find_printer_index_by_hnd(p, hnd);
317
318         if (!Printer) {
319                 DEBUG(2,("delete_printer_handle: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(hnd)));
320                 return WERR_BADFID;
321         }
322
323         /*
324          * It turns out that Windows allows delete printer on a handle
325          * opened by an admin user, then used on a pipe handle created
326          * by an anonymous user..... but they're working on security.... riiight !
327          * JRA.
328          */
329
330         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
331                 DEBUG(3, ("delete_printer_handle: denied by handle\n"));
332                 return WERR_ACCESS_DENIED;
333         }
334
335         /* this does not need a become root since the access check has been
336            done on the handle already */
337
338         if (del_a_printer( Printer->sharename ) != 0) {
339                 DEBUG(3,("Error deleting printer %s\n", Printer->sharename));
340                 return WERR_BADFID;
341         }
342
343         return delete_printer_hook(p->mem_ctx, p->server_info->ptok,
344                                    Printer->sharename );
345 }
346
347 /****************************************************************************
348  Return the snum of a printer corresponding to an handle.
349 ****************************************************************************/
350
351 static bool get_printer_snum(pipes_struct *p, POLICY_HND *hnd, int *number,
352                              struct share_params **params)
353 {
354         Printer_entry *Printer = find_printer_index_by_hnd(p, hnd);
355
356         if (!Printer) {
357                 DEBUG(2,("get_printer_snum: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(hnd)));
358                 return False;
359         }
360
361         switch (Printer->printer_type) {
362                 case SPLHND_PRINTER:
363                         DEBUG(4,("short name:%s\n", Printer->sharename));
364                         *number = print_queue_snum(Printer->sharename);
365                         return (*number != -1);
366                 case SPLHND_SERVER:
367                         return False;
368                 default:
369                         return False;
370         }
371 }
372
373 /****************************************************************************
374  Set printer handle type.
375  Check if it's \\server or \\server\printer
376 ****************************************************************************/
377
378 static bool set_printer_hnd_printertype(Printer_entry *Printer, char *handlename)
379 {
380         DEBUG(3,("Setting printer type=%s\n", handlename));
381
382         if ( strlen(handlename) < 3 ) {
383                 DEBUGADD(4,("A print server must have at least 1 char ! %s\n", handlename));
384                 return False;
385         }
386
387         /* it's a print server */
388         if (*handlename=='\\' && *(handlename+1)=='\\' && !strchr_m(handlename+2, '\\')) {
389                 DEBUGADD(4,("Printer is a print server\n"));
390                 Printer->printer_type = SPLHND_SERVER;
391         }
392         /* it's a printer (set_printer_hnd_name() will handle port monitors */
393         else {
394                 DEBUGADD(4,("Printer is a printer\n"));
395                 Printer->printer_type = SPLHND_PRINTER;
396         }
397
398         return True;
399 }
400
401 /****************************************************************************
402  Set printer handle name..  Accept names like \\server, \\server\printer,
403  \\server\SHARE, & "\\server\,XcvMonitor Standard TCP/IP Port"    See
404  the MSDN docs regarding OpenPrinter() for details on the XcvData() and
405  XcvDataPort() interface.
406 ****************************************************************************/
407
408 static bool set_printer_hnd_name(Printer_entry *Printer, char *handlename)
409 {
410         int snum;
411         int n_services=lp_numservices();
412         char *aprinter, *printername;
413         const char *servername;
414         fstring sname;
415         bool found=False;
416         NT_PRINTER_INFO_LEVEL *printer = NULL;
417         WERROR result;
418
419         DEBUG(4,("Setting printer name=%s (len=%lu)\n", handlename, (unsigned long)strlen(handlename)));
420
421         aprinter = handlename;
422         if ( *handlename == '\\' ) {
423                 servername = canon_servername(handlename);
424                 if ( (aprinter = strchr_m( servername, '\\' )) != NULL ) {
425                         *aprinter = '\0';
426                         aprinter++;
427                 }
428         } else {
429                 servername = "";
430         }
431
432         /* save the servername to fill in replies on this handle */
433
434         if ( !is_myname_or_ipaddr( servername ) )
435                 return False;
436
437         fstrcpy( Printer->servername, servername );
438
439         if ( Printer->printer_type == SPLHND_SERVER )
440                 return True;
441
442         if ( Printer->printer_type != SPLHND_PRINTER )
443                 return False;
444
445         DEBUGADD(5, ("searching for [%s]\n", aprinter ));
446
447         /* check for the Port Monitor Interface */
448
449         if ( strequal( aprinter, SPL_XCV_MONITOR_TCPMON ) ) {
450                 Printer->printer_type = SPLHND_PORTMON_TCP;
451                 fstrcpy(sname, SPL_XCV_MONITOR_TCPMON);
452                 found = True;
453         }
454         else if ( strequal( aprinter, SPL_XCV_MONITOR_LOCALMON ) ) {
455                 Printer->printer_type = SPLHND_PORTMON_LOCAL;
456                 fstrcpy(sname, SPL_XCV_MONITOR_LOCALMON);
457                 found = True;
458         }
459
460         /* Search all sharenames first as this is easier than pulling
461            the printer_info_2 off of disk. Don't use find_service() since
462            that calls out to map_username() */
463
464         /* do another loop to look for printernames */
465
466         for (snum=0; !found && snum<n_services; snum++) {
467
468                 /* no point going on if this is not a printer */
469
470                 if ( !(lp_snum_ok(snum) && lp_print_ok(snum)) )
471                         continue;
472
473                 fstrcpy(sname, lp_servicename(snum));
474                 if ( strequal( aprinter, sname ) ) {
475                         found = True;
476                         break;
477                 }
478
479                 /* no point looking up the printer object if
480                    we aren't allowing printername != sharename */
481
482                 if ( lp_force_printername(snum) )
483                         continue;
484
485                 fstrcpy(sname, lp_servicename(snum));
486
487                 printer = NULL;
488
489                 /* This call doesn't fill in the location or comment from
490                  * a CUPS server for efficiency with large numbers of printers.
491                  * JRA.
492                  */
493
494                 result = get_a_printer_search( NULL, &printer, 2, sname );
495                 if ( !W_ERROR_IS_OK(result) ) {
496                         DEBUG(0,("set_printer_hnd_name: failed to lookup printer [%s] -- result [%s]\n",
497                                 sname, win_errstr(result)));
498                         continue;
499                 }
500
501                 /* printername is always returned as \\server\printername */
502                 if ( !(printername = strchr_m(&printer->info_2->printername[2], '\\')) ) {
503                         DEBUG(0,("set_printer_hnd_name: info2->printername in wrong format! [%s]\n",
504                                 printer->info_2->printername));
505                         free_a_printer( &printer, 2);
506                         continue;
507                 }
508
509                 printername++;
510
511                 if ( strequal(printername, aprinter) ) {
512                         free_a_printer( &printer, 2);
513                         found = True;
514                         break;
515                 }
516
517                 DEBUGADD(10, ("printername: %s\n", printername));
518
519                 free_a_printer( &printer, 2);
520         }
521
522         free_a_printer( &printer, 2);
523
524         if ( !found ) {
525                 DEBUGADD(4,("Printer not found\n"));
526                 return False;
527         }
528
529         DEBUGADD(4,("set_printer_hnd_name: Printer found: %s -> %s\n", aprinter, sname));
530
531         fstrcpy(Printer->sharename, sname);
532
533         return True;
534 }
535
536 /****************************************************************************
537  Find first available printer slot. creates a printer handle for you.
538  ****************************************************************************/
539
540 static bool open_printer_hnd(pipes_struct *p, POLICY_HND *hnd, char *name, uint32 access_granted)
541 {
542         Printer_entry *new_printer;
543
544         DEBUG(10,("open_printer_hnd: name [%s]\n", name));
545
546         new_printer = TALLOC_ZERO_P(NULL, Printer_entry);
547         if (new_printer == NULL) {
548                 return false;
549         }
550         talloc_set_destructor(new_printer, printer_entry_destructor);
551
552         if (!create_policy_hnd(p, hnd, new_printer)) {
553                 TALLOC_FREE(new_printer);
554                 return False;
555         }
556
557         /* Add to the internal list. */
558         DLIST_ADD(printers_list, new_printer);
559
560         new_printer->notify.option=NULL;
561
562         if (!set_printer_hnd_printertype(new_printer, name)) {
563                 close_printer_handle(p, hnd);
564                 return False;
565         }
566
567         if (!set_printer_hnd_name(new_printer, name)) {
568                 close_printer_handle(p, hnd);
569                 return False;
570         }
571
572         new_printer->access_granted = access_granted;
573
574         DEBUG(5, ("%d printer handles active\n", (int)p->pipe_handles->count ));
575
576         return True;
577 }
578
579 /***************************************************************************
580  check to see if the client motify handle is monitoring the notification
581  given by (notify_type, notify_field).
582  **************************************************************************/
583
584 static bool is_monitoring_event_flags(uint32 flags, uint16 notify_type,
585                                       uint16 notify_field)
586 {
587         return True;
588 }
589
590 static bool is_monitoring_event(Printer_entry *p, uint16 notify_type,
591                                 uint16 notify_field)
592 {
593         struct spoolss_NotifyOption *option = p->notify.option;
594         uint32 i, j;
595
596         /*
597          * Flags should always be zero when the change notify
598          * is registered by the client's spooler.  A user Win32 app
599          * might use the flags though instead of the NOTIFY_OPTION_INFO
600          * --jerry
601          */
602
603         if (!option) {
604                 return False;
605         }
606
607         if (p->notify.flags)
608                 return is_monitoring_event_flags(
609                         p->notify.flags, notify_type, notify_field);
610
611         for (i = 0; i < option->count; i++) {
612
613                 /* Check match for notify_type */
614
615                 if (option->types[i].type != notify_type)
616                         continue;
617
618                 /* Check match for field */
619
620                 for (j = 0; j < option->types[i].count; j++) {
621                         if (option->types[i].fields[j] == notify_field) {
622                                 return True;
623                         }
624                 }
625         }
626
627         DEBUG(10, ("Open handle for \\\\%s\\%s is not monitoring 0x%02x/0x%02x\n",
628                    p->servername, p->sharename, notify_type, notify_field));
629
630         return False;
631 }
632
633 #define SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(_data, _integer) \
634         _data->data.integer[0] = _integer; \
635         _data->data.integer[1] = 0;
636
637
638 #define SETUP_SPOOLSS_NOTIFY_DATA_STRING(_data, _p) \
639         _data->data.string.string = talloc_strdup(mem_ctx, _p); \
640         if (!_data->data.string.string) {\
641                 _data->data.string.size = 0; \
642         } \
643         _data->data.string.size = strlen_m_term(_p) * 2;
644
645 #define SETUP_SPOOLSS_NOTIFY_DATA_DEVMODE(_data, _devmode) \
646         _data->data.devmode.devmode = _devmode;
647
648 #define SETUP_SPOOLSS_NOTIFY_DATA_SECDESC(_data, _size, _sd) \
649         _data->data.sd.sd = dup_sec_desc(mem_ctx, _sd); \
650         if (!_data->data.sd.sd) { \
651                 _data->data.sd.sd_size = 0; \
652         } \
653         _data->data.sd.sd_size = _size;
654
655 static void init_systemtime_buffer(TALLOC_CTX *mem_ctx,
656                                    struct tm *t,
657                                    const char **pp,
658                                    uint32_t *plen)
659 {
660         struct spoolss_Time st;
661         uint32_t len = 16;
662         char *p;
663
664         if (!init_systemtime(&st, t)) {
665                 return;
666         }
667
668         p = talloc_array(mem_ctx, char, len);
669         if (!p) {
670                 return;
671         }
672
673         /*
674          * Systemtime must be linearized as a set of UINT16's.
675          * Fix from Benjamin (Bj) Kuit bj@it.uts.edu.au
676          */
677
678         SSVAL(p, 0, st.year);
679         SSVAL(p, 2, st.month);
680         SSVAL(p, 4, st.day_of_week);
681         SSVAL(p, 6, st.day);
682         SSVAL(p, 8, st.hour);
683         SSVAL(p, 10, st.minute);
684         SSVAL(p, 12, st.second);
685         SSVAL(p, 14, st.millisecond);
686
687         *pp = p;
688         *plen = len;
689 }
690
691 /* Convert a notification message to a struct spoolss_Notify */
692
693 static void notify_one_value(struct spoolss_notify_msg *msg,
694                              struct spoolss_Notify *data,
695                              TALLOC_CTX *mem_ctx)
696 {
697         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, msg->notify.value[0]);
698 }
699
700 static void notify_string(struct spoolss_notify_msg *msg,
701                           struct spoolss_Notify *data,
702                           TALLOC_CTX *mem_ctx)
703 {
704         /* The length of the message includes the trailing \0 */
705
706         data->data.string.size = msg->len * 2;
707         data->data.string.string = talloc_strdup(mem_ctx, msg->notify.data);
708         if (!data->data.string.string) {
709                 data->data.string.size = 0;
710                 return;
711         }
712 }
713
714 static void notify_system_time(struct spoolss_notify_msg *msg,
715                                struct spoolss_Notify *data,
716                                TALLOC_CTX *mem_ctx)
717 {
718         data->data.string.string = NULL;
719         data->data.string.size = 0;
720
721         if (msg->len != sizeof(time_t)) {
722                 DEBUG(5, ("notify_system_time: received wrong sized message (%d)\n",
723                           msg->len));
724                 return;
725         }
726
727         init_systemtime_buffer(mem_ctx, gmtime((time_t *)msg->notify.data),
728                                &data->data.string.string,
729                                &data->data.string.size);
730 }
731
732 struct notify2_message_table {
733         const char *name;
734         void (*fn)(struct spoolss_notify_msg *msg,
735                    struct spoolss_Notify *data, TALLOC_CTX *mem_ctx);
736 };
737
738 static struct notify2_message_table printer_notify_table[] = {
739         /* 0x00 */ { "PRINTER_NOTIFY_SERVER_NAME", notify_string },
740         /* 0x01 */ { "PRINTER_NOTIFY_PRINTER_NAME", notify_string },
741         /* 0x02 */ { "PRINTER_NOTIFY_SHARE_NAME", notify_string },
742         /* 0x03 */ { "PRINTER_NOTIFY_PORT_NAME", notify_string },
743         /* 0x04 */ { "PRINTER_NOTIFY_DRIVER_NAME", notify_string },
744         /* 0x05 */ { "PRINTER_NOTIFY_COMMENT", notify_string },
745         /* 0x06 */ { "PRINTER_NOTIFY_LOCATION", notify_string },
746         /* 0x07 */ { "PRINTER_NOTIFY_DEVMODE", NULL },
747         /* 0x08 */ { "PRINTER_NOTIFY_SEPFILE", notify_string },
748         /* 0x09 */ { "PRINTER_NOTIFY_PRINT_PROCESSOR", notify_string },
749         /* 0x0a */ { "PRINTER_NOTIFY_PARAMETERS", NULL },
750         /* 0x0b */ { "PRINTER_NOTIFY_DATATYPE", notify_string },
751         /* 0x0c */ { "PRINTER_NOTIFY_SECURITY_DESCRIPTOR", NULL },
752         /* 0x0d */ { "PRINTER_NOTIFY_ATTRIBUTES", notify_one_value },
753         /* 0x0e */ { "PRINTER_NOTIFY_PRIORITY", notify_one_value },
754         /* 0x0f */ { "PRINTER_NOTIFY_DEFAULT_PRIORITY", NULL },
755         /* 0x10 */ { "PRINTER_NOTIFY_START_TIME", NULL },
756         /* 0x11 */ { "PRINTER_NOTIFY_UNTIL_TIME", NULL },
757         /* 0x12 */ { "PRINTER_NOTIFY_STATUS", notify_one_value },
758 };
759
760 static struct notify2_message_table job_notify_table[] = {
761         /* 0x00 */ { "JOB_NOTIFY_PRINTER_NAME", NULL },
762         /* 0x01 */ { "JOB_NOTIFY_MACHINE_NAME", NULL },
763         /* 0x02 */ { "JOB_NOTIFY_PORT_NAME", NULL },
764         /* 0x03 */ { "JOB_NOTIFY_USER_NAME", notify_string },
765         /* 0x04 */ { "JOB_NOTIFY_NOTIFY_NAME", NULL },
766         /* 0x05 */ { "JOB_NOTIFY_DATATYPE", NULL },
767         /* 0x06 */ { "JOB_NOTIFY_PRINT_PROCESSOR", NULL },
768         /* 0x07 */ { "JOB_NOTIFY_PARAMETERS", NULL },
769         /* 0x08 */ { "JOB_NOTIFY_DRIVER_NAME", NULL },
770         /* 0x09 */ { "JOB_NOTIFY_DEVMODE", NULL },
771         /* 0x0a */ { "JOB_NOTIFY_STATUS", notify_one_value },
772         /* 0x0b */ { "JOB_NOTIFY_STATUS_STRING", NULL },
773         /* 0x0c */ { "JOB_NOTIFY_SECURITY_DESCRIPTOR", NULL },
774         /* 0x0d */ { "JOB_NOTIFY_DOCUMENT", notify_string },
775         /* 0x0e */ { "JOB_NOTIFY_PRIORITY", NULL },
776         /* 0x0f */ { "JOB_NOTIFY_POSITION", NULL },
777         /* 0x10 */ { "JOB_NOTIFY_SUBMITTED", notify_system_time },
778         /* 0x11 */ { "JOB_NOTIFY_START_TIME", NULL },
779         /* 0x12 */ { "JOB_NOTIFY_UNTIL_TIME", NULL },
780         /* 0x13 */ { "JOB_NOTIFY_TIME", NULL },
781         /* 0x14 */ { "JOB_NOTIFY_TOTAL_PAGES", notify_one_value },
782         /* 0x15 */ { "JOB_NOTIFY_PAGES_PRINTED", NULL },
783         /* 0x16 */ { "JOB_NOTIFY_TOTAL_BYTES", notify_one_value },
784         /* 0x17 */ { "JOB_NOTIFY_BYTES_PRINTED", NULL },
785 };
786
787
788 /***********************************************************************
789  Allocate talloc context for container object
790  **********************************************************************/
791
792 static void notify_msg_ctr_init( SPOOLSS_NOTIFY_MSG_CTR *ctr )
793 {
794         if ( !ctr )
795                 return;
796
797         ctr->ctx = talloc_init("notify_msg_ctr_init %p", ctr);
798
799         return;
800 }
801
802 /***********************************************************************
803  release all allocated memory and zero out structure
804  **********************************************************************/
805
806 static void notify_msg_ctr_destroy( SPOOLSS_NOTIFY_MSG_CTR *ctr )
807 {
808         if ( !ctr )
809                 return;
810
811         if ( ctr->ctx )
812                 talloc_destroy(ctr->ctx);
813
814         ZERO_STRUCTP(ctr);
815
816         return;
817 }
818
819 /***********************************************************************
820  **********************************************************************/
821
822 static TALLOC_CTX* notify_ctr_getctx( SPOOLSS_NOTIFY_MSG_CTR *ctr )
823 {
824         if ( !ctr )
825                 return NULL;
826
827         return ctr->ctx;
828 }
829
830 /***********************************************************************
831  **********************************************************************/
832
833 static SPOOLSS_NOTIFY_MSG_GROUP* notify_ctr_getgroup( SPOOLSS_NOTIFY_MSG_CTR *ctr, uint32 idx )
834 {
835         if ( !ctr || !ctr->msg_groups )
836                 return NULL;
837
838         if ( idx >= ctr->num_groups )
839                 return NULL;
840
841         return &ctr->msg_groups[idx];
842
843 }
844
845 /***********************************************************************
846  How many groups of change messages do we have ?
847  **********************************************************************/
848
849 static int notify_msg_ctr_numgroups( SPOOLSS_NOTIFY_MSG_CTR *ctr )
850 {
851         if ( !ctr )
852                 return 0;
853
854         return ctr->num_groups;
855 }
856
857 /***********************************************************************
858  Add a SPOOLSS_NOTIFY_MSG_CTR to the correct group
859  **********************************************************************/
860
861 static int notify_msg_ctr_addmsg( SPOOLSS_NOTIFY_MSG_CTR *ctr, SPOOLSS_NOTIFY_MSG *msg )
862 {
863         SPOOLSS_NOTIFY_MSG_GROUP        *groups = NULL;
864         SPOOLSS_NOTIFY_MSG_GROUP        *msg_grp = NULL;
865         SPOOLSS_NOTIFY_MSG              *msg_list = NULL;
866         int                             i, new_slot;
867
868         if ( !ctr || !msg )
869                 return 0;
870
871         /* loop over all groups looking for a matching printer name */
872
873         for ( i=0; i<ctr->num_groups; i++ ) {
874                 if ( strcmp(ctr->msg_groups[i].printername, msg->printer) == 0 )
875                         break;
876         }
877
878         /* add a new group? */
879
880         if ( i == ctr->num_groups ) {
881                 ctr->num_groups++;
882
883                 if ( !(groups = TALLOC_REALLOC_ARRAY( ctr->ctx, ctr->msg_groups, SPOOLSS_NOTIFY_MSG_GROUP, ctr->num_groups)) ) {
884                         DEBUG(0,("notify_msg_ctr_addmsg: talloc_realloc() failed!\n"));
885                         return 0;
886                 }
887                 ctr->msg_groups = groups;
888
889                 /* clear the new entry and set the printer name */
890
891                 ZERO_STRUCT( ctr->msg_groups[ctr->num_groups-1] );
892                 fstrcpy( ctr->msg_groups[ctr->num_groups-1].printername, msg->printer );
893         }
894
895         /* add the change messages; 'i' is the correct index now regardless */
896
897         msg_grp = &ctr->msg_groups[i];
898
899         msg_grp->num_msgs++;
900
901         if ( !(msg_list = TALLOC_REALLOC_ARRAY( ctr->ctx, msg_grp->msgs, SPOOLSS_NOTIFY_MSG, msg_grp->num_msgs )) ) {
902                 DEBUG(0,("notify_msg_ctr_addmsg: talloc_realloc() failed for new message [%d]!\n", msg_grp->num_msgs));
903                 return 0;
904         }
905         msg_grp->msgs = msg_list;
906
907         new_slot = msg_grp->num_msgs-1;
908         memcpy( &msg_grp->msgs[new_slot], msg, sizeof(SPOOLSS_NOTIFY_MSG) );
909
910         /* need to allocate own copy of data */
911
912         if ( msg->len != 0 )
913                 msg_grp->msgs[new_slot].notify.data = (char *)
914                         TALLOC_MEMDUP( ctr->ctx, msg->notify.data, msg->len );
915
916         return ctr->num_groups;
917 }
918
919 /***********************************************************************
920  Send a change notication message on all handles which have a call
921  back registered
922  **********************************************************************/
923
924 static void send_notify2_changes( SPOOLSS_NOTIFY_MSG_CTR *ctr, uint32 idx )
925 {
926         Printer_entry            *p;
927         TALLOC_CTX               *mem_ctx = notify_ctr_getctx( ctr );
928         SPOOLSS_NOTIFY_MSG_GROUP *msg_group = notify_ctr_getgroup( ctr, idx );
929         SPOOLSS_NOTIFY_MSG       *messages;
930         int                      sending_msg_count;
931
932         if ( !msg_group ) {
933                 DEBUG(5,("send_notify2_changes() called with no msg group!\n"));
934                 return;
935         }
936
937         messages = msg_group->msgs;
938
939         if ( !messages ) {
940                 DEBUG(5,("send_notify2_changes() called with no messages!\n"));
941                 return;
942         }
943
944         DEBUG(8,("send_notify2_changes: Enter...[%s]\n", msg_group->printername));
945
946         /* loop over all printers */
947
948         for (p = printers_list; p; p = p->next) {
949                 struct spoolss_Notify *notifies;
950                 uint32_t count = 0;
951                 uint32_t id;
952                 int     i;
953
954                 /* Is there notification on this handle? */
955
956                 if ( !p->notify.client_connected )
957                         continue;
958
959                 DEBUG(10,("Client connected! [\\\\%s\\%s]\n", p->servername, p->sharename));
960
961                 /* For this printer?  Print servers always receive
962                    notifications. */
963
964                 if ( ( p->printer_type == SPLHND_PRINTER )  &&
965                     ( !strequal(msg_group->printername, p->sharename) ) )
966                         continue;
967
968                 DEBUG(10,("Our printer\n"));
969
970                 /* allocate the max entries possible */
971
972                 notifies = TALLOC_ZERO_ARRAY(mem_ctx, struct spoolss_Notify, msg_group->num_msgs);
973                 if (!notifies) {
974                         return;
975                 }
976
977                 /* build the array of change notifications */
978
979                 sending_msg_count = 0;
980
981                 for ( i=0; i<msg_group->num_msgs; i++ ) {
982                         SPOOLSS_NOTIFY_MSG      *msg = &messages[i];
983
984                         /* Are we monitoring this event? */
985
986                         if (!is_monitoring_event(p, msg->type, msg->field))
987                                 continue;
988
989                         sending_msg_count++;
990
991
992                         DEBUG(10,("process_notify2_message: Sending message type [0x%x] field [0x%2x] for printer [%s]\n",
993                                 msg->type, msg->field, p->sharename));
994
995                         /*
996                          * if the is a printer notification handle and not a job notification
997                          * type, then set the id to 0.  Other wise just use what was specified
998                          * in the message.
999                          *
1000                          * When registering change notification on a print server handle
1001                          * we always need to send back the id (snum) matching the printer
1002                          * for which the change took place.  For change notify registered
1003                          * on a printer handle, this does not matter and the id should be 0.
1004                          *
1005                          * --jerry
1006                          */
1007
1008                         if ( ( p->printer_type == SPLHND_PRINTER ) && ( msg->type == PRINTER_NOTIFY_TYPE ) )
1009                                 id = 0;
1010                         else
1011                                 id = msg->id;
1012
1013
1014                         /* Convert unix jobid to smb jobid */
1015
1016                         if (msg->flags & SPOOLSS_NOTIFY_MSG_UNIX_JOBID) {
1017                                 id = sysjob_to_jobid(msg->id);
1018
1019                                 if (id == -1) {
1020                                         DEBUG(3, ("no such unix jobid %d\n", msg->id));
1021                                         goto done;
1022                                 }
1023                         }
1024
1025                         construct_info_data( &notifies[count], msg->type, msg->field, id );
1026
1027                         switch(msg->type) {
1028                         case PRINTER_NOTIFY_TYPE:
1029                                 if ( printer_notify_table[msg->field].fn )
1030                                         printer_notify_table[msg->field].fn(msg, &notifies[count], mem_ctx);
1031                                 break;
1032
1033                         case JOB_NOTIFY_TYPE:
1034                                 if ( job_notify_table[msg->field].fn )
1035                                         job_notify_table[msg->field].fn(msg, &notifies[count], mem_ctx);
1036                                 break;
1037
1038                         default:
1039                                 DEBUG(5, ("Unknown notification type %d\n", msg->type));
1040                                 goto done;
1041                         }
1042
1043                         count++;
1044                 }
1045
1046                 if ( sending_msg_count ) {
1047                         NTSTATUS status;
1048                         WERROR werr;
1049                         union spoolss_ReplyPrinterInfo info;
1050                         struct spoolss_NotifyInfo info0;
1051                         uint32_t reply_result;
1052
1053                         info0.version   = 0x2;
1054                         info0.flags     = count ? 0x00020000 /* ??? */ : PRINTER_NOTIFY_INFO_DISCARDED;
1055                         info0.count     = count;
1056                         info0.notifies  = notifies;
1057
1058                         info.info0 = &info0;
1059
1060                         status = rpccli_spoolss_RouterReplyPrinterEx(notify_cli_pipe, mem_ctx,
1061                                                                      &p->notify.client_hnd,
1062                                                                      p->notify.change, /* color */
1063                                                                      p->notify.flags,
1064                                                                      &reply_result,
1065                                                                      0, /* reply_type, must be 0 */
1066                                                                      info,
1067                                                                      &werr);
1068                         if (!NT_STATUS_IS_OK(status) || !W_ERROR_IS_OK(werr)) {
1069                                 DEBUG(1,("RouterReplyPrinterEx to client: %s failed: %s\n",
1070                                         notify_cli_pipe->srv_name_slash,
1071                                         win_errstr(werr)));
1072                         }
1073                         switch (reply_result) {
1074                                 case 0:
1075                                         break;
1076                                 case PRINTER_NOTIFY_INFO_DISCARDED:
1077                                 case PRINTER_NOTIFY_INFO_DISCARDNOTED:
1078                                 case PRINTER_NOTIFY_INFO_COLOR_MISMATCH:
1079                                         break;
1080                                 default:
1081                                         break;
1082                         }
1083                 }
1084         }
1085
1086 done:
1087         DEBUG(8,("send_notify2_changes: Exit...\n"));
1088         return;
1089 }
1090
1091 /***********************************************************************
1092  **********************************************************************/
1093
1094 static bool notify2_unpack_msg( SPOOLSS_NOTIFY_MSG *msg, struct timeval *tv, void *buf, size_t len )
1095 {
1096
1097         uint32 tv_sec, tv_usec;
1098         size_t offset = 0;
1099
1100         /* Unpack message */
1101
1102         offset += tdb_unpack((uint8 *)buf + offset, len - offset, "f",
1103                              msg->printer);
1104
1105         offset += tdb_unpack((uint8 *)buf + offset, len - offset, "ddddddd",
1106                                 &tv_sec, &tv_usec,
1107                                 &msg->type, &msg->field, &msg->id, &msg->len, &msg->flags);
1108
1109         if (msg->len == 0)
1110                 tdb_unpack((uint8 *)buf + offset, len - offset, "dd",
1111                            &msg->notify.value[0], &msg->notify.value[1]);
1112         else
1113                 tdb_unpack((uint8 *)buf + offset, len - offset, "B",
1114                            &msg->len, &msg->notify.data);
1115
1116         DEBUG(3, ("notify2_unpack_msg: got NOTIFY2 message for printer %s, jobid %u type %d, field 0x%02x, flags 0x%04x\n",
1117                   msg->printer, (unsigned int)msg->id, msg->type, msg->field, msg->flags));
1118
1119         tv->tv_sec = tv_sec;
1120         tv->tv_usec = tv_usec;
1121
1122         if (msg->len == 0)
1123                 DEBUG(3, ("notify2_unpack_msg: value1 = %d, value2 = %d\n", msg->notify.value[0],
1124                           msg->notify.value[1]));
1125         else
1126                 dump_data(3, (uint8 *)msg->notify.data, msg->len);
1127
1128         return True;
1129 }
1130
1131 /********************************************************************
1132  Receive a notify2 message list
1133  ********************************************************************/
1134
1135 static void receive_notify2_message_list(struct messaging_context *msg,
1136                                          void *private_data,
1137                                          uint32_t msg_type,
1138                                          struct server_id server_id,
1139                                          DATA_BLOB *data)
1140 {
1141         size_t                  msg_count, i;
1142         char                    *buf = (char *)data->data;
1143         char                    *msg_ptr;
1144         size_t                  msg_len;
1145         SPOOLSS_NOTIFY_MSG      notify;
1146         SPOOLSS_NOTIFY_MSG_CTR  messages;
1147         int                     num_groups;
1148
1149         if (data->length < 4) {
1150                 DEBUG(0,("receive_notify2_message_list: bad message format (len < 4)!\n"));
1151                 return;
1152         }
1153
1154         msg_count = IVAL(buf, 0);
1155         msg_ptr = buf + 4;
1156
1157         DEBUG(5, ("receive_notify2_message_list: got %lu messages in list\n", (unsigned long)msg_count));
1158
1159         if (msg_count == 0) {
1160                 DEBUG(0,("receive_notify2_message_list: bad message format (msg_count == 0) !\n"));
1161                 return;
1162         }
1163
1164         /* initialize the container */
1165
1166         ZERO_STRUCT( messages );
1167         notify_msg_ctr_init( &messages );
1168
1169         /*
1170          * build message groups for each printer identified
1171          * in a change_notify msg.  Remember that a PCN message
1172          * includes the handle returned for the srv_spoolss_replyopenprinter()
1173          * call.  Therefore messages are grouped according to printer handle.
1174          */
1175
1176         for ( i=0; i<msg_count; i++ ) {
1177                 struct timeval msg_tv;
1178
1179                 if (msg_ptr + 4 - buf > data->length) {
1180                         DEBUG(0,("receive_notify2_message_list: bad message format (len > buf_size) !\n"));
1181                         return;
1182                 }
1183
1184                 msg_len = IVAL(msg_ptr,0);
1185                 msg_ptr += 4;
1186
1187                 if (msg_ptr + msg_len - buf > data->length) {
1188                         DEBUG(0,("receive_notify2_message_list: bad message format (bad len) !\n"));
1189                         return;
1190                 }
1191
1192                 /* unpack messages */
1193
1194                 ZERO_STRUCT( notify );
1195                 notify2_unpack_msg( &notify, &msg_tv, msg_ptr, msg_len );
1196                 msg_ptr += msg_len;
1197
1198                 /* add to correct list in container */
1199
1200                 notify_msg_ctr_addmsg( &messages, &notify );
1201
1202                 /* free memory that might have been allocated by notify2_unpack_msg() */
1203
1204                 if ( notify.len != 0 )
1205                         SAFE_FREE( notify.notify.data );
1206         }
1207
1208         /* process each group of messages */
1209
1210         num_groups = notify_msg_ctr_numgroups( &messages );
1211         for ( i=0; i<num_groups; i++ )
1212                 send_notify2_changes( &messages, i );
1213
1214
1215         /* cleanup */
1216
1217         DEBUG(10,("receive_notify2_message_list: processed %u messages\n", (uint32)msg_count ));
1218
1219         notify_msg_ctr_destroy( &messages );
1220
1221         return;
1222 }
1223
1224 /********************************************************************
1225  Send a message to ourself about new driver being installed
1226  so we can upgrade the information for each printer bound to this
1227  driver
1228  ********************************************************************/
1229
1230 static bool srv_spoolss_drv_upgrade_printer(char* drivername)
1231 {
1232         int len = strlen(drivername);
1233
1234         if (!len)
1235                 return False;
1236
1237         DEBUG(10,("srv_spoolss_drv_upgrade_printer: Sending message about driver upgrade [%s]\n",
1238                 drivername));
1239
1240         messaging_send_buf(smbd_messaging_context(), procid_self(),
1241                            MSG_PRINTER_DRVUPGRADE,
1242                            (uint8 *)drivername, len+1);
1243
1244         return True;
1245 }
1246
1247 /**********************************************************************
1248  callback to receive a MSG_PRINTER_DRVUPGRADE message and interate
1249  over all printers, upgrading ones as necessary
1250  **********************************************************************/
1251
1252 void do_drv_upgrade_printer(struct messaging_context *msg,
1253                             void *private_data,
1254                             uint32_t msg_type,
1255                             struct server_id server_id,
1256                             DATA_BLOB *data)
1257 {
1258         fstring drivername;
1259         int snum;
1260         int n_services = lp_numservices();
1261         size_t len;
1262
1263         len = MIN(data->length,sizeof(drivername)-1);
1264         strncpy(drivername, (const char *)data->data, len);
1265
1266         DEBUG(10,("do_drv_upgrade_printer: Got message for new driver [%s]\n", drivername ));
1267
1268         /* Iterate the printer list */
1269
1270         for (snum=0; snum<n_services; snum++)
1271         {
1272                 if (lp_snum_ok(snum) && lp_print_ok(snum) )
1273                 {
1274                         WERROR result;
1275                         NT_PRINTER_INFO_LEVEL *printer = NULL;
1276
1277                         result = get_a_printer(NULL, &printer, 2, lp_const_servicename(snum));
1278                         if (!W_ERROR_IS_OK(result))
1279                                 continue;
1280
1281                         if (printer && printer->info_2 && !strcmp(drivername, printer->info_2->drivername))
1282                         {
1283                                 DEBUG(6,("Updating printer [%s]\n", printer->info_2->printername));
1284
1285                                 /* all we care about currently is the change_id */
1286
1287                                 result = mod_a_printer(printer, 2);
1288                                 if (!W_ERROR_IS_OK(result)) {
1289                                         DEBUG(3,("do_drv_upgrade_printer: mod_a_printer() failed with status [%s]\n",
1290                                                 win_errstr(result)));
1291                                 }
1292                         }
1293
1294                         free_a_printer(&printer, 2);
1295                 }
1296         }
1297
1298         /* all done */
1299 }
1300
1301 /********************************************************************
1302  Update the cache for all printq's with a registered client
1303  connection
1304  ********************************************************************/
1305
1306 void update_monitored_printq_cache( void )
1307 {
1308         Printer_entry *printer = printers_list;
1309         int snum;
1310
1311         /* loop through all printers and update the cache where
1312            client_connected == True */
1313         while ( printer )
1314         {
1315                 if ( (printer->printer_type == SPLHND_PRINTER)
1316                         && printer->notify.client_connected )
1317                 {
1318                         snum = print_queue_snum(printer->sharename);
1319                         print_queue_status( snum, NULL, NULL );
1320                 }
1321
1322                 printer = printer->next;
1323         }
1324
1325         return;
1326 }
1327 /********************************************************************
1328  Send a message to ourself about new driver being installed
1329  so we can upgrade the information for each printer bound to this
1330  driver
1331  ********************************************************************/
1332
1333 static bool srv_spoolss_reset_printerdata(char* drivername)
1334 {
1335         int len = strlen(drivername);
1336
1337         if (!len)
1338                 return False;
1339
1340         DEBUG(10,("srv_spoolss_reset_printerdata: Sending message about resetting printerdata [%s]\n",
1341                 drivername));
1342
1343         messaging_send_buf(smbd_messaging_context(), procid_self(),
1344                            MSG_PRINTERDATA_INIT_RESET,
1345                            (uint8 *)drivername, len+1);
1346
1347         return True;
1348 }
1349
1350 /**********************************************************************
1351  callback to receive a MSG_PRINTERDATA_INIT_RESET message and interate
1352  over all printers, resetting printer data as neessary
1353  **********************************************************************/
1354
1355 void reset_all_printerdata(struct messaging_context *msg,
1356                            void *private_data,
1357                            uint32_t msg_type,
1358                            struct server_id server_id,
1359                            DATA_BLOB *data)
1360 {
1361         fstring drivername;
1362         int snum;
1363         int n_services = lp_numservices();
1364         size_t len;
1365
1366         len = MIN( data->length, sizeof(drivername)-1 );
1367         strncpy( drivername, (const char *)data->data, len );
1368
1369         DEBUG(10,("reset_all_printerdata: Got message for new driver [%s]\n", drivername ));
1370
1371         /* Iterate the printer list */
1372
1373         for ( snum=0; snum<n_services; snum++ )
1374         {
1375                 if ( lp_snum_ok(snum) && lp_print_ok(snum) )
1376                 {
1377                         WERROR result;
1378                         NT_PRINTER_INFO_LEVEL *printer = NULL;
1379
1380                         result = get_a_printer( NULL, &printer, 2, lp_const_servicename(snum) );
1381                         if ( !W_ERROR_IS_OK(result) )
1382                                 continue;
1383
1384                         /*
1385                          * if the printer is bound to the driver,
1386                          * then reset to the new driver initdata
1387                          */
1388
1389                         if ( printer && printer->info_2 && !strcmp(drivername, printer->info_2->drivername) )
1390                         {
1391                                 DEBUG(6,("reset_all_printerdata: Updating printer [%s]\n", printer->info_2->printername));
1392
1393                                 if ( !set_driver_init(printer, 2) ) {
1394                                         DEBUG(5,("reset_all_printerdata: Error resetting printer data for printer [%s], driver [%s]!\n",
1395                                                 printer->info_2->printername, printer->info_2->drivername));
1396                                 }
1397
1398                                 result = mod_a_printer( printer, 2 );
1399                                 if ( !W_ERROR_IS_OK(result) ) {
1400                                         DEBUG(3,("reset_all_printerdata: mod_a_printer() failed!  (%s)\n",
1401                                                 get_dos_error_msg(result)));
1402                                 }
1403                         }
1404
1405                         free_a_printer( &printer, 2 );
1406                 }
1407         }
1408
1409         /* all done */
1410
1411         return;
1412 }
1413
1414 /****************************************************************
1415  _spoolss_OpenPrinter
1416 ****************************************************************/
1417
1418 WERROR _spoolss_OpenPrinter(pipes_struct *p,
1419                             struct spoolss_OpenPrinter *r)
1420 {
1421         struct spoolss_OpenPrinterEx e;
1422         WERROR werr;
1423
1424         ZERO_STRUCT(e.in.userlevel);
1425
1426         e.in.printername        = r->in.printername;
1427         e.in.datatype           = r->in.datatype;
1428         e.in.devmode_ctr        = r->in.devmode_ctr;
1429         e.in.access_mask        = r->in.access_mask;
1430         e.in.level              = 0;
1431
1432         e.out.handle            = r->out.handle;
1433
1434         werr = _spoolss_OpenPrinterEx(p, &e);
1435
1436         if (W_ERROR_EQUAL(werr, WERR_INVALID_PARAM)) {
1437                 /* OpenPrinterEx returns this for a bad
1438                  * printer name. We must return WERR_INVALID_PRINTER_NAME
1439                  * instead.
1440                  */
1441                 werr = WERR_INVALID_PRINTER_NAME;
1442         }
1443
1444         return werr;
1445 }
1446
1447 /********************************************************************
1448  FIXME: temporary convert_devicemode_new function
1449  ********************************************************************/
1450
1451 static bool convert_devicemode_new(const char *printername,
1452                                    struct spoolss_DeviceMode *devmode,
1453                                    NT_DEVICEMODE **pp_nt_devmode)
1454 {
1455         NT_DEVICEMODE *nt_devmode = *pp_nt_devmode;
1456
1457         /*
1458          * Ensure nt_devmode is a valid pointer
1459          * as we will be overwriting it.
1460          */
1461
1462         if (nt_devmode == NULL) {
1463                 DEBUG(5, ("convert_devicemode_new: allocating a generic devmode\n"));
1464                 if ((nt_devmode = construct_nt_devicemode(printername)) == NULL)
1465                         return false;
1466         }
1467
1468         rpcstr_push(nt_devmode->devicename, devmode->devicename, 31, 0);
1469         rpcstr_push(nt_devmode->formname, devmode->formname, 31, 0);
1470
1471         nt_devmode->specversion         = devmode->specversion;
1472         nt_devmode->driverversion       = devmode->driverversion;
1473         nt_devmode->size                = devmode->size;
1474         nt_devmode->fields              = devmode->fields;
1475         nt_devmode->orientation         = devmode->orientation;
1476         nt_devmode->papersize           = devmode->papersize;
1477         nt_devmode->paperlength         = devmode->paperlength;
1478         nt_devmode->paperwidth          = devmode->paperwidth;
1479         nt_devmode->scale               = devmode->scale;
1480         nt_devmode->copies              = devmode->copies;
1481         nt_devmode->defaultsource       = devmode->defaultsource;
1482         nt_devmode->printquality        = devmode->printquality;
1483         nt_devmode->color               = devmode->color;
1484         nt_devmode->duplex              = devmode->duplex;
1485         nt_devmode->yresolution         = devmode->yresolution;
1486         nt_devmode->ttoption            = devmode->ttoption;
1487         nt_devmode->collate             = devmode->collate;
1488
1489         nt_devmode->logpixels           = devmode->logpixels;
1490         nt_devmode->bitsperpel          = devmode->bitsperpel;
1491         nt_devmode->pelswidth           = devmode->pelswidth;
1492         nt_devmode->pelsheight          = devmode->pelsheight;
1493         nt_devmode->displayflags        = devmode->displayflags;
1494         nt_devmode->displayfrequency    = devmode->displayfrequency;
1495         nt_devmode->icmmethod           = devmode->icmmethod;
1496         nt_devmode->icmintent           = devmode->icmintent;
1497         nt_devmode->mediatype           = devmode->mediatype;
1498         nt_devmode->dithertype          = devmode->dithertype;
1499         nt_devmode->reserved1           = devmode->reserved1;
1500         nt_devmode->reserved2           = devmode->reserved2;
1501         nt_devmode->panningwidth        = devmode->panningwidth;
1502         nt_devmode->panningheight       = devmode->panningheight;
1503
1504         /*
1505          * Only change private and driverextra if the incoming devmode
1506          * has a new one. JRA.
1507          */
1508
1509         if ((devmode->__driverextra_length != 0) && (devmode->driverextra_data.data != NULL)) {
1510                 SAFE_FREE(nt_devmode->nt_dev_private);
1511                 nt_devmode->driverextra = devmode->__driverextra_length;
1512                 if((nt_devmode->nt_dev_private=SMB_MALLOC_ARRAY(uint8, nt_devmode->driverextra)) == NULL)
1513                         return false;
1514                 memcpy(nt_devmode->nt_dev_private, devmode->driverextra_data.data, nt_devmode->driverextra);
1515         }
1516
1517         *pp_nt_devmode = nt_devmode;
1518
1519         return true;
1520 }
1521
1522 /****************************************************************
1523  _spoolss_OpenPrinterEx
1524 ****************************************************************/
1525
1526 WERROR _spoolss_OpenPrinterEx(pipes_struct *p,
1527                               struct spoolss_OpenPrinterEx *r)
1528 {
1529         POLICY_HND              *handle = r->out.handle;
1530         char *name = CONST_DISCARD(char *, r->in.printername);
1531         int snum;
1532         Printer_entry *Printer=NULL;
1533
1534         if (!name) {
1535                 return WERR_INVALID_PARAM;
1536         }
1537
1538         /* some sanity check because you can open a printer or a print server */
1539         /* aka: \\server\printer or \\server */
1540
1541         DEBUGADD(3,("checking name: %s\n",name));
1542
1543         if (!open_printer_hnd(p, handle, name, 0)) {
1544                 ZERO_STRUCTP(r->out.handle);
1545                 return WERR_INVALID_PARAM;
1546         }
1547
1548         Printer=find_printer_index_by_hnd(p, handle);
1549         if ( !Printer ) {
1550                 DEBUG(0,("_spoolss_OpenPrinterEx: logic error.  Can't find printer "
1551                         "handle we created for printer %s\n", name ));
1552                 close_printer_handle(p,handle);
1553                 ZERO_STRUCTP(r->out.handle);
1554                 return WERR_INVALID_PARAM;
1555         }
1556
1557         /*
1558          * First case: the user is opening the print server:
1559          *
1560          * Disallow MS AddPrinterWizard if parameter disables it. A Win2k
1561          * client 1st tries an OpenPrinterEx with access==0, MUST be allowed.
1562          *
1563          * Then both Win2k and WinNT clients try an OpenPrinterEx with
1564          * SERVER_ALL_ACCESS, which we allow only if the user is root (uid=0)
1565          * or if the user is listed in the smb.conf printer admin parameter.
1566          *
1567          * Then they try OpenPrinterEx with SERVER_READ which we allow. This lets the
1568          * client view printer folder, but does not show the MSAPW.
1569          *
1570          * Note: this test needs code to check access rights here too. Jeremy
1571          * could you look at this?
1572          *
1573          * Second case: the user is opening a printer:
1574          * NT doesn't let us connect to a printer if the connecting user
1575          * doesn't have print permission.
1576          *
1577          * Third case: user is opening a Port Monitor
1578          * access checks same as opening a handle to the print server.
1579          */
1580
1581         switch (Printer->printer_type )
1582         {
1583         case SPLHND_SERVER:
1584         case SPLHND_PORTMON_TCP:
1585         case SPLHND_PORTMON_LOCAL:
1586                 /* Printserver handles use global struct... */
1587
1588                 snum = -1;
1589
1590                 /* Map standard access rights to object specific access rights */
1591
1592                 se_map_standard(&r->in.access_mask,
1593                                 &printserver_std_mapping);
1594
1595                 /* Deny any object specific bits that don't apply to print
1596                    servers (i.e printer and job specific bits) */
1597
1598                 r->in.access_mask &= SPECIFIC_RIGHTS_MASK;
1599
1600                 if (r->in.access_mask &
1601                     ~(SERVER_ACCESS_ADMINISTER | SERVER_ACCESS_ENUMERATE)) {
1602                         DEBUG(3, ("access DENIED for non-printserver bits\n"));
1603                         close_printer_handle(p, handle);
1604                         ZERO_STRUCTP(r->out.handle);
1605                         return WERR_ACCESS_DENIED;
1606                 }
1607
1608                 /* Allow admin access */
1609
1610                 if ( r->in.access_mask & SERVER_ACCESS_ADMINISTER )
1611                 {
1612                         SE_PRIV se_printop = SE_PRINT_OPERATOR;
1613
1614                         if (!lp_ms_add_printer_wizard()) {
1615                                 close_printer_handle(p, handle);
1616                                 ZERO_STRUCTP(r->out.handle);
1617                                 return WERR_ACCESS_DENIED;
1618                         }
1619
1620                         /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
1621                            and not a printer admin, then fail */
1622
1623                         if ((p->server_info->utok.uid != 0) &&
1624                             !user_has_privileges(p->server_info->ptok,
1625                                                  &se_printop ) &&
1626                             !token_contains_name_in_list(
1627                                     uidtoname(p->server_info->utok.uid),
1628                                     NULL, NULL,
1629                                     p->server_info->ptok,
1630                                     lp_printer_admin(snum))) {
1631                                 close_printer_handle(p, handle);
1632                                 ZERO_STRUCTP(r->out.handle);
1633                                 return WERR_ACCESS_DENIED;
1634                         }
1635
1636                         r->in.access_mask = SERVER_ACCESS_ADMINISTER;
1637                 }
1638                 else
1639                 {
1640                         r->in.access_mask = SERVER_ACCESS_ENUMERATE;
1641                 }
1642
1643                 DEBUG(4,("Setting print server access = %s\n", (r->in.access_mask == SERVER_ACCESS_ADMINISTER)
1644                         ? "SERVER_ACCESS_ADMINISTER" : "SERVER_ACCESS_ENUMERATE" ));
1645
1646                 /* We fall through to return WERR_OK */
1647                 break;
1648
1649         case SPLHND_PRINTER:
1650                 /* NT doesn't let us connect to a printer if the connecting user
1651                    doesn't have print permission.  */
1652
1653                 if (!get_printer_snum(p, handle, &snum, NULL)) {
1654                         close_printer_handle(p, handle);
1655                         ZERO_STRUCTP(r->out.handle);
1656                         return WERR_BADFID;
1657                 }
1658
1659                 se_map_standard(&r->in.access_mask, &printer_std_mapping);
1660
1661                 /* map an empty access mask to the minimum access mask */
1662                 if (r->in.access_mask == 0x0)
1663                         r->in.access_mask = PRINTER_ACCESS_USE;
1664
1665                 /*
1666                  * If we are not serving the printer driver for this printer,
1667                  * map PRINTER_ACCESS_ADMINISTER to PRINTER_ACCESS_USE.  This
1668                  * will keep NT clients happy  --jerry
1669                  */
1670
1671                 if (lp_use_client_driver(snum)
1672                         && (r->in.access_mask & PRINTER_ACCESS_ADMINISTER))
1673                 {
1674                         r->in.access_mask = PRINTER_ACCESS_USE;
1675                 }
1676
1677                 /* check smb.conf parameters and the the sec_desc */
1678
1679                 if ( !check_access(get_client_fd(), lp_hostsallow(snum), lp_hostsdeny(snum)) ) {
1680                         DEBUG(3, ("access DENIED (hosts allow/deny) for printer open\n"));
1681                         ZERO_STRUCTP(r->out.handle);
1682                         return WERR_ACCESS_DENIED;
1683                 }
1684
1685                 if (!user_ok_token(uidtoname(p->server_info->utok.uid), NULL,
1686                                    p->server_info->ptok, snum) ||
1687                     !print_access_check(p->server_info, snum,
1688                                         r->in.access_mask)) {
1689                         DEBUG(3, ("access DENIED for printer open\n"));
1690                         close_printer_handle(p, handle);
1691                         ZERO_STRUCTP(r->out.handle);
1692                         return WERR_ACCESS_DENIED;
1693                 }
1694
1695                 if ((r->in.access_mask & SPECIFIC_RIGHTS_MASK)& ~(PRINTER_ACCESS_ADMINISTER|PRINTER_ACCESS_USE)) {
1696                         DEBUG(3, ("access DENIED for printer open - unknown bits\n"));
1697                         close_printer_handle(p, handle);
1698                         ZERO_STRUCTP(r->out.handle);
1699                         return WERR_ACCESS_DENIED;
1700                 }
1701
1702                 if (r->in.access_mask & PRINTER_ACCESS_ADMINISTER)
1703                         r->in.access_mask = PRINTER_ACCESS_ADMINISTER;
1704                 else
1705                         r->in.access_mask = PRINTER_ACCESS_USE;
1706
1707                 DEBUG(4,("Setting printer access = %s\n", (r->in.access_mask == PRINTER_ACCESS_ADMINISTER)
1708                         ? "PRINTER_ACCESS_ADMINISTER" : "PRINTER_ACCESS_USE" ));
1709
1710                 break;
1711
1712         default:
1713                 /* sanity check to prevent programmer error */
1714                 ZERO_STRUCTP(r->out.handle);
1715                 return WERR_BADFID;
1716         }
1717
1718         Printer->access_granted = r->in.access_mask;
1719
1720         /*
1721          * If the client sent a devmode in the OpenPrinter() call, then
1722          * save it here in case we get a job submission on this handle
1723          */
1724
1725          if ( (Printer->printer_type != SPLHND_SERVER)
1726                 && r->in.devmode_ctr.devmode )
1727          {
1728                 convert_devicemode_new(Printer->sharename,
1729                                        r->in.devmode_ctr.devmode,
1730                                        &Printer->nt_devmode);
1731          }
1732
1733 #if 0   /* JERRY -- I'm doubtful this is really effective */
1734         /* HACK ALERT!!! Sleep for 1/3 of a second to try trigger a LAN/WAN
1735            optimization in Windows 2000 clients  --jerry */
1736
1737         if ( (r->in.access_mask == PRINTER_ACCESS_ADMINISTER)
1738                 && (RA_WIN2K == get_remote_arch()) )
1739         {
1740                 DEBUG(10,("_spoolss_OpenPrinterEx: Enabling LAN/WAN hack for Win2k clients.\n"));
1741                 sys_usleep( 500000 );
1742         }
1743 #endif
1744
1745         return WERR_OK;
1746 }
1747
1748 /****************************************************************************
1749 ****************************************************************************/
1750
1751 static bool printer_info2_to_nt_printer_info2(struct spoolss_SetPrinterInfo2 *r,
1752                                               NT_PRINTER_INFO_LEVEL_2 *d)
1753 {
1754         DEBUG(7,("printer_info2_to_nt_printer_info2\n"));
1755
1756         if (!r || !d) {
1757                 return false;
1758         }
1759
1760         d->attributes           = r->attributes;
1761         d->priority             = r->priority;
1762         d->default_priority     = r->defaultpriority;
1763         d->starttime            = r->starttime;
1764         d->untiltime            = r->untiltime;
1765         d->status               = r->status;
1766         d->cjobs                = r->cjobs;
1767
1768         fstrcpy(d->servername,  r->servername);
1769         fstrcpy(d->printername, r->printername);
1770         fstrcpy(d->sharename,   r->sharename);
1771         fstrcpy(d->portname,    r->portname);
1772         fstrcpy(d->drivername,  r->drivername);
1773         slprintf(d->comment, sizeof(d->comment)-1, "%s", r->comment);
1774         fstrcpy(d->location,    r->location);
1775         fstrcpy(d->sepfile,     r->sepfile);
1776         fstrcpy(d->printprocessor, r->printprocessor);
1777         fstrcpy(d->datatype,    r->datatype);
1778         fstrcpy(d->parameters,  r->parameters);
1779
1780         return true;
1781 }
1782
1783 /****************************************************************************
1784 ****************************************************************************/
1785
1786 static bool convert_printer_info_new(struct spoolss_SetPrinterInfoCtr *info_ctr,
1787                                      NT_PRINTER_INFO_LEVEL *printer)
1788 {
1789         bool ret;
1790
1791         switch (info_ctr->level) {
1792         case 2:
1793                 /* allocate memory if needed.  Messy because
1794                    convert_printer_info is used to update an existing
1795                    printer or build a new one */
1796
1797                 if (!printer->info_2) {
1798                         printer->info_2 = TALLOC_ZERO_P(printer, NT_PRINTER_INFO_LEVEL_2);
1799                         if (!printer->info_2) {
1800                                 DEBUG(0,("convert_printer_info_new: "
1801                                         "talloc() failed!\n"));
1802                                 return false;
1803                         }
1804                 }
1805
1806                 ret = printer_info2_to_nt_printer_info2(info_ctr->info.info2,
1807                                                         printer->info_2);
1808                 printer->info_2->setuptime = time(NULL);
1809                 return ret;
1810         }
1811
1812         return false;
1813 }
1814
1815 /*******************************************************************
1816 ********************************************************************/
1817
1818 static bool string_array_to_fstring_array(const char **sarray, fstring **farray)
1819 {
1820         int i;
1821
1822         if (!sarray) {
1823                 *farray = NULL;
1824                 return true;
1825         }
1826
1827         *farray = SMB_MALLOC_ARRAY(fstring, 1);
1828         if (!*farray) {
1829                 return false;
1830         }
1831
1832         for (i=0; sarray[i] != NULL; i++) {
1833                 *farray = SMB_REALLOC_ARRAY(*farray, fstring, i+2);
1834                 if (!*farray) {
1835                         return false;
1836                 }
1837                 fstrcpy((*farray)[i], sarray[i]);
1838         }
1839
1840         fstrcpy((*farray)[i], "");
1841
1842         return true;
1843 }
1844
1845 /*******************************************************************
1846 ********************************************************************/
1847
1848 static bool driver_info3_to_nt_driver_info3(struct spoolss_AddDriverInfo3 *r,
1849                                             NT_PRINTER_DRIVER_INFO_LEVEL_3 **p)
1850 {
1851         NT_PRINTER_DRIVER_INFO_LEVEL_3 *d;
1852
1853         DEBUG(7,("driver_info3_to_nt_driver_info3: Converting from UNICODE to ASCII\n"));
1854
1855         if (*p == NULL) {
1856                 *p = SMB_MALLOC_P(NT_PRINTER_DRIVER_INFO_LEVEL_3);
1857                 if (*p == NULL) {
1858                         return false;
1859                 }
1860                 ZERO_STRUCTP(*p);
1861         }
1862
1863         d = *p;
1864
1865         d->cversion =                   r->version;
1866
1867         fstrcpy(d->name,                r->driver_name);
1868         fstrcpy(d->environment,         r->architecture);
1869         fstrcpy(d->driverpath,          r->driver_path);
1870         fstrcpy(d->datafile,            r->data_file);
1871         fstrcpy(d->configfile,          r->config_file);
1872         fstrcpy(d->helpfile,            r->help_file);
1873         fstrcpy(d->monitorname,         r->monitor_name);
1874         fstrcpy(d->defaultdatatype,     r->default_datatype);
1875
1876         DEBUGADD(8,( "version:         %d\n", d->cversion));
1877         DEBUGADD(8,( "name:            %s\n", d->name));
1878         DEBUGADD(8,( "environment:     %s\n", d->environment));
1879         DEBUGADD(8,( "driverpath:      %s\n", d->driverpath));
1880         DEBUGADD(8,( "datafile:        %s\n", d->datafile));
1881         DEBUGADD(8,( "configfile:      %s\n", d->configfile));
1882         DEBUGADD(8,( "helpfile:        %s\n", d->helpfile));
1883         DEBUGADD(8,( "monitorname:     %s\n", d->monitorname));
1884         DEBUGADD(8,( "defaultdatatype: %s\n", d->defaultdatatype));
1885
1886         if (r->dependent_files) {
1887                 if (!string_array_to_fstring_array(r->dependent_files->string,
1888                                                    &d->dependentfiles)) {
1889                         SAFE_FREE(*p);
1890                         return false;
1891                 }
1892         }
1893
1894         return true;
1895 }
1896
1897 /*******************************************************************
1898 ********************************************************************/
1899
1900 static bool driver_info6_to_nt_driver_info6(struct spoolss_AddDriverInfo6 *r,
1901                                             NT_PRINTER_DRIVER_INFO_LEVEL_6 **p)
1902 {
1903         NT_PRINTER_DRIVER_INFO_LEVEL_6 *d;
1904
1905         DEBUG(7,("driver_info6_to_nt_driver_info6: Converting from UNICODE to ASCII\n"));
1906
1907         if (*p == NULL) {
1908                 *p = SMB_MALLOC_P(NT_PRINTER_DRIVER_INFO_LEVEL_6);
1909                 if (*p == NULL) {
1910                         return false;
1911                 }
1912                 ZERO_STRUCTP(*p);
1913         }
1914
1915         d = *p;
1916
1917         d->version =                    r->version;
1918
1919         fstrcpy(d->name,                r->driver_name);
1920         fstrcpy(d->environment,         r->architecture);
1921         fstrcpy(d->driverpath,          r->driver_path);
1922         fstrcpy(d->datafile,            r->data_file);
1923         fstrcpy(d->configfile,          r->config_file);
1924         fstrcpy(d->helpfile,            r->help_file);
1925         fstrcpy(d->monitorname,         r->monitor_name);
1926         fstrcpy(d->defaultdatatype,     r->default_datatype);
1927
1928         DEBUGADD(8,( "version:         %d\n", d->version));
1929         DEBUGADD(8,( "name:            %s\n", d->name));
1930         DEBUGADD(8,( "environment:     %s\n", d->environment));
1931         DEBUGADD(8,( "driverpath:      %s\n", d->driverpath));
1932         DEBUGADD(8,( "datafile:        %s\n", d->datafile));
1933         DEBUGADD(8,( "configfile:      %s\n", d->configfile));
1934         DEBUGADD(8,( "helpfile:        %s\n", d->helpfile));
1935         DEBUGADD(8,( "monitorname:     %s\n", d->monitorname));
1936         DEBUGADD(8,( "defaultdatatype: %s\n", d->defaultdatatype));
1937
1938         if (r->dependent_files) {
1939                 if (!string_array_to_fstring_array(r->dependent_files->string,
1940                                                    &d->dependentfiles)) {
1941                         goto error;
1942                 }
1943         }
1944
1945         if (r->previous_names) {
1946                 if (!string_array_to_fstring_array(r->previous_names->string,
1947                                                    &d->previousnames)) {
1948                         goto error;
1949                 }
1950         }
1951
1952         return true;
1953
1954  error:
1955         SAFE_FREE(*p);
1956         return false;
1957 }
1958
1959 /********************************************************************
1960  ********************************************************************/
1961
1962 static bool convert_printer_driver_info(const struct spoolss_AddDriverInfoCtr *r,
1963                                         NT_PRINTER_DRIVER_INFO_LEVEL *printer,
1964                                         uint32_t level)
1965 {
1966         switch (level) {
1967         case 3:
1968                 printer->info_3 = NULL;
1969                 if (!driver_info3_to_nt_driver_info3(r->info.info3, &printer->info_3)) {
1970                         return false;
1971                 }
1972                 break;
1973         case 6:
1974                 printer->info_6 = NULL;
1975                 if (!driver_info6_to_nt_driver_info6(r->info.info6, &printer->info_6)) {
1976                         return false;
1977                 }
1978                 break;
1979         default:
1980                 return false;
1981         }
1982
1983         return true;
1984 }
1985
1986 bool convert_devicemode(const char *printername, const DEVICEMODE *devmode,
1987                                 NT_DEVICEMODE **pp_nt_devmode)
1988 {
1989         NT_DEVICEMODE *nt_devmode = *pp_nt_devmode;
1990
1991         /*
1992          * Ensure nt_devmode is a valid pointer
1993          * as we will be overwriting it.
1994          */
1995
1996         if (nt_devmode == NULL) {
1997                 DEBUG(5, ("convert_devicemode: allocating a generic devmode\n"));
1998                 if ((nt_devmode = construct_nt_devicemode(printername)) == NULL)
1999                         return False;
2000         }
2001
2002         rpcstr_pull(nt_devmode->devicename,devmode->devicename.buffer, 31, -1, 0);
2003         rpcstr_pull(nt_devmode->formname,devmode->formname.buffer, 31, -1, 0);
2004
2005         nt_devmode->specversion=devmode->specversion;
2006         nt_devmode->driverversion=devmode->driverversion;
2007         nt_devmode->size=devmode->size;
2008         nt_devmode->fields=devmode->fields;
2009         nt_devmode->orientation=devmode->orientation;
2010         nt_devmode->papersize=devmode->papersize;
2011         nt_devmode->paperlength=devmode->paperlength;
2012         nt_devmode->paperwidth=devmode->paperwidth;
2013         nt_devmode->scale=devmode->scale;
2014         nt_devmode->copies=devmode->copies;
2015         nt_devmode->defaultsource=devmode->defaultsource;
2016         nt_devmode->printquality=devmode->printquality;
2017         nt_devmode->color=devmode->color;
2018         nt_devmode->duplex=devmode->duplex;
2019         nt_devmode->yresolution=devmode->yresolution;
2020         nt_devmode->ttoption=devmode->ttoption;
2021         nt_devmode->collate=devmode->collate;
2022
2023         nt_devmode->logpixels=devmode->logpixels;
2024         nt_devmode->bitsperpel=devmode->bitsperpel;
2025         nt_devmode->pelswidth=devmode->pelswidth;
2026         nt_devmode->pelsheight=devmode->pelsheight;
2027         nt_devmode->displayflags=devmode->displayflags;
2028         nt_devmode->displayfrequency=devmode->displayfrequency;
2029         nt_devmode->icmmethod=devmode->icmmethod;
2030         nt_devmode->icmintent=devmode->icmintent;
2031         nt_devmode->mediatype=devmode->mediatype;
2032         nt_devmode->dithertype=devmode->dithertype;
2033         nt_devmode->reserved1=devmode->reserved1;
2034         nt_devmode->reserved2=devmode->reserved2;
2035         nt_devmode->panningwidth=devmode->panningwidth;
2036         nt_devmode->panningheight=devmode->panningheight;
2037
2038         /*
2039          * Only change private and driverextra if the incoming devmode
2040          * has a new one. JRA.
2041          */
2042
2043         if ((devmode->driverextra != 0) && (devmode->dev_private != NULL)) {
2044                 SAFE_FREE(nt_devmode->nt_dev_private);
2045                 nt_devmode->driverextra=devmode->driverextra;
2046                 if((nt_devmode->nt_dev_private=SMB_MALLOC_ARRAY(uint8, nt_devmode->driverextra)) == NULL)
2047                         return False;
2048                 memcpy(nt_devmode->nt_dev_private, devmode->dev_private, nt_devmode->driverextra);
2049         }
2050
2051         *pp_nt_devmode = nt_devmode;
2052
2053         return True;
2054 }
2055
2056 /********************************************************************
2057  * _spoolss_enddocprinter_internal.
2058  ********************************************************************/
2059
2060 static WERROR _spoolss_enddocprinter_internal(pipes_struct *p, POLICY_HND *handle)
2061 {
2062         Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
2063         int snum;
2064
2065         if (!Printer) {
2066                 DEBUG(2,("_spoolss_enddocprinter_internal: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
2067                 return WERR_BADFID;
2068         }
2069
2070         if (!get_printer_snum(p, handle, &snum, NULL))
2071                 return WERR_BADFID;
2072
2073         Printer->document_started=False;
2074         print_job_end(snum, Printer->jobid,NORMAL_CLOSE);
2075         /* error codes unhandled so far ... */
2076
2077         return WERR_OK;
2078 }
2079
2080 /****************************************************************
2081  _spoolss_ClosePrinter
2082 ****************************************************************/
2083
2084 WERROR _spoolss_ClosePrinter(pipes_struct *p,
2085                              struct spoolss_ClosePrinter *r)
2086 {
2087         POLICY_HND *handle = r->in.handle;
2088
2089         Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
2090
2091         if (Printer && Printer->document_started)
2092                 _spoolss_enddocprinter_internal(p, handle);          /* print job was not closed */
2093
2094         if (!close_printer_handle(p, handle))
2095                 return WERR_BADFID;
2096
2097         /* clear the returned printer handle.  Observed behavior
2098            from Win2k server.  Don't think this really matters.
2099            Previous code just copied the value of the closed
2100            handle.    --jerry */
2101
2102         ZERO_STRUCTP(r->out.handle);
2103
2104         return WERR_OK;
2105 }
2106
2107 /****************************************************************
2108  _spoolss_DeletePrinter
2109 ****************************************************************/
2110
2111 WERROR _spoolss_DeletePrinter(pipes_struct *p,
2112                               struct spoolss_DeletePrinter *r)
2113 {
2114         POLICY_HND *handle = r->in.handle;
2115         Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
2116         WERROR result;
2117
2118         if (Printer && Printer->document_started)
2119                 _spoolss_enddocprinter_internal(p, handle);  /* print job was not closed */
2120
2121         result = delete_printer_handle(p, handle);
2122
2123         update_c_setprinter(False);
2124
2125         return result;
2126 }
2127
2128 /*******************************************************************
2129  * static function to lookup the version id corresponding to an
2130  * long architecture string
2131  ******************************************************************/
2132
2133 static int get_version_id (char * arch)
2134 {
2135         int i;
2136         struct table_node archi_table[]= {
2137
2138                 {"Windows 4.0",          "WIN40",       0 },
2139                 {"Windows NT x86",       "W32X86",      2 },
2140                 {"Windows NT R4000",     "W32MIPS",     2 },
2141                 {"Windows NT Alpha_AXP", "W32ALPHA",    2 },
2142                 {"Windows NT PowerPC",   "W32PPC",      2 },
2143                 {"Windows IA64",         "IA64",        3 },
2144                 {"Windows x64",          "x64",         3 },
2145                 {NULL,                   "",            -1 }
2146         };
2147
2148         for (i=0; archi_table[i].long_archi != NULL; i++)
2149         {
2150                 if (strcmp(arch, archi_table[i].long_archi) == 0)
2151                         return (archi_table[i].version);
2152         }
2153
2154         return -1;
2155 }
2156
2157 /****************************************************************
2158  _spoolss_DeletePrinterDriver
2159 ****************************************************************/
2160
2161 WERROR _spoolss_DeletePrinterDriver(pipes_struct *p,
2162                                     struct spoolss_DeletePrinterDriver *r)
2163 {
2164         char *driver;
2165         char *arch;
2166         NT_PRINTER_DRIVER_INFO_LEVEL    info;
2167         NT_PRINTER_DRIVER_INFO_LEVEL    info_win2k;
2168         int                             version;
2169         WERROR                          status;
2170         WERROR                          status_win2k = WERR_ACCESS_DENIED;
2171         SE_PRIV                         se_printop = SE_PRINT_OPERATOR;
2172
2173         /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
2174            and not a printer admin, then fail */
2175
2176         if ( (p->server_info->utok.uid != 0)
2177                 && !user_has_privileges(p->server_info->ptok, &se_printop )
2178                 && !token_contains_name_in_list(
2179                         uidtoname(p->server_info->utok.uid), NULL,
2180                         NULL, p->server_info->ptok,
2181                         lp_printer_admin(-1)) )
2182         {
2183                 return WERR_ACCESS_DENIED;
2184         }
2185
2186         driver = CONST_DISCARD(char *, r->in.driver);
2187         arch   = CONST_DISCARD(char *, r->in.architecture);
2188
2189         /* check that we have a valid driver name first */
2190
2191         if ((version=get_version_id(arch)) == -1)
2192                 return WERR_INVALID_ENVIRONMENT;
2193
2194         ZERO_STRUCT(info);
2195         ZERO_STRUCT(info_win2k);
2196
2197         if (!W_ERROR_IS_OK(get_a_printer_driver(&info, 3, driver, arch, version)))
2198         {
2199                 /* try for Win2k driver if "Windows NT x86" */
2200
2201                 if ( version == 2 ) {
2202                         version = 3;
2203                         if (!W_ERROR_IS_OK(get_a_printer_driver(&info, 3, driver, arch, version))) {
2204                                 status = WERR_UNKNOWN_PRINTER_DRIVER;
2205                                 goto done;
2206                         }
2207                 }
2208                 /* otherwise it was a failure */
2209                 else {
2210                         status = WERR_UNKNOWN_PRINTER_DRIVER;
2211                         goto done;
2212                 }
2213
2214         }
2215
2216         if (printer_driver_in_use(info.info_3)) {
2217                 status = WERR_PRINTER_DRIVER_IN_USE;
2218                 goto done;
2219         }
2220
2221         if ( version == 2 )
2222         {
2223                 if (W_ERROR_IS_OK(get_a_printer_driver(&info_win2k, 3, driver, arch, 3)))
2224                 {
2225                         /* if we get to here, we now have 2 driver info structures to remove */
2226                         /* remove the Win2k driver first*/
2227
2228                         status_win2k = delete_printer_driver(
2229                                 p, info_win2k.info_3, 3, False );
2230                         free_a_printer_driver( info_win2k, 3 );
2231
2232                         /* this should not have failed---if it did, report to client */
2233                         if ( !W_ERROR_IS_OK(status_win2k) )
2234                         {
2235                                 status = status_win2k;
2236                                 goto done;
2237                         }
2238                 }
2239         }
2240
2241         status = delete_printer_driver(p, info.info_3, version, False);
2242
2243         /* if at least one of the deletes succeeded return OK */
2244
2245         if ( W_ERROR_IS_OK(status) || W_ERROR_IS_OK(status_win2k) )
2246                 status = WERR_OK;
2247
2248 done:
2249         free_a_printer_driver( info, 3 );
2250
2251         return status;
2252 }
2253
2254 /****************************************************************
2255  _spoolss_DeletePrinterDriverEx
2256 ****************************************************************/
2257
2258 WERROR _spoolss_DeletePrinterDriverEx(pipes_struct *p,
2259                                       struct spoolss_DeletePrinterDriverEx *r)
2260 {
2261         char *driver;
2262         char *arch;
2263         NT_PRINTER_DRIVER_INFO_LEVEL    info;
2264         NT_PRINTER_DRIVER_INFO_LEVEL    info_win2k;
2265         int                             version;
2266         uint32_t                        flags = r->in.delete_flags;
2267         bool                            delete_files;
2268         WERROR                          status;
2269         WERROR                          status_win2k = WERR_ACCESS_DENIED;
2270         SE_PRIV                         se_printop = SE_PRINT_OPERATOR;
2271
2272         /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
2273            and not a printer admin, then fail */
2274
2275         if ( (p->server_info->utok.uid != 0)
2276                 && !user_has_privileges(p->server_info->ptok, &se_printop )
2277                 && !token_contains_name_in_list(
2278                         uidtoname(p->server_info->utok.uid), NULL, NULL,
2279                         p->server_info->ptok, lp_printer_admin(-1)) )
2280         {
2281                 return WERR_ACCESS_DENIED;
2282         }
2283
2284         driver = CONST_DISCARD(char *, r->in.driver);
2285         arch   = CONST_DISCARD(char *, r->in.architecture);
2286
2287         /* check that we have a valid driver name first */
2288         if ((version=get_version_id(arch)) == -1) {
2289                 /* this is what NT returns */
2290                 return WERR_INVALID_ENVIRONMENT;
2291         }
2292
2293         if ( flags & DPD_DELETE_SPECIFIC_VERSION )
2294                 version = r->in.version;
2295
2296         ZERO_STRUCT(info);
2297         ZERO_STRUCT(info_win2k);
2298
2299         status = get_a_printer_driver(&info, 3, driver, arch, version);
2300
2301         if ( !W_ERROR_IS_OK(status) )
2302         {
2303                 /*
2304                  * if the client asked for a specific version,
2305                  * or this is something other than Windows NT x86,
2306                  * then we've failed
2307                  */
2308
2309                 if ( (flags&DPD_DELETE_SPECIFIC_VERSION) || (version !=2) )
2310                         goto done;
2311
2312                 /* try for Win2k driver if "Windows NT x86" */
2313
2314                 version = 3;
2315                 if (!W_ERROR_IS_OK(get_a_printer_driver(&info, 3, driver, arch, version))) {
2316                         status = WERR_UNKNOWN_PRINTER_DRIVER;
2317                         goto done;
2318                 }
2319         }
2320
2321         if ( printer_driver_in_use(info.info_3) ) {
2322                 status = WERR_PRINTER_DRIVER_IN_USE;
2323                 goto done;
2324         }
2325
2326         /*
2327          * we have a couple of cases to consider.
2328          * (1) Are any files in use?  If so and DPD_DELTE_ALL_FILE is set,
2329          *     then the delete should fail if **any** files overlap with
2330          *     other drivers
2331          * (2) If DPD_DELTE_UNUSED_FILES is sert, then delete all
2332          *     non-overlapping files
2333          * (3) If neither DPD_DELTE_ALL_FILE nor DPD_DELTE_ALL_FILES
2334          *     is set, the do not delete any files
2335          * Refer to MSDN docs on DeletePrinterDriverEx() for details.
2336          */
2337
2338         delete_files = flags & (DPD_DELETE_ALL_FILES|DPD_DELETE_UNUSED_FILES);
2339
2340         /* fail if any files are in use and DPD_DELETE_ALL_FILES is set */
2341
2342         if ( delete_files && printer_driver_files_in_use(info.info_3) & (flags&DPD_DELETE_ALL_FILES) ) {
2343                 /* no idea of the correct error here */
2344                 status = WERR_ACCESS_DENIED;
2345                 goto done;
2346         }
2347
2348
2349         /* also check for W32X86/3 if necessary; maybe we already have? */
2350
2351         if ( (version == 2) && ((flags&DPD_DELETE_SPECIFIC_VERSION) != DPD_DELETE_SPECIFIC_VERSION)  ) {
2352                 if (W_ERROR_IS_OK(get_a_printer_driver(&info_win2k, 3, driver, arch, 3)))
2353                 {
2354
2355                         if ( delete_files && printer_driver_files_in_use(info_win2k.info_3) & (flags&DPD_DELETE_ALL_FILES) ) {
2356                                 /* no idea of the correct error here */
2357                                 free_a_printer_driver( info_win2k, 3 );
2358                                 status = WERR_ACCESS_DENIED;
2359                                 goto done;
2360                         }
2361
2362                         /* if we get to here, we now have 2 driver info structures to remove */
2363                         /* remove the Win2k driver first*/
2364
2365                         status_win2k = delete_printer_driver(
2366                                 p, info_win2k.info_3, 3, delete_files);
2367                         free_a_printer_driver( info_win2k, 3 );
2368
2369                         /* this should not have failed---if it did, report to client */
2370
2371                         if ( !W_ERROR_IS_OK(status_win2k) )
2372                                 goto done;
2373                 }
2374         }
2375
2376         status = delete_printer_driver(p, info.info_3, version, delete_files);
2377
2378         if ( W_ERROR_IS_OK(status) || W_ERROR_IS_OK(status_win2k) )
2379                 status = WERR_OK;
2380 done:
2381         free_a_printer_driver( info, 3 );
2382
2383         return status;
2384 }
2385
2386
2387 /****************************************************************************
2388  Internal routine for retreiving printerdata
2389  ***************************************************************************/
2390
2391 static WERROR get_printer_dataex( TALLOC_CTX *ctx, NT_PRINTER_INFO_LEVEL *printer,
2392                                   const char *key, const char *value, uint32 *type, uint8 **data,
2393                                   uint32 *needed, uint32 in_size  )
2394 {
2395         REGISTRY_VALUE          *val;
2396         uint32                  size;
2397         int                     data_len;
2398
2399         if ( !(val = get_printer_data( printer->info_2, key, value)) )
2400                 return WERR_BADFILE;
2401
2402         *type = regval_type( val );
2403
2404         DEBUG(5,("get_printer_dataex: allocating %d\n", in_size));
2405
2406         size = regval_size( val );
2407
2408         /* copy the min(in_size, len) */
2409
2410         if ( in_size ) {
2411                 data_len = (size > in_size) ? in_size : size*sizeof(uint8);
2412
2413                 /* special case for 0 length values */
2414                 if ( data_len ) {
2415                         if ( (*data  = (uint8 *)TALLOC_MEMDUP(ctx, regval_data_p(val), data_len)) == NULL )
2416                                 return WERR_NOMEM;
2417                 }
2418                 else {
2419                         if ( (*data  = (uint8 *)TALLOC_ZERO(ctx, in_size)) == NULL )
2420                                 return WERR_NOMEM;
2421                 }
2422         }
2423         else
2424                 *data = NULL;
2425
2426         *needed = size;
2427
2428         DEBUG(5,("get_printer_dataex: copy done\n"));
2429
2430         return WERR_OK;
2431 }
2432
2433 /****************************************************************************
2434  Internal routine for removing printerdata
2435  ***************************************************************************/
2436
2437 static WERROR delete_printer_dataex( NT_PRINTER_INFO_LEVEL *printer, const char *key, const char *value )
2438 {
2439         return delete_printer_data( printer->info_2, key, value );
2440 }
2441
2442 /****************************************************************************
2443  Internal routine for storing printerdata
2444  ***************************************************************************/
2445
2446 WERROR set_printer_dataex( NT_PRINTER_INFO_LEVEL *printer, const char *key, const char *value,
2447                                   uint32 type, uint8 *data, int real_len  )
2448 {
2449         /* the registry objects enforce uniqueness based on value name */
2450
2451         return add_printer_data( printer->info_2, key, value, type, data, real_len );
2452 }
2453
2454 /********************************************************************
2455  GetPrinterData on a printer server Handle.
2456 ********************************************************************/
2457
2458 static WERROR getprinterdata_printer_server(TALLOC_CTX *ctx, fstring value, uint32 *type, uint8 **data, uint32 *needed, uint32 in_size)
2459 {
2460         int i;
2461
2462         DEBUG(8,("getprinterdata_printer_server:%s\n", value));
2463
2464         if (!StrCaseCmp(value, "W3SvcInstalled")) {
2465                 *type = REG_DWORD;
2466                 if ( !(*data = TALLOC_ARRAY(ctx, uint8, sizeof(uint32) )) )
2467                         return WERR_NOMEM;
2468                 SIVAL(*data, 0, 0x00);
2469                 *needed = 0x4;
2470                 return WERR_OK;
2471         }
2472
2473         if (!StrCaseCmp(value, "BeepEnabled")) {
2474                 *type = REG_DWORD;
2475                 if ( !(*data = TALLOC_ARRAY(ctx, uint8, sizeof(uint32) )) )
2476                         return WERR_NOMEM;
2477                 SIVAL(*data, 0, 0x00);
2478                 *needed = 0x4;
2479                 return WERR_OK;
2480         }
2481
2482         if (!StrCaseCmp(value, "EventLog")) {
2483                 *type = REG_DWORD;
2484                 if ( !(*data = TALLOC_ARRAY(ctx, uint8, sizeof(uint32) )) )
2485                         return WERR_NOMEM;
2486                 /* formally was 0x1b */
2487                 SIVAL(*data, 0, 0x0);
2488                 *needed = 0x4;
2489                 return WERR_OK;
2490         }
2491
2492         if (!StrCaseCmp(value, "NetPopup")) {
2493                 *type = REG_DWORD;
2494                 if ( !(*data = TALLOC_ARRAY(ctx, uint8, sizeof(uint32) )) )
2495                         return WERR_NOMEM;
2496                 SIVAL(*data, 0, 0x00);
2497                 *needed = 0x4;
2498                 return WERR_OK;
2499         }
2500
2501         if (!StrCaseCmp(value, "MajorVersion")) {
2502                 *type = REG_DWORD;
2503                 if ( !(*data = TALLOC_ARRAY(ctx, uint8, sizeof(uint32) )) )
2504                         return WERR_NOMEM;
2505
2506                 /* Windows NT 4.0 seems to not allow uploading of drivers
2507                    to a server that reports 0x3 as the MajorVersion.
2508                    need to investigate more how Win2k gets around this .
2509                    -- jerry */
2510
2511                 if ( RA_WINNT == get_remote_arch() )
2512                         SIVAL(*data, 0, 2);
2513                 else
2514                         SIVAL(*data, 0, 3);
2515
2516                 *needed = 0x4;
2517                 return WERR_OK;
2518         }
2519
2520         if (!StrCaseCmp(value, "MinorVersion")) {
2521                 *type = REG_DWORD;
2522                 if ( !(*data = TALLOC_ARRAY(ctx, uint8, sizeof(uint32) )) )
2523                         return WERR_NOMEM;
2524                 SIVAL(*data, 0, 0);
2525                 *needed = 0x4;
2526                 return WERR_OK;
2527         }
2528
2529         /* REG_BINARY
2530          *  uint32 size          = 0x114
2531          *  uint32 major         = 5
2532          *  uint32 minor         = [0|1]
2533          *  uint32 build         = [2195|2600]
2534          *  extra unicode string = e.g. "Service Pack 3"
2535          */
2536         if (!StrCaseCmp(value, "OSVersion")) {
2537                 *type = REG_BINARY;
2538                 *needed = 0x114;
2539
2540                 if ( !(*data = TALLOC_ZERO_ARRAY(ctx, uint8, (*needed > in_size) ? *needed:in_size )) )
2541                         return WERR_NOMEM;
2542
2543                 SIVAL(*data, 0, *needed);       /* size */
2544                 SIVAL(*data, 4, 5);             /* Windows 2000 == 5.0 */
2545                 SIVAL(*data, 8, 0);
2546                 SIVAL(*data, 12, 2195);         /* build */
2547
2548                 /* leave extra string empty */
2549
2550                 return WERR_OK;
2551         }
2552
2553
2554         if (!StrCaseCmp(value, "DefaultSpoolDirectory")) {
2555                 const char *string="C:\\PRINTERS";
2556                 *type = REG_SZ;
2557                 *needed = 2*(strlen(string)+1);
2558                 if((*data  = (uint8 *)TALLOC(ctx, (*needed > in_size) ? *needed:in_size )) == NULL)
2559                         return WERR_NOMEM;
2560                 memset(*data, 0, (*needed > in_size) ? *needed:in_size);
2561
2562                 /* it's done by hand ready to go on the wire */
2563                 for (i=0; i<strlen(string); i++) {
2564                         (*data)[2*i]=string[i];
2565                         (*data)[2*i+1]='\0';
2566                 }
2567                 return WERR_OK;
2568         }
2569
2570         if (!StrCaseCmp(value, "Architecture")) {
2571                 const char *string="Windows NT x86";
2572                 *type = REG_SZ;
2573                 *needed = 2*(strlen(string)+1);
2574                 if((*data  = (uint8 *)TALLOC(ctx, (*needed > in_size) ? *needed:in_size )) == NULL)
2575                         return WERR_NOMEM;
2576                 memset(*data, 0, (*needed > in_size) ? *needed:in_size);
2577                 for (i=0; i<strlen(string); i++) {
2578                         (*data)[2*i]=string[i];
2579                         (*data)[2*i+1]='\0';
2580                 }
2581                 return WERR_OK;
2582         }
2583
2584         if (!StrCaseCmp(value, "DsPresent")) {
2585                 *type = REG_DWORD;
2586                 if ( !(*data = TALLOC_ARRAY(ctx, uint8, sizeof(uint32) )) )
2587                         return WERR_NOMEM;
2588
2589                 /* only show the publish check box if we are a
2590                    memeber of a AD domain */
2591
2592                 if ( lp_security() == SEC_ADS )
2593                         SIVAL(*data, 0, 0x01);
2594                 else
2595                         SIVAL(*data, 0, 0x00);
2596
2597                 *needed = 0x4;
2598                 return WERR_OK;
2599         }
2600
2601         if (!StrCaseCmp(value, "DNSMachineName")) {
2602                 const char *hostname = get_mydnsfullname();
2603
2604                 if (!hostname)
2605                         return WERR_BADFILE;
2606                 *type = REG_SZ;
2607                 *needed = 2*(strlen(hostname)+1);
2608                 if((*data  = (uint8 *)TALLOC(ctx, (*needed > in_size) ? *needed:in_size )) == NULL)
2609                         return WERR_NOMEM;
2610                 memset(*data, 0, (*needed > in_size) ? *needed:in_size);
2611                 for (i=0; i<strlen(hostname); i++) {
2612                         (*data)[2*i]=hostname[i];
2613                         (*data)[2*i+1]='\0';
2614                 }
2615                 return WERR_OK;
2616         }
2617
2618
2619         return WERR_BADFILE;
2620 }
2621
2622 /********************************************************************
2623  * spoolss_getprinterdata
2624  ********************************************************************/
2625
2626 WERROR _spoolss_getprinterdata(pipes_struct *p, SPOOL_Q_GETPRINTERDATA *q_u, SPOOL_R_GETPRINTERDATA *r_u)
2627 {
2628         POLICY_HND      *handle = &q_u->handle;
2629         UNISTR2         *valuename = &q_u->valuename;
2630         uint32          in_size = q_u->size;
2631         uint32          *type = &r_u->type;
2632         uint32          *out_size = &r_u->size;
2633         uint8           **data = &r_u->data;
2634         uint32          *needed = &r_u->needed;
2635         WERROR          status;
2636         fstring         value;
2637         Printer_entry   *Printer = find_printer_index_by_hnd(p, handle);
2638         NT_PRINTER_INFO_LEVEL   *printer = NULL;
2639         int             snum = 0;
2640
2641         /*
2642          * Reminder: when it's a string, the length is in BYTES
2643          * even if UNICODE is negociated.
2644          *
2645          * JFM, 4/19/1999
2646          */
2647
2648         *out_size = in_size;
2649
2650         /* in case of problem, return some default values */
2651
2652         *needed = 0;
2653         *type   = 0;
2654
2655         DEBUG(4,("_spoolss_getprinterdata\n"));
2656
2657         if ( !Printer ) {
2658                 DEBUG(2,("_spoolss_getprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
2659                 status = WERR_BADFID;
2660                 goto done;
2661         }
2662
2663         unistr2_to_ascii(value, valuename, sizeof(value));
2664
2665         if ( Printer->printer_type == SPLHND_SERVER )
2666                 status = getprinterdata_printer_server( p->mem_ctx, value, type, data, needed, *out_size );
2667         else
2668         {
2669                 if ( !get_printer_snum(p,handle, &snum, NULL) ) {
2670                         status = WERR_BADFID;
2671                         goto done;
2672                 }
2673
2674                 status = get_a_printer(Printer, &printer, 2, lp_servicename(snum));
2675                 if ( !W_ERROR_IS_OK(status) )
2676                         goto done;
2677
2678                 /* XP sends this and wants to change id value from the PRINTER_INFO_0 */
2679
2680                 if ( strequal(value, "ChangeId") ) {
2681                         *type = REG_DWORD;
2682                         *needed = sizeof(uint32);
2683                         if ( (*data = (uint8*)TALLOC(p->mem_ctx, sizeof(uint32))) == NULL) {
2684                                 status = WERR_NOMEM;
2685                                 goto done;
2686                         }
2687                         SIVAL( *data, 0, printer->info_2->changeid );
2688                         status = WERR_OK;
2689                 }
2690                 else
2691                         status = get_printer_dataex( p->mem_ctx, printer, SPOOL_PRINTERDATA_KEY, value, type, data, needed, *out_size );
2692         }
2693
2694         if (*needed > *out_size)
2695                 status = WERR_MORE_DATA;
2696
2697 done:
2698         if ( !W_ERROR_IS_OK(status) )
2699         {
2700                 DEBUG(5, ("error %d: allocating %d\n", W_ERROR_V(status),*out_size));
2701
2702                 /* reply this param doesn't exist */
2703
2704                 if ( *out_size ) {
2705                         if((*data=(uint8 *)TALLOC_ZERO_ARRAY(p->mem_ctx, uint8, *out_size)) == NULL) {
2706                                 if ( printer )
2707                                         free_a_printer( &printer, 2 );
2708                                 return WERR_NOMEM;
2709                         }
2710                 } else {
2711                         *data = NULL;
2712                 }
2713         }
2714
2715         /* cleanup & exit */
2716
2717         if ( printer )
2718                 free_a_printer( &printer, 2 );
2719
2720         return status;
2721 }
2722
2723 /*********************************************************
2724  Connect to the client machine.
2725 **********************************************************/
2726
2727 static bool spoolss_connect_to_client(struct rpc_pipe_client **pp_pipe,
2728                         struct sockaddr_storage *client_ss, const char *remote_machine)
2729 {
2730         NTSTATUS ret;
2731         struct cli_state *the_cli;
2732         struct sockaddr_storage rm_addr;
2733
2734         if ( is_zero_addr((struct sockaddr *)client_ss) ) {
2735                 if ( !resolve_name( remote_machine, &rm_addr, 0x20) ) {
2736                         DEBUG(2,("spoolss_connect_to_client: Can't resolve address for %s\n", remote_machine));
2737                         return False;
2738                 }
2739
2740                 if (ismyaddr((struct sockaddr *)&rm_addr)) {
2741                         DEBUG(0,("spoolss_connect_to_client: Machine %s is one of our addresses. Cannot add to ourselves.\n", remote_machine));
2742                         return False;
2743                 }
2744         } else {
2745                 char addr[INET6_ADDRSTRLEN];
2746                 rm_addr = *client_ss;
2747                 print_sockaddr(addr, sizeof(addr), &rm_addr);
2748                 DEBUG(5,("spoolss_connect_to_client: Using address %s (no name resolution necessary)\n",
2749                         addr));
2750         }
2751
2752         /* setup the connection */
2753
2754         ret = cli_full_connection( &the_cli, global_myname(), remote_machine,
2755                 &rm_addr, 0, "IPC$", "IPC",
2756                 "", /* username */
2757                 "", /* domain */
2758                 "", /* password */
2759                 0, lp_client_signing(), NULL );
2760
2761         if ( !NT_STATUS_IS_OK( ret ) ) {
2762                 DEBUG(2,("spoolss_connect_to_client: connection to [%s] failed!\n",
2763                         remote_machine ));
2764                 return False;
2765         }
2766
2767         if ( the_cli->protocol != PROTOCOL_NT1 ) {
2768                 DEBUG(0,("spoolss_connect_to_client: machine %s didn't negotiate NT protocol.\n", remote_machine));
2769                 cli_shutdown(the_cli);
2770                 return False;
2771         }
2772
2773         /*
2774          * Ok - we have an anonymous connection to the IPC$ share.
2775          * Now start the NT Domain stuff :-).
2776          */
2777
2778         ret = cli_rpc_pipe_open_noauth(the_cli, &syntax_spoolss, pp_pipe);
2779         if (!NT_STATUS_IS_OK(ret)) {
2780                 DEBUG(2,("spoolss_connect_to_client: unable to open the spoolss pipe on machine %s. Error was : %s.\n",
2781                         remote_machine, nt_errstr(ret)));
2782                 cli_shutdown(the_cli);
2783                 return False;
2784         }
2785
2786         return True;
2787 }
2788
2789 /***************************************************************************
2790  Connect to the client.
2791 ****************************************************************************/
2792
2793 static bool srv_spoolss_replyopenprinter(int snum, const char *printer,
2794                                         uint32 localprinter, uint32 type,
2795                                         POLICY_HND *handle, struct sockaddr_storage *client_ss)
2796 {
2797         WERROR result;
2798         NTSTATUS status;
2799
2800         /*
2801          * If it's the first connection, contact the client
2802          * and connect to the IPC$ share anonymously
2803          */
2804         if (smb_connections==0) {
2805                 fstring unix_printer;
2806
2807                 fstrcpy(unix_printer, printer+2); /* the +2 is to strip the leading 2 backslashs */
2808
2809                 if ( !spoolss_connect_to_client( &notify_cli_pipe, client_ss, unix_printer ))
2810                         return False;
2811
2812                 messaging_register(smbd_messaging_context(), NULL,
2813                                    MSG_PRINTER_NOTIFY2,
2814                                    receive_notify2_message_list);
2815                 /* Tell the connections db we're now interested in printer
2816                  * notify messages. */
2817                 register_message_flags( True, FLAG_MSG_PRINT_NOTIFY );
2818         }
2819
2820         /*
2821          * Tell the specific printing tdb we want messages for this printer
2822          * by registering our PID.
2823          */
2824
2825         if (!print_notify_register_pid(snum))
2826                 DEBUG(0,("print_notify_register_pid: Failed to register our pid for printer %s\n", printer ));
2827
2828         smb_connections++;
2829
2830         status = rpccli_spoolss_ReplyOpenPrinter(notify_cli_pipe, talloc_tos(),
2831                                                  printer,
2832                                                  localprinter,
2833                                                  type,
2834                                                  0,
2835                                                  NULL,
2836                                                  handle,
2837                                                  &result);
2838         if (!NT_STATUS_IS_OK(status) || !W_ERROR_IS_OK(result))
2839                 DEBUG(5,("srv_spoolss_reply_open_printer: Client RPC returned [%s]\n",
2840                         win_errstr(result)));
2841
2842         return (W_ERROR_IS_OK(result));
2843 }
2844
2845 /****************************************************************
2846  ****************************************************************/
2847
2848 static struct spoolss_NotifyOption *dup_spoolss_NotifyOption(TALLOC_CTX *mem_ctx,
2849                                                              const struct spoolss_NotifyOption *r)
2850 {
2851         struct spoolss_NotifyOption *option;
2852         uint32_t i,k;
2853
2854         if (!r) {
2855                 return NULL;
2856         }
2857
2858         option = talloc_zero(mem_ctx, struct spoolss_NotifyOption);
2859         if (!option) {
2860                 return NULL;
2861         }
2862
2863         *option = *r;
2864
2865         if (!option->count) {
2866                 return option;
2867         }
2868
2869         option->types = talloc_zero_array(option,
2870                 struct spoolss_NotifyOptionType, option->count);
2871         if (!option->types) {
2872                 talloc_free(option);
2873                 return NULL;
2874         }
2875
2876         for (i=0; i < option->count; i++) {
2877                 option->types[i] = r->types[i];
2878
2879                 if (option->types[i].count) {
2880                         option->types[i].fields = talloc_zero_array(option,
2881                                 enum spoolss_Field, option->types[i].count);
2882                         if (!option->types[i].fields) {
2883                                 talloc_free(option);
2884                                 return NULL;
2885                         }
2886                         for (k=0; k<option->types[i].count; k++) {
2887                                 option->types[i].fields[k] =
2888                                         r->types[i].fields[k];
2889                         }
2890                 }
2891         }
2892
2893         return option;
2894 }
2895
2896 /****************************************************************
2897  * _spoolss_RemoteFindFirstPrinterChangeNotifyEx
2898  *
2899  * before replying OK: status=0 a rpc call is made to the workstation
2900  * asking ReplyOpenPrinter
2901  *
2902  * in fact ReplyOpenPrinter is the changenotify equivalent on the spoolss pipe
2903  * called from api_spoolss_rffpcnex
2904 ****************************************************************/
2905
2906 WERROR _spoolss_RemoteFindFirstPrinterChangeNotifyEx(pipes_struct *p,
2907                                                      struct spoolss_RemoteFindFirstPrinterChangeNotifyEx *r)
2908 {
2909         POLICY_HND *handle = r->in.handle;
2910         int snum = -1;
2911         struct spoolss_NotifyOption *option = r->in.notify_options;
2912         struct sockaddr_storage client_ss;
2913
2914         /* store the notify value in the printer struct */
2915
2916         Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
2917
2918         if (!Printer) {
2919                 DEBUG(2,("_spoolss_RemoteFindFirstPrinterChangeNotifyEx: "
2920                         "Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
2921                 return WERR_BADFID;
2922         }
2923
2924         Printer->notify.flags           = r->in.flags;
2925         Printer->notify.options         = r->in.options;
2926         Printer->notify.printerlocal    = r->in.printer_local;
2927
2928         TALLOC_FREE(Printer->notify.option);
2929         Printer->notify.option = dup_spoolss_NotifyOption(Printer, option);
2930
2931         fstrcpy(Printer->notify.localmachine, r->in.local_machine);
2932
2933         /* Connect to the client machine and send a ReplyOpenPrinter */
2934
2935         if ( Printer->printer_type == SPLHND_SERVER)
2936                 snum = -1;
2937         else if ( (Printer->printer_type == SPLHND_PRINTER) &&
2938                         !get_printer_snum(p, handle, &snum, NULL) )
2939                 return WERR_BADFID;
2940
2941         if (!interpret_string_addr(&client_ss, p->client_address,
2942                                    AI_NUMERICHOST)) {
2943                 return WERR_SERVER_UNAVAILABLE;
2944         }
2945
2946         if(!srv_spoolss_replyopenprinter(snum, Printer->notify.localmachine,
2947                                         Printer->notify.printerlocal, 1,
2948                                         &Printer->notify.client_hnd, &client_ss))
2949                 return WERR_SERVER_UNAVAILABLE;
2950
2951         Printer->notify.client_connected=True;
2952
2953         return WERR_OK;
2954 }
2955
2956 /*******************************************************************
2957  * fill a notify_info_data with the servername
2958  ********************************************************************/
2959
2960 void spoolss_notify_server_name(int snum,
2961                                        struct spoolss_Notify *data,
2962                                        print_queue_struct *queue,
2963                                        NT_PRINTER_INFO_LEVEL *printer,
2964                                        TALLOC_CTX *mem_ctx)
2965 {
2966         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, printer->info_2->servername);
2967 }
2968
2969 /*******************************************************************
2970  * fill a notify_info_data with the printername (not including the servername).
2971  ********************************************************************/
2972
2973 void spoolss_notify_printer_name(int snum,
2974                                         struct spoolss_Notify *data,
2975                                         print_queue_struct *queue,
2976                                         NT_PRINTER_INFO_LEVEL *printer,
2977                                         TALLOC_CTX *mem_ctx)
2978 {
2979         /* the notify name should not contain the \\server\ part */
2980         char *p = strrchr(printer->info_2->printername, '\\');
2981
2982         if (!p) {
2983                 p = printer->info_2->printername;
2984         } else {
2985                 p++;
2986         }
2987
2988         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, p);
2989 }
2990
2991 /*******************************************************************
2992  * fill a notify_info_data with the servicename
2993  ********************************************************************/
2994
2995 void spoolss_notify_share_name(int snum,
2996                                       struct spoolss_Notify *data,
2997                                       print_queue_struct *queue,
2998                                       NT_PRINTER_INFO_LEVEL *printer,
2999                                       TALLOC_CTX *mem_ctx)
3000 {
3001         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, lp_servicename(snum));
3002 }
3003
3004 /*******************************************************************
3005  * fill a notify_info_data with the port name
3006  ********************************************************************/
3007
3008 void spoolss_notify_port_name(int snum,
3009                                      struct spoolss_Notify *data,
3010                                      print_queue_struct *queue,
3011                                      NT_PRINTER_INFO_LEVEL *printer,
3012                                      TALLOC_CTX *mem_ctx)
3013 {
3014         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, printer->info_2->portname);
3015 }
3016
3017 /*******************************************************************
3018  * fill a notify_info_data with the printername
3019  * but it doesn't exist, have to see what to do
3020  ********************************************************************/
3021
3022 void spoolss_notify_driver_name(int snum,
3023                                        struct spoolss_Notify *data,
3024                                        print_queue_struct *queue,
3025                                        NT_PRINTER_INFO_LEVEL *printer,
3026                                        TALLOC_CTX *mem_ctx)
3027 {
3028         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, printer->info_2->drivername);
3029 }
3030
3031 /*******************************************************************
3032  * fill a notify_info_data with the comment
3033  ********************************************************************/
3034
3035 void spoolss_notify_comment(int snum,
3036                                    struct spoolss_Notify *data,
3037                                    print_queue_struct *queue,
3038                                    NT_PRINTER_INFO_LEVEL *printer,
3039                                    TALLOC_CTX *mem_ctx)
3040 {
3041         char *p;
3042
3043         if (*printer->info_2->comment == '\0') {
3044                 p = lp_comment(snum);
3045         } else {
3046                 p = printer->info_2->comment;
3047         }
3048
3049         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, printer->info_2->comment);
3050 }
3051
3052 /*******************************************************************
3053  * fill a notify_info_data with the comment
3054  * location = "Room 1, floor 2, building 3"
3055  ********************************************************************/
3056
3057 void spoolss_notify_location(int snum,
3058                                     struct spoolss_Notify *data,
3059                                     print_queue_struct *queue,
3060                                     NT_PRINTER_INFO_LEVEL *printer,
3061                                     TALLOC_CTX *mem_ctx)
3062 {
3063         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, printer->info_2->location);
3064 }
3065
3066 /*******************************************************************
3067  * fill a notify_info_data with the device mode
3068  * jfm:xxxx don't to it for know but that's a real problem !!!
3069  ********************************************************************/
3070
3071 static void spoolss_notify_devmode(int snum,
3072                                    struct spoolss_Notify *data,
3073                                    print_queue_struct *queue,
3074                                    NT_PRINTER_INFO_LEVEL *printer,
3075                                    TALLOC_CTX *mem_ctx)
3076 {
3077         /* for a dummy implementation we have to zero the fields */
3078         SETUP_SPOOLSS_NOTIFY_DATA_DEVMODE(data, NULL);
3079 }
3080
3081 /*******************************************************************
3082  * fill a notify_info_data with the separator file name
3083  ********************************************************************/
3084
3085 void spoolss_notify_sepfile(int snum,
3086                                    struct spoolss_Notify *data,
3087                                    print_queue_struct *queue,
3088                                    NT_PRINTER_INFO_LEVEL *printer,
3089                                    TALLOC_CTX *mem_ctx)
3090 {
3091         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, printer->info_2->sepfile);
3092 }
3093
3094 /*******************************************************************
3095  * fill a notify_info_data with the print processor
3096  * jfm:xxxx return always winprint to indicate we don't do anything to it
3097  ********************************************************************/
3098
3099 void spoolss_notify_print_processor(int snum,
3100                                            struct spoolss_Notify *data,
3101                                            print_queue_struct *queue,
3102                                            NT_PRINTER_INFO_LEVEL *printer,
3103                                            TALLOC_CTX *mem_ctx)
3104 {
3105         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, printer->info_2->printprocessor);
3106 }
3107
3108 /*******************************************************************
3109  * fill a notify_info_data with the print processor options
3110  * jfm:xxxx send an empty string
3111  ********************************************************************/
3112
3113 void spoolss_notify_parameters(int snum,
3114                                       struct spoolss_Notify *data,
3115                                       print_queue_struct *queue,
3116                                       NT_PRINTER_INFO_LEVEL *printer,
3117                                       TALLOC_CTX *mem_ctx)
3118 {
3119         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, printer->info_2->parameters);
3120 }
3121
3122 /*******************************************************************
3123  * fill a notify_info_data with the data type
3124  * jfm:xxxx always send RAW as data type
3125  ********************************************************************/
3126
3127 void spoolss_notify_datatype(int snum,
3128                                     struct spoolss_Notify *data,
3129                                     print_queue_struct *queue,
3130                                     NT_PRINTER_INFO_LEVEL *printer,
3131                                     TALLOC_CTX *mem_ctx)
3132 {
3133         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, printer->info_2->datatype);
3134 }
3135
3136 /*******************************************************************
3137  * fill a notify_info_data with the security descriptor
3138  * jfm:xxxx send an null pointer to say no security desc
3139  * have to implement security before !
3140  ********************************************************************/
3141
3142 static void spoolss_notify_security_desc(int snum,
3143                                          struct spoolss_Notify *data,
3144                                          print_queue_struct *queue,
3145                                          NT_PRINTER_INFO_LEVEL *printer,
3146                                          TALLOC_CTX *mem_ctx)
3147 {
3148         SETUP_SPOOLSS_NOTIFY_DATA_SECDESC(data,
3149                                           printer->info_2->secdesc_buf->sd_size,
3150                                           printer->info_2->secdesc_buf->sd);
3151 }
3152
3153 /*******************************************************************
3154  * fill a notify_info_data with the attributes
3155  * jfm:xxxx a samba printer is always shared
3156  ********************************************************************/
3157
3158 void spoolss_notify_attributes(int snum,
3159                                       struct spoolss_Notify *data,
3160                                       print_queue_struct *queue,
3161                                       NT_PRINTER_INFO_LEVEL *printer,
3162                                       TALLOC_CTX *mem_ctx)
3163 {
3164         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, printer->info_2->attributes);
3165 }
3166
3167 /*******************************************************************
3168  * fill a notify_info_data with the priority
3169  ********************************************************************/
3170
3171 static void spoolss_notify_priority(int snum,
3172                                     struct spoolss_Notify *data,
3173                                     print_queue_struct *queue,
3174                                     NT_PRINTER_INFO_LEVEL *printer,
3175                                     TALLOC_CTX *mem_ctx)
3176 {
3177         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, printer->info_2->priority);
3178 }
3179
3180 /*******************************************************************
3181  * fill a notify_info_data with the default priority
3182  ********************************************************************/
3183
3184 static void spoolss_notify_default_priority(int snum,
3185                                             struct spoolss_Notify *data,
3186                                             print_queue_struct *queue,
3187                                             NT_PRINTER_INFO_LEVEL *printer,
3188                                             TALLOC_CTX *mem_ctx)
3189 {
3190         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, printer->info_2->default_priority);
3191 }
3192
3193 /*******************************************************************
3194  * fill a notify_info_data with the start time
3195  ********************************************************************/
3196
3197 static void spoolss_notify_start_time(int snum,
3198                                       struct spoolss_Notify *data,
3199                                       print_queue_struct *queue,
3200                                       NT_PRINTER_INFO_LEVEL *printer,
3201                                       TALLOC_CTX *mem_ctx)
3202 {
3203         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, printer->info_2->starttime);
3204 }
3205
3206 /*******************************************************************
3207  * fill a notify_info_data with the until time
3208  ********************************************************************/
3209
3210 static void spoolss_notify_until_time(int snum,
3211                                       struct spoolss_Notify *data,
3212                                       print_queue_struct *queue,
3213                                       NT_PRINTER_INFO_LEVEL *printer,
3214                                       TALLOC_CTX *mem_ctx)
3215 {
3216         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, printer->info_2->untiltime);
3217 }
3218
3219 /*******************************************************************
3220  * fill a notify_info_data with the status
3221  ********************************************************************/
3222
3223 static void spoolss_notify_status(int snum,
3224                                   struct spoolss_Notify *data,
3225                                   print_queue_struct *queue,
3226                                   NT_PRINTER_INFO_LEVEL *printer,
3227                                   TALLOC_CTX *mem_ctx)
3228 {
3229         print_status_struct status;
3230
3231         print_queue_length(snum, &status);
3232         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, status.status);
3233 }
3234
3235 /*******************************************************************
3236  * fill a notify_info_data with the number of jobs queued
3237  ********************************************************************/
3238
3239 void spoolss_notify_cjobs(int snum,
3240                                  struct spoolss_Notify *data,
3241                                  print_queue_struct *queue,
3242                                  NT_PRINTER_INFO_LEVEL *printer,
3243                                  TALLOC_CTX *mem_ctx)
3244 {
3245         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, print_queue_length(snum, NULL));
3246 }
3247
3248 /*******************************************************************
3249  * fill a notify_info_data with the average ppm
3250  ********************************************************************/
3251
3252 static void spoolss_notify_average_ppm(int snum,
3253                                        struct spoolss_Notify *data,
3254                                        print_queue_struct *queue,
3255                                        NT_PRINTER_INFO_LEVEL *printer,
3256                                        TALLOC_CTX *mem_ctx)
3257 {
3258         /* always respond 8 pages per minutes */
3259         /* a little hard ! */
3260         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, printer->info_2->averageppm);
3261 }
3262
3263 /*******************************************************************
3264  * fill a notify_info_data with username
3265  ********************************************************************/
3266
3267 static void spoolss_notify_username(int snum,
3268                                     struct spoolss_Notify *data,
3269                                     print_queue_struct *queue,
3270                                     NT_PRINTER_INFO_LEVEL *printer,
3271                                     TALLOC_CTX *mem_ctx)
3272 {
3273         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, queue->fs_user);
3274 }
3275
3276 /*******************************************************************
3277  * fill a notify_info_data with job status
3278  ********************************************************************/
3279
3280 static void spoolss_notify_job_status(int snum,
3281                                       struct spoolss_Notify *data,
3282                                       print_queue_struct *queue,
3283                                       NT_PRINTER_INFO_LEVEL *printer,
3284                                       TALLOC_CTX *mem_ctx)
3285 {
3286         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, nt_printj_status(queue->status));
3287 }
3288
3289 /*******************************************************************
3290  * fill a notify_info_data with job name
3291  ********************************************************************/
3292
3293 static void spoolss_notify_job_name(int snum,
3294                                     struct spoolss_Notify *data,
3295                                     print_queue_struct *queue,
3296                                     NT_PRINTER_INFO_LEVEL *printer,
3297                                     TALLOC_CTX *mem_ctx)
3298 {
3299         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, queue->fs_file);
3300 }
3301
3302 /*******************************************************************
3303  * fill a notify_info_data with job status
3304  ********************************************************************/
3305
3306 static void spoolss_notify_job_status_string(int snum,
3307                                              struct spoolss_Notify *data,
3308                                              print_queue_struct *queue,
3309                                              NT_PRINTER_INFO_LEVEL *printer,
3310                                              TALLOC_CTX *mem_ctx)
3311 {
3312         /*
3313          * Now we're returning job status codes we just return a "" here. JRA.
3314          */
3315
3316         const char *p = "";
3317
3318 #if 0 /* NO LONGER NEEDED - JRA. 02/22/2001 */
3319         p = "unknown";
3320
3321         switch (queue->status) {
3322         case LPQ_QUEUED:
3323                 p = "Queued";
3324                 break;
3325         case LPQ_PAUSED:
3326                 p = "";    /* NT provides the paused string */
3327                 break;
3328         case LPQ_SPOOLING:
3329                 p = "Spooling";
3330                 break;
3331         case LPQ_PRINTING:
3332                 p = "Printing";
3333                 break;
3334         }
3335 #endif /* NO LONGER NEEDED. */
3336
3337         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, p);
3338 }
3339
3340 /*******************************************************************
3341  * fill a notify_info_data with job time
3342  ********************************************************************/
3343
3344 static void spoolss_notify_job_time(int snum,
3345                                     struct spoolss_Notify *data,
3346                                     print_queue_struct *queue,
3347                                     NT_PRINTER_INFO_LEVEL *printer,
3348                                     TALLOC_CTX *mem_ctx)
3349 {
3350         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, 0);
3351 }
3352
3353 /*******************************************************************
3354  * fill a notify_info_data with job size
3355  ********************************************************************/
3356
3357 static void spoolss_notify_job_size(int snum,
3358                                     struct spoolss_Notify *data,
3359                                     print_queue_struct *queue,
3360                                     NT_PRINTER_INFO_LEVEL *printer,
3361                                     TALLOC_CTX *mem_ctx)
3362 {
3363         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, queue->size);
3364 }
3365
3366 /*******************************************************************
3367  * fill a notify_info_data with page info
3368  ********************************************************************/
3369 static void spoolss_notify_total_pages(int snum,
3370                                 struct spoolss_Notify *data,
3371                                 print_queue_struct *queue,
3372                                 NT_PRINTER_INFO_LEVEL *printer,
3373                                 TALLOC_CTX *mem_ctx)
3374 {
3375         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, queue->page_count);
3376 }
3377
3378 /*******************************************************************
3379  * fill a notify_info_data with pages printed info.
3380  ********************************************************************/
3381 static void spoolss_notify_pages_printed(int snum,
3382                                 struct spoolss_Notify *data,
3383                                 print_queue_struct *queue,
3384                                 NT_PRINTER_INFO_LEVEL *printer,
3385                                 TALLOC_CTX *mem_ctx)
3386 {
3387         /* Add code when back-end tracks this */
3388         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, 0);
3389 }
3390
3391 /*******************************************************************
3392  Fill a notify_info_data with job position.
3393  ********************************************************************/
3394
3395 static void spoolss_notify_job_position(int snum,
3396                                         struct spoolss_Notify *data,
3397                                         print_queue_struct *queue,
3398                                         NT_PRINTER_INFO_LEVEL *printer,
3399                                         TALLOC_CTX *mem_ctx)
3400 {
3401         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, queue->job);
3402 }
3403
3404 /*******************************************************************
3405  Fill a notify_info_data with submitted time.
3406  ********************************************************************/
3407
3408 static void spoolss_notify_submitted_time(int snum,
3409                                           struct spoolss_Notify *data,
3410                                           print_queue_struct *queue,
3411                                           NT_PRINTER_INFO_LEVEL *printer,
3412                                           TALLOC_CTX *mem_ctx)
3413 {
3414         data->data.string.string = NULL;
3415         data->data.string.size = 0;
3416
3417         init_systemtime_buffer(mem_ctx, gmtime(&queue->time),
3418                                &data->data.string.string,
3419                                &data->data.string.size);
3420
3421 }
3422
3423 struct s_notify_info_data_table
3424 {
3425         enum spoolss_NotifyType type;
3426         enum spoolss_Field field;
3427         const char *name;
3428         enum spoolss_NotifyTable variable_type;
3429         void (*fn) (int snum, struct spoolss_Notify *data,
3430                     print_queue_struct *queue,
3431                     NT_PRINTER_INFO_LEVEL *printer, TALLOC_CTX *mem_ctx);
3432 };
3433
3434 /* A table describing the various print notification constants and
3435    whether the notification data is a pointer to a variable sized
3436    buffer, a one value uint32 or a two value uint32. */
3437
3438 static const struct s_notify_info_data_table notify_info_data_table[] =
3439 {
3440 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SERVER_NAME,         "PRINTER_NOTIFY_SERVER_NAME",         NOTIFY_TABLE_STRING,   spoolss_notify_server_name },
3441 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PRINTER_NAME,        "PRINTER_NOTIFY_PRINTER_NAME",        NOTIFY_TABLE_STRING,   spoolss_notify_printer_name },
3442 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SHARE_NAME,          "PRINTER_NOTIFY_SHARE_NAME",          NOTIFY_TABLE_STRING,   spoolss_notify_share_name },
3443 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PORT_NAME,           "PRINTER_NOTIFY_PORT_NAME",           NOTIFY_TABLE_STRING,   spoolss_notify_port_name },
3444 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DRIVER_NAME,         "PRINTER_NOTIFY_DRIVER_NAME",         NOTIFY_TABLE_STRING,   spoolss_notify_driver_name },
3445 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_COMMENT,             "PRINTER_NOTIFY_COMMENT",             NOTIFY_TABLE_STRING,   spoolss_notify_comment },
3446 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_LOCATION,            "PRINTER_NOTIFY_LOCATION",            NOTIFY_TABLE_STRING,   spoolss_notify_location },
3447 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DEVMODE,             "PRINTER_NOTIFY_DEVMODE",             NOTIFY_TABLE_DEVMODE,  spoolss_notify_devmode },
3448 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SEPFILE,             "PRINTER_NOTIFY_SEPFILE",             NOTIFY_TABLE_STRING,   spoolss_notify_sepfile },
3449 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PRINT_PROCESSOR,     "PRINTER_NOTIFY_PRINT_PROCESSOR",     NOTIFY_TABLE_STRING,   spoolss_notify_print_processor },
3450 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PARAMETERS,          "PRINTER_NOTIFY_PARAMETERS",          NOTIFY_TABLE_STRING,   spoolss_notify_parameters },
3451 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DATATYPE,            "PRINTER_NOTIFY_DATATYPE",            NOTIFY_TABLE_STRING,   spoolss_notify_datatype },
3452 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SECURITY_DESCRIPTOR, "PRINTER_NOTIFY_SECURITY_DESCRIPTOR", NOTIFY_TABLE_SECURITYDESCRIPTOR,   spoolss_notify_security_desc },
3453 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_ATTRIBUTES,          "PRINTER_NOTIFY_ATTRIBUTES",          NOTIFY_TABLE_DWORD,    spoolss_notify_attributes },
3454 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PRIORITY,            "PRINTER_NOTIFY_PRIORITY",            NOTIFY_TABLE_DWORD,    spoolss_notify_priority },
3455 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DEFAULT_PRIORITY,    "PRINTER_NOTIFY_DEFAULT_PRIORITY",    NOTIFY_TABLE_DWORD,    spoolss_notify_default_priority },
3456 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_START_TIME,          "PRINTER_NOTIFY_START_TIME",          NOTIFY_TABLE_DWORD,    spoolss_notify_start_time },
3457 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_UNTIL_TIME,          "PRINTER_NOTIFY_UNTIL_TIME",          NOTIFY_TABLE_DWORD,    spoolss_notify_until_time },
3458 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_STATUS,              "PRINTER_NOTIFY_STATUS",              NOTIFY_TABLE_DWORD,    spoolss_notify_status },
3459 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_STATUS_STRING,       "PRINTER_NOTIFY_STATUS_STRING",       NOTIFY_TABLE_STRING,   NULL },
3460 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_CJOBS,               "PRINTER_NOTIFY_CJOBS",               NOTIFY_TABLE_DWORD,    spoolss_notify_cjobs },
3461 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_AVERAGE_PPM,         "PRINTER_NOTIFY_AVERAGE_PPM",         NOTIFY_TABLE_DWORD,    spoolss_notify_average_ppm },
3462 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_TOTAL_PAGES,         "PRINTER_NOTIFY_TOTAL_PAGES",         NOTIFY_TABLE_DWORD,    NULL },
3463 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PAGES_PRINTED,       "PRINTER_NOTIFY_PAGES_PRINTED",       NOTIFY_TABLE_DWORD,    NULL },
3464 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_TOTAL_BYTES,         "PRINTER_NOTIFY_TOTAL_BYTES",         NOTIFY_TABLE_DWORD,    NULL },
3465 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_BYTES_PRINTED,       "PRINTER_NOTIFY_BYTES_PRINTED",       NOTIFY_TABLE_DWORD,    NULL },
3466 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_PRINTER_NAME,            "JOB_NOTIFY_PRINTER_NAME",            NOTIFY_TABLE_STRING,   spoolss_notify_printer_name },
3467 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_MACHINE_NAME,            "JOB_NOTIFY_MACHINE_NAME",            NOTIFY_TABLE_STRING,   spoolss_notify_server_name },
3468 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_PORT_NAME,               "JOB_NOTIFY_PORT_NAME",               NOTIFY_TABLE_STRING,   spoolss_notify_port_name },
3469 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_USER_NAME,               "JOB_NOTIFY_USER_NAME",               NOTIFY_TABLE_STRING,   spoolss_notify_username },
3470 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_NOTIFY_NAME,             "JOB_NOTIFY_NOTIFY_NAME",             NOTIFY_TABLE_STRING,   spoolss_notify_username },
3471 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_DATATYPE,                "JOB_NOTIFY_DATATYPE",                NOTIFY_TABLE_STRING,   spoolss_notify_datatype },
3472 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_PRINT_PROCESSOR,         "JOB_NOTIFY_PRINT_PROCESSOR",         NOTIFY_TABLE_STRING,   spoolss_notify_print_processor },
3473 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_PARAMETERS,              "JOB_NOTIFY_PARAMETERS",              NOTIFY_TABLE_STRING,   spoolss_notify_parameters },
3474 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_DRIVER_NAME,             "JOB_NOTIFY_DRIVER_NAME",             NOTIFY_TABLE_STRING,   spoolss_notify_driver_name },
3475 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_DEVMODE,                 "JOB_NOTIFY_DEVMODE",                 NOTIFY_TABLE_DEVMODE,  spoolss_notify_devmode },
3476 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_STATUS,                  "JOB_NOTIFY_STATUS",                  NOTIFY_TABLE_DWORD,    spoolss_notify_job_status },
3477 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_STATUS_STRING,           "JOB_NOTIFY_STATUS_STRING",           NOTIFY_TABLE_STRING,   spoolss_notify_job_status_string },
3478 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_SECURITY_DESCRIPTOR,     "JOB_NOTIFY_SECURITY_DESCRIPTOR",     NOTIFY_TABLE_SECURITYDESCRIPTOR,   NULL },
3479 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_DOCUMENT,                "JOB_NOTIFY_DOCUMENT",                NOTIFY_TABLE_STRING,   spoolss_notify_job_name },
3480 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_PRIORITY,                "JOB_NOTIFY_PRIORITY",                NOTIFY_TABLE_DWORD,    spoolss_notify_priority },
3481 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_POSITION,                "JOB_NOTIFY_POSITION",                NOTIFY_TABLE_DWORD,    spoolss_notify_job_position },
3482 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_SUBMITTED,               "JOB_NOTIFY_SUBMITTED",               NOTIFY_TABLE_TIME,     spoolss_notify_submitted_time },
3483 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_START_TIME,              "JOB_NOTIFY_START_TIME",              NOTIFY_TABLE_DWORD,    spoolss_notify_start_time },
3484 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_UNTIL_TIME,              "JOB_NOTIFY_UNTIL_TIME",              NOTIFY_TABLE_DWORD,    spoolss_notify_until_time },
3485 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_TIME,                    "JOB_NOTIFY_TIME",                    NOTIFY_TABLE_DWORD,    spoolss_notify_job_time },
3486 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_TOTAL_PAGES,             "JOB_NOTIFY_TOTAL_PAGES",             NOTIFY_TABLE_DWORD,    spoolss_notify_total_pages },
3487 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_PAGES_PRINTED,           "JOB_NOTIFY_PAGES_PRINTED",           NOTIFY_TABLE_DWORD,    spoolss_notify_pages_printed },
3488 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_TOTAL_BYTES,             "JOB_NOTIFY_TOTAL_BYTES",             NOTIFY_TABLE_DWORD,    spoolss_notify_job_size },
3489 };
3490
3491 /*******************************************************************
3492  Return the variable_type of info_data structure.
3493 ********************************************************************/
3494
3495 static uint32_t variable_type_of_notify_info_data(enum spoolss_NotifyType type,
3496                                                   enum spoolss_Field field)
3497 {
3498         int i=0;
3499
3500         for (i = 0; i < ARRAY_SIZE(notify_info_data_table); i++) {
3501                 if ( (notify_info_data_table[i].type == type) &&
3502                      (notify_info_data_table[i].field == field) ) {
3503                         return notify_info_data_table[i].variable_type;
3504                 }
3505         }
3506
3507         DEBUG(5, ("invalid notify data type %d/%d\n", type, field));
3508
3509         return 0;
3510 }
3511
3512 /****************************************************************************
3513 ****************************************************************************/
3514
3515 static bool search_notify(enum spoolss_NotifyType type,
3516                           enum spoolss_Field field,
3517                           int *value)
3518 {
3519         int i;
3520
3521         for (i = 0; i < ARRAY_SIZE(notify_info_data_table); i++) {
3522                 if (notify_info_data_table[i].type == type &&
3523                     notify_info_data_table[i].field == field &&
3524                     notify_info_data_table[i].fn != NULL) {
3525                         *value = i;
3526                         return True;
3527                 }
3528         }
3529
3530         return False;
3531 }
3532
3533 /****************************************************************************
3534 ****************************************************************************/
3535
3536 void construct_info_data(struct spoolss_Notify *info_data,
3537                          enum spoolss_NotifyType type,
3538                          enum spoolss_Field field,
3539                          int id)
3540 {
3541         info_data->type                 = type;
3542         info_data->field                = field;
3543         info_data->variable_type        = variable_type_of_notify_info_data(type, field);
3544         info_data->job_id               = id;
3545 }
3546
3547 /*******************************************************************
3548  *
3549  * fill a notify_info struct with info asked
3550  *
3551  ********************************************************************/
3552
3553 static bool construct_notify_printer_info(Printer_entry *print_hnd,
3554                                           struct spoolss_NotifyInfo *info,
3555                                           int snum,
3556                                           const struct spoolss_NotifyOptionType *option_type,
3557                                           uint32_t id,
3558                                           TALLOC_CTX *mem_ctx)
3559 {
3560         int field_num,j;
3561         enum spoolss_NotifyType type;
3562         enum spoolss_Field field;
3563
3564         struct spoolss_Notify *current_data;
3565         NT_PRINTER_INFO_LEVEL *printer = NULL;
3566         print_queue_struct *queue=NULL;
3567
3568         type = option_type->type;
3569
3570         DEBUG(4,("construct_notify_printer_info: Notify type: [%s], number of notify info: [%d] on printer: [%s]\n",
3571                 (type == PRINTER_NOTIFY_TYPE ? "PRINTER_NOTIFY_TYPE" : "JOB_NOTIFY_TYPE"),
3572                 option_type->count, lp_servicename(snum)));
3573
3574         if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &printer, 2, lp_const_servicename(snum))))
3575                 return False;
3576
3577         for(field_num=0; field_num < option_type->count; field_num++) {
3578                 field = option_type->fields[field_num];
3579
3580                 DEBUG(4,("construct_notify_printer_info: notify [%d]: type [%x], field [%x]\n", field_num, type, field));
3581
3582                 if (!search_notify(type, field, &j) )
3583                         continue;
3584
3585                 info->notifies = TALLOC_REALLOC_ARRAY(info, info->notifies,
3586                                                       struct spoolss_Notify,
3587                                                       info->count + 1);
3588                 if (info->notifies == NULL) {
3589                         DEBUG(2,("construct_notify_printer_info: failed to enlarge buffer info->data!\n"));
3590                         free_a_printer(&printer, 2);
3591                         return False;
3592                 }
3593
3594                 current_data = &info->notifies[info->count];
3595
3596                 construct_info_data(current_data, type, field, id);
3597
3598                 DEBUG(10,("construct_notify_printer_info: calling [%s]  snum=%d  printername=[%s])\n",
3599                                 notify_info_data_table[j].name, snum, printer->info_2->printername ));
3600
3601                 notify_info_data_table[j].fn(snum, current_data, queue,
3602                                              printer, mem_ctx);
3603
3604                 info->count++;
3605         }
3606
3607         free_a_printer(&printer, 2);
3608         return True;
3609 }
3610
3611 /*******************************************************************
3612  *
3613  * fill a notify_info struct with info asked
3614  *
3615  ********************************************************************/
3616
3617 static bool construct_notify_jobs_info(print_queue_struct *queue,
3618                                        struct spoolss_NotifyInfo *info,
3619                                        NT_PRINTER_INFO_LEVEL *printer,
3620                                        int snum,
3621                                        const struct spoolss_NotifyOptionType *option_type,
3622                                        uint32_t id,
3623                                        TALLOC_CTX *mem_ctx)
3624 {
3625         int field_num,j;
3626         enum spoolss_NotifyType type;
3627         enum spoolss_Field field;
3628         struct spoolss_Notify *current_data;
3629
3630         DEBUG(4,("construct_notify_jobs_info\n"));
3631
3632         type = option_type->type;
3633
3634         DEBUGADD(4,("Notify type: [%s], number of notify info: [%d]\n",
3635                 (type == PRINTER_NOTIFY_TYPE ? "PRINTER_NOTIFY_TYPE" : "JOB_NOTIFY_TYPE"),
3636                 option_type->count));
3637
3638         for(field_num=0; field_num<option_type->count; field_num++) {
3639                 field = option_type->fields[field_num];
3640
3641                 if (!search_notify(type, field, &j) )
3642                         continue;
3643
3644                 info->notifies = TALLOC_REALLOC_ARRAY(info, info->notifies,
3645                                                       struct spoolss_Notify,
3646                                                       info->count + 1);
3647                 if (info->notifies == NULL) {
3648                         DEBUG(2,("construct_notify_jobs_info: failed to enlarg buffer info->data!\n"));
3649                         return False;
3650                 }
3651
3652                 current_data=&(info->notifies[info->count]);
3653
3654                 construct_info_data(current_data, type, field, id);
3655                 notify_info_data_table[j].fn(snum, current_data, queue,
3656                                              printer, mem_ctx);
3657                 info->count++;
3658         }
3659
3660         return True;
3661 }
3662
3663 /*
3664  * JFM: The enumeration is not that simple, it's even non obvious.
3665  *
3666  * let's take an example: I want to monitor the PRINTER SERVER for
3667  * the printer's name and the number of jobs currently queued.
3668  * So in the NOTIFY_OPTION, I have one NOTIFY_OPTION_TYPE structure.
3669  * Its type is PRINTER_NOTIFY_TYPE and it has 2 fields NAME and CJOBS.
3670  *
3671  * I have 3 printers on the back of my server.
3672  *
3673  * Now the response is a NOTIFY_INFO structure, with 6 NOTIFY_INFO_DATA
3674  * structures.
3675  *   Number     Data                    Id
3676  *      1       printer 1 name          1
3677  *      2       printer 1 cjob          1
3678  *      3       printer 2 name          2
3679  *      4       printer 2 cjob          2
3680  *      5       printer 3 name          3
3681  *      6       printer 3 name          3
3682  *
3683  * that's the print server case, the printer case is even worse.
3684  */
3685
3686 /*******************************************************************
3687  *
3688  * enumerate all printers on the printserver
3689  * fill a notify_info struct with info asked
3690  *
3691  ********************************************************************/
3692
3693 static WERROR printserver_notify_info(pipes_struct *p, POLICY_HND *hnd,
3694                                       struct spoolss_NotifyInfo *info,
3695                                       TALLOC_CTX *mem_ctx)
3696 {
3697         int snum;
3698         Printer_entry *Printer=find_printer_index_by_hnd(p, hnd);
3699         int n_services=lp_numservices();
3700         int i;
3701         struct spoolss_NotifyOption *option;
3702         struct spoolss_NotifyOptionType option_type;
3703
3704         DEBUG(4,("printserver_notify_info\n"));
3705
3706         if (!Printer)
3707                 return WERR_BADFID;
3708
3709         option = Printer->notify.option;
3710
3711         info->version   = 2;
3712         info->notifies  = NULL;
3713         info->count     = 0;
3714
3715         /* a bug in xp sp2 rc2 causes it to send a fnpcn request without
3716            sending a ffpcn() request first */
3717
3718         if ( !option )
3719                 return WERR_BADFID;
3720
3721         for (i=0; i<option->count; i++) {
3722                 option_type = option->types[i];
3723
3724                 if (option_type.type != PRINTER_NOTIFY_TYPE)
3725                         continue;
3726
3727                 for (snum=0; snum<n_services; snum++)
3728                 {
3729                         if ( lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) )
3730                                 construct_notify_printer_info ( Printer, info, snum, &option_type, snum, mem_ctx );
3731                 }
3732         }
3733
3734 #if 0
3735         /*
3736          * Debugging information, don't delete.
3737          */
3738
3739         DEBUG(1,("dumping the NOTIFY_INFO\n"));
3740         DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
3741         DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3742
3743         for (i=0; i<info->count; i++) {
3744                 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3745                 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
3746                 info->data[i].id, info->data[i].size, info->data[i].enc_type));
3747         }
3748 #endif
3749
3750         return WERR_OK;
3751 }
3752
3753 /*******************************************************************
3754  *
3755  * fill a notify_info struct with info asked
3756  *
3757  ********************************************************************/
3758
3759 static WERROR printer_notify_info(pipes_struct *p, POLICY_HND *hnd, struct spoolss_NotifyInfo *info,
3760                                   TALLOC_CTX *mem_ctx)
3761 {
3762         int snum;
3763         Printer_entry *Printer=find_printer_index_by_hnd(p, hnd);
3764         int i;
3765         uint32 id;
3766         struct spoolss_NotifyOption *option;
3767         struct spoolss_NotifyOptionType option_type;
3768         int count,j;
3769         print_queue_struct *queue=NULL;
3770         print_status_struct status;
3771
3772         DEBUG(4,("printer_notify_info\n"));
3773
3774         if (!Printer)
3775                 return WERR_BADFID;
3776
3777         option = Printer->notify.option;
3778         id = 0x0;
3779
3780         info->version   = 2;
3781         info->notifies  = NULL;
3782         info->count     = 0;
3783
3784         /* a bug in xp sp2 rc2 causes it to send a fnpcn request without
3785            sending a ffpcn() request first */
3786
3787         if ( !option )
3788                 return WERR_BADFID;
3789
3790         get_printer_snum(p, hnd, &snum, NULL);
3791
3792         for (i=0; i<option->count; i++) {
3793                 option_type = option->types[i];
3794
3795                 switch (option_type.type) {
3796                 case PRINTER_NOTIFY_TYPE:
3797                         if(construct_notify_printer_info(Printer, info, snum,
3798                                                          &option_type, id,
3799                                                          mem_ctx))
3800                                 id--;
3801                         break;
3802
3803                 case JOB_NOTIFY_TYPE: {
3804                         NT_PRINTER_INFO_LEVEL *printer = NULL;
3805
3806                         count = print_queue_status(snum, &queue, &status);
3807
3808                         if (!W_ERROR_IS_OK(get_a_printer(Printer, &printer, 2, lp_const_servicename(snum))))
3809                                 goto done;
3810
3811                         for (j=0; j<count; j++) {
3812                                 construct_notify_jobs_info(&queue[j], info,
3813                                                            printer, snum,
3814                                                            &option_type,
3815                                                            queue[j].job,
3816                                                            mem_ctx);
3817                         }
3818
3819                         free_a_printer(&printer, 2);
3820
3821                 done:
3822                         SAFE_FREE(queue);
3823                         break;
3824                 }
3825                 }
3826         }
3827
3828         /*
3829          * Debugging information, don't delete.
3830          */
3831         /*
3832         DEBUG(1,("dumping the NOTIFY_INFO\n"));
3833         DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
3834         DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3835
3836         for (i=0; i<info->count; i++) {
3837                 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3838                 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
3839                 info->data[i].id, info->data[i].size, info->data[i].enc_type));
3840         }
3841         */
3842         return WERR_OK;
3843 }
3844
3845 /****************************************************************
3846  _spoolss_RouterRefreshPrinterChangeNotify
3847 ****************************************************************/
3848
3849 WERROR _spoolss_RouterRefreshPrinterChangeNotify(pipes_struct *p,
3850                                                  struct spoolss_RouterRefreshPrinterChangeNotify *r)
3851 {
3852         POLICY_HND *handle = r->in.handle;
3853         struct spoolss_NotifyInfo *info;
3854
3855         Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
3856         WERROR result = WERR_BADFID;
3857
3858         /* we always have a spoolss_NotifyInfo struct */
3859         info = talloc_zero(p->mem_ctx, struct spoolss_NotifyInfo);
3860         if (!info) {
3861                 result = WERR_NOMEM;
3862                 goto done;
3863         }
3864
3865         *r->out.info = info;
3866
3867         if (!Printer) {
3868                 DEBUG(2,("_spoolss_RouterRefreshPrinterChangeNotify: "
3869                         "Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
3870                 goto done;
3871         }
3872
3873         DEBUG(4,("Printer type %x\n",Printer->printer_type));
3874
3875         /*
3876          *      We are now using the change value, and
3877          *      I should check for PRINTER_NOTIFY_OPTIONS_REFRESH but as
3878          *      I don't have a global notification system, I'm sending back all the
3879          *      informations even when _NOTHING_ has changed.
3880          */
3881
3882         /* We need to keep track of the change value to send back in
3883            RRPCN replies otherwise our updates are ignored. */
3884
3885         Printer->notify.fnpcn = True;
3886
3887         if (Printer->notify.client_connected) {
3888                 DEBUG(10,("_spoolss_RouterRefreshPrinterChangeNotify: "
3889                         "Saving change value in request [%x]\n",
3890                         r->in.change_low));
3891                 Printer->notify.change = r->in.change_low;
3892         }
3893
3894         /* just ignore the spoolss_NotifyOption */
3895
3896         switch (Printer->printer_type) {
3897                 case SPLHND_SERVER:
3898                         result = printserver_notify_info(p, handle, info, p->mem_ctx);
3899                         break;
3900
3901                 case SPLHND_PRINTER:
3902                         result = printer_notify_info(p, handle, info, p->mem_ctx);
3903                         break;
3904         }
3905
3906         Printer->notify.fnpcn = False;
3907
3908 done:
3909         return result;
3910 }
3911
3912 /********************************************************************
3913  * construct_printer_info_0
3914  * fill a printer_info_0 struct
3915  ********************************************************************/
3916
3917 static bool construct_printer_info_0(Printer_entry *print_hnd, PRINTER_INFO_0 *printer, int snum)
3918 {
3919         char *chaine = NULL;
3920         int count;
3921         NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
3922         counter_printer_0 *session_counter;
3923         uint32 global_counter;
3924         struct tm *t;
3925         time_t setuptime;
3926         print_status_struct status;
3927         TALLOC_CTX *ctx = talloc_tos();
3928
3929         if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
3930                 return False;
3931
3932         init_unistr(&printer->printername, ntprinter->info_2->printername);
3933
3934         chaine = talloc_asprintf(ctx, "\\\\%s", get_server_name(print_hnd));
3935         if (!chaine) {
3936                 free_a_printer(&ntprinter,2);
3937                 return false;
3938         }
3939
3940         count = print_queue_length(snum, &status);
3941
3942         /* check if we already have a counter for this printer */
3943         for(session_counter = counter_list; session_counter; session_counter = session_counter->next) {
3944                 if (session_counter->snum == snum)
3945                         break;
3946         }
3947
3948         init_unistr(&printer->servername, chaine);
3949
3950         /* it's the first time, add it to the list */
3951         if (session_counter==NULL) {
3952                 if((session_counter=SMB_MALLOC_P(counter_printer_0)) == NULL) {
3953                         free_a_printer(&ntprinter, 2);
3954                         return False;
3955                 }
3956                 ZERO_STRUCTP(session_counter);
3957                 session_counter->snum=snum;
3958                 session_counter->counter=0;
3959                 DLIST_ADD(counter_list, session_counter);
3960         }
3961
3962         /* increment it */
3963         session_counter->counter++;
3964
3965         /* JFM:
3966          * the global_counter should be stored in a TDB as it's common to all the clients
3967          * and should be zeroed on samba startup
3968          */
3969         global_counter=session_counter->counter;
3970         printer->cjobs = count;
3971         printer->total_jobs = 0;
3972         printer->total_bytes = 0;
3973
3974         setuptime = (time_t)ntprinter->info_2->setuptime;
3975         t=gmtime(&setuptime);
3976
3977         printer->year = t->tm_year+1900;
3978         printer->month = t->tm_mon+1;
3979         printer->dayofweek = t->tm_wday;
3980         printer->day = t->tm_mday;
3981         printer->hour = t->tm_hour;
3982         printer->minute = t->tm_min;
3983         printer->second = t->tm_sec;
3984         printer->milliseconds = 0;
3985
3986         printer->global_counter = global_counter;
3987         printer->total_pages = 0;
3988
3989         /* in 2.2 we reported ourselves as 0x0004 and 0x0565 */
3990         printer->major_version = 0x0005;        /* NT 5 */
3991         printer->build_version = 0x0893;        /* build 2195 */
3992
3993         printer->unknown7 = 0x1;
3994         printer->unknown8 = 0x0;
3995         printer->unknown9 = 0x0;
3996         printer->session_counter = session_counter->counter;
3997         printer->unknown11 = 0x0;
3998         printer->printer_errors = 0x0;          /* number of print failure */
3999         printer->unknown13 = 0x0;
4000         printer->unknown14 = 0x1;
4001         printer->unknown15 = 0x024a;            /* 586 Pentium ? */
4002         printer->unknown16 =  0x0;
4003         printer->change_id = ntprinter->info_2->changeid; /* ChangeID in milliseconds*/
4004         printer->unknown18 =  0x0;
4005         printer->status = nt_printq_status(status.status);
4006         printer->unknown20 =  0x0;
4007         printer->c_setprinter = get_c_setprinter(); /* monotonically increasing sum of delta printer counts */
4008         printer->unknown22 = 0x0;
4009         printer->unknown23 = 0x6;               /* 6  ???*/
4010         printer->unknown24 = 0;                 /* unknown 24 to 26 are always 0 */
4011         printer->unknown25 = 0;
4012         printer->unknown26 = 0;
4013         printer->unknown27 = 0;
4014         printer->unknown28 = 0;
4015         printer->unknown29 = 0;
4016
4017         free_a_printer(&ntprinter,2);
4018         return (True);
4019 }
4020
4021 /********************************************************************
4022  * construct_printer_info_1
4023  * fill a printer_info_1 struct
4024  ********************************************************************/
4025 static bool construct_printer_info_1(Printer_entry *print_hnd, uint32 flags, PRINTER_INFO_1 *printer, int snum)
4026 {
4027         char *chaine = NULL;
4028         NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4029         TALLOC_CTX *ctx = talloc_tos();
4030
4031         if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
4032                 return false;
4033
4034         printer->flags=flags;
4035
4036         if (*ntprinter->info_2->comment == '\0') {
4037                 init_unistr(&printer->comment, lp_comment(snum));
4038                 chaine = talloc_asprintf(ctx,
4039                                 "%s,%s,%s", ntprinter->info_2->printername,
4040                                 ntprinter->info_2->drivername, lp_comment(snum));
4041         }
4042         else {
4043                 init_unistr(&printer->comment, ntprinter->info_2->comment); /* saved comment. */
4044                 chaine = talloc_asprintf(ctx,
4045                                 "%s,%s,%s", ntprinter->info_2->printername,
4046                                 ntprinter->info_2->drivername, ntprinter->info_2->comment);
4047         }
4048
4049         if (!chaine) {
4050                 free_a_printer(&ntprinter,2);
4051                 return false;
4052         }
4053
4054         init_unistr(&printer->description, chaine);
4055         init_unistr(&printer->name, ntprinter->info_2->printername);
4056
4057         free_a_printer(&ntprinter,2);
4058
4059         return True;
4060 }
4061
4062 /****************************************************************************
4063  Free a DEVMODE struct.
4064 ****************************************************************************/
4065
4066 static void free_dev_mode(DEVICEMODE *dev)
4067 {
4068         if (dev == NULL)
4069                 return;
4070
4071         SAFE_FREE(dev->dev_private);
4072         SAFE_FREE(dev);
4073 }
4074
4075
4076 /****************************************************************************
4077  Convert an NT_DEVICEMODE to a DEVICEMODE structure.  Both pointers
4078  should be valid upon entry
4079 ****************************************************************************/
4080
4081 static bool convert_nt_devicemode( DEVICEMODE *devmode, NT_DEVICEMODE *ntdevmode )
4082 {
4083         if ( !devmode || !ntdevmode )
4084                 return False;
4085
4086         init_unistr(&devmode->devicename, ntdevmode->devicename);
4087
4088         init_unistr(&devmode->formname, ntdevmode->formname);
4089
4090         devmode->specversion      = ntdevmode->specversion;
4091         devmode->driverversion    = ntdevmode->driverversion;
4092         devmode->size             = ntdevmode->size;
4093         devmode->driverextra      = ntdevmode->driverextra;
4094         devmode->fields           = ntdevmode->fields;
4095
4096         devmode->orientation      = ntdevmode->orientation;
4097         devmode->papersize        = ntdevmode->papersize;
4098         devmode->paperlength      = ntdevmode->paperlength;
4099         devmode->paperwidth       = ntdevmode->paperwidth;
4100         devmode->scale            = ntdevmode->scale;
4101         devmode->copies           = ntdevmode->copies;
4102         devmode->defaultsource    = ntdevmode->defaultsource;
4103         devmode->printquality     = ntdevmode->printquality;
4104         devmode->color            = ntdevmode->color;
4105         devmode->duplex           = ntdevmode->duplex;
4106         devmode->yresolution      = ntdevmode->yresolution;
4107         devmode->ttoption         = ntdevmode->ttoption;
4108         devmode->collate          = ntdevmode->collate;
4109         devmode->icmmethod        = ntdevmode->icmmethod;
4110         devmode->icmintent        = ntdevmode->icmintent;
4111         devmode->mediatype        = ntdevmode->mediatype;
4112         devmode->dithertype       = ntdevmode->dithertype;
4113
4114         if (ntdevmode->nt_dev_private != NULL) {
4115                 if ((devmode->dev_private=(uint8 *)memdup(ntdevmode->nt_dev_private, ntdevmode->driverextra)) == NULL)
4116                         return False;
4117         }
4118
4119         return True;
4120 }
4121
4122 /****************************************************************************
4123  Create a DEVMODE struct. Returns malloced memory.
4124 ****************************************************************************/
4125
4126 DEVICEMODE *construct_dev_mode(const char *servicename)
4127 {
4128         NT_PRINTER_INFO_LEVEL   *printer = NULL;
4129         DEVICEMODE              *devmode = NULL;
4130
4131         DEBUG(7,("construct_dev_mode\n"));
4132
4133         DEBUGADD(8,("getting printer characteristics\n"));
4134
4135         if (!W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, servicename)))
4136                 return NULL;
4137
4138         if ( !printer->info_2->devmode ) {
4139                 DEBUG(5, ("BONG! There was no device mode!\n"));
4140                 goto done;
4141         }
4142
4143         if ((devmode = SMB_MALLOC_P(DEVICEMODE)) == NULL) {
4144                 DEBUG(2,("construct_dev_mode: malloc fail.\n"));
4145                 goto done;
4146         }
4147
4148         ZERO_STRUCTP(devmode);
4149
4150         DEBUGADD(8,("loading DEVICEMODE\n"));
4151
4152         if ( !convert_nt_devicemode( devmode, printer->info_2->devmode ) ) {
4153                 free_dev_mode( devmode );
4154                 devmode = NULL;
4155         }
4156
4157 done:
4158         free_a_printer(&printer,2);
4159
4160         return devmode;
4161 }
4162
4163 /********************************************************************
4164  * construct_printer_info_2
4165  * fill a printer_info_2 struct
4166  ********************************************************************/
4167
4168 static bool construct_printer_info_2(Printer_entry *print_hnd, PRINTER_INFO_2 *printer, int snum)
4169 {
4170         int count;
4171         NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4172
4173         print_status_struct status;
4174
4175         if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
4176                 return False;
4177
4178         count = print_queue_length(snum, &status);
4179
4180         init_unistr(&printer->servername, ntprinter->info_2->servername); /* servername*/
4181         init_unistr(&printer->printername, ntprinter->info_2->printername);                             /* printername*/
4182         init_unistr(&printer->sharename, lp_servicename(snum));                 /* sharename */
4183         init_unistr(&printer->portname, ntprinter->info_2->portname);                   /* port */
4184         init_unistr(&printer->drivername, ntprinter->info_2->drivername);       /* drivername */
4185
4186         if (*ntprinter->info_2->comment == '\0')
4187                 init_unistr(&printer->comment, lp_comment(snum));                       /* comment */
4188         else
4189                 init_unistr(&printer->comment, ntprinter->info_2->comment); /* saved comment. */
4190
4191         init_unistr(&printer->location, ntprinter->info_2->location);           /* location */
4192         init_unistr(&printer->sepfile, ntprinter->info_2->sepfile);             /* separator file */
4193         init_unistr(&printer->printprocessor, ntprinter->info_2->printprocessor);/* print processor */
4194         init_unistr(&printer->datatype, ntprinter->info_2->datatype);           /* datatype */
4195         init_unistr(&printer->parameters, ntprinter->info_2->parameters);       /* parameters (of print processor) */
4196
4197         printer->attributes = ntprinter->info_2->attributes;
4198
4199         printer->priority = ntprinter->info_2->priority;                                /* priority */
4200         printer->defaultpriority = ntprinter->info_2->default_priority;         /* default priority */
4201         printer->starttime = ntprinter->info_2->starttime;                      /* starttime */
4202         printer->untiltime = ntprinter->info_2->untiltime;                      /* untiltime */
4203         printer->status = nt_printq_status(status.status);                      /* status */
4204         printer->cjobs = count;                                                 /* jobs */
4205         printer->averageppm = ntprinter->info_2->averageppm;                    /* average pages per minute */
4206
4207         if ( !(printer->devmode = construct_dev_mode(
4208                        lp_const_servicename(snum))) )
4209                 DEBUG(8, ("Returning NULL Devicemode!\n"));
4210
4211         printer->secdesc = NULL;
4212
4213         if ( ntprinter->info_2->secdesc_buf
4214                 && ntprinter->info_2->secdesc_buf->sd_size != 0 )
4215         {
4216                 /* don't use talloc_steal() here unless you do a deep steal of all
4217                    the SEC_DESC members */
4218
4219                 printer->secdesc = dup_sec_desc( talloc_tos(),
4220                         ntprinter->info_2->secdesc_buf->sd );
4221         }
4222
4223         free_a_printer(&ntprinter, 2);
4224
4225         return True;
4226 }
4227
4228 /********************************************************************
4229  * construct_printer_info_3
4230  * fill a printer_info_3 struct
4231  ********************************************************************/
4232
4233 static bool construct_printer_info_3(Printer_entry *print_hnd, PRINTER_INFO_3 **pp_printer, int snum)
4234 {
4235         NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4236         PRINTER_INFO_3 *printer = NULL;
4237
4238         if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
4239                 return False;
4240
4241         *pp_printer = NULL;
4242         if ((printer = SMB_MALLOC_P(PRINTER_INFO_3)) == NULL) {
4243                 DEBUG(2,("construct_printer_info_3: malloc fail.\n"));
4244                 free_a_printer(&ntprinter, 2);
4245                 return False;
4246         }
4247
4248         ZERO_STRUCTP(printer);
4249
4250         /* These are the components of the SD we are returning. */
4251
4252         if (ntprinter->info_2->secdesc_buf && ntprinter->info_2->secdesc_buf->sd_size != 0) {
4253                 /* don't use talloc_steal() here unless you do a deep steal of all
4254                    the SEC_DESC members */
4255
4256                 printer->secdesc = dup_sec_desc( talloc_tos(),
4257                         ntprinter->info_2->secdesc_buf->sd );
4258         }
4259
4260         free_a_printer(&ntprinter, 2);
4261
4262         *pp_printer = printer;
4263         return True;
4264 }
4265
4266 /********************************************************************
4267  * construct_printer_info_4
4268  * fill a printer_info_4 struct
4269  ********************************************************************/
4270
4271 static bool construct_printer_info_4(Printer_entry *print_hnd, PRINTER_INFO_4 *printer, int snum)
4272 {
4273         NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4274
4275         if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
4276                 return False;
4277
4278         init_unistr(&printer->printername, ntprinter->info_2->printername);                             /* printername*/
4279         init_unistr(&printer->servername, ntprinter->info_2->servername); /* servername*/
4280         printer->attributes = ntprinter->info_2->attributes;
4281
4282         free_a_printer(&ntprinter, 2);
4283         return True;
4284 }
4285
4286 /********************************************************************
4287  * construct_printer_info_5
4288  * fill a printer_info_5 struct
4289  ********************************************************************/
4290
4291 static bool construct_printer_info_5(Printer_entry *print_hnd, PRINTER_INFO_5 *printer, int snum)
4292 {
4293         NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4294
4295         if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
4296                 return False;
4297
4298         init_unistr(&printer->printername, ntprinter->info_2->printername);
4299         init_unistr(&printer->portname, ntprinter->info_2->portname);
4300         printer->attributes = ntprinter->info_2->attributes;
4301
4302         /* these two are not used by NT+ according to MSDN */
4303
4304         printer->device_not_selected_timeout = 0x0;  /* have seen 0x3a98 */
4305         printer->transmission_retry_timeout  = 0x0;  /* have seen 0xafc8 */
4306
4307         free_a_printer(&ntprinter, 2);
4308
4309         return True;
4310 }
4311
4312 /********************************************************************
4313  * construct_printer_info_6
4314  * fill a printer_info_6 struct
4315  ********************************************************************/
4316
4317 static bool construct_printer_info_6(Printer_entry *print_hnd,
4318                                      PRINTER_INFO_6 *printer,
4319                                      int snum)
4320 {
4321         NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4322         int count;
4323         print_status_struct status;
4324
4325         if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2,
4326                                          lp_const_servicename(snum))))
4327                 return False;
4328
4329         count = print_queue_length(snum, &status);
4330
4331         printer->status = nt_printq_status(status.status);
4332
4333         free_a_printer(&ntprinter, 2);
4334
4335         return True;
4336 }
4337
4338 /********************************************************************
4339  * construct_printer_info_7
4340  * fill a printer_info_7 struct
4341  ********************************************************************/
4342
4343 static bool construct_printer_info_7(Printer_entry *print_hnd, PRINTER_INFO_7 *printer, int snum)
4344 {
4345         char *guid_str = NULL;
4346         struct GUID guid;
4347
4348         if (is_printer_published(print_hnd, snum, &guid)) {
4349                 if (asprintf(&guid_str, "{%s}",
4350                              GUID_string(talloc_tos(), &guid)) == -1) {
4351                         return false;
4352                 }
4353                 strupper_m(guid_str);
4354                 init_unistr(&printer->guid, guid_str);
4355                 SAFE_FREE(guid_str);
4356                 printer->action = DSPRINT_PUBLISH;
4357         } else {
4358                 init_unistr(&printer->guid, "");
4359                 printer->action = DSPRINT_UNPUBLISH;
4360         }
4361
4362         return True;
4363 }
4364
4365 /********************************************************************
4366  Spoolss_enumprinters.
4367 ********************************************************************/
4368
4369 static WERROR enum_all_printers_info_1(uint32 flags, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4370 {
4371         int snum;
4372         int i;
4373         int n_services=lp_numservices();
4374         PRINTER_INFO_1 *printers=NULL;
4375         PRINTER_INFO_1 current_prt;
4376         WERROR result = WERR_OK;
4377
4378         DEBUG(4,("enum_all_printers_info_1\n"));
4379
4380         for (snum=0; snum<n_services; snum++) {
4381                 if (lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) ) {
4382                         DEBUG(4,("Found a printer in smb.conf: %s[%x]\n", lp_servicename(snum), snum));
4383
4384                         if (construct_printer_info_1(NULL, flags, &current_prt, snum)) {
4385                                 if((printers=SMB_REALLOC_ARRAY(printers, PRINTER_INFO_1, *returned +1)) == NULL) {
4386                                         DEBUG(2,("enum_all_printers_info_1: failed to enlarge printers buffer!\n"));
4387                                         *returned=0;
4388                                         return WERR_NOMEM;
4389                                 }
4390                                 DEBUG(4,("ReAlloced memory for [%d] PRINTER_INFO_1\n", *returned));
4391
4392                                 memcpy(&printers[*returned], &current_prt, sizeof(PRINTER_INFO_1));
4393                                 (*returned)++;
4394                         }
4395                 }
4396         }
4397
4398         /* check the required size. */
4399         for (i=0; i<*returned; i++)
4400                 (*needed) += spoolss_size_printer_info_1(&printers[i]);
4401
4402         if (*needed > offered) {
4403                 result = WERR_INSUFFICIENT_BUFFER;
4404                 goto out;
4405         }
4406
4407         if (!rpcbuf_alloc_size(buffer, *needed)) {
4408                 result = WERR_NOMEM;
4409                 goto out;
4410         }
4411
4412         /* fill the buffer with the structures */
4413         for (i=0; i<*returned; i++)
4414                 smb_io_printer_info_1("", buffer, &printers[i], 0);
4415
4416 out:
4417         /* clear memory */
4418
4419         SAFE_FREE(printers);
4420
4421         if ( !W_ERROR_IS_OK(result) )
4422                 *returned = 0;
4423
4424         return result;
4425 }
4426
4427 /********************************************************************
4428  enum_all_printers_info_1_local.
4429 *********************************************************************/
4430
4431 static WERROR enum_all_printers_info_1_local(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4432 {
4433         DEBUG(4,("enum_all_printers_info_1_local\n"));
4434
4435         return enum_all_printers_info_1(PRINTER_ENUM_ICON8, buffer, offered, needed, returned);
4436 }
4437
4438 /********************************************************************
4439  enum_all_printers_info_1_name.
4440 *********************************************************************/
4441
4442 static WERROR enum_all_printers_info_1_name(fstring name, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4443 {
4444         char *s = name;
4445
4446         DEBUG(4,("enum_all_printers_info_1_name\n"));
4447
4448         if ((name[0] == '\\') && (name[1] == '\\'))
4449                 s = name + 2;
4450
4451         if (is_myname_or_ipaddr(s)) {
4452                 return enum_all_printers_info_1(PRINTER_ENUM_ICON8, buffer, offered, needed, returned);
4453         }
4454         else
4455                 return WERR_INVALID_NAME;
4456 }
4457
4458 #if 0   /* JERRY -- disabled for now.  Don't think this is used, tested, or correct */
4459 /********************************************************************
4460  enum_all_printers_info_1_remote.
4461 *********************************************************************/
4462
4463 static WERROR enum_all_printers_info_1_remote(fstring name, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4464 {
4465         PRINTER_INFO_1 *printer;
4466         fstring printername;
4467         fstring desc;
4468         fstring comment;
4469         DEBUG(4,("enum_all_printers_info_1_remote\n"));
4470         WERROR result = WERR_OK;
4471
4472         /* JFM: currently it's more a place holder than anything else.
4473          * In the spooler world there is a notion of server registration.
4474          * the print servers are registered on the PDC (in the same domain)
4475          *
4476          * We should have a TDB here. The registration is done thru an
4477          * undocumented RPC call.
4478          */
4479
4480         if((printer=SMB_MALLOC_P(PRINTER_INFO_1)) == NULL)
4481                 return WERR_NOMEM;
4482
4483         *returned=1;
4484
4485         slprintf(printername, sizeof(printername)-1,"Windows NT Remote Printers!!\\\\%s", name);
4486         slprintf(desc, sizeof(desc)-1,"%s", name);
4487         slprintf(comment, sizeof(comment)-1, "Logged on Domain");
4488
4489         init_unistr(&printer->description, desc);
4490         init_unistr(&printer->name, printername);
4491         init_unistr(&printer->comment, comment);
4492         printer->flags=PRINTER_ENUM_ICON3|PRINTER_ENUM_CONTAINER;
4493
4494         /* check the required size. */
4495         *needed += spoolss_size_printer_info_1(printer);
4496
4497         if (*needed > offered) {
4498                 result = WERR_INSUFFICIENT_BUFFER;
4499                 goto out;
4500         }
4501
4502         if (!rpcbuf_alloc_size(buffer, *needed)) {
4503                 result = WERR_NOMEM;
4504                 goto out;
4505         }
4506
4507         /* fill the buffer with the structures */
4508         smb_io_printer_info_1("", buffer, printer, 0);
4509
4510 out:
4511         /* clear memory */
4512         SAFE_FREE(printer);
4513
4514         if ( !W_ERROR_IS_OK(result) )
4515                 *returned = 0;
4516
4517         return result;
4518 }
4519
4520 #endif
4521
4522 /********************************************************************
4523  enum_all_printers_info_1_network.
4524 *********************************************************************/
4525
4526 static WERROR enum_all_printers_info_1_network(fstring name, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4527 {
4528         char *s = name;
4529
4530         DEBUG(4,("enum_all_printers_info_1_network\n"));
4531
4532         /* If we respond to a enum_printers level 1 on our name with flags
4533            set to PRINTER_ENUM_REMOTE with a list of printers then these
4534            printers incorrectly appear in the APW browse list.
4535            Specifically the printers for the server appear at the workgroup
4536            level where all the other servers in the domain are
4537            listed. Windows responds to this call with a
4538            WERR_CAN_NOT_COMPLETE so we should do the same. */
4539
4540         if (name[0] == '\\' && name[1] == '\\')
4541                  s = name + 2;
4542
4543         if (is_myname_or_ipaddr(s))
4544                  return WERR_CAN_NOT_COMPLETE;
4545
4546         return enum_all_printers_info_1(PRINTER_ENUM_NAME, buffer, offered, needed, returned);
4547 }
4548
4549 /********************************************************************
4550  * api_spoolss_enumprinters
4551  *
4552  * called from api_spoolss_enumprinters (see this to understand)
4553  ********************************************************************/
4554
4555 static WERROR enum_all_printers_info_2(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4556 {
4557         int snum;
4558         int i;
4559         int n_services=lp_numservices();
4560         PRINTER_INFO_2 *printers=NULL;
4561         PRINTER_INFO_2 current_prt;
4562         WERROR result = WERR_OK;
4563
4564         *returned = 0;
4565
4566         for (snum=0; snum<n_services; snum++) {
4567                 if (lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) ) {
4568                         DEBUG(4,("Found a printer in smb.conf: %s[%x]\n", lp_servicename(snum), snum));
4569
4570                         if (construct_printer_info_2(NULL, &current_prt, snum)) {
4571                                 if ( !(printers=SMB_REALLOC_ARRAY(printers, PRINTER_INFO_2, *returned +1)) ) {
4572                                         DEBUG(2,("enum_all_printers_info_2: failed to enlarge printers buffer!\n"));
4573                                         *returned = 0;
4574                                         return WERR_NOMEM;
4575                                 }
4576
4577                                 DEBUG(4,("ReAlloced memory for [%d] PRINTER_INFO_2\n", *returned + 1));
4578
4579                                 memcpy(&printers[*returned], &current_prt, sizeof(PRINTER_INFO_2));
4580
4581                                 (*returned)++;
4582                         }
4583                 }
4584         }
4585
4586         /* check the required size. */
4587         for (i=0; i<*returned; i++)
4588                 (*needed) += spoolss_size_printer_info_2(&printers[i]);
4589
4590         if (*needed > offered) {
4591                 result = WERR_INSUFFICIENT_BUFFER;
4592                 goto out;
4593         }
4594
4595         if (!rpcbuf_alloc_size(buffer, *needed)) {
4596                 result = WERR_NOMEM;
4597                 goto out;
4598         }
4599
4600         /* fill the buffer with the structures */
4601         for (i=0; i<*returned; i++)
4602                 smb_io_printer_info_2("", buffer, &(printers[i]), 0);
4603
4604 out:
4605         /* clear memory */
4606
4607         for (i=0; i<*returned; i++)
4608                 free_devmode(printers[i].devmode);
4609
4610         SAFE_FREE(printers);
4611
4612         if ( !W_ERROR_IS_OK(result) )
4613                 *returned = 0;
4614
4615         return result;
4616 }
4617
4618 /********************************************************************
4619  * handle enumeration of printers at level 1
4620  ********************************************************************/
4621
4622 static WERROR enumprinters_level1( uint32 flags, fstring name,
4623                                  RPC_BUFFER *buffer, uint32 offered,
4624                                  uint32 *needed, uint32 *returned)
4625 {
4626         /* Not all the flags are equals */
4627
4628         if (flags & PRINTER_ENUM_LOCAL)
4629                 return enum_all_printers_info_1_local(buffer, offered, needed, returned);
4630
4631         if (flags & PRINTER_ENUM_NAME)
4632                 return enum_all_printers_info_1_name(name, buffer, offered, needed, returned);
4633
4634 #if 0   /* JERRY - disabled for now */
4635         if (flags & PRINTER_ENUM_REMOTE)
4636                 return enum_all_printers_info_1_remote(name, buffer, offered, needed, returned);
4637 #endif
4638
4639         if (flags & PRINTER_ENUM_NETWORK)
4640                 return enum_all_printers_info_1_network(name, buffer, offered, needed, returned);
4641
4642         return WERR_OK; /* NT4sp5 does that */
4643 }
4644
4645 /********************************************************************
4646  * handle enumeration of printers at level 2
4647  ********************************************************************/
4648
4649 static WERROR enumprinters_level2( uint32 flags, const char *servername,
4650                                  RPC_BUFFER *buffer, uint32 offered,
4651                                  uint32 *needed, uint32 *returned)
4652 {
4653         if (flags & PRINTER_ENUM_LOCAL) {
4654                         return enum_all_printers_info_2(buffer, offered, needed, returned);
4655         }
4656
4657         if (flags & PRINTER_ENUM_NAME) {
4658                 if (is_myname_or_ipaddr(canon_servername(servername)))
4659                         return enum_all_printers_info_2(buffer, offered, needed, returned);
4660                 else
4661                         return WERR_INVALID_NAME;
4662         }
4663
4664         if (flags & PRINTER_ENUM_REMOTE)
4665                 return WERR_UNKNOWN_LEVEL;
4666
4667         return WERR_OK;
4668 }
4669
4670 /********************************************************************
4671  * handle enumeration of printers at level 5
4672  ********************************************************************/
4673
4674 static WERROR enumprinters_level5( uint32 flags, const char *servername,
4675                                  RPC_BUFFER *buffer, uint32 offered,
4676                                  uint32 *needed, uint32 *returned)
4677 {
4678 /*      return enum_all_printers_info_5(buffer, offered, needed, returned);*/
4679         return WERR_OK;
4680 }
4681
4682 /********************************************************************
4683  * api_spoolss_enumprinters
4684  *
4685  * called from api_spoolss_enumprinters (see this to understand)
4686  ********************************************************************/
4687
4688 WERROR _spoolss_enumprinters( pipes_struct *p, SPOOL_Q_ENUMPRINTERS *q_u, SPOOL_R_ENUMPRINTERS *r_u)
4689 {
4690         uint32 flags = q_u->flags;
4691         UNISTR2 *servername = &q_u->servername;
4692         uint32 level = q_u->level;
4693         RPC_BUFFER *buffer = NULL;
4694         uint32 offered = q_u->offered;
4695         uint32 *needed = &r_u->needed;
4696         uint32 *returned = &r_u->returned;
4697
4698         fstring name;
4699
4700         /* that's an [in out] buffer */
4701
4702         if (!q_u->buffer && (offered!=0)) {
4703                 return WERR_INVALID_PARAM;
4704         }
4705
4706         if (offered > MAX_RPC_DATA_SIZE) {
4707                 return WERR_INVALID_PARAM;
4708         }
4709
4710         rpcbuf_move(q_u->buffer, &r_u->buffer);
4711         buffer = r_u->buffer;
4712
4713         DEBUG(4,("_spoolss_enumprinters\n"));
4714
4715         *needed=0;
4716         *returned=0;
4717
4718         /*
4719          * Level 1:
4720          *          flags==PRINTER_ENUM_NAME
4721          *           if name=="" then enumerates all printers
4722          *           if name!="" then enumerate the printer
4723          *          flags==PRINTER_ENUM_REMOTE
4724          *          name is NULL, enumerate printers
4725          * Level 2: name!="" enumerates printers, name can't be NULL
4726          * Level 3: doesn't exist
4727          * Level 4: does a local registry lookup
4728          * Level 5: same as Level 2
4729          */
4730
4731         unistr2_to_ascii(name, servername, sizeof(name));
4732         strupper_m(name);
4733
4734         switch (level) {
4735         case 1:
4736                 return enumprinters_level1(flags, name, buffer, offered, needed, returned);
4737         case 2:
4738                 return enumprinters_level2(flags, name, buffer, offered, needed, returned);
4739         case 5:
4740                 return enumprinters_level5(flags, name, buffer, offered, needed, returned);
4741         case 3:
4742         case 4:
4743                 break;
4744         }
4745         return WERR_UNKNOWN_LEVEL;
4746 }
4747
4748 /****************************************************************************
4749 ****************************************************************************/
4750
4751 static WERROR getprinter_level_0(Printer_entry *print_hnd, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
4752 {
4753         PRINTER_INFO_0 *printer=NULL;
4754         WERROR result = WERR_OK;
4755
4756         if((printer=SMB_MALLOC_P(PRINTER_INFO_0)) == NULL)
4757                 return WERR_NOMEM;
4758
4759         construct_printer_info_0(print_hnd, printer, snum);
4760
4761         /* check the required size. */
4762         *needed += spoolss_size_printer_info_0(printer);
4763
4764         if (*needed > offered) {
4765                 result = WERR_INSUFFICIENT_BUFFER;
4766                 goto out;
4767         }
4768
4769         if (!rpcbuf_alloc_size(buffer, *needed)) {
4770                 result = WERR_NOMEM;
4771                 goto out;
4772         }
4773
4774         /* fill the buffer with the structures */
4775         smb_io_printer_info_0("", buffer, printer, 0);
4776
4777 out:
4778         /* clear memory */
4779
4780         SAFE_FREE(printer);
4781
4782         return result;
4783 }
4784
4785 /****************************************************************************
4786 ****************************************************************************/
4787
4788 static WERROR getprinter_level_1(Printer_entry *print_hnd, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
4789 {
4790         PRINTER_INFO_1 *printer=NULL;
4791         WERROR result = WERR_OK;
4792
4793         if((printer=SMB_MALLOC_P(PRINTER_INFO_1)) == NULL)
4794                 return WERR_NOMEM;
4795
4796         construct_printer_info_1(print_hnd, PRINTER_ENUM_ICON8, printer, snum);
4797
4798         /* check the required size. */
4799         *needed += spoolss_size_printer_info_1(printer);
4800
4801         if (*needed > offered) {
4802                 result = WERR_INSUFFICIENT_BUFFER;
4803                 goto out;
4804         }
4805
4806         if (!rpcbuf_alloc_size(buffer, *needed)) {
4807                 result = WERR_NOMEM;
4808                 goto out;
4809         }
4810
4811         /* fill the buffer with the structures */
4812         smb_io_printer_info_1("", buffer, printer, 0);
4813
4814 out:
4815         /* clear memory */
4816         SAFE_FREE(printer);
4817
4818         return result;
4819 }
4820
4821 /****************************************************************************
4822 ****************************************************************************/
4823
4824 static WERROR getprinter_level_2(Printer_entry *print_hnd, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
4825 {
4826         PRINTER_INFO_2 *printer=NULL;
4827         WERROR result = WERR_OK;
4828
4829         if((printer=SMB_MALLOC_P(PRINTER_INFO_2))==NULL)
4830                 return WERR_NOMEM;
4831
4832         construct_printer_info_2(print_hnd, printer, snum);
4833
4834         /* check the required size. */
4835         *needed += spoolss_size_printer_info_2(printer);
4836
4837         if (*needed > offered) {
4838                 result = WERR_INSUFFICIENT_BUFFER;
4839                 goto out;
4840         }
4841
4842         if (!rpcbuf_alloc_size(buffer, *needed)) {
4843                 result = WERR_NOMEM;
4844                 goto out;
4845         }
4846
4847         /* fill the buffer with the structures */
4848         if (!smb_io_printer_info_2("", buffer, printer, 0))
4849                 result = WERR_NOMEM;
4850
4851 out:
4852         /* clear memory */
4853         free_printer_info_2(printer);
4854
4855         return result;
4856 }
4857
4858 /****************************************************************************
4859 ****************************************************************************/
4860
4861 static WERROR getprinter_level_3(Printer_entry *print_hnd, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
4862 {
4863         PRINTER_INFO_3 *printer=NULL;
4864         WERROR result = WERR_OK;
4865
4866         if (!construct_printer_info_3(print_hnd, &printer, snum))
4867                 return WERR_NOMEM;
4868
4869         /* check the required size. */
4870         *needed += spoolss_size_printer_info_3(printer);
4871
4872         if (*needed > offered) {
4873                 result = WERR_INSUFFICIENT_BUFFER;
4874                 goto out;
4875         }
4876
4877         if (!rpcbuf_alloc_size(buffer, *needed)) {
4878                 result = WERR_NOMEM;
4879                 goto out;
4880         }
4881
4882         /* fill the buffer with the structures */
4883         smb_io_printer_info_3("", buffer, printer, 0);
4884
4885 out:
4886         /* clear memory */
4887         free_printer_info_3(printer);
4888
4889         return result;
4890 }
4891
4892 /****************************************************************************
4893 ****************************************************************************/
4894
4895 static WERROR getprinter_level_4(Printer_entry *print_hnd, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
4896 {
4897         PRINTER_INFO_4 *printer=NULL;
4898         WERROR result = WERR_OK;
4899
4900         if((printer=SMB_MALLOC_P(PRINTER_INFO_4))==NULL)
4901                 return WERR_NOMEM;
4902
4903         if (!construct_printer_info_4(print_hnd, printer, snum)) {
4904                 SAFE_FREE(printer);
4905                 return WERR_NOMEM;
4906         }
4907
4908         /* check the required size. */
4909         *needed += spoolss_size_printer_info_4(printer);
4910
4911         if (*needed > offered) {
4912                 result = WERR_INSUFFICIENT_BUFFER;
4913                 goto out;
4914         }
4915
4916         if (!rpcbuf_alloc_size(buffer, *needed)) {
4917                 result = WERR_NOMEM;
4918                 goto out;
4919         }
4920
4921         /* fill the buffer with the structures */
4922         smb_io_printer_info_4("", buffer, printer, 0);
4923
4924 out:
4925         /* clear memory */
4926         free_printer_info_4(printer);
4927
4928         return result;
4929 }
4930
4931 /****************************************************************************
4932 ****************************************************************************/
4933
4934 static WERROR getprinter_level_5(Printer_entry *print_hnd, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
4935 {
4936         PRINTER_INFO_5 *printer=NULL;
4937         WERROR result = WERR_OK;
4938
4939         if((printer=SMB_MALLOC_P(PRINTER_INFO_5))==NULL)
4940                 return WERR_NOMEM;
4941
4942         if (!construct_printer_info_5(print_hnd, printer, snum)) {
4943                 free_printer_info_5(printer);
4944                 return WERR_NOMEM;
4945         }
4946
4947         /* check the required size. */
4948         *needed += spoolss_size_printer_info_5(printer);
4949
4950         if (*needed > offered) {
4951                 result = WERR_INSUFFICIENT_BUFFER;
4952                 goto out;
4953         }
4954
4955         if (!rpcbuf_alloc_size(buffer, *needed)) {
4956                 result = WERR_NOMEM;
4957                 goto out;
4958         }
4959
4960         /* fill the buffer with the structures */
4961         smb_io_printer_info_5("", buffer, printer, 0);
4962
4963 out:
4964         /* clear memory */
4965         free_printer_info_5(printer);
4966
4967         return result;
4968 }
4969
4970 static WERROR getprinter_level_6(Printer_entry *print_hnd,
4971                                  int snum,
4972                                  RPC_BUFFER *buffer, uint32 offered,
4973                                  uint32 *needed)
4974 {
4975         PRINTER_INFO_6 *printer;
4976         WERROR result = WERR_OK;
4977
4978         if ((printer = SMB_MALLOC_P(PRINTER_INFO_6)) == NULL) {
4979                 return WERR_NOMEM;
4980         }
4981
4982         if (!construct_printer_info_6(print_hnd, printer, snum)) {
4983                 free_printer_info_6(printer);
4984                 return WERR_NOMEM;
4985         }
4986
4987         /* check the required size. */
4988         *needed += spoolss_size_printer_info_6(printer);
4989
4990         if (*needed > offered) {
4991                 result = WERR_INSUFFICIENT_BUFFER;
4992                 goto out;
4993         }
4994
4995         if (!rpcbuf_alloc_size(buffer, *needed)) {
4996                 result = WERR_NOMEM;
4997                 goto out;
4998         }
4999
5000         /* fill the buffer with the structures */
5001         smb_io_printer_info_6("", buffer, printer, 0);
5002
5003 out:
5004         /* clear memory */
5005         free_printer_info_6(printer);
5006
5007         return result;
5008 }
5009
5010 static WERROR getprinter_level_7(Printer_entry *print_hnd, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
5011 {
5012         PRINTER_INFO_7 *printer=NULL;
5013         WERROR result = WERR_OK;
5014
5015         if((printer=SMB_MALLOC_P(PRINTER_INFO_7))==NULL)
5016                 return WERR_NOMEM;
5017
5018         if (!construct_printer_info_7(print_hnd, printer, snum)) {
5019                 result = WERR_NOMEM;
5020                 goto out;
5021         }
5022
5023         /* check the required size. */
5024         *needed += spoolss_size_printer_info_7(printer);
5025
5026         if (*needed > offered) {
5027                 result = WERR_INSUFFICIENT_BUFFER;
5028                 goto out;
5029         }
5030
5031         if (!rpcbuf_alloc_size(buffer, *needed)) {
5032                 result = WERR_NOMEM;
5033                 goto out;
5034
5035         }
5036
5037         /* fill the buffer with the structures */
5038         smb_io_printer_info_7("", buffer, printer, 0);
5039
5040 out:
5041         /* clear memory */
5042         free_printer_info_7(printer);
5043
5044         return result;
5045 }
5046
5047 /****************************************************************************
5048 ****************************************************************************/
5049
5050 WERROR _spoolss_getprinter(pipes_struct *p, SPOOL_Q_GETPRINTER *q_u, SPOOL_R_GETPRINTER *r_u)
5051 {
5052         POLICY_HND *handle = &q_u->handle;
5053         uint32 level = q_u->level;
5054         RPC_BUFFER *buffer = NULL;
5055         uint32 offered = q_u->offered;
5056         uint32 *needed = &r_u->needed;
5057         Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
5058
5059         int snum;
5060
5061         /* that's an [in out] buffer */
5062
5063         if (!q_u->buffer && (offered!=0)) {
5064                 return WERR_INVALID_PARAM;
5065         }
5066
5067         if (offered > MAX_RPC_DATA_SIZE) {
5068                 return WERR_INVALID_PARAM;
5069         }
5070
5071         rpcbuf_move(q_u->buffer, &r_u->buffer);
5072         buffer = r_u->buffer;
5073
5074         *needed=0;
5075
5076         if (!get_printer_snum(p, handle, &snum, NULL))
5077                 return WERR_BADFID;
5078
5079         switch (level) {
5080         case 0:
5081                 return getprinter_level_0(Printer, snum, buffer, offered, needed);
5082         case 1:
5083                 return getprinter_level_1(Printer, snum, buffer, offered, needed);
5084         case 2:
5085                 return getprinter_level_2(Printer, snum, buffer, offered, needed);
5086         case 3:
5087                 return getprinter_level_3(Printer, snum, buffer, offered, needed);
5088         case 4:
5089                 return getprinter_level_4(Printer, snum, buffer, offered, needed);
5090         case 5:
5091                 return getprinter_level_5(Printer, snum, buffer, offered, needed);
5092         case 6:
5093                 return getprinter_level_6(Printer, snum, buffer, offered, needed);
5094         case 7:
5095                 return getprinter_level_7(Printer, snum, buffer, offered, needed);
5096         }
5097         return WERR_UNKNOWN_LEVEL;
5098 }
5099
5100 /********************************************************************
5101  * fill a DRIVER_INFO_1 struct
5102  ********************************************************************/
5103
5104 static void fill_printer_driver_info_1(DRIVER_INFO_1 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, const char *servername, fstring architecture)
5105 {
5106         init_unistr( &info->name, driver.info_3->name);
5107 }
5108
5109 /********************************************************************
5110  * construct_printer_driver_info_1
5111  ********************************************************************/
5112
5113 static WERROR construct_printer_driver_info_1(DRIVER_INFO_1 *info, int snum, const char *servername, fstring architecture, uint32 version)
5114 {
5115         NT_PRINTER_INFO_LEVEL *printer = NULL;
5116         NT_PRINTER_DRIVER_INFO_LEVEL driver;
5117
5118         ZERO_STRUCT(driver);
5119
5120         if (!W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, lp_const_servicename(snum))))
5121                 return WERR_INVALID_PRINTER_NAME;
5122
5123         if (!W_ERROR_IS_OK(get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version))) {
5124                 free_a_printer(&printer, 2);
5125                 return WERR_UNKNOWN_PRINTER_DRIVER;
5126         }
5127
5128         fill_printer_driver_info_1(info, driver, servername, architecture);
5129
5130         free_a_printer(&printer,2);
5131
5132         return WERR_OK;
5133 }
5134
5135 /********************************************************************
5136  * construct_printer_driver_info_2
5137  * fill a printer_info_2 struct
5138  ********************************************************************/
5139
5140 static void fill_printer_driver_info_2(DRIVER_INFO_2 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, const char *servername)
5141 {
5142         TALLOC_CTX *ctx = talloc_tos();
5143         char *temp = NULL;
5144         const char *cservername = canon_servername(servername);
5145
5146         info->version=driver.info_3->cversion;
5147
5148         init_unistr( &info->name, driver.info_3->name );
5149         init_unistr( &info->architecture, driver.info_3->environment );
5150
5151         if (strlen(driver.info_3->driverpath)) {
5152                 temp = talloc_asprintf(ctx,
5153                                 "\\\\%s%s",
5154                                 cservername,
5155                                 driver.info_3->driverpath);
5156                 init_unistr( &info->driverpath, temp );
5157         } else {
5158                 init_unistr( &info->driverpath, "" );
5159         }
5160
5161         TALLOC_FREE(temp);
5162         if (strlen(driver.info_3->datafile)) {
5163                 temp = talloc_asprintf(ctx,
5164                                 "\\\\%s%s",
5165                                 cservername,
5166                                 driver.info_3->datafile);
5167                 init_unistr( &info->datafile, temp );
5168         } else
5169                 init_unistr( &info->datafile, "" );
5170
5171         TALLOC_FREE(temp);
5172         if (strlen(driver.info_3->configfile)) {
5173                 temp = talloc_asprintf(ctx,
5174                                 "\\\\%s%s",
5175                                 cservername,
5176                                 driver.info_3->configfile);
5177                 init_unistr( &info->configfile, temp );
5178         } else
5179                 init_unistr( &info->configfile, "" );
5180 }
5181
5182 /********************************************************************
5183  * construct_printer_driver_info_2
5184  * fill a printer_info_2 struct
5185  ********************************************************************/
5186
5187 static WERROR construct_printer_driver_info_2(DRIVER_INFO_2 *info, int snum, const char *servername, fstring architecture, uint32 version)
5188 {
5189         NT_PRINTER_INFO_LEVEL *printer = NULL;
5190         NT_PRINTER_DRIVER_INFO_LEVEL driver;
5191
5192         ZERO_STRUCT(printer);
5193         ZERO_STRUCT(driver);
5194
5195         if (!W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, lp_const_servicename(snum))))
5196                 return WERR_INVALID_PRINTER_NAME;
5197
5198         if (!W_ERROR_IS_OK(get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version))) {
5199                 free_a_printer(&printer, 2);
5200                 return WERR_UNKNOWN_PRINTER_DRIVER;
5201         }
5202
5203         fill_printer_driver_info_2(info, driver, servername);
5204
5205         free_a_printer(&printer,2);
5206
5207         return WERR_OK;
5208 }
5209
5210 /********************************************************************
5211  * copy a strings array and convert to UNICODE
5212  *
5213  * convert an array of ascii string to a UNICODE string
5214  ********************************************************************/
5215
5216 static uint32 init_unistr_array(uint16 **uni_array, fstring *char_array, const char *servername)
5217 {
5218         int i=0;
5219         int j=0;
5220         const char *v;
5221         char *line = NULL;
5222         TALLOC_CTX *ctx = talloc_tos();
5223
5224         DEBUG(6,("init_unistr_array\n"));
5225         *uni_array=NULL;
5226
5227         while (true) {
5228                 if ( !char_array ) {
5229                         v = "";
5230                 } else {
5231                         v = char_array[i];
5232                         if (!v)
5233                                 v = ""; /* hack to handle null lists */
5234                 }
5235
5236                 /* hack to allow this to be used in places other than when generating
5237                    the list of dependent files */
5238
5239                 TALLOC_FREE(line);
5240                 if ( servername ) {
5241                         line = talloc_asprintf(ctx,
5242                                         "\\\\%s%s",
5243                                         canon_servername(servername),
5244                                         v);
5245                 } else {
5246                         line = talloc_strdup(ctx, v);
5247                 }
5248
5249                 if (!line) {
5250                         SAFE_FREE(*uni_array);
5251                         return 0;
5252                 }
5253                 DEBUGADD(6,("%d:%s:%lu\n", i, line, (unsigned long)strlen(line)));
5254
5255                 /* add one extra unit16 for the second terminating NULL */
5256
5257                 if ( (*uni_array=SMB_REALLOC_ARRAY(*uni_array, uint16, j+1+strlen(line)+2)) == NULL ) {
5258                         DEBUG(2,("init_unistr_array: Realloc error\n" ));
5259                         return 0;
5260                 }
5261
5262                 if ( !strlen(v) )
5263                         break;
5264
5265                 j += (rpcstr_push((*uni_array+j), line, sizeof(uint16)*strlen(line)+2, STR_TERMINATE) / sizeof(uint16));
5266                 i++;
5267         }
5268
5269         if (*uni_array) {
5270                 /* special case for ""; we need to add both NULL's here */
5271                 if (!j)
5272                         (*uni_array)[j++]=0x0000;
5273                 (*uni_array)[j]=0x0000;
5274         }
5275
5276         DEBUGADD(6,("last one:done\n"));
5277
5278         /* return size of array in uint16's */
5279
5280         return j+1;
5281 }
5282
5283 /********************************************************************
5284  * construct_printer_info_3
5285  * fill a printer_info_3 struct
5286  ********************************************************************/
5287
5288 static void fill_printer_driver_info_3(DRIVER_INFO_3 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, const char *servername)
5289 {
5290         char *temp = NULL;
5291         TALLOC_CTX *ctx = talloc_tos();
5292         const char *cservername = canon_servername(servername);
5293
5294         ZERO_STRUCTP(info);
5295
5296         info->version=driver.info_3->cversion;
5297
5298         init_unistr( &info->name, driver.info_3->name );
5299         init_unistr( &info->architecture, driver.info_3->environment );
5300
5301         if (strlen(driver.info_3->driverpath)) {
5302                 temp = talloc_asprintf(ctx,
5303                                 "\\\\%s%s",
5304                                 cservername,
5305                                 driver.info_3->driverpath);
5306                 init_unistr( &info->driverpath, temp );
5307         } else
5308                 init_unistr( &info->driverpath, "" );
5309
5310         TALLOC_FREE(temp);
5311         if (strlen(driver.info_3->datafile)) {
5312                 temp = talloc_asprintf(ctx,
5313                                 "\\\\%s%s",
5314                                 cservername,
5315                                 driver.info_3->datafile);
5316                 init_unistr( &info->datafile, temp );
5317         } else
5318                 init_unistr( &info->datafile, "" );
5319
5320         TALLOC_FREE(temp);
5321         if (strlen(driver.info_3->configfile)) {
5322                 temp = talloc_asprintf(ctx,
5323                                 "\\\\%s%s",
5324                                 cservername,
5325                                 driver.info_3->configfile);
5326                 init_unistr( &info->configfile, temp );
5327         } else
5328                 init_unistr( &info->configfile, "" );
5329
5330         TALLOC_FREE(temp);
5331         if (strlen(driver.info_3->helpfile)) {
5332                 temp = talloc_asprintf(ctx,
5333                                 "\\\\%s%s",
5334                                 cservername,
5335                                 driver.info_3->helpfile);
5336                 init_unistr( &info->helpfile, temp );
5337         } else
5338                 init_unistr( &info->helpfile, "" );
5339
5340         TALLOC_FREE(temp);
5341         init_unistr( &info->monitorname, driver.info_3->monitorname );
5342         init_unistr( &info->defaultdatatype, driver.info_3->defaultdatatype );
5343
5344         info->dependentfiles=NULL;
5345         init_unistr_array(&info->dependentfiles, driver.info_3->dependentfiles, cservername);
5346 }
5347
5348 /********************************************************************
5349  * construct_printer_info_3
5350  * fill a printer_info_3 struct
5351  ********************************************************************/
5352
5353 static WERROR construct_printer_driver_info_3(DRIVER_INFO_3 *info, int snum, const char *servername, fstring architecture, uint32 version)
5354 {
5355         NT_PRINTER_INFO_LEVEL *printer = NULL;
5356         NT_PRINTER_DRIVER_INFO_LEVEL driver;
5357         WERROR status;
5358         ZERO_STRUCT(driver);
5359
5360         status=get_a_printer(NULL, &printer, 2, lp_const_servicename(snum) );
5361         DEBUG(8,("construct_printer_driver_info_3: status: %s\n", win_errstr(status)));
5362         if (!W_ERROR_IS_OK(status))
5363                 return WERR_INVALID_PRINTER_NAME;
5364
5365         status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
5366         DEBUG(8,("construct_printer_driver_info_3: status: %s\n", win_errstr(status)));
5367
5368 #if 0   /* JERRY */
5369
5370         /*
5371          * I put this code in during testing.  Helpful when commenting out the
5372          * support for DRIVER_INFO_6 in regards to win2k.  Not needed in general
5373          * as win2k always queries the driver using an infor level of 6.
5374          * I've left it in (but ifdef'd out) because I'll probably
5375          * use it in experimentation again in the future.   --jerry 22/01/2002
5376          */
5377
5378         if (!W_ERROR_IS_OK(status)) {
5379                 /*
5380                  * Is this a W2k client ?
5381                  */
5382                 if (version == 3) {
5383                         /* Yes - try again with a WinNT driver. */
5384                         version = 2;
5385                         status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
5386                         DEBUG(8,("construct_printer_driver_info_3: status: %s\n", win_errstr(status)));
5387                 }
5388 #endif
5389
5390                 if (!W_ERROR_IS_OK(status)) {
5391                         free_a_printer(&printer,2);
5392                         return WERR_UNKNOWN_PRINTER_DRIVER;
5393                 }
5394
5395 #if 0   /* JERRY */
5396         }
5397 #endif
5398
5399
5400         fill_printer_driver_info_3(info, driver, servername);
5401
5402         free_a_printer(&printer,2);
5403
5404         return WERR_OK;
5405 }
5406
5407 /********************************************************************
5408  * construct_printer_info_6
5409  * fill a printer_info_6 struct - we know that driver is really level 3. This sucks. JRA.
5410  ********************************************************************/
5411
5412 static void fill_printer_driver_info_6(DRIVER_INFO_6 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, const char *servername)
5413 {
5414         char *temp = NULL;
5415         fstring nullstr;
5416         TALLOC_CTX *ctx = talloc_tos();
5417         const char *cservername = canon_servername(servername);
5418
5419         ZERO_STRUCTP(info);
5420         memset(&nullstr, '\0', sizeof(fstring));
5421
5422         info->version=driver.info_3->cversion;
5423
5424         init_unistr( &info->name, driver.info_3->name );
5425         init_unistr( &info->architecture, driver.info_3->environment );
5426
5427         if (strlen(driver.info_3->driverpath)) {
5428                 temp = talloc_asprintf(ctx,
5429                                 "\\\\%s%s",
5430                                 cservername,
5431                                 driver.info_3->driverpath);
5432                 init_unistr( &info->driverpath, temp );
5433         } else
5434                 init_unistr( &info->driverpath, "" );
5435
5436         TALLOC_FREE(temp);
5437         if (strlen(driver.info_3->datafile)) {
5438                 temp = talloc_asprintf(ctx,
5439                                 "\\\\%s%s",
5440                                 cservername,
5441                                 driver.info_3->datafile);
5442                 init_unistr( &info->datafile, temp );
5443         } else
5444                 init_unistr( &info->datafile, "" );
5445
5446         TALLOC_FREE(temp);
5447         if (strlen(driver.info_3->configfile)) {
5448                 temp = talloc_asprintf(ctx,
5449                                 "\\\\%s%s",
5450                                 cservername,
5451                                 driver.info_3->configfile);
5452                 init_unistr( &info->configfile, temp );
5453         } else
5454                 init_unistr( &info->configfile, "" );
5455
5456         TALLOC_FREE(temp);
5457         if (strlen(driver.info_3->helpfile)) {
5458                 temp = talloc_asprintf(ctx,
5459                                 "\\\\%s%s",
5460                                 cservername,
5461                                 driver.info_3->helpfile);
5462                 init_unistr( &info->helpfile, temp );
5463         } else
5464                 init_unistr( &info->helpfile, "" );
5465
5466         TALLOC_FREE(temp);
5467         init_unistr( &info->monitorname, driver.info_3->monitorname );
5468         init_unistr( &info->defaultdatatype, driver.info_3->defaultdatatype );
5469
5470         info->dependentfiles = NULL;
5471         init_unistr_array( &info->dependentfiles, driver.info_3->dependentfiles, servername );
5472
5473         info->previousdrivernames=NULL;
5474         init_unistr_array(&info->previousdrivernames, &nullstr, servername);
5475
5476         info->driver_date=0;
5477
5478         info->padding=0;
5479         info->driver_version_low=0;
5480         info->driver_version_high=0;
5481
5482         init_unistr( &info->mfgname, "");
5483         init_unistr( &info->oem_url, "");
5484         init_unistr( &info->hardware_id, "");
5485         init_unistr( &info->provider, "");
5486 }
5487
5488 /********************************************************************
5489  * construct_printer_info_6
5490  * fill a printer_info_6 struct
5491  ********************************************************************/
5492
5493 static WERROR construct_printer_driver_info_6(DRIVER_INFO_6 *info, int snum,
5494               const char *servername, fstring architecture, uint32 version)
5495 {
5496         NT_PRINTER_INFO_LEVEL           *printer = NULL;
5497         NT_PRINTER_DRIVER_INFO_LEVEL    driver;
5498         WERROR                          status;
5499
5500         ZERO_STRUCT(driver);
5501
5502         status=get_a_printer(NULL, &printer, 2, lp_const_servicename(snum) );
5503
5504         DEBUG(8,("construct_printer_driver_info_6: status: %s\n", win_errstr(status)));
5505
5506         if (!W_ERROR_IS_OK(status))
5507                 return WERR_INVALID_PRINTER_NAME;
5508
5509         status = get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
5510
5511         DEBUG(8,("construct_printer_driver_info_6: status: %s\n", win_errstr(status)));
5512
5513         if (!W_ERROR_IS_OK(status))
5514         {
5515                 /*
5516                  * Is this a W2k client ?
5517                  */
5518
5519                 if (version < 3) {
5520                         free_a_printer(&printer,2);
5521                         return WERR_UNKNOWN_PRINTER_DRIVER;
5522                 }
5523
5524                 /* Yes - try again with a WinNT driver. */
5525                 version = 2;
5526                 status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
5527                 DEBUG(8,("construct_printer_driver_info_6: status: %s\n", win_errstr(status)));
5528                 if (!W_ERROR_IS_OK(status)) {
5529                         free_a_printer(&printer,2);
5530                         return WERR_UNKNOWN_PRINTER_DRIVER;
5531                 }
5532         }
5533
5534         fill_printer_driver_info_6(info, driver, servername);
5535
5536         free_a_printer(&printer,2);
5537         free_a_printer_driver(driver, 3);
5538
5539         return WERR_OK;
5540 }
5541
5542 /****************************************************************************
5543 ****************************************************************************/
5544
5545 static void free_printer_driver_info_3(DRIVER_INFO_3 *info)
5546 {
5547         SAFE_FREE(info->dependentfiles);
5548 }
5549
5550 /****************************************************************************
5551 ****************************************************************************/
5552
5553 static void free_printer_driver_info_6(DRIVER_INFO_6 *info)
5554 {
5555         SAFE_FREE(info->dependentfiles);
5556 }
5557
5558 /****************************************************************************
5559 ****************************************************************************/
5560
5561 static WERROR getprinterdriver2_level1(const char *servername, fstring architecture, uint32 version, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
5562 {
5563         DRIVER_INFO_1 *info=NULL;
5564         WERROR result;
5565
5566         if((info=SMB_MALLOC_P(DRIVER_INFO_1)) == NULL)
5567                 return WERR_NOMEM;
5568
5569         result = construct_printer_driver_info_1(info, snum, servername, architecture, version);
5570         if (!W_ERROR_IS_OK(result))
5571                 goto out;
5572
5573         /* check the required size. */
5574         *needed += spoolss_size_printer_driver_info_1(info);
5575
5576         if (*needed > offered) {
5577                 result = WERR_INSUFFICIENT_BUFFER;
5578                 goto out;
5579         }
5580
5581         if (!rpcbuf_alloc_size(buffer, *needed)) {
5582                 result = WERR_NOMEM;
5583                 goto out;
5584         }
5585
5586         /* fill the buffer with the structures */
5587         smb_io_printer_driver_info_1("", buffer, info, 0);
5588
5589 out:
5590         /* clear memory */
5591         SAFE_FREE(info);
5592
5593         return result;
5594 }
5595
5596 /****************************************************************************
5597 ****************************************************************************/
5598
5599 static WERROR getprinterdriver2_level2(const char *servername, fstring architecture, uint32 version, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
5600 {
5601         DRIVER_INFO_2 *info=NULL;
5602         WERROR result;
5603
5604         if((info=SMB_MALLOC_P(DRIVER_INFO_2)) == NULL)
5605                 return WERR_NOMEM;
5606
5607         result = construct_printer_driver_info_2(info, snum, servername, architecture, version);
5608         if (!W_ERROR_IS_OK(result))
5609                 goto out;
5610
5611         /* check the required size. */
5612         *needed += spoolss_size_printer_driver_info_2(info);
5613
5614         if (*needed > offered) {
5615                 result = WERR_INSUFFICIENT_BUFFER;
5616                 goto out;
5617         }
5618
5619         if (!rpcbuf_alloc_size(buffer, *needed)) {
5620                 result = WERR_NOMEM;
5621                 goto out;
5622         }
5623
5624         /* fill the buffer with the structures */
5625         smb_io_printer_driver_info_2("", buffer, info, 0);
5626
5627 out:
5628         /* clear memory */
5629         SAFE_FREE(info);
5630
5631         return result;
5632 }
5633
5634 /****************************************************************************
5635 ****************************************************************************/
5636
5637 static WERROR getprinterdriver2_level3(const char *servername, fstring architecture, uint32 version, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
5638 {
5639         DRIVER_INFO_3 info;
5640         WERROR result;
5641
5642         ZERO_STRUCT(info);
5643
5644         result = construct_printer_driver_info_3(&info, snum, servername, architecture, version);
5645         if (!W_ERROR_IS_OK(result))
5646                 goto out;
5647
5648         /* check the required size. */
5649         *needed += spoolss_size_printer_driver_info_3(&info);
5650
5651         if (*needed > offered) {
5652                 result = WERR_INSUFFICIENT_BUFFER;
5653                 goto out;
5654         }
5655
5656         if (!rpcbuf_alloc_size(buffer, *needed)) {
5657                 result = WERR_NOMEM;
5658                 goto out;
5659         }
5660
5661         /* fill the buffer with the structures */
5662         smb_io_printer_driver_info_3("", buffer, &info, 0);
5663
5664 out:
5665         free_printer_driver_info_3(&info);
5666
5667         return result;
5668 }
5669
5670 /****************************************************************************
5671 ****************************************************************************/
5672
5673 static WERROR getprinterdriver2_level6(const char *servername, fstring architecture, uint32 version, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
5674 {
5675         DRIVER_INFO_6 info;
5676         WERROR result;
5677
5678         ZERO_STRUCT(info);
5679
5680         result = construct_printer_driver_info_6(&info, snum, servername, architecture, version);
5681         if (!W_ERROR_IS_OK(result))
5682                 goto out;
5683
5684         /* check the required size. */
5685         *needed += spoolss_size_printer_driver_info_6(&info);
5686
5687         if (*needed > offered) {
5688                 result = WERR_INSUFFICIENT_BUFFER;
5689                 goto out;
5690         }
5691
5692         if (!rpcbuf_alloc_size(buffer, *needed)) {
5693                 result = WERR_NOMEM;
5694                 goto out;
5695         }
5696
5697         /* fill the buffer with the structures */
5698         smb_io_printer_driver_info_6("", buffer, &info, 0);
5699
5700 out:
5701         free_printer_driver_info_6(&info);
5702
5703         return result;
5704 }
5705
5706 /****************************************************************************
5707 ****************************************************************************/
5708
5709 WERROR _spoolss_getprinterdriver2(pipes_struct *p, SPOOL_Q_GETPRINTERDRIVER2 *q_u, SPOOL_R_GETPRINTERDRIVER2 *r_u)
5710 {
5711         POLICY_HND *handle = &q_u->handle;
5712         UNISTR2 *uni_arch = &q_u->architecture;
5713         uint32 level = q_u->level;
5714         uint32 clientmajorversion = q_u->clientmajorversion;
5715         RPC_BUFFER *buffer = NULL;
5716         uint32 offered = q_u->offered;
5717         uint32 *needed = &r_u->needed;
5718         uint32 *servermajorversion = &r_u->servermajorversion;
5719         uint32 *serverminorversion = &r_u->serverminorversion;
5720         Printer_entry *printer;
5721
5722         fstring servername;
5723         fstring architecture;
5724         int snum;
5725
5726         /* that's an [in out] buffer */
5727
5728         if (!q_u->buffer && (offered!=0)) {
5729                 return WERR_INVALID_PARAM;
5730         }
5731
5732         if (offered > MAX_RPC_DATA_SIZE) {
5733                 return WERR_INVALID_PARAM;
5734         }
5735
5736         rpcbuf_move(q_u->buffer, &r_u->buffer);
5737         buffer = r_u->buffer;
5738
5739         DEBUG(4,("_spoolss_getprinterdriver2\n"));
5740
5741         if ( !(printer = find_printer_index_by_hnd( p, handle )) ) {
5742                 DEBUG(0,("_spoolss_getprinterdriver2: invalid printer handle!\n"));
5743                 return WERR_INVALID_PRINTER_NAME;
5744         }
5745
5746         *needed = 0;
5747         *servermajorversion = 0;
5748         *serverminorversion = 0;
5749
5750         fstrcpy(servername, get_server_name( printer ));
5751         unistr2_to_ascii(architecture, uni_arch, sizeof(architecture));
5752
5753         if (!get_printer_snum(p, handle, &snum, NULL))
5754                 return WERR_BADFID;
5755
5756         switch (level) {
5757         case 1:
5758                 return getprinterdriver2_level1(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
5759         case 2:
5760                 return getprinterdriver2_level2(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
5761         case 3:
5762                 return getprinterdriver2_level3(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
5763         case 6:
5764                 return getprinterdriver2_level6(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
5765 #if 0   /* JERRY */
5766         case 101:
5767                 /* apparently this call is the equivalent of
5768                    EnumPrinterDataEx() for the DsDriver key */
5769                 break;
5770 #endif
5771         }
5772
5773         return WERR_UNKNOWN_LEVEL;
5774 }
5775
5776
5777 /****************************************************************
5778  _spoolss_StartPagePrinter
5779 ****************************************************************/
5780
5781 WERROR _spoolss_StartPagePrinter(pipes_struct *p,
5782                                  struct spoolss_StartPagePrinter *r)
5783 {
5784         POLICY_HND *handle = r->in.handle;
5785
5786         Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5787
5788         if (!Printer) {
5789                 DEBUG(3,("_spoolss_StartPagePrinter: "
5790                         "Error in startpageprinter printer handle\n"));
5791                 return WERR_BADFID;
5792         }
5793
5794         Printer->page_started=True;
5795         return WERR_OK;
5796 }
5797
5798 /****************************************************************
5799  _spoolss_EndPagePrinter
5800 ****************************************************************/
5801
5802 WERROR _spoolss_EndPagePrinter(pipes_struct *p,
5803                                struct spoolss_EndPagePrinter *r)
5804 {
5805         POLICY_HND *handle = r->in.handle;
5806         int snum;
5807
5808         Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5809
5810         if (!Printer) {
5811                 DEBUG(2,("_spoolss_EndPagePrinter: Invalid handle (%s:%u:%u).\n",
5812                         OUR_HANDLE(handle)));
5813                 return WERR_BADFID;
5814         }
5815
5816         if (!get_printer_snum(p, handle, &snum, NULL))
5817                 return WERR_BADFID;
5818
5819         Printer->page_started=False;
5820         print_job_endpage(snum, Printer->jobid);
5821
5822         return WERR_OK;
5823 }
5824
5825 /****************************************************************
5826  _spoolss_StartDocPrinter
5827 ****************************************************************/
5828
5829 WERROR _spoolss_StartDocPrinter(pipes_struct *p,
5830                                 struct spoolss_StartDocPrinter *r)
5831 {
5832         POLICY_HND *handle = r->in.handle;
5833         uint32_t *jobid = r->out.job_id;
5834         struct spoolss_DocumentInfo1 *info_1;
5835         int snum;
5836         Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5837
5838         if (!Printer) {
5839                 DEBUG(2,("_spoolss_StartDocPrinter: "
5840                         "Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
5841                 return WERR_BADFID;
5842         }
5843
5844         if (r->in.level != 1) {
5845                 return WERR_UNKNOWN_LEVEL;
5846         }
5847
5848         info_1 = r->in.info.info1;
5849
5850         /*
5851          * a nice thing with NT is it doesn't listen to what you tell it.
5852          * when asked to send _only_ RAW datas, it tries to send datas
5853          * in EMF format.
5854          *
5855          * So I add checks like in NT Server ...
5856          */
5857
5858         if (info_1->datatype) {
5859                 if (strcmp(info_1->datatype, "RAW") != 0) {
5860                         (*jobid)=0;
5861                         return WERR_INVALID_DATATYPE;
5862                 }
5863         }
5864
5865         /* get the share number of the printer */
5866         if (!get_printer_snum(p, handle, &snum, NULL)) {
5867                 return WERR_BADFID;
5868         }
5869
5870         Printer->jobid = print_job_start(p->server_info, snum,
5871                                          CONST_DISCARD(char *,info_1->document_name),
5872                                          Printer->nt_devmode);
5873
5874         /* An error occured in print_job_start() so return an appropriate
5875            NT error code. */
5876
5877         if (Printer->jobid == -1) {
5878                 return map_werror_from_unix(errno);
5879         }
5880
5881         Printer->document_started=True;
5882         (*jobid) = Printer->jobid;
5883
5884         return WERR_OK;
5885 }
5886
5887 /****************************************************************
5888  _spoolss_EndDocPrinter
5889 ****************************************************************/
5890
5891 WERROR _spoolss_EndDocPrinter(pipes_struct *p,
5892                               struct spoolss_EndDocPrinter *r)
5893 {
5894         POLICY_HND *handle = r->in.handle;
5895
5896         return _spoolss_enddocprinter_internal(p, handle);
5897 }
5898
5899 /****************************************************************
5900  _spoolss_WritePrinter
5901 ****************************************************************/
5902
5903 WERROR _spoolss_WritePrinter(pipes_struct *p,
5904                              struct spoolss_WritePrinter *r)
5905 {
5906         POLICY_HND *handle = r->in.handle;
5907         uint32 buffer_size = r->in._data_size;
5908         uint8 *buffer = r->in.data.data;
5909         uint32 *buffer_written = &r->in._data_size;
5910         int snum;
5911         Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5912
5913         if (!Printer) {
5914                 DEBUG(2,("_spoolss_WritePrinter: Invalid handle (%s:%u:%u)\n",
5915                         OUR_HANDLE(handle)));
5916                 *r->out.num_written = r->in._data_size;
5917                 return WERR_BADFID;
5918         }
5919
5920         if (!get_printer_snum(p, handle, &snum, NULL))
5921                 return WERR_BADFID;
5922
5923         (*buffer_written) = (uint32)print_job_write(snum, Printer->jobid, (const char *)buffer,
5924                                         (SMB_OFF_T)-1, (size_t)buffer_size);
5925         if (*buffer_written == (uint32)-1) {
5926                 *r->out.num_written = 0;
5927                 if (errno == ENOSPC)
5928                         return WERR_NO_SPOOL_SPACE;
5929                 else
5930                         return WERR_ACCESS_DENIED;
5931         }
5932
5933         *r->out.num_written = r->in._data_size;
5934
5935         return WERR_OK;
5936 }
5937
5938 /********************************************************************
5939  * api_spoolss_getprinter
5940  * called from the spoolss dispatcher
5941  *
5942  ********************************************************************/
5943
5944 static WERROR control_printer(POLICY_HND *handle, uint32 command,
5945                               pipes_struct *p)
5946 {
5947         int snum;
5948         WERROR errcode = WERR_BADFUNC;
5949         Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5950
5951         if (!Printer) {
5952                 DEBUG(2,("control_printer: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
5953                 return WERR_BADFID;
5954         }
5955
5956         if (!get_printer_snum(p, handle, &snum, NULL))
5957                 return WERR_BADFID;
5958
5959         switch (command) {
5960         case SPOOLSS_PRINTER_CONTROL_PAUSE:
5961                 if (print_queue_pause(p->server_info, snum, &errcode)) {
5962                         errcode = WERR_OK;
5963                 }
5964                 break;
5965         case SPOOLSS_PRINTER_CONTROL_RESUME:
5966         case SPOOLSS_PRINTER_CONTROL_UNPAUSE:
5967                 if (print_queue_resume(p->server_info, snum, &errcode)) {
5968                         errcode = WERR_OK;
5969                 }
5970                 break;
5971         case SPOOLSS_PRINTER_CONTROL_PURGE:
5972                 if (print_queue_purge(p->server_info, snum, &errcode)) {
5973                         errcode = WERR_OK;
5974                 }
5975                 break;
5976         default:
5977                 return WERR_UNKNOWN_LEVEL;
5978         }
5979
5980         return errcode;
5981 }
5982
5983
5984 /****************************************************************
5985  _spoolss_AbortPrinter
5986  * From MSDN: "Deletes printer's spool file if printer is configured
5987  * for spooling"
5988 ****************************************************************/
5989
5990 WERROR _spoolss_AbortPrinter(pipes_struct *p,
5991                              struct spoolss_AbortPrinter *r)
5992 {
5993         POLICY_HND      *handle = r->in.handle;
5994         Printer_entry   *Printer = find_printer_index_by_hnd(p, handle);
5995         int             snum;
5996         WERROR          errcode = WERR_OK;
5997
5998         if (!Printer) {
5999                 DEBUG(2,("_spoolss_AbortPrinter: Invalid handle (%s:%u:%u)\n",
6000                         OUR_HANDLE(handle)));
6001                 return WERR_BADFID;
6002         }
6003
6004         if (!get_printer_snum(p, handle, &snum, NULL))
6005                 return WERR_BADFID;
6006
6007         print_job_delete(p->server_info, snum, Printer->jobid, &errcode );
6008
6009         return errcode;
6010 }
6011
6012 /********************************************************************
6013  * called by spoolss_api_setprinter
6014  * when updating a printer description
6015  ********************************************************************/
6016
6017 static WERROR update_printer_sec(POLICY_HND *handle,
6018                                  pipes_struct *p, SEC_DESC_BUF *secdesc_ctr)
6019 {
6020         SEC_DESC_BUF *new_secdesc_ctr = NULL, *old_secdesc_ctr = NULL;
6021         WERROR result;
6022         int snum;
6023
6024         Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
6025
6026         if (!Printer || !get_printer_snum(p, handle, &snum, NULL)) {
6027                 DEBUG(2,("update_printer_sec: Invalid handle (%s:%u:%u)\n",
6028                          OUR_HANDLE(handle)));
6029
6030                 result = WERR_BADFID;
6031                 goto done;
6032         }
6033
6034         if (!secdesc_ctr) {
6035                 DEBUG(10,("update_printer_sec: secdesc_ctr is NULL !\n"));
6036                 result = WERR_INVALID_PARAM;
6037                 goto done;
6038         }
6039
6040         /* Check the user has permissions to change the security
6041            descriptor.  By experimentation with two NT machines, the user
6042            requires Full Access to the printer to change security
6043            information. */
6044
6045         if ( Printer->access_granted != PRINTER_ACCESS_ADMINISTER ) {
6046                 DEBUG(4,("update_printer_sec: updated denied by printer permissions\n"));
6047                 result = WERR_ACCESS_DENIED;
6048                 goto done;
6049         }
6050
6051         /* NT seems to like setting the security descriptor even though
6052            nothing may have actually changed. */
6053
6054         if ( !nt_printing_getsec(p->mem_ctx, Printer->sharename, &old_secdesc_ctr)) {
6055                 DEBUG(2,("update_printer_sec: nt_printing_getsec() failed\n"));
6056                 result = WERR_BADFID;
6057                 goto done;
6058         }
6059
6060         if (DEBUGLEVEL >= 10) {
6061                 SEC_ACL *the_acl;
6062                 int i;
6063
6064                 the_acl = old_secdesc_ctr->sd->dacl;
6065                 DEBUG(10, ("old_secdesc_ctr for %s has %d aces:\n",
6066                            PRINTERNAME(snum), the_acl->num_aces));
6067
6068                 for (i = 0; i < the_acl->num_aces; i++) {
6069                         DEBUG(10, ("%s 0x%08x\n", sid_string_dbg(
6070                                            &the_acl->aces[i].trustee),
6071                                   the_acl->aces[i].access_mask));
6072                 }
6073
6074                 the_acl = secdesc_ctr->sd->dacl;
6075
6076                 if (the_acl) {
6077                         DEBUG(10, ("secdesc_ctr for %s has %d aces:\n",
6078                                    PRINTERNAME(snum), the_acl->num_aces));
6079
6080                         for (i = 0; i < the_acl->num_aces; i++) {
6081                                 DEBUG(10, ("%s 0x%08x\n", sid_string_dbg(
6082                                                    &the_acl->aces[i].trustee),
6083                                            the_acl->aces[i].access_mask));
6084                         }
6085                 } else {
6086                         DEBUG(10, ("dacl for secdesc_ctr is NULL\n"));
6087                 }
6088         }
6089
6090         new_secdesc_ctr = sec_desc_merge(p->mem_ctx, secdesc_ctr, old_secdesc_ctr);
6091         if (!new_secdesc_ctr) {
6092                 result = WERR_NOMEM;
6093                 goto done;
6094         }
6095
6096         if (sec_desc_equal(new_secdesc_ctr->sd, old_secdesc_ctr->sd)) {
6097                 result = WERR_OK;
6098                 goto done;
6099         }
6100
6101         result = nt_printing_setsec(Printer->sharename, new_secdesc_ctr);
6102
6103  done:
6104
6105         return result;
6106 }
6107
6108 /********************************************************************
6109  Canonicalize printer info from a client
6110
6111  ATTN: It does not matter what we set the servername to hear
6112  since we do the necessary work in get_a_printer() to set it to
6113  the correct value based on what the client sent in the
6114  _spoolss_open_printer_ex().
6115  ********************************************************************/
6116
6117 static bool check_printer_ok(NT_PRINTER_INFO_LEVEL_2 *info, int snum)
6118 {
6119         fstring printername;
6120         const char *p;
6121
6122         DEBUG(5,("check_printer_ok: servername=%s printername=%s sharename=%s "
6123                 "portname=%s drivername=%s comment=%s location=%s\n",
6124                 info->servername, info->printername, info->sharename,
6125                 info->portname, info->drivername, info->comment, info->location));
6126
6127         /* we force some elements to "correct" values */
6128         slprintf(info->servername, sizeof(info->servername)-1, "\\\\%s", global_myname());
6129         fstrcpy(info->sharename, lp_servicename(snum));
6130
6131         /* check to see if we allow printername != sharename */
6132
6133         if ( lp_force_printername(snum) ) {
6134                 slprintf(info->printername, sizeof(info->printername)-1, "\\\\%s\\%s",
6135                         global_myname(), info->sharename );
6136         } else {
6137
6138                 /* make sure printername is in \\server\printername format */
6139
6140                 fstrcpy( printername, info->printername );
6141                 p = printername;
6142                 if ( printername[0] == '\\' && printername[1] == '\\' ) {
6143                         if ( (p = strchr_m( &printername[2], '\\' )) != NULL )
6144                                 p++;
6145                 }
6146
6147                 slprintf(info->printername, sizeof(info->printername)-1, "\\\\%s\\%s",
6148                          global_myname(), p );
6149         }
6150
6151         info->attributes |= PRINTER_ATTRIBUTE_SAMBA;
6152         info->attributes &= ~PRINTER_ATTRIBUTE_NOT_SAMBA;
6153
6154
6155
6156         return True;
6157 }
6158
6159 /****************************************************************************
6160 ****************************************************************************/
6161
6162 WERROR add_port_hook(TALLOC_CTX *ctx, NT_USER_TOKEN *token, const char *portname, const char *uri )
6163 {
6164         char *cmd = lp_addport_cmd();
6165         char *command = NULL;
6166         int ret;
6167         SE_PRIV se_printop = SE_PRINT_OPERATOR;
6168         bool is_print_op = False;
6169
6170         if ( !*cmd ) {
6171                 return WERR_ACCESS_DENIED;
6172         }
6173
6174         command = talloc_asprintf(ctx,
6175                         "%s \"%s\" \"%s\"", cmd, portname, uri );
6176         if (!command) {
6177                 return WERR_NOMEM;
6178         }
6179
6180         if ( token )
6181                 is_print_op = user_has_privileges( token, &se_printop );
6182
6183         DEBUG(10,("Running [%s]\n", command));
6184
6185         /********* BEGIN SePrintOperatorPrivilege **********/
6186
6187         if ( is_print_op )
6188                 become_root();
6189
6190         ret = smbrun(command, NULL);
6191
6192         if ( is_print_op )
6193                 unbecome_root();
6194
6195         /********* END SePrintOperatorPrivilege **********/
6196
6197         DEBUGADD(10,("returned [%d]\n", ret));
6198
6199         TALLOC_FREE(command);
6200
6201         if ( ret != 0 ) {
6202                 return WERR_ACCESS_DENIED;
6203         }
6204
6205         return WERR_OK;
6206 }
6207
6208 /****************************************************************************
6209 ****************************************************************************/
6210
6211 bool add_printer_hook(TALLOC_CTX *ctx, NT_USER_TOKEN *token, NT_PRINTER_INFO_LEVEL *printer)
6212 {
6213         char *cmd = lp_addprinter_cmd();
6214         char **qlines;
6215         char *command = NULL;
6216         int numlines;
6217         int ret;
6218         int fd;
6219         SE_PRIV se_printop = SE_PRINT_OPERATOR;
6220         bool is_print_op = False;
6221         char *remote_machine = talloc_strdup(ctx, "%m");
6222
6223         if (!remote_machine) {
6224                 return false;
6225         }
6226         remote_machine = talloc_sub_basic(ctx,
6227                                 current_user_info.smb_name,
6228                                 current_user_info.domain,
6229                                 remote_machine);
6230         if (!remote_machine) {
6231                 return false;
6232         }
6233
6234         command = talloc_asprintf(ctx,
6235                         "%s \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\"",
6236                         cmd, printer->info_2->printername, printer->info_2->sharename,
6237                         printer->info_2->portname, printer->info_2->drivername,
6238                         printer->info_2->location, printer->info_2->comment, remote_machine);
6239         if (!command) {
6240                 return false;
6241         }
6242
6243         if ( token )
6244                 is_print_op = user_has_privileges( token, &se_printop );
6245
6246         DEBUG(10,("Running [%s]\n", command));
6247
6248         /********* BEGIN SePrintOperatorPrivilege **********/
6249
6250         if ( is_print_op )
6251                 become_root();
6252
6253         if ( (ret = smbrun(command, &fd)) == 0 ) {
6254                 /* Tell everyone we updated smb.conf. */
6255                 message_send_all(smbd_messaging_context(),
6256                                  MSG_SMB_CONF_UPDATED, NULL, 0, NULL);
6257         }
6258
6259         if ( is_print_op )
6260                 unbecome_root();
6261
6262         /********* END SePrintOperatorPrivilege **********/
6263
6264         DEBUGADD(10,("returned [%d]\n", ret));
6265
6266         TALLOC_FREE(command);
6267         TALLOC_FREE(remote_machine);
6268
6269         if ( ret != 0 ) {
6270                 if (fd != -1)
6271                         close(fd);
6272                 return False;
6273         }
6274
6275         /* reload our services immediately */
6276         reload_services( False );
6277
6278         numlines = 0;
6279         /* Get lines and convert them back to dos-codepage */
6280         qlines = fd_lines_load(fd, &numlines, 0, NULL);
6281         DEBUGADD(10,("Lines returned = [%d]\n", numlines));
6282         close(fd);
6283
6284         /* Set the portname to what the script says the portname should be. */
6285         /* but don't require anything to be return from the script exit a good error code */
6286
6287         if (numlines) {
6288                 /* Set the portname to what the script says the portname should be. */
6289                 strncpy(printer->info_2->portname, qlines[0], sizeof(printer->info_2->portname));
6290                 DEBUGADD(6,("Line[0] = [%s]\n", qlines[0]));
6291         }
6292
6293         TALLOC_FREE(qlines);
6294         return True;
6295 }
6296
6297
6298 /********************************************************************
6299  * Called by spoolss_api_setprinter
6300  * when updating a printer description.
6301  ********************************************************************/
6302
6303 static WERROR update_printer(pipes_struct *p, POLICY_HND *handle,
6304                              struct spoolss_SetPrinterInfoCtr *info_ctr,
6305                              struct spoolss_DeviceMode *devmode)
6306 {
6307         int snum;
6308         NT_PRINTER_INFO_LEVEL *printer = NULL, *old_printer = NULL;
6309         Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
6310         WERROR result;
6311         UNISTR2 buffer;
6312         fstring asc_buffer;
6313
6314         DEBUG(8,("update_printer\n"));
6315
6316         result = WERR_OK;
6317
6318         if (!Printer) {
6319                 result = WERR_BADFID;
6320                 goto done;
6321         }
6322
6323         if (!get_printer_snum(p, handle, &snum, NULL)) {
6324                 result = WERR_BADFID;
6325                 goto done;
6326         }
6327
6328         if (!W_ERROR_IS_OK(get_a_printer(Printer, &printer, 2, lp_const_servicename(snum))) ||
6329             (!W_ERROR_IS_OK(get_a_printer(Printer, &old_printer, 2, lp_const_servicename(snum))))) {
6330                 result = WERR_BADFID;
6331                 goto done;
6332         }
6333
6334         DEBUGADD(8,("Converting info_2 struct\n"));
6335
6336         /*
6337          * convert_printer_info converts the incoming
6338          * info from the client and overwrites the info
6339          * just read from the tdb in the pointer 'printer'.
6340          */
6341
6342         if (!convert_printer_info_new(info_ctr, printer)) {
6343                 result =  WERR_NOMEM;
6344                 goto done;
6345         }
6346
6347         if (devmode) {
6348                 /* we have a valid devmode
6349                    convert it and link it*/
6350
6351                 DEBUGADD(8,("update_printer: Converting the devicemode struct\n"));
6352                 if (!convert_devicemode_new(printer->info_2->printername,
6353                                             devmode,
6354                                             &printer->info_2->devmode)) {
6355                         result =  WERR_NOMEM;
6356                         goto done;
6357                 }
6358         }
6359
6360         /* Do sanity check on the requested changes for Samba */
6361
6362         if (!check_printer_ok(printer->info_2, snum)) {
6363                 result = WERR_INVALID_PARAM;
6364                 goto done;
6365         }
6366
6367         /* FIXME!!! If the driver has changed we really should verify that
6368            it is installed before doing much else   --jerry */
6369
6370         /* Check calling user has permission to update printer description */
6371
6372         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
6373                 DEBUG(3, ("update_printer: printer property change denied by handle\n"));
6374                 result = WERR_ACCESS_DENIED;
6375                 goto done;
6376         }
6377
6378         /* Call addprinter hook */
6379         /* Check changes to see if this is really needed */
6380
6381         if ( *lp_addprinter_cmd()
6382                 && (!strequal(printer->info_2->drivername, old_printer->info_2->drivername)
6383                         || !strequal(printer->info_2->comment, old_printer->info_2->comment)
6384                         || !strequal(printer->info_2->portname, old_printer->info_2->portname)
6385                         || !strequal(printer->info_2->location, old_printer->info_2->location)) )
6386         {
6387                 /* add_printer_hook() will call reload_services() */
6388
6389                 if ( !add_printer_hook(p->mem_ctx, p->server_info->ptok,
6390                                        printer) ) {
6391                         result = WERR_ACCESS_DENIED;
6392                         goto done;
6393                 }
6394         }
6395
6396         /*
6397          * When a *new* driver is bound to a printer, the drivername is used to
6398          * lookup previously saved driver initialization info, which is then
6399          * bound to the printer, simulating what happens in the Windows arch.
6400          */
6401         if (!strequal(printer->info_2->drivername, old_printer->info_2->drivername))
6402         {
6403                 if (!set_driver_init(printer, 2))
6404                 {
6405                         DEBUG(5,("update_printer: Error restoring driver initialization data for driver [%s]!\n",
6406                                 printer->info_2->drivername));
6407                 }
6408
6409                 DEBUG(10,("update_printer: changing driver [%s]!  Sending event!\n",
6410                         printer->info_2->drivername));
6411
6412                 notify_printer_driver(snum, printer->info_2->drivername);
6413         }
6414
6415         /*
6416          * flag which changes actually occured.  This is a small subset of
6417          * all the possible changes.  We also have to update things in the
6418          * DsSpooler key.
6419          */
6420
6421         if (!strequal(printer->info_2->comment, old_printer->info_2->comment)) {
6422                 init_unistr2( &buffer, printer->info_2->comment, UNI_STR_TERMINATE);
6423                 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "description",
6424                         REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6425
6426                 notify_printer_comment(snum, printer->info_2->comment);
6427         }
6428
6429         if (!strequal(printer->info_2->sharename, old_printer->info_2->sharename)) {
6430                 init_unistr2( &buffer, printer->info_2->sharename, UNI_STR_TERMINATE);
6431                 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "shareName",
6432                         REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6433
6434                 notify_printer_sharename(snum, printer->info_2->sharename);
6435         }
6436
6437         if (!strequal(printer->info_2->printername, old_printer->info_2->printername)) {
6438                 char *pname;
6439
6440                 if ( (pname = strchr_m( printer->info_2->printername+2, '\\' )) != NULL )
6441                         pname++;
6442                 else
6443                         pname = printer->info_2->printername;
6444
6445
6446                 init_unistr2( &buffer, pname, UNI_STR_TERMINATE);
6447                 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "printerName",
6448                         REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6449
6450                 notify_printer_printername( snum, pname );
6451         }
6452
6453         if (!strequal(printer->info_2->portname, old_printer->info_2->portname)) {
6454                 init_unistr2( &buffer, printer->info_2->portname, UNI_STR_TERMINATE);
6455                 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "portName",
6456                         REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6457
6458                 notify_printer_port(snum, printer->info_2->portname);
6459         }
6460
6461         if (!strequal(printer->info_2->location, old_printer->info_2->location)) {
6462                 init_unistr2( &buffer, printer->info_2->location, UNI_STR_TERMINATE);
6463                 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "location",
6464                         REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6465
6466                 notify_printer_location(snum, printer->info_2->location);
6467         }
6468
6469         /* here we need to update some more DsSpooler keys */
6470         /* uNCName, serverName, shortServerName */
6471
6472         init_unistr2( &buffer, global_myname(), UNI_STR_TERMINATE);
6473         set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "serverName",
6474                 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6475         set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "shortServerName",
6476                 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6477
6478         slprintf( asc_buffer, sizeof(asc_buffer)-1, "\\\\%s\\%s",
6479                  global_myname(), printer->info_2->sharename );
6480         init_unistr2( &buffer, asc_buffer, UNI_STR_TERMINATE);
6481         set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "uNCName",
6482                 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6483
6484         /* Update printer info */
6485         result = mod_a_printer(printer, 2);
6486
6487 done:
6488         free_a_printer(&printer, 2);
6489         free_a_printer(&old_printer, 2);
6490
6491
6492         return result;
6493 }
6494
6495 /****************************************************************************
6496 ****************************************************************************/
6497 static WERROR publish_or_unpublish_printer(pipes_struct *p, POLICY_HND *handle,
6498                                            struct spoolss_SetPrinterInfo7 *info7)
6499 {
6500 #ifdef HAVE_ADS
6501         int snum;
6502         Printer_entry *Printer;
6503
6504         if ( lp_security() != SEC_ADS ) {
6505                 return WERR_UNKNOWN_LEVEL;
6506         }
6507
6508         Printer = find_printer_index_by_hnd(p, handle);
6509
6510         DEBUG(5,("publish_or_unpublish_printer, action = %d\n",info7->action));
6511
6512         if (!Printer)
6513                 return WERR_BADFID;
6514
6515         if (!get_printer_snum(p, handle, &snum, NULL))
6516                 return WERR_BADFID;
6517
6518         nt_printer_publish(Printer, snum, info7->action);
6519
6520         return WERR_OK;
6521 #else
6522         return WERR_UNKNOWN_LEVEL;
6523 #endif
6524 }
6525
6526 /****************************************************************
6527  _spoolss_SetPrinter
6528 ****************************************************************/
6529
6530 WERROR _spoolss_SetPrinter(pipes_struct *p,
6531                            struct spoolss_SetPrinter *r)
6532 {
6533         POLICY_HND *handle = r->in.handle;
6534         WERROR result;
6535
6536         Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
6537
6538         if (!Printer) {
6539                 DEBUG(2,("_spoolss_SetPrinter: Invalid handle (%s:%u:%u)\n",
6540                         OUR_HANDLE(handle)));
6541                 return WERR_BADFID;
6542         }
6543
6544         /* check the level */
6545         switch (r->in.info_ctr->level) {
6546                 case 0:
6547                         return control_printer(handle, r->in.command, p);
6548                 case 2:
6549                         result = update_printer(p, handle,
6550                                                 r->in.info_ctr,
6551                                                 r->in.devmode_ctr->devmode);
6552                         if (!W_ERROR_IS_OK(result))
6553                                 return result;
6554                         if (r->in.secdesc_ctr->sd)
6555                                 result = update_printer_sec(handle, p,
6556                                                             r->in.secdesc_ctr);
6557                         return result;
6558                 case 3:
6559                         return update_printer_sec(handle, p,
6560                                                   r->in.secdesc_ctr);
6561                 case 7:
6562                         return publish_or_unpublish_printer(p, handle,
6563                                                             r->in.info_ctr->info.info7);
6564                 default:
6565                         return WERR_UNKNOWN_LEVEL;
6566         }
6567 }
6568
6569 /****************************************************************
6570  _spoolss_FindClosePrinterNotify
6571 ****************************************************************/
6572
6573 WERROR _spoolss_FindClosePrinterNotify(pipes_struct *p,
6574                                        struct spoolss_FindClosePrinterNotify *r)
6575 {
6576         POLICY_HND *handle = r->in.handle;
6577         Printer_entry *Printer= find_printer_index_by_hnd(p, handle);
6578
6579         if (!Printer) {
6580                 DEBUG(2,("_spoolss_FindClosePrinterNotify: "
6581                         "Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
6582                 return WERR_BADFID;
6583         }
6584
6585         if (Printer->notify.client_connected==True) {
6586                 int snum = -1;
6587
6588                 if ( Printer->printer_type == SPLHND_SERVER)
6589                         snum = -1;
6590                 else if ( (Printer->printer_type == SPLHND_PRINTER) &&
6591                                 !get_printer_snum(p, handle, &snum, NULL) )
6592                         return WERR_BADFID;
6593
6594                 srv_spoolss_replycloseprinter(snum, &Printer->notify.client_hnd);
6595         }
6596
6597         Printer->notify.flags=0;
6598         Printer->notify.options=0;
6599         Printer->notify.localmachine[0]='\0';
6600         Printer->notify.printerlocal=0;
6601         TALLOC_FREE(Printer->notify.option);
6602         Printer->notify.client_connected=False;
6603
6604         return WERR_OK;
6605 }
6606
6607 /****************************************************************
6608  _spoolss_AddJob
6609 ****************************************************************/
6610
6611 WERROR _spoolss_AddJob(pipes_struct *p,
6612                        struct spoolss_AddJob *r)
6613 {
6614         if (!r->in.buffer && (r->in.offered != 0)) {
6615                 return WERR_INVALID_PARAM;
6616         }
6617
6618         /* this is what a NT server returns for AddJob. AddJob must fail on
6619          * non-local printers */
6620
6621         if (r->in.level != 1) {
6622                 return WERR_UNKNOWN_LEVEL;
6623         }
6624
6625         return WERR_INVALID_PARAM;
6626 }
6627
6628 /****************************************************************************
6629 ****************************************************************************/
6630
6631 static void fill_job_info_1(JOB_INFO_1 *job_info, const print_queue_struct *queue,
6632                             int position, int snum,
6633                             const NT_PRINTER_INFO_LEVEL *ntprinter)
6634 {
6635         struct tm *t;
6636
6637         t=gmtime(&queue->time);
6638
6639         job_info->jobid=queue->job;
6640         init_unistr(&job_info->printername, lp_servicename(snum));
6641         init_unistr(&job_info->machinename, ntprinter->info_2->servername);
6642         init_unistr(&job_info->username, queue->fs_user);
6643         init_unistr(&job_info->document, queue->fs_file);
6644         init_unistr(&job_info->datatype, "RAW");
6645         init_unistr(&job_info->text_status, "");
6646         job_info->status=nt_printj_status(queue->status);
6647         job_info->priority=queue->priority;
6648         job_info->position=position;
6649         job_info->totalpages=queue->page_count;
6650         job_info->pagesprinted=0;
6651
6652         make_systemtime(&job_info->submitted, t);
6653 }
6654
6655 /****************************************************************************
6656 ****************************************************************************/
6657
6658 static bool fill_job_info_2(JOB_INFO_2 *job_info, const print_queue_struct *queue,
6659                             int position, int snum,
6660                             const NT_PRINTER_INFO_LEVEL *ntprinter,
6661                             DEVICEMODE *devmode)
6662 {
6663         struct tm *t;
6664
6665         t=gmtime(&queue->time);
6666
6667         job_info->jobid=queue->job;
6668
6669         init_unistr(&job_info->printername, ntprinter->info_2->printername);
6670
6671         init_unistr(&job_info->machinename, ntprinter->info_2->servername);
6672         init_unistr(&job_info->username, queue->fs_user);
6673         init_unistr(&job_info->document, queue->fs_file);
6674         init_unistr(&job_info->notifyname, queue->fs_user);
6675         init_unistr(&job_info->datatype, "RAW");
6676         init_unistr(&job_info->printprocessor, "winprint");
6677         init_unistr(&job_info->parameters, "");
6678         init_unistr(&job_info->drivername, ntprinter->info_2->drivername);
6679         init_unistr(&job_info->text_status, "");
6680
6681 /* and here the security descriptor */
6682
6683         job_info->status=nt_printj_status(queue->status);
6684         job_info->priority=queue->priority;
6685         job_info->position=position;
6686         job_info->starttime=0;
6687         job_info->untiltime=0;
6688         job_info->totalpages=queue->page_count;
6689         job_info->size=queue->size;
6690         make_systemtime(&(job_info->submitted), t);
6691         job_info->timeelapsed=0;
6692         job_info->pagesprinted=0;
6693
6694         job_info->devmode = devmode;
6695
6696         return (True);
6697 }
6698
6699 /****************************************************************************
6700  Enumjobs at level 1.
6701 ****************************************************************************/
6702
6703 static WERROR enumjobs_level1(const print_queue_struct *queue, int snum,
6704                               const NT_PRINTER_INFO_LEVEL *ntprinter,
6705                               RPC_BUFFER *buffer, uint32 offered,
6706                               uint32 *needed, uint32 *returned)
6707 {
6708         JOB_INFO_1 *info;
6709         int i;
6710         WERROR result = WERR_OK;
6711
6712         info=SMB_MALLOC_ARRAY(JOB_INFO_1,*returned);
6713         if (info==NULL) {
6714                 *returned=0;
6715                 return WERR_NOMEM;
6716         }
6717
6718         for (i=0; i<*returned; i++)
6719                 fill_job_info_1( &info[i], &queue[i], i, snum, ntprinter );
6720
6721         /* check the required size. */
6722         for (i=0; i<*returned; i++)
6723                 (*needed) += spoolss_size_job_info_1(&info[i]);
6724
6725         if (*needed > offered) {
6726                 result = WERR_INSUFFICIENT_BUFFER;
6727                 goto out;
6728         }
6729
6730         if (!rpcbuf_alloc_size(buffer, *needed)) {
6731                 result = WERR_NOMEM;
6732                 goto out;
6733         }
6734
6735         /* fill the buffer with the structures */
6736         for (i=0; i<*returned; i++)
6737                 smb_io_job_info_1("", buffer, &info[i], 0);
6738
6739 out:
6740         /* clear memory */
6741         SAFE_FREE(info);
6742
6743         if ( !W_ERROR_IS_OK(result) )
6744                 *returned = 0;
6745
6746         return result;
6747 }
6748
6749 /****************************************************************************
6750  Enumjobs at level 2.
6751 ****************************************************************************/
6752
6753 static WERROR enumjobs_level2(const print_queue_struct *queue, int snum,
6754                               const NT_PRINTER_INFO_LEVEL *ntprinter,
6755                               RPC_BUFFER *buffer, uint32 offered,
6756                               uint32 *needed, uint32 *returned)
6757 {
6758         JOB_INFO_2 *info = NULL;
6759         int i;
6760         WERROR result = WERR_OK;
6761         DEVICEMODE *devmode = NULL;
6762
6763         if ( !(info = SMB_MALLOC_ARRAY(JOB_INFO_2,*returned)) ) {
6764                 *returned=0;
6765                 return WERR_NOMEM;
6766         }
6767
6768         /* this should not be a failure condition if the devmode is NULL */
6769
6770         devmode = construct_dev_mode(lp_const_servicename(snum));
6771
6772         for (i=0; i<*returned; i++)
6773                 fill_job_info_2(&(info[i]), &queue[i], i, snum, ntprinter, devmode);
6774
6775         /* check the required size. */
6776         for (i=0; i<*returned; i++)
6777                 (*needed) += spoolss_size_job_info_2(&info[i]);
6778
6779         if (*needed > offered) {
6780                 result = WERR_INSUFFICIENT_BUFFER;
6781                 goto out;
6782         }
6783
6784         if (!rpcbuf_alloc_size(buffer, *needed)) {
6785                 result = WERR_NOMEM;
6786                 goto out;
6787         }
6788
6789         /* fill the buffer with the structures */
6790         for (i=0; i<*returned; i++)
6791                 smb_io_job_info_2("", buffer, &info[i], 0);
6792
6793 out:
6794         free_devmode(devmode);
6795         SAFE_FREE(info);
6796
6797         if ( !W_ERROR_IS_OK(result) )
6798                 *returned = 0;
6799
6800         return result;
6801
6802 }
6803
6804 /****************************************************************************
6805  Enumjobs.
6806 ****************************************************************************/
6807
6808 WERROR _spoolss_enumjobs( pipes_struct *p, SPOOL_Q_ENUMJOBS *q_u, SPOOL_R_ENUMJOBS *r_u)
6809 {
6810         POLICY_HND *handle = &q_u->handle;
6811         uint32 level = q_u->level;
6812         RPC_BUFFER *buffer = NULL;
6813         uint32 offered = q_u->offered;
6814         uint32 *needed = &r_u->needed;
6815         uint32 *returned = &r_u->returned;
6816         WERROR wret;
6817         NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
6818         int snum;
6819         print_status_struct prt_status;
6820         print_queue_struct *queue=NULL;
6821
6822         /* that's an [in out] buffer */
6823
6824         if (!q_u->buffer && (offered!=0)) {
6825                 return WERR_INVALID_PARAM;
6826         }
6827
6828         if (offered > MAX_RPC_DATA_SIZE) {
6829                 return WERR_INVALID_PARAM;
6830         }
6831
6832         rpcbuf_move(q_u->buffer, &r_u->buffer);
6833         buffer = r_u->buffer;
6834
6835         DEBUG(4,("_spoolss_enumjobs\n"));
6836
6837         *needed=0;
6838         *returned=0;
6839
6840         /* lookup the printer snum and tdb entry */
6841
6842         if (!get_printer_snum(p, handle, &snum, NULL))
6843                 return WERR_BADFID;
6844
6845         wret = get_a_printer(NULL, &ntprinter, 2, lp_servicename(snum));
6846         if ( !W_ERROR_IS_OK(wret) )
6847                 return wret;
6848
6849         *returned = print_queue_status(snum, &queue, &prt_status);
6850         DEBUGADD(4,("count:[%d], status:[%d], [%s]\n", *returned, prt_status.status, prt_status.message));
6851
6852         if (*returned == 0) {
6853                 SAFE_FREE(queue);
6854                 free_a_printer(&ntprinter, 2);
6855                 return WERR_OK;
6856         }
6857
6858         switch (level) {
6859         case 1:
6860                 wret = enumjobs_level1(queue, snum, ntprinter, buffer, offered, needed, returned);
6861                 break;
6862         case 2:
6863                 wret = enumjobs_level2(queue, snum, ntprinter, buffer, offered, needed, returned);
6864                 break;
6865         default:
6866                 *returned=0;
6867                 wret = WERR_UNKNOWN_LEVEL;
6868                 break;
6869         }
6870
6871         SAFE_FREE(queue);
6872         free_a_printer( &ntprinter, 2 );
6873         return wret;
6874 }
6875
6876 /****************************************************************
6877  _spoolss_ScheduleJob
6878 ****************************************************************/
6879
6880 WERROR _spoolss_ScheduleJob(pipes_struct *p,
6881                             struct spoolss_ScheduleJob *r)
6882 {
6883         return WERR_OK;
6884 }
6885
6886 /****************************************************************
6887  _spoolss_SetJob
6888 ****************************************************************/
6889
6890 WERROR _spoolss_SetJob(pipes_struct *p,
6891                        struct spoolss_SetJob *r)
6892 {
6893         POLICY_HND *handle = r->in.handle;
6894         uint32 jobid = r->in.job_id;
6895         uint32 command = r->in.command;
6896
6897         int snum;
6898         WERROR errcode = WERR_BADFUNC;
6899
6900         if (!get_printer_snum(p, handle, &snum, NULL)) {
6901                 return WERR_BADFID;
6902         }
6903
6904         if (!print_job_exists(lp_const_servicename(snum), jobid)) {
6905                 return WERR_INVALID_PRINTER_NAME;
6906         }
6907
6908         switch (command) {
6909         case SPOOLSS_JOB_CONTROL_CANCEL:
6910         case SPOOLSS_JOB_CONTROL_DELETE:
6911                 if (print_job_delete(p->server_info, snum, jobid, &errcode)) {
6912                         errcode = WERR_OK;
6913                 }
6914                 break;
6915         case SPOOLSS_JOB_CONTROL_PAUSE:
6916                 if (print_job_pause(p->server_info, snum, jobid, &errcode)) {
6917                         errcode = WERR_OK;
6918                 }
6919                 break;
6920         case SPOOLSS_JOB_CONTROL_RESTART:
6921         case SPOOLSS_JOB_CONTROL_RESUME:
6922                 if (print_job_resume(p->server_info, snum, jobid, &errcode)) {
6923                         errcode = WERR_OK;
6924                 }
6925                 break;
6926         default:
6927                 return WERR_UNKNOWN_LEVEL;
6928         }
6929
6930         return errcode;
6931 }
6932
6933 /****************************************************************************
6934  Enumerates all printer drivers at level 1.
6935 ****************************************************************************/
6936
6937 static WERROR enumprinterdrivers_level1(const char *servername, fstring architecture, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
6938 {
6939         int i;
6940         int ndrivers;
6941         uint32 version;
6942         fstring *list = NULL;
6943         NT_PRINTER_DRIVER_INFO_LEVEL driver;
6944         DRIVER_INFO_1 *driver_info_1=NULL;
6945         WERROR result = WERR_OK;
6946
6947         *returned=0;
6948
6949         for (version=0; version<DRIVER_MAX_VERSION; version++) {
6950                 list=NULL;
6951                 ndrivers=get_ntdrivers(&list, architecture, version);
6952                 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
6953
6954                 if(ndrivers == -1) {
6955                         SAFE_FREE(driver_info_1);
6956                         return WERR_NOMEM;
6957                 }
6958
6959                 if(ndrivers != 0) {
6960                         if((driver_info_1=SMB_REALLOC_ARRAY(driver_info_1, DRIVER_INFO_1, *returned+ndrivers )) == NULL) {
6961                                 DEBUG(0,("enumprinterdrivers_level1: failed to enlarge driver info buffer!\n"));
6962                                 SAFE_FREE(list);
6963                                 return WERR_NOMEM;
6964                         }
6965                 }
6966
6967                 for (i=0; i<ndrivers; i++) {
6968                         WERROR status;
6969                         DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
6970                         ZERO_STRUCT(driver);
6971                         status = get_a_printer_driver(&driver, 3, list[i],
6972                                                       architecture, version);
6973                         if (!W_ERROR_IS_OK(status)) {
6974                                 SAFE_FREE(list);
6975                                 SAFE_FREE(driver_info_1);
6976                                 return status;
6977                         }
6978                         fill_printer_driver_info_1(&driver_info_1[*returned+i], driver, servername, architecture );
6979                         free_a_printer_driver(driver, 3);
6980                 }
6981
6982                 *returned+=ndrivers;
6983                 SAFE_FREE(list);
6984         }
6985
6986         /* check the required size. */
6987         for (i=0; i<*returned; i++) {
6988                 DEBUGADD(6,("adding driver [%d]'s size\n",i));
6989                 *needed += spoolss_size_printer_driver_info_1(&driver_info_1[i]);
6990         }
6991
6992         if (*needed > offered) {
6993                 result = WERR_INSUFFICIENT_BUFFER;
6994                 goto out;
6995         }
6996
6997         if (!rpcbuf_alloc_size(buffer, *needed)) {
6998                 result = WERR_NOMEM;
6999                 goto out;
7000         }
7001
7002         /* fill the buffer with the driver structures */
7003         for (i=0; i<*returned; i++) {
7004                 DEBUGADD(6,("adding driver [%d] to buffer\n",i));
7005                 smb_io_printer_driver_info_1("", buffer, &driver_info_1[i], 0);
7006         }
7007
7008 out:
7009         SAFE_FREE(driver_info_1);
7010
7011         if ( !W_ERROR_IS_OK(result) )
7012                 *returned = 0;
7013
7014         return result;
7015 }
7016
7017 /****************************************************************************
7018  Enumerates all printer drivers at level 2.
7019 ****************************************************************************/
7020
7021 static WERROR enumprinterdrivers_level2(const char *servername, fstring architecture, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
7022 {
7023         int i;
7024         int ndrivers;
7025         uint32 version;
7026         fstring *list = NULL;
7027         NT_PRINTER_DRIVER_INFO_LEVEL driver;
7028         DRIVER_INFO_2 *driver_info_2=NULL;
7029         WERROR result = WERR_OK;
7030
7031         *returned=0;
7032
7033         for (version=0; version<DRIVER_MAX_VERSION; version++) {
7034                 list=NULL;
7035                 ndrivers=get_ntdrivers(&list, architecture, version);
7036                 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
7037
7038                 if(ndrivers == -1) {
7039                         SAFE_FREE(driver_info_2);
7040                         return WERR_NOMEM;
7041                 }
7042
7043                 if(ndrivers != 0) {
7044                         if((driver_info_2=SMB_REALLOC_ARRAY(driver_info_2, DRIVER_INFO_2, *returned+ndrivers )) == NULL) {
7045                                 DEBUG(0,("enumprinterdrivers_level2: failed to enlarge driver info buffer!\n"));
7046                                 SAFE_FREE(list);
7047                                 return WERR_NOMEM;
7048                         }
7049                 }
7050
7051                 for (i=0; i<ndrivers; i++) {
7052                         WERROR status;
7053
7054                         DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
7055                         ZERO_STRUCT(driver);
7056                         status = get_a_printer_driver(&driver, 3, list[i],
7057                                                       architecture, version);
7058                         if (!W_ERROR_IS_OK(status)) {
7059                                 SAFE_FREE(list);
7060                                 SAFE_FREE(driver_info_2);
7061                                 return status;
7062                         }
7063                         fill_printer_driver_info_2(&driver_info_2[*returned+i], driver, servername);
7064                         free_a_printer_driver(driver, 3);
7065                 }
7066
7067                 *returned+=ndrivers;
7068                 SAFE_FREE(list);
7069         }
7070
7071         /* check the required size. */
7072         for (i=0; i<*returned; i++) {
7073                 DEBUGADD(6,("adding driver [%d]'s size\n",i));
7074                 *needed += spoolss_size_printer_driver_info_2(&(driver_info_2[i]));
7075         }
7076
7077         if (*needed > offered) {
7078                 result = WERR_INSUFFICIENT_BUFFER;
7079                 goto out;
7080         }
7081
7082         if (!rpcbuf_alloc_size(buffer, *needed)) {
7083                 result = WERR_NOMEM;
7084                 goto out;
7085         }
7086
7087         /* fill the buffer with the form structures */
7088         for (i=0; i<*returned; i++) {
7089                 DEBUGADD(6,("adding driver [%d] to buffer\n",i));
7090                 smb_io_printer_driver_info_2("", buffer, &(driver_info_2[i]), 0);
7091         }
7092
7093 out:
7094         SAFE_FREE(driver_info_2);
7095
7096         if ( !W_ERROR_IS_OK(result) )
7097                 *returned = 0;
7098
7099         return result;
7100 }
7101
7102 /****************************************************************************
7103  Enumerates all printer drivers at level 3.
7104 ****************************************************************************/
7105
7106 static WERROR enumprinterdrivers_level3(const char *servername, fstring architecture, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
7107 {
7108         int i;
7109         int ndrivers;
7110         uint32 version;
7111         fstring *list = NULL;
7112         DRIVER_INFO_3 *driver_info_3=NULL;
7113         NT_PRINTER_DRIVER_INFO_LEVEL driver;
7114         WERROR result = WERR_OK;
7115
7116         *returned=0;
7117
7118         for (version=0; version<DRIVER_MAX_VERSION; version++) {
7119                 list=NULL;
7120                 ndrivers=get_ntdrivers(&list, architecture, version);
7121                 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
7122
7123                 if(ndrivers == -1) {
7124                         SAFE_FREE(driver_info_3);
7125                         return WERR_NOMEM;
7126                 }
7127
7128                 if(ndrivers != 0) {
7129                         if((driver_info_3=SMB_REALLOC_ARRAY(driver_info_3, DRIVER_INFO_3, *returned+ndrivers )) == NULL) {
7130                                 DEBUG(0,("enumprinterdrivers_level3: failed to enlarge driver info buffer!\n"));
7131                                 SAFE_FREE(list);
7132                                 return WERR_NOMEM;
7133                         }
7134                 }
7135
7136                 for (i=0; i<ndrivers; i++) {
7137                         WERROR status;
7138
7139                         DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
7140                         ZERO_STRUCT(driver);
7141                         status = get_a_printer_driver(&driver, 3, list[i],
7142                                                       architecture, version);
7143                         if (!W_ERROR_IS_OK(status)) {
7144                                 SAFE_FREE(list);
7145                                 SAFE_FREE(driver_info_3);
7146                                 return status;
7147                         }
7148                         fill_printer_driver_info_3(&driver_info_3[*returned+i], driver, servername);
7149                         free_a_printer_driver(driver, 3);
7150                 }
7151
7152                 *returned+=ndrivers;
7153                 SAFE_FREE(list);
7154         }
7155
7156         /* check the required size. */
7157         for (i=0; i<*returned; i++) {
7158                 DEBUGADD(6,("adding driver [%d]'s size\n",i));
7159                 *needed += spoolss_size_printer_driver_info_3(&driver_info_3[i]);
7160         }
7161
7162         if (*needed > offered) {
7163                 result = WERR_INSUFFICIENT_BUFFER;
7164                 goto out;
7165         }
7166
7167         if (!rpcbuf_alloc_size(buffer, *needed)) {
7168                 result = WERR_NOMEM;
7169                 goto out;
7170         }
7171
7172         /* fill the buffer with the driver structures */
7173         for (i=0; i<*returned; i++) {
7174                 DEBUGADD(6,("adding driver [%d] to buffer\n",i));
7175                 smb_io_printer_driver_info_3("", buffer, &driver_info_3[i], 0);
7176         }
7177
7178 out:
7179         for (i=0; i<*returned; i++) {
7180                 SAFE_FREE(driver_info_3[i].dependentfiles);
7181         }
7182
7183         SAFE_FREE(driver_info_3);
7184
7185         if ( !W_ERROR_IS_OK(result) )
7186                 *returned = 0;
7187
7188         return result;
7189 }
7190
7191 /****************************************************************************
7192  Enumerates all printer drivers.
7193 ****************************************************************************/
7194
7195 WERROR _spoolss_enumprinterdrivers( pipes_struct *p, SPOOL_Q_ENUMPRINTERDRIVERS *q_u, SPOOL_R_ENUMPRINTERDRIVERS *r_u)
7196 {
7197         uint32 level = q_u->level;
7198         RPC_BUFFER *buffer = NULL;
7199         uint32 offered = q_u->offered;
7200         uint32 *needed = &r_u->needed;
7201         uint32 *returned = &r_u->returned;
7202         const char *cservername;
7203         fstring servername;
7204         fstring architecture;
7205
7206         /* that's an [in out] buffer */
7207
7208         if (!q_u->buffer && (offered!=0)) {
7209                 return WERR_INVALID_PARAM;
7210         }
7211
7212         if (offered > MAX_RPC_DATA_SIZE) {
7213                 return WERR_INVALID_PARAM;
7214         }
7215
7216         rpcbuf_move(q_u->buffer, &r_u->buffer);
7217         buffer = r_u->buffer;
7218
7219         DEBUG(4,("_spoolss_enumprinterdrivers\n"));
7220
7221         *needed   = 0;
7222         *returned = 0;
7223
7224         unistr2_to_ascii(architecture, &q_u->environment, sizeof(architecture));
7225         unistr2_to_ascii(servername, &q_u->name, sizeof(servername));
7226
7227         cservername = canon_servername(servername);
7228
7229         if (!is_myname_or_ipaddr(cservername))
7230                 return WERR_UNKNOWN_PRINTER_DRIVER;
7231
7232         switch (level) {
7233         case 1:
7234                 return enumprinterdrivers_level1(cservername, architecture, buffer, offered, needed, returned);
7235         case 2:
7236                 return enumprinterdrivers_level2(cservername, architecture, buffer, offered, needed, returned);
7237         case 3:
7238                 return enumprinterdrivers_level3(cservername, architecture, buffer, offered, needed, returned);
7239         default:
7240                 return WERR_UNKNOWN_LEVEL;
7241         }
7242 }
7243
7244 /****************************************************************************
7245 ****************************************************************************/
7246
7247 static WERROR fill_form_info_1(TALLOC_CTX *mem_ctx,
7248                                struct spoolss_FormInfo1 *form,
7249                                nt_forms_struct *list)
7250 {
7251         form->form_name         = talloc_strdup(mem_ctx, list->name);
7252         W_ERROR_HAVE_NO_MEMORY(form->form_name);
7253
7254         form->flags             = list->flag;
7255         form->size.width        = list->width;
7256         form->size.height       = list->length;
7257         form->area.left         = list->left;
7258         form->area.top          = list->top;
7259         form->area.right        = list->right;
7260         form->area.bottom       = list->bottom;
7261
7262         return WERR_OK;
7263 }
7264
7265 /****************************************************************
7266  _spoolss_EnumForms
7267 ****************************************************************/
7268
7269 WERROR _spoolss_EnumForms(pipes_struct *p,
7270                           struct spoolss_EnumForms *r)
7271 {
7272         nt_forms_struct *list=NULL;
7273         nt_forms_struct *builtinlist=NULL;
7274         union spoolss_FormInfo *info;
7275         uint32_t count;
7276         uint32_t numbuiltinforms;
7277         size_t buffer_size = 0;
7278         int i;
7279
7280         *r->out.count = 0;
7281
7282         /* that's an [in out] buffer */
7283
7284         if (!r->in.buffer && (r->in.offered != 0) ) {
7285                 return WERR_INVALID_PARAM;
7286         }
7287
7288         DEBUG(4,("_spoolss_EnumForms\n"));
7289         DEBUGADD(5,("Offered buffer size [%d]\n", r->in.offered));
7290         DEBUGADD(5,("Info level [%d]\n",          r->in.level));
7291
7292         numbuiltinforms = get_builtin_ntforms(&builtinlist);
7293         DEBUGADD(5,("Number of builtin forms [%d]\n",     numbuiltinforms));
7294         count = get_ntforms(&list);
7295         DEBUGADD(5,("Number of user forms [%d]\n",     count));
7296         count += numbuiltinforms;
7297
7298         if (count == 0) {
7299                 SAFE_FREE(builtinlist);
7300                 SAFE_FREE(list);
7301                 return WERR_NO_MORE_ITEMS;
7302         }
7303
7304         info = TALLOC_ARRAY(p->mem_ctx, union spoolss_FormInfo, count);
7305         if (!info) {
7306                 SAFE_FREE(builtinlist);
7307                 SAFE_FREE(list);
7308                 return WERR_NOMEM;
7309         }
7310
7311         switch (r->in.level) {
7312         case 1:
7313                 /* construct the list of form structures */
7314                 for (i=0; i<numbuiltinforms; i++) {
7315                         DEBUGADD(6,("Filling form number [%d]\n",i));
7316                         fill_form_info_1(info, &info[i].info1, &builtinlist[i]);
7317                 }
7318
7319                 SAFE_FREE(builtinlist);
7320
7321                 for (; i<count; i++) {
7322                         DEBUGADD(6,("Filling form number [%d]\n",i));
7323                         fill_form_info_1(info, &info[i].info1, &list[i-numbuiltinforms]);
7324                 }
7325
7326                 SAFE_FREE(list);
7327
7328                 /* check the required size. */
7329                 for (i=0; i<numbuiltinforms; i++) {
7330                         DEBUGADD(6,("adding form [%d]'s size\n",i));
7331                         buffer_size += ndr_size_spoolss_FormInfo1(&info[i].info1, NULL, 0);
7332                 }
7333                 for (; i<count; i++) {
7334                         DEBUGADD(6,("adding form [%d]'s size\n",i));
7335                         buffer_size += ndr_size_spoolss_FormInfo1(&info[i].info1, NULL, 0);
7336                 }
7337
7338                 *r->out.needed = buffer_size;
7339
7340                 if (*r->out.needed > r->in.offered) {
7341                         TALLOC_FREE(info);
7342                         return WERR_INSUFFICIENT_BUFFER;
7343                 }
7344
7345                 *r->out.count = count;
7346                 *r->out.info = info;
7347
7348                 return WERR_OK;
7349
7350         default:
7351                 SAFE_FREE(list);
7352                 SAFE_FREE(builtinlist);
7353                 return WERR_UNKNOWN_LEVEL;
7354         }
7355 }
7356
7357 /****************************************************************
7358  _spoolss_GetForm
7359 ****************************************************************/
7360
7361 WERROR _spoolss_GetForm(pipes_struct *p,
7362                         struct spoolss_GetForm *r)
7363 {
7364         uint32 level = r->in.level;
7365         uint32 offered = r->in.offered;
7366         uint32 *needed = r->out.needed;
7367
7368         nt_forms_struct *list=NULL;
7369         nt_forms_struct builtin_form;
7370         bool foundBuiltin;
7371         union spoolss_FormInfo info;
7372         struct spoolss_FormInfo1 form_1;
7373         int numofforms=0, i=0;
7374
7375         /* that's an [in out] buffer */
7376
7377         if (!r->in.buffer && (offered!=0)) {
7378                 return WERR_INVALID_PARAM;
7379         }
7380
7381         DEBUG(4,("_spoolss_GetForm\n"));
7382         DEBUGADD(5,("Offered buffer size [%d]\n", offered));
7383         DEBUGADD(5,("Info level [%d]\n",          level));
7384
7385         foundBuiltin = get_a_builtin_ntform_by_string(r->in.form_name, &builtin_form);
7386         if (!foundBuiltin) {
7387                 numofforms = get_ntforms(&list);
7388                 DEBUGADD(5,("Number of forms [%d]\n",     numofforms));
7389
7390                 if (numofforms == 0)
7391                         return WERR_BADFID;
7392         }
7393
7394         ZERO_STRUCT(form_1);
7395
7396         switch (level) {
7397         case 1:
7398                 if (foundBuiltin) {
7399                         fill_form_info_1(p->mem_ctx, &form_1, &builtin_form);
7400                 } else {
7401
7402                         /* Check if the requested name is in the list of form structures */
7403                         for (i=0; i<numofforms; i++) {
7404
7405                                 DEBUG(4,("_spoolss_GetForm: checking form %s (want %s)\n",
7406                                         list[i].name, r->in.form_name));
7407
7408                                 if (strequal(r->in.form_name, list[i].name)) {
7409                                         DEBUGADD(6,("Found form %s number [%d]\n",
7410                                                 r->in.form_name, i));
7411                                         fill_form_info_1(p->mem_ctx, &form_1, &list[i]);
7412                                         break;
7413                                 }
7414                         }
7415
7416                         SAFE_FREE(list);
7417                         if (i == numofforms) {
7418                                 return WERR_BADFID;
7419                         }
7420                 }
7421                 /* check the required size. */
7422
7423                 info.info1 = form_1;
7424
7425                 *needed = ndr_size_spoolss_FormInfo(&info, 1, NULL, 0);
7426
7427                 if (*needed > offered) {
7428                         r->out.info = NULL;
7429                         return WERR_INSUFFICIENT_BUFFER;
7430                 }
7431
7432                 r->out.info->info1 = form_1;
7433
7434                 /* fill the buffer with the form structures */
7435                 DEBUGADD(6,("adding form %s [%d] to buffer\n",
7436                         r->in.form_name, i));
7437
7438                 return WERR_OK;
7439
7440         default:
7441                 SAFE_FREE(list);
7442                 return WERR_UNKNOWN_LEVEL;
7443         }
7444 }
7445
7446 /****************************************************************************
7447 ****************************************************************************/
7448
7449 static WERROR fill_port_1(TALLOC_CTX *mem_ctx,
7450                           struct spoolss_PortInfo1 *r,
7451                           const char *name)
7452 {
7453         r->port_name = talloc_strdup(mem_ctx, name);
7454         W_ERROR_HAVE_NO_MEMORY(r->port_name);
7455
7456         return WERR_OK;
7457 }
7458
7459 /****************************************************************************
7460  TODO: This probably needs distinguish between TCP/IP and Local ports
7461  somehow.
7462 ****************************************************************************/
7463
7464 static WERROR fill_port_2(TALLOC_CTX *mem_ctx,
7465                           struct spoolss_PortInfo2 *r,
7466                           const char *name)
7467 {
7468         r->port_name = talloc_strdup(mem_ctx, name);
7469         W_ERROR_HAVE_NO_MEMORY(r->port_name);
7470
7471         r->monitor_name = talloc_strdup(mem_ctx, "Local Monitor");
7472         W_ERROR_HAVE_NO_MEMORY(r->monitor_name);
7473
7474         r->description = talloc_strdup(mem_ctx, SPL_LOCAL_PORT); /* FIXME */
7475         W_ERROR_HAVE_NO_MEMORY(r->description);
7476
7477         r->port_type = SPOOLSS_PORT_TYPE_WRITE;
7478         r->reserved = 0;
7479
7480         return WERR_OK;
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(TALLOC_CTX *mem_ctx,
7549                                 union spoolss_PortInfo **info_p,
7550                                 uint32_t offered,
7551                                 uint32_t *needed,
7552                                 uint32_t *count)
7553 {
7554         union spoolss_PortInfo *info = NULL;
7555         int i=0;
7556         WERROR result = WERR_OK;
7557         char **qlines = NULL;
7558         int numlines = 0;
7559
7560         result = enumports_hook(talloc_tos(), &numlines, &qlines );
7561         if (!W_ERROR_IS_OK(result)) {
7562                 goto out;
7563         }
7564
7565         if (numlines) {
7566                 info = TALLOC_ARRAY(mem_ctx, union spoolss_PortInfo, numlines);
7567                 if (!info) {
7568                         DEBUG(10,("Returning WERR_NOMEM\n"));
7569                         result = WERR_NOMEM;
7570                         goto out;
7571                 }
7572
7573                 for (i=0; i<numlines; i++) {
7574                         DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
7575                         result = fill_port_1(info, &info[i].info1, qlines[i]);
7576                         if (!W_ERROR_IS_OK(result)) {
7577                                 goto out;
7578                         }
7579                 }
7580         }
7581         TALLOC_FREE(qlines);
7582
7583         /* check the required size. */
7584         for (i=0; i<numlines; i++) {
7585                 DEBUGADD(6,("adding port [%d]'s size\n", i));
7586                 *needed += ndr_size_spoolss_PortInfo1(&info[i].info1, NULL, 0);
7587         }
7588
7589         if (*needed > offered) {
7590                 result = WERR_INSUFFICIENT_BUFFER;
7591                 goto out;
7592         }
7593
7594 out:
7595         if (!W_ERROR_IS_OK(result)) {
7596                 TALLOC_FREE(info);
7597                 TALLOC_FREE(qlines);
7598                 *count = 0;
7599                 *info_p = NULL;
7600                 return result;
7601         }
7602
7603         *info_p = info;
7604         *count = numlines;
7605
7606         return WERR_OK;
7607 }
7608
7609 /****************************************************************************
7610  enumports level 2.
7611 ****************************************************************************/
7612
7613 static WERROR enumports_level_2(TALLOC_CTX *mem_ctx,
7614                                 union spoolss_PortInfo **info_p,
7615                                 uint32_t offered,
7616                                 uint32_t *needed,
7617                                 uint32_t *count)
7618 {
7619         union spoolss_PortInfo *info = NULL;
7620         int i=0;
7621         WERROR result = WERR_OK;
7622         char **qlines = NULL;
7623         int numlines = 0;
7624
7625         result = enumports_hook(talloc_tos(), &numlines, &qlines );
7626         if (!W_ERROR_IS_OK(result)) {
7627                 goto out;
7628         }
7629
7630         if (numlines) {
7631                 info = TALLOC_ARRAY(mem_ctx, union spoolss_PortInfo, numlines);
7632                 if (!info) {
7633                         DEBUG(10,("Returning WERR_NOMEM\n"));
7634                         result = WERR_NOMEM;
7635                         goto out;
7636                 }
7637
7638                 for (i=0; i<numlines; i++) {
7639                         DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
7640                         result = fill_port_2(info, &info[i].info2, qlines[i]);
7641                         if (!W_ERROR_IS_OK(result)) {
7642                                 goto out;
7643                         }
7644                 }
7645         }
7646         TALLOC_FREE(qlines);
7647
7648         /* check the required size. */
7649         for (i=0; i<numlines; i++) {
7650                 DEBUGADD(6,("adding port [%d]'s size\n", i));
7651                 *needed += ndr_size_spoolss_PortInfo2(&info[i].info2, NULL, 0);
7652         }
7653
7654         if (*needed > offered) {
7655                 result = WERR_INSUFFICIENT_BUFFER;
7656                 goto out;
7657         }
7658
7659 out:
7660         if (!W_ERROR_IS_OK(result)) {
7661                 TALLOC_FREE(info);
7662                 TALLOC_FREE(qlines);
7663                 *count = 0;
7664                 *info_p = NULL;
7665                 return result;
7666         }
7667
7668         *info_p = info;
7669         *count = numlines;
7670
7671         return WERR_OK;
7672 }
7673
7674 /****************************************************************
7675  _spoolss_EnumPorts
7676 ****************************************************************/
7677
7678 WERROR _spoolss_EnumPorts(pipes_struct *p,
7679                           struct spoolss_EnumPorts *r)
7680 {
7681         /* that's an [in out] buffer */
7682
7683         if (!r->in.buffer && (r->in.offered != 0)) {
7684                 return WERR_INVALID_PARAM;
7685         }
7686
7687         DEBUG(4,("_spoolss_EnumPorts\n"));
7688
7689         *r->out.count = 0;
7690         *r->out.needed = 0;
7691         *r->out.info = NULL;
7692
7693         switch (r->in.level) {
7694         case 1:
7695                 return enumports_level_1(p->mem_ctx, r->out.info,
7696                                          r->in.offered, r->out.needed,
7697                                          r->out.count);
7698         case 2:
7699                 return enumports_level_2(p->mem_ctx, r->out.info,
7700                                          r->in.offered, r->out.needed,
7701                                          r->out.count);
7702         default:
7703                 return WERR_UNKNOWN_LEVEL;
7704         }
7705 }
7706
7707 /****************************************************************************
7708 ****************************************************************************/
7709
7710 static WERROR spoolss_addprinterex_level_2(pipes_struct *p,
7711                                            const char *server,
7712                                            struct spoolss_SetPrinterInfoCtr *info_ctr,
7713                                            struct spoolss_DeviceMode *devmode,
7714                                            struct security_descriptor *sec_desc,
7715                                            struct spoolss_UserLevelCtr *user_ctr,
7716                                            POLICY_HND *handle)
7717 {
7718         NT_PRINTER_INFO_LEVEL *printer = NULL;
7719         fstring name;
7720         int     snum;
7721         WERROR err = WERR_OK;
7722
7723         if ( !(printer = TALLOC_ZERO_P(NULL, NT_PRINTER_INFO_LEVEL)) ) {
7724                 DEBUG(0,("spoolss_addprinterex_level_2: malloc fail.\n"));
7725                 return WERR_NOMEM;
7726         }
7727
7728         /* convert from UNICODE to ASCII - this allocates the info_2 struct inside *printer.*/
7729         if (!convert_printer_info_new(info_ctr, printer)) {
7730                 free_a_printer(&printer, 2);
7731                 return WERR_NOMEM;
7732         }
7733
7734         /* check to see if the printer already exists */
7735
7736         if ((snum = print_queue_snum(printer->info_2->sharename)) != -1) {
7737                 DEBUG(5, ("spoolss_addprinterex_level_2: Attempted to add a printer named [%s] when one already existed!\n",
7738                         printer->info_2->sharename));
7739                 free_a_printer(&printer, 2);
7740                 return WERR_PRINTER_ALREADY_EXISTS;
7741         }
7742
7743         /* FIXME!!!  smbd should check to see if the driver is installed before
7744            trying to add a printer like this  --jerry */
7745
7746         if (*lp_addprinter_cmd() ) {
7747                 if ( !add_printer_hook(p->mem_ctx, p->server_info->ptok,
7748                                        printer) ) {
7749                         free_a_printer(&printer,2);
7750                         return WERR_ACCESS_DENIED;
7751                 }
7752         } else {
7753                 DEBUG(0,("spoolss_addprinterex_level_2: add printer for printer %s called and no"
7754                         "smb.conf parameter \"addprinter command\" is defined. This"
7755                         "parameter must exist for this call to succeed\n",
7756                         printer->info_2->sharename ));
7757         }
7758
7759         /* use our primary netbios name since get_a_printer() will convert
7760            it to what the client expects on a case by case basis */
7761
7762         slprintf(name, sizeof(name)-1, "\\\\%s\\%s", global_myname(),
7763              printer->info_2->sharename);
7764
7765
7766         if ((snum = print_queue_snum(printer->info_2->sharename)) == -1) {
7767                 free_a_printer(&printer,2);
7768                 return WERR_ACCESS_DENIED;
7769         }
7770
7771         /* you must be a printer admin to add a new printer */
7772         if (!print_access_check(NULL, snum, PRINTER_ACCESS_ADMINISTER)) {
7773                 free_a_printer(&printer,2);
7774                 return WERR_ACCESS_DENIED;
7775         }
7776
7777         /*
7778          * Do sanity check on the requested changes for Samba.
7779          */
7780
7781         if (!check_printer_ok(printer->info_2, snum)) {
7782                 free_a_printer(&printer,2);
7783                 return WERR_INVALID_PARAM;
7784         }
7785
7786         /*
7787          * When a printer is created, the drivername bound to the printer is used
7788          * to lookup previously saved driver initialization info, which is then
7789          * bound to the new printer, simulating what happens in the Windows arch.
7790          */
7791
7792         if (!devmode)
7793         {
7794                 set_driver_init(printer, 2);
7795         }
7796         else
7797         {
7798                 /* A valid devmode was included, convert and link it
7799                 */
7800                 DEBUGADD(10, ("spoolss_addprinterex_level_2: devmode included, converting\n"));
7801
7802                 if (!convert_devicemode_new(printer->info_2->printername,
7803                                             devmode,
7804                                             &printer->info_2->devmode))
7805                         return  WERR_NOMEM;
7806         }
7807
7808         /* write the ASCII on disk */
7809         err = mod_a_printer(printer, 2);
7810         if (!W_ERROR_IS_OK(err)) {
7811                 free_a_printer(&printer,2);
7812                 return err;
7813         }
7814
7815         if (!open_printer_hnd(p, handle, name, PRINTER_ACCESS_ADMINISTER)) {
7816                 /* Handle open failed - remove addition. */
7817                 del_a_printer(printer->info_2->sharename);
7818                 free_a_printer(&printer,2);
7819                 ZERO_STRUCTP(handle);
7820                 return WERR_ACCESS_DENIED;
7821         }
7822
7823         update_c_setprinter(False);
7824         free_a_printer(&printer,2);
7825
7826         return WERR_OK;
7827 }
7828
7829 /****************************************************************
7830  _spoolss_AddPrinterEx
7831 ****************************************************************/
7832
7833 WERROR _spoolss_AddPrinterEx(pipes_struct *p,
7834                              struct spoolss_AddPrinterEx *r)
7835 {
7836         switch (r->in.info_ctr->level) {
7837         case 1:
7838                 /* we don't handle yet */
7839                 /* but I know what to do ... */
7840                 return WERR_UNKNOWN_LEVEL;
7841         case 2:
7842                 return spoolss_addprinterex_level_2(p, r->in.server,
7843                                                     r->in.info_ctr,
7844                                                     r->in.devmode_ctr->devmode,
7845                                                     r->in.secdesc_ctr->sd,
7846                                                     r->in.userlevel_ctr,
7847                                                     r->out.handle);
7848         default:
7849                 return WERR_UNKNOWN_LEVEL;
7850         }
7851 }
7852
7853 /****************************************************************
7854  _spoolss_AddPrinterDriver
7855 ****************************************************************/
7856
7857 WERROR _spoolss_AddPrinterDriver(pipes_struct *p,
7858                                  struct spoolss_AddPrinterDriver *r)
7859 {
7860         uint32_t level = r->in.info_ctr->level;
7861         struct spoolss_AddDriverInfoCtr *info = r->in.info_ctr;
7862         WERROR err = WERR_OK;
7863         NT_PRINTER_DRIVER_INFO_LEVEL driver;
7864         fstring driver_name;
7865         uint32 version;
7866         const char *fn;
7867
7868         switch (p->hdr_req.opnum) {
7869                 case NDR_SPOOLSS_ADDPRINTERDRIVER:
7870                         fn = "_spoolss_AddPrinterDriver";
7871                         break;
7872                 case NDR_SPOOLSS_ADDPRINTERDRIVEREX:
7873                         fn = "_spoolss_AddPrinterDriverEx";
7874                         break;
7875                 default:
7876                         return WERR_INVALID_PARAM;
7877         }
7878
7879
7880         /* FIXME */
7881         if (level != 3 && level != 6) {
7882                 /* Clever hack from Martin Zielinski <mz@seh.de>
7883                  * to allow downgrade from level 8 (Vista).
7884                  */
7885                 DEBUG(0,("%s: level %d not yet implemented\n", fn, level));
7886                 return WERR_UNKNOWN_LEVEL;
7887         }
7888
7889         ZERO_STRUCT(driver);
7890
7891         if (!convert_printer_driver_info(info, &driver, level)) {
7892                 err = WERR_NOMEM;
7893                 goto done;
7894         }
7895
7896         DEBUG(5,("Cleaning driver's information\n"));
7897         err = clean_up_driver_struct(p, driver, level);
7898         if (!W_ERROR_IS_OK(err))
7899                 goto done;
7900
7901         DEBUG(5,("Moving driver to final destination\n"));
7902         if( !W_ERROR_IS_OK(err = move_driver_to_download_area(p, driver, level,
7903                                                               &err)) ) {
7904                 goto done;
7905         }
7906
7907         if (add_a_printer_driver(driver, level)!=0) {
7908                 err = WERR_ACCESS_DENIED;
7909                 goto done;
7910         }
7911
7912         switch(level) {
7913         case 3:
7914                 fstrcpy(driver_name,
7915                         driver.info_3->name ? driver.info_3->name : "");
7916                 break;
7917         case 6:
7918                 fstrcpy(driver_name,
7919                         driver.info_6->name ?  driver.info_6->name : "");
7920                 break;
7921         }
7922
7923         /*
7924          * I think this is where he DrvUpgradePrinter() hook would be
7925          * be called in a driver's interface DLL on a Windows NT 4.0/2k
7926          * server.  Right now, we just need to send ourselves a message
7927          * to update each printer bound to this driver.   --jerry
7928          */
7929
7930         if (!srv_spoolss_drv_upgrade_printer(driver_name)) {
7931                 DEBUG(0,("%s: Failed to send message about upgrading driver [%s]!\n",
7932                         fn, driver_name));
7933         }
7934
7935         /*
7936          * Based on the version (e.g. driver destination dir: 0=9x,2=Nt/2k,3=2k/Xp),
7937          * decide if the driver init data should be deleted. The rules are:
7938          *  1) never delete init data if it is a 9x driver, they don't use it anyway
7939          *  2) delete init data only if there is no 2k/Xp driver
7940          *  3) always delete init data
7941          * The generalized rule is always use init data from the highest order driver.
7942          * It is necessary to follow the driver install by an initialization step to
7943          * finish off this process.
7944         */
7945         if (level == 3)
7946                 version = driver.info_3->cversion;
7947         else if (level == 6)
7948                 version = driver.info_6->version;
7949         else
7950                 version = -1;
7951         switch (version) {
7952                 /*
7953                  * 9x printer driver - never delete init data
7954                 */
7955                 case 0:
7956                         DEBUG(10,("%s: init data not deleted for 9x driver [%s]\n",
7957                                 fn, driver_name));
7958                         break;
7959
7960                 /*
7961                  * Nt or 2k (compatiblity mode) printer driver - only delete init data if
7962                  * there is no 2k/Xp driver init data for this driver name.
7963                 */
7964                 case 2:
7965                 {
7966                         NT_PRINTER_DRIVER_INFO_LEVEL driver1;
7967
7968                         if (!W_ERROR_IS_OK(get_a_printer_driver(&driver1, 3, driver_name, "Windows NT x86", 3))) {
7969                                 /*
7970                                  * No 2k/Xp driver found, delete init data (if any) for the new Nt driver.
7971                                 */
7972                                 if (!del_driver_init(driver_name))
7973                                         DEBUG(6,("%s: del_driver_init(%s) Nt failed!\n",
7974                                                 fn, driver_name));
7975                         } else {
7976                                 /*
7977                                  * a 2k/Xp driver was found, don't delete init data because Nt driver will use it.
7978                                 */
7979                                 free_a_printer_driver(driver1,3);
7980                                 DEBUG(10,("%s: init data not deleted for Nt driver [%s]\n",
7981                                         fn, driver_name));
7982                         }
7983                 }
7984                 break;
7985
7986                 /*
7987                  * 2k or Xp printer driver - always delete init data
7988                 */
7989                 case 3:
7990                         if (!del_driver_init(driver_name))
7991                                 DEBUG(6,("%s: del_driver_init(%s) 2k/Xp failed!\n",
7992                                         fn, driver_name));
7993                         break;
7994
7995                 default:
7996                         DEBUG(0,("%s: invalid level=%d\n", fn, level));
7997                         break;
7998         }
7999
8000
8001 done:
8002         free_a_printer_driver(driver, level);
8003         return err;
8004 }
8005
8006 /****************************************************************
8007  _spoolss_AddPrinterDriverEx
8008 ****************************************************************/
8009
8010 WERROR _spoolss_AddPrinterDriverEx(pipes_struct *p,
8011                                    struct spoolss_AddPrinterDriverEx *r)
8012 {
8013         struct spoolss_AddPrinterDriver a;
8014
8015         /*
8016          * we only support the semantics of AddPrinterDriver()
8017          * i.e. only copy files that are newer than existing ones
8018          */
8019
8020         if (r->in.flags != APD_COPY_NEW_FILES) {
8021                 return WERR_ACCESS_DENIED;
8022         }
8023
8024         a.in.servername         = r->in.servername;
8025         a.in.info_ctr           = r->in.info_ctr;
8026
8027         return _spoolss_AddPrinterDriver(p, &a);
8028 }
8029
8030 /****************************************************************************
8031 ****************************************************************************/
8032
8033 struct _spoolss_paths {
8034         int type;
8035         const char *share;
8036         const char *dir;
8037 };
8038
8039 enum { SPOOLSS_DRIVER_PATH, SPOOLSS_PRTPROCS_PATH };
8040
8041 static const struct _spoolss_paths spoolss_paths[]= {
8042         { SPOOLSS_DRIVER_PATH,          "print$",       "DRIVERS" },
8043         { SPOOLSS_PRTPROCS_PATH,        "prnproc$",     "PRTPROCS" }
8044 };
8045
8046 static WERROR compose_spoolss_server_path(TALLOC_CTX *mem_ctx,
8047                                           const char *servername,
8048                                           const char *environment,
8049                                           int component,
8050                                           char **path)
8051 {
8052         const char *pservername = NULL;
8053         const char *long_archi = SPOOLSS_ARCHITECTURE_NT_X86;
8054         const char *short_archi;
8055
8056         *path = NULL;
8057
8058         /* environment may be empty */
8059         if (environment && strlen(environment)) {
8060                 long_archi = environment;
8061         }
8062
8063         /* servername may be empty */
8064         if (servername && strlen(servername)) {
8065                 pservername = canon_servername(servername);
8066
8067                 if (!is_myname_or_ipaddr(pservername)) {
8068                         return WERR_INVALID_PARAM;
8069                 }
8070         }
8071
8072         if (!(short_archi = get_short_archi(long_archi))) {
8073                 return WERR_INVALID_ENVIRONMENT;
8074         }
8075
8076         switch (component) {
8077         case SPOOLSS_PRTPROCS_PATH:
8078         case SPOOLSS_DRIVER_PATH:
8079                 if (pservername) {
8080                         *path = talloc_asprintf(mem_ctx,
8081                                         "\\\\%s\\%s\\%s",
8082                                         pservername,
8083                                         spoolss_paths[component].share,
8084                                         short_archi);
8085                 } else {
8086                         *path = talloc_asprintf(mem_ctx, "%s\\%s\\%s",
8087                                         SPOOLSS_DEFAULT_SERVER_PATH,
8088                                         spoolss_paths[component].dir,
8089                                         short_archi);
8090                 }
8091                 break;
8092         default:
8093                 return WERR_INVALID_PARAM;
8094         }
8095
8096         if (!*path) {
8097                 return WERR_NOMEM;
8098         }
8099
8100         return WERR_OK;
8101 }
8102
8103 /****************************************************************************
8104 ****************************************************************************/
8105
8106 static WERROR getprinterdriverdir_level_1(TALLOC_CTX *mem_ctx,
8107                                           const char *servername,
8108                                           const char *environment,
8109                                           struct spoolss_DriverDirectoryInfo1 *r,
8110                                           uint32_t offered,
8111                                           uint32_t *needed)
8112 {
8113         WERROR werr;
8114         char *path = NULL;
8115
8116         werr = compose_spoolss_server_path(mem_ctx,
8117                                            servername,
8118                                            environment,
8119                                            SPOOLSS_DRIVER_PATH,
8120                                            &path);
8121         if (!W_ERROR_IS_OK(werr)) {
8122                 return werr;
8123         }
8124
8125         DEBUG(4,("printer driver directory: [%s]\n", path));
8126
8127         r->directory_name = path;
8128
8129         *needed += ndr_size_spoolss_DriverDirectoryInfo1(r, NULL, 0);
8130
8131         if (*needed > offered) {
8132                 talloc_free(path);
8133                 return WERR_INSUFFICIENT_BUFFER;
8134         }
8135
8136         return WERR_OK;
8137 }
8138
8139 /****************************************************************
8140  _spoolss_GetPrinterDriverDirectory
8141 ****************************************************************/
8142
8143 WERROR _spoolss_GetPrinterDriverDirectory(pipes_struct *p,
8144                                           struct spoolss_GetPrinterDriverDirectory *r)
8145 {
8146         WERROR werror;
8147
8148         /* that's an [in out] buffer */
8149
8150         if (!r->in.buffer && (r->in.offered != 0)) {
8151                 return WERR_INVALID_PARAM;
8152         }
8153
8154         DEBUG(5,("_spoolss_GetPrinterDriverDirectory: level %d\n",
8155                 r->in.level));
8156
8157         *r->out.needed = 0;
8158
8159         /* r->in.level is ignored */
8160
8161         werror = getprinterdriverdir_level_1(p->mem_ctx,
8162                                              r->in.server,
8163                                              r->in.environment,
8164                                              &r->out.info->info1,
8165                                              r->in.offered,
8166                                              r->out.needed);
8167         if (!W_ERROR_IS_OK(werror)) {
8168                 TALLOC_FREE(r->out.info);
8169         }
8170
8171         return werror;
8172 }
8173
8174 /****************************************************************************
8175 ****************************************************************************/
8176
8177 WERROR _spoolss_enumprinterdata(pipes_struct *p, SPOOL_Q_ENUMPRINTERDATA *q_u, SPOOL_R_ENUMPRINTERDATA *r_u)
8178 {
8179         POLICY_HND *handle = &q_u->handle;
8180         uint32 idx               = q_u->index;
8181         uint32 in_value_len      = q_u->valuesize;
8182         uint32 in_data_len       = q_u->datasize;
8183         uint32 *out_max_value_len = &r_u->valuesize;
8184         uint16 **out_value       = &r_u->value;
8185         uint32 *out_value_len    = &r_u->realvaluesize;
8186         uint32 *out_type         = &r_u->type;
8187         uint32 *out_max_data_len = &r_u->datasize;
8188         uint8  **data_out        = &r_u->data;
8189         uint32 *out_data_len     = &r_u->realdatasize;
8190
8191         NT_PRINTER_INFO_LEVEL *printer = NULL;
8192
8193         uint32          biggest_valuesize;
8194         uint32          biggest_datasize;
8195         uint32          data_len;
8196         Printer_entry   *Printer = find_printer_index_by_hnd(p, handle);
8197         int             snum;
8198         WERROR          result;
8199         REGISTRY_VALUE  *val = NULL;
8200         NT_PRINTER_DATA *p_data;
8201         int             i, key_index, num_values;
8202         int             name_length;
8203
8204         *out_type = 0;
8205
8206         *out_max_data_len = 0;
8207         *data_out         = NULL;
8208         *out_data_len     = 0;
8209
8210         DEBUG(5,("spoolss_enumprinterdata\n"));
8211
8212         if (!Printer) {
8213                 DEBUG(2,("_spoolss_enumprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8214                 return WERR_BADFID;
8215         }
8216
8217         if (!get_printer_snum(p,handle, &snum, NULL))
8218                 return WERR_BADFID;
8219
8220         result = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8221         if (!W_ERROR_IS_OK(result))
8222                 return result;
8223
8224         p_data = printer->info_2->data;
8225         key_index = lookup_printerkey( p_data, SPOOL_PRINTERDATA_KEY );
8226
8227         result = WERR_OK;
8228
8229         /*
8230          * The NT machine wants to know the biggest size of value and data
8231          *
8232          * cf: MSDN EnumPrinterData remark section
8233          */
8234
8235         if ( !in_value_len && !in_data_len && (key_index != -1) )
8236         {
8237                 DEBUGADD(6,("Activating NT mega-hack to find sizes\n"));
8238
8239                 biggest_valuesize = 0;
8240                 biggest_datasize  = 0;
8241
8242                 num_values = regval_ctr_numvals( p_data->keys[key_index].values );
8243
8244                 for ( i=0; i<num_values; i++ )
8245                 {
8246                         val = regval_ctr_specific_value( p_data->keys[key_index].values, i );
8247
8248                         name_length = strlen(val->valuename);
8249                         if ( strlen(val->valuename) > biggest_valuesize )
8250                                 biggest_valuesize = name_length;
8251
8252                         if ( val->size > biggest_datasize )
8253                                 biggest_datasize = val->size;
8254
8255                         DEBUG(6,("current values: [%d], [%d]\n", biggest_valuesize,
8256                                 biggest_datasize));
8257                 }
8258
8259                 /* the value is an UNICODE string but real_value_size is the length
8260                    in bytes including the trailing 0 */
8261
8262                 *out_value_len = 2 * (1+biggest_valuesize);
8263                 *out_data_len  = biggest_datasize;
8264
8265                 DEBUG(6,("final values: [%d], [%d]\n", *out_value_len, *out_data_len));
8266
8267                 goto done;
8268         }
8269
8270         /*
8271          * the value len is wrong in NT sp3
8272          * that's the number of bytes not the number of unicode chars
8273          */
8274
8275         if ( key_index != -1 )
8276                 val = regval_ctr_specific_value( p_data->keys[key_index].values, idx );
8277
8278         if ( !val )
8279         {
8280
8281                 /* out_value should default to "" or else NT4 has
8282                    problems unmarshalling the response */
8283
8284                 *out_max_value_len=(in_value_len/sizeof(uint16));
8285
8286                 if (in_value_len) {
8287                         if((*out_value=(uint16 *)TALLOC_ZERO(p->mem_ctx, in_value_len*sizeof(uint8))) == NULL)
8288                         {
8289                                 result = WERR_NOMEM;
8290                                 goto done;
8291                         }
8292                         *out_value_len = (uint32)rpcstr_push((char *)*out_value, "", in_value_len, 0);
8293                 } else {
8294                         *out_value=NULL;
8295                         *out_value_len = 0;
8296                 }
8297
8298                 /* the data is counted in bytes */
8299
8300                 *out_max_data_len = in_data_len;
8301                 *out_data_len     = in_data_len;
8302
8303                 /* only allocate when given a non-zero data_len */
8304
8305                 if ( in_data_len && ((*data_out=(uint8 *)TALLOC_ZERO(p->mem_ctx, in_data_len*sizeof(uint8))) == NULL) )
8306                 {
8307                         result = WERR_NOMEM;
8308                         goto done;
8309                 }
8310
8311                 result = WERR_NO_MORE_ITEMS;
8312         }
8313         else
8314         {
8315                 /*
8316                  * the value is:
8317                  * - counted in bytes in the request
8318                  * - counted in UNICODE chars in the max reply
8319                  * - counted in bytes in the real size
8320                  *
8321                  * take a pause *before* coding not *during* coding
8322                  */
8323
8324                 /* name */
8325                 *out_max_value_len=(in_value_len/sizeof(uint16));
8326                 if (in_value_len) {
8327                         if ( (*out_value = (uint16 *)TALLOC_ZERO(p->mem_ctx, in_value_len*sizeof(uint8))) == NULL )
8328                         {
8329                                 result = WERR_NOMEM;
8330                                 goto done;
8331                         }
8332
8333                         *out_value_len = (uint32)rpcstr_push((char *)*out_value, regval_name(val), (size_t)in_value_len, 0);
8334                 } else {
8335                         *out_value = NULL;
8336                         *out_value_len = 0;
8337                 }
8338
8339                 /* type */
8340
8341                 *out_type = regval_type( val );
8342
8343                 /* data - counted in bytes */
8344
8345                 *out_max_data_len = in_data_len;
8346                 if ( in_data_len && (*data_out = (uint8 *)TALLOC_ZERO(p->mem_ctx, in_data_len*sizeof(uint8))) == NULL)
8347                 {
8348                         result = WERR_NOMEM;
8349                         goto done;
8350                 }
8351                 data_len = regval_size(val);
8352                 if ( *data_out && data_len )
8353                         memcpy( *data_out, regval_data_p(val), data_len );
8354                 *out_data_len = data_len;
8355         }
8356
8357 done:
8358         free_a_printer(&printer, 2);
8359         return result;
8360 }
8361
8362 /****************************************************************************
8363 ****************************************************************************/
8364
8365 WERROR _spoolss_setprinterdata( pipes_struct *p, SPOOL_Q_SETPRINTERDATA *q_u, SPOOL_R_SETPRINTERDATA *r_u)
8366 {
8367         POLICY_HND              *handle = &q_u->handle;
8368         UNISTR2                 *value = &q_u->value;
8369         uint32                  type = q_u->type;
8370         uint8                   *data = q_u->data;
8371         uint32                  real_len = q_u->real_len;
8372
8373         NT_PRINTER_INFO_LEVEL   *printer = NULL;
8374         int                     snum=0;
8375         WERROR                  status = WERR_OK;
8376         Printer_entry           *Printer=find_printer_index_by_hnd(p, handle);
8377         fstring                 valuename;
8378
8379         DEBUG(5,("spoolss_setprinterdata\n"));
8380
8381         if (!Printer) {
8382                 DEBUG(2,("_spoolss_setprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8383                 return WERR_BADFID;
8384         }
8385
8386         if ( Printer->printer_type == SPLHND_SERVER ) {
8387                 DEBUG(10,("_spoolss_setprinterdata: Not implemented for server handles yet\n"));
8388                 return WERR_INVALID_PARAM;
8389         }
8390
8391         if (!get_printer_snum(p,handle, &snum, NULL))
8392                 return WERR_BADFID;
8393
8394         /*
8395          * Access check : NT returns "access denied" if you make a
8396          * SetPrinterData call without the necessary privildge.
8397          * we were originally returning OK if nothing changed
8398          * which made Win2k issue **a lot** of SetPrinterData
8399          * when connecting to a printer  --jerry
8400          */
8401
8402         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER)
8403         {
8404                 DEBUG(3, ("_spoolss_setprinterdata: change denied by handle access permissions\n"));
8405                 status = WERR_ACCESS_DENIED;
8406                 goto done;
8407         }
8408
8409         status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8410         if (!W_ERROR_IS_OK(status))
8411                 return status;
8412
8413         unistr2_to_ascii(valuename, value, sizeof(valuename));
8414
8415         /*
8416          * When client side code sets a magic printer data key, detect it and save
8417          * the current printer data and the magic key's data (its the DEVMODE) for
8418          * future printer/driver initializations.
8419          */
8420         if ( (type == REG_BINARY) && strequal( valuename, PHANTOM_DEVMODE_KEY))
8421         {
8422                 /* Set devmode and printer initialization info */
8423                 status = save_driver_init( printer, 2, data, real_len );
8424
8425                 srv_spoolss_reset_printerdata( printer->info_2->drivername );
8426         }
8427         else
8428         {
8429         status = set_printer_dataex( printer, SPOOL_PRINTERDATA_KEY, valuename,
8430                                         type, data, real_len );
8431                 if ( W_ERROR_IS_OK(status) )
8432                         status = mod_a_printer(printer, 2);
8433         }
8434
8435 done:
8436         free_a_printer(&printer, 2);
8437
8438         return status;
8439 }
8440
8441 /****************************************************************
8442  _spoolss_ResetPrinter
8443 ****************************************************************/
8444
8445 WERROR _spoolss_ResetPrinter(pipes_struct *p,
8446                              struct spoolss_ResetPrinter *r)
8447 {
8448         POLICY_HND      *handle = r->in.handle;
8449         Printer_entry   *Printer=find_printer_index_by_hnd(p, handle);
8450         int             snum;
8451
8452         DEBUG(5,("_spoolss_ResetPrinter\n"));
8453
8454         /*
8455          * All we do is to check to see if the handle and queue is valid.
8456          * This call really doesn't mean anything to us because we only
8457          * support RAW printing.   --jerry
8458          */
8459
8460         if (!Printer) {
8461                 DEBUG(2,("_spoolss_ResetPrinter: Invalid handle (%s:%u:%u).\n",
8462                         OUR_HANDLE(handle)));
8463                 return WERR_BADFID;
8464         }
8465
8466         if (!get_printer_snum(p,handle, &snum, NULL))
8467                 return WERR_BADFID;
8468
8469
8470         /* blindly return success */
8471         return WERR_OK;
8472 }
8473
8474 /****************************************************************
8475  _spoolss_DeletePrinterData
8476 ****************************************************************/
8477
8478 WERROR _spoolss_DeletePrinterData(pipes_struct *p,
8479                                   struct spoolss_DeletePrinterData *r)
8480 {
8481         POLICY_HND      *handle = r->in.handle;
8482         NT_PRINTER_INFO_LEVEL   *printer = NULL;
8483         int             snum=0;
8484         WERROR          status = WERR_OK;
8485         Printer_entry   *Printer=find_printer_index_by_hnd(p, handle);
8486
8487         DEBUG(5,("_spoolss_DeletePrinterData\n"));
8488
8489         if (!Printer) {
8490                 DEBUG(2,("_spoolss_DeletePrinterData: Invalid handle (%s:%u:%u).\n",
8491                         OUR_HANDLE(handle)));
8492                 return WERR_BADFID;
8493         }
8494
8495         if (!get_printer_snum(p, handle, &snum, NULL))
8496                 return WERR_BADFID;
8497
8498         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
8499                 DEBUG(3, ("_spoolss_DeletePrinterData: "
8500                         "printer properties change denied by handle\n"));
8501                 return WERR_ACCESS_DENIED;
8502         }
8503
8504         status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8505         if (!W_ERROR_IS_OK(status))
8506                 return status;
8507
8508         if (!r->in.value_name) {
8509                 free_a_printer(&printer, 2);
8510                 return WERR_NOMEM;
8511         }
8512
8513         status = delete_printer_dataex( printer, SPOOL_PRINTERDATA_KEY,
8514                                         r->in.value_name );
8515
8516         if ( W_ERROR_IS_OK(status) )
8517                 mod_a_printer( printer, 2 );
8518
8519         free_a_printer(&printer, 2);
8520
8521         return status;
8522 }
8523
8524 /****************************************************************
8525  _spoolss_AddForm
8526 ****************************************************************/
8527
8528 WERROR _spoolss_AddForm(pipes_struct *p,
8529                         struct spoolss_AddForm *r)
8530 {
8531         POLICY_HND *handle = r->in.handle;
8532         struct spoolss_AddFormInfo1 *form = r->in.info.info1;
8533         nt_forms_struct tmpForm;
8534         int snum;
8535         WERROR status = WERR_OK;
8536         NT_PRINTER_INFO_LEVEL *printer = NULL;
8537
8538         int count=0;
8539         nt_forms_struct *list=NULL;
8540         Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8541
8542         DEBUG(5,("_spoolss_AddForm\n"));
8543
8544         if (!Printer) {
8545                 DEBUG(2,("_spoolss_AddForm: Invalid handle (%s:%u:%u).\n",
8546                         OUR_HANDLE(handle)));
8547                 return WERR_BADFID;
8548         }
8549
8550
8551         /* forms can be added on printer of on the print server handle */
8552
8553         if ( Printer->printer_type == SPLHND_PRINTER )
8554         {
8555                 if (!get_printer_snum(p,handle, &snum, NULL))
8556                         return WERR_BADFID;
8557
8558                 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8559                 if (!W_ERROR_IS_OK(status))
8560                         goto done;
8561         }
8562
8563         if ( !(Printer->access_granted & (PRINTER_ACCESS_ADMINISTER|SERVER_ACCESS_ADMINISTER)) ) {
8564                 DEBUG(2,("_spoolss_addform: denied by handle permissions.\n"));
8565                 status = WERR_ACCESS_DENIED;
8566                 goto done;
8567         }
8568
8569         /* can't add if builtin */
8570
8571         if (get_a_builtin_ntform_by_string(form->form_name, &tmpForm)) {
8572                 status = WERR_FILE_EXISTS;
8573                 goto done;
8574         }
8575
8576         count = get_ntforms(&list);
8577
8578         if(!add_a_form(&list, form, &count)) {
8579                 status =  WERR_NOMEM;
8580                 goto done;
8581         }
8582
8583         write_ntforms(&list, count);
8584
8585         /*
8586          * ChangeID must always be set if this is a printer
8587          */
8588
8589         if ( Printer->printer_type == SPLHND_PRINTER )
8590                 status = mod_a_printer(printer, 2);
8591
8592 done:
8593         if ( printer )
8594                 free_a_printer(&printer, 2);
8595         SAFE_FREE(list);
8596
8597         return status;
8598 }
8599
8600 /****************************************************************
8601  _spoolss_DeleteForm
8602 ****************************************************************/
8603
8604 WERROR _spoolss_DeleteForm(pipes_struct *p,
8605                            struct spoolss_DeleteForm *r)
8606 {
8607         POLICY_HND *handle = r->in.handle;
8608         const char *form_name = r->in.form_name;
8609         nt_forms_struct tmpForm;
8610         int count=0;
8611         nt_forms_struct *list=NULL;
8612         Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8613         int snum;
8614         WERROR status = WERR_OK;
8615         NT_PRINTER_INFO_LEVEL *printer = NULL;
8616
8617         DEBUG(5,("_spoolss_DeleteForm\n"));
8618
8619         if (!Printer) {
8620                 DEBUG(2,("_spoolss_DeleteForm: Invalid handle (%s:%u:%u).\n",
8621                         OUR_HANDLE(handle)));
8622                 return WERR_BADFID;
8623         }
8624
8625         /* forms can be deleted on printer of on the print server handle */
8626
8627         if ( Printer->printer_type == SPLHND_PRINTER )
8628         {
8629                 if (!get_printer_snum(p,handle, &snum, NULL))
8630                         return WERR_BADFID;
8631
8632                 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8633                 if (!W_ERROR_IS_OK(status))
8634                         goto done;
8635         }
8636
8637         if ( !(Printer->access_granted & (PRINTER_ACCESS_ADMINISTER|SERVER_ACCESS_ADMINISTER)) ) {
8638                 DEBUG(2,("_spoolss_DeleteForm: denied by handle permissions.\n"));
8639                 status = WERR_ACCESS_DENIED;
8640                 goto done;
8641         }
8642
8643         /* can't delete if builtin */
8644
8645         if (get_a_builtin_ntform_by_string(form_name,&tmpForm)) {
8646                 status = WERR_INVALID_PARAM;
8647                 goto done;
8648         }
8649
8650         count = get_ntforms(&list);
8651
8652         if ( !delete_a_form(&list, form_name, &count, &status ))
8653                 goto done;
8654
8655         /*
8656          * ChangeID must always be set if this is a printer
8657          */
8658
8659         if ( Printer->printer_type == SPLHND_PRINTER )
8660                 status = mod_a_printer(printer, 2);
8661
8662 done:
8663         if ( printer )
8664                 free_a_printer(&printer, 2);
8665         SAFE_FREE(list);
8666
8667         return status;
8668 }
8669
8670 /****************************************************************
8671  _spoolss_SetForm
8672 ****************************************************************/
8673
8674 WERROR _spoolss_SetForm(pipes_struct *p,
8675                         struct spoolss_SetForm *r)
8676 {
8677         POLICY_HND *handle = r->in.handle;
8678         struct spoolss_AddFormInfo1 *form = r->in.info.info1;
8679         nt_forms_struct tmpForm;
8680         int snum;
8681         WERROR status = WERR_OK;
8682         NT_PRINTER_INFO_LEVEL *printer = NULL;
8683
8684         int count=0;
8685         nt_forms_struct *list=NULL;
8686         Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8687
8688         DEBUG(5,("_spoolss_SetForm\n"));
8689
8690         if (!Printer) {
8691                 DEBUG(2,("_spoolss_SetForm: Invalid handle (%s:%u:%u).\n",
8692                         OUR_HANDLE(handle)));
8693                 return WERR_BADFID;
8694         }
8695
8696         /* forms can be modified on printer of on the print server handle */
8697
8698         if ( Printer->printer_type == SPLHND_PRINTER )
8699         {
8700                 if (!get_printer_snum(p,handle, &snum, NULL))
8701                         return WERR_BADFID;
8702
8703                 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8704                 if (!W_ERROR_IS_OK(status))
8705                         goto done;
8706         }
8707
8708         if ( !(Printer->access_granted & (PRINTER_ACCESS_ADMINISTER|SERVER_ACCESS_ADMINISTER)) ) {
8709                 DEBUG(2,("_spoolss_SetForm: denied by handle permissions\n"));
8710                 status = WERR_ACCESS_DENIED;
8711                 goto done;
8712         }
8713
8714         /* can't set if builtin */
8715         if (get_a_builtin_ntform_by_string(form->form_name, &tmpForm)) {
8716                 status = WERR_INVALID_PARAM;
8717                 goto done;
8718         }
8719
8720         count = get_ntforms(&list);
8721         update_a_form(&list, form, count);
8722         write_ntforms(&list, count);
8723
8724         /*
8725          * ChangeID must always be set if this is a printer
8726          */
8727
8728         if ( Printer->printer_type == SPLHND_PRINTER )
8729                 status = mod_a_printer(printer, 2);
8730
8731
8732 done:
8733         if ( printer )
8734                 free_a_printer(&printer, 2);
8735         SAFE_FREE(list);
8736
8737         return status;
8738 }
8739
8740 /****************************************************************************
8741  fill_print_processor1
8742 ****************************************************************************/
8743
8744 static WERROR fill_print_processor1(TALLOC_CTX *mem_ctx,
8745                                     struct spoolss_PrintProcessorInfo1 *r,
8746                                     const char *print_processor_name)
8747 {
8748         r->print_processor_name = talloc_strdup(mem_ctx, print_processor_name);
8749         W_ERROR_HAVE_NO_MEMORY(r->print_processor_name);
8750
8751         return WERR_OK;
8752 }
8753
8754 /****************************************************************************
8755  enumprintprocessors level 1.
8756 ****************************************************************************/
8757
8758 static WERROR enumprintprocessors_level_1(TALLOC_CTX *mem_ctx,
8759                                           union spoolss_PrintProcessorInfo **info_p,
8760                                           uint32_t offered,
8761                                           uint32_t *needed,
8762                                           uint32_t *count)
8763 {
8764         union spoolss_PrintProcessorInfo *info;
8765         WERROR result;
8766
8767         info = TALLOC_ARRAY(mem_ctx, union spoolss_PrintProcessorInfo, 1);
8768         W_ERROR_HAVE_NO_MEMORY(info);
8769
8770         *count = 1;
8771
8772         result = fill_print_processor1(info, &info[0].info1, "winprint");
8773         if (!W_ERROR_IS_OK(result)) {
8774                 goto out;
8775         }
8776
8777         *needed += ndr_size_spoolss_PrintProcessorInfo1(&info[0].info1, NULL, 0);
8778
8779         if (*needed > offered) {
8780                 result = WERR_INSUFFICIENT_BUFFER;
8781                 goto out;
8782         }
8783
8784  out:
8785         if (!W_ERROR_IS_OK(result)) {
8786                 TALLOC_FREE(info);
8787                 *count = 0;
8788                 return result;
8789         }
8790
8791         *info_p = info;
8792
8793         return WERR_OK;
8794 }
8795
8796 /****************************************************************
8797  _spoolss_EnumPrintProcessors
8798 ****************************************************************/
8799
8800 WERROR _spoolss_EnumPrintProcessors(pipes_struct *p,
8801                                     struct spoolss_EnumPrintProcessors *r)
8802 {
8803         /* that's an [in out] buffer */
8804
8805         if (!r->in.buffer && (r->in.offered != 0)) {
8806                 return WERR_INVALID_PARAM;
8807         }
8808
8809         DEBUG(5,("_spoolss_EnumPrintProcessors\n"));
8810
8811         /*
8812          * Enumerate the print processors ...
8813          *
8814          * Just reply with "winprint", to keep NT happy
8815          * and I can use my nice printer checker.
8816          */
8817
8818         *r->out.count = 0;
8819         *r->out.needed = 0;
8820         *r->out.info = NULL;
8821
8822         switch (r->in.level) {
8823         case 1:
8824                 return enumprintprocessors_level_1(p->mem_ctx, r->out.info,
8825                                                    r->in.offered, r->out.needed,
8826                                                    r->out.count);
8827         default:
8828                 return WERR_UNKNOWN_LEVEL;
8829         }
8830 }
8831
8832 /****************************************************************************
8833  fill_printprocdatatype1
8834 ****************************************************************************/
8835
8836 static WERROR fill_printprocdatatype1(TALLOC_CTX *mem_ctx,
8837                                       struct spoolss_PrintProcDataTypesInfo1 *r,
8838                                       const char *name_array)
8839 {
8840         r->name_array = talloc_strdup(mem_ctx, name_array);
8841         W_ERROR_HAVE_NO_MEMORY(r->name_array);
8842
8843         return WERR_OK;
8844 }
8845
8846 /****************************************************************************
8847  enumprintprocdatatypes level 1.
8848 ****************************************************************************/
8849
8850 static WERROR enumprintprocdatatypes_level_1(TALLOC_CTX *mem_ctx,
8851                                              union spoolss_PrintProcDataTypesInfo **info_p,
8852                                              uint32_t offered,
8853                                              uint32_t *needed,
8854                                              uint32_t *count)
8855 {
8856         WERROR result;
8857         union spoolss_PrintProcDataTypesInfo *info;
8858
8859         info = TALLOC_ARRAY(mem_ctx, union spoolss_PrintProcDataTypesInfo, 1);
8860         W_ERROR_HAVE_NO_MEMORY(info);
8861
8862         *count = 1;
8863
8864         result = fill_printprocdatatype1(info, &info[0].info1, "RAW");
8865         if (!W_ERROR_IS_OK(result)) {
8866                 goto out;
8867         }
8868
8869         *needed += ndr_size_spoolss_PrintProcDataTypesInfo1(&info[0].info1, NULL, 0);
8870
8871         if (*needed > offered) {
8872                 result = WERR_INSUFFICIENT_BUFFER;
8873                 goto out;
8874         }
8875
8876  out:
8877         if (!W_ERROR_IS_OK(result)) {
8878                 TALLOC_FREE(info);
8879                 *count = 0;
8880                 return result;
8881         }
8882
8883         *info_p = info;
8884
8885         return WERR_OK;
8886 }
8887
8888 /****************************************************************
8889  _spoolss_EnumPrintProcDataTypes
8890 ****************************************************************/
8891
8892 WERROR _spoolss_EnumPrintProcDataTypes(pipes_struct *p,
8893                                        struct spoolss_EnumPrintProcDataTypes *r)
8894 {
8895         /* that's an [in out] buffer */
8896
8897         if (!r->in.buffer && (r->in.offered != 0)) {
8898                 return WERR_INVALID_PARAM;
8899         }
8900
8901         DEBUG(5,("_spoolss_EnumPrintProcDataTypes\n"));
8902
8903         *r->out.count = 0;
8904         *r->out.needed = 0;
8905         *r->out.info = NULL;
8906
8907         switch (r->in.level) {
8908         case 1:
8909                 return enumprintprocdatatypes_level_1(p->mem_ctx, r->out.info,
8910                                                       r->in.offered, r->out.needed,
8911                                                       r->out.count);
8912         default:
8913                 return WERR_UNKNOWN_LEVEL;
8914         }
8915 }
8916
8917 /****************************************************************************
8918  fill_monitor_1
8919 ****************************************************************************/
8920
8921 static WERROR fill_monitor_1(TALLOC_CTX *mem_ctx,
8922                              struct spoolss_MonitorInfo1 *r,
8923                              const char *monitor_name)
8924 {
8925         r->monitor_name                 = talloc_strdup(mem_ctx, monitor_name);
8926         W_ERROR_HAVE_NO_MEMORY(r->monitor_name);
8927
8928         return WERR_OK;
8929 }
8930
8931 /****************************************************************************
8932  fill_monitor_2
8933 ****************************************************************************/
8934
8935 static WERROR fill_monitor_2(TALLOC_CTX *mem_ctx,
8936                              struct spoolss_MonitorInfo2 *r,
8937                              const char *monitor_name,
8938                              const char *environment,
8939                              const char *dll_name)
8940 {
8941         r->monitor_name                 = talloc_strdup(mem_ctx, monitor_name);
8942         W_ERROR_HAVE_NO_MEMORY(r->monitor_name);
8943         r->environment                  = talloc_strdup(mem_ctx, environment);
8944         W_ERROR_HAVE_NO_MEMORY(r->environment);
8945         r->dll_name                     = talloc_strdup(mem_ctx, dll_name);
8946         W_ERROR_HAVE_NO_MEMORY(r->dll_name);
8947
8948         return WERR_OK;
8949 }
8950
8951 /****************************************************************************
8952  enumprintmonitors level 1.
8953 ****************************************************************************/
8954
8955 static WERROR enumprintmonitors_level_1(TALLOC_CTX *mem_ctx,
8956                                         union spoolss_MonitorInfo **info_p,
8957                                         uint32_t offered,
8958                                         uint32_t *needed,
8959                                         uint32_t *count)
8960 {
8961         union spoolss_MonitorInfo *info;
8962         WERROR result = WERR_OK;
8963         int i;
8964
8965         info = TALLOC_ARRAY(mem_ctx, union spoolss_MonitorInfo, 2);
8966         W_ERROR_HAVE_NO_MEMORY(info);
8967
8968         *count = 2;
8969
8970         result = fill_monitor_1(info, &info[0].info1,
8971                                 SPL_LOCAL_PORT /* FIXME */);
8972         if (!W_ERROR_IS_OK(result)) {
8973                 goto out;
8974         }
8975
8976         result = fill_monitor_1(info, &info[1].info1,
8977                                 SPL_TCPIP_PORT /* FIXME */);
8978         if (!W_ERROR_IS_OK(result)) {
8979                 goto out;
8980         }
8981
8982         for (i=0; i<*count; i++) {
8983                 *needed += ndr_size_spoolss_MonitorInfo1(&info[i].info1, NULL, 0);
8984         }
8985
8986         if (*needed > offered) {
8987                 result = WERR_INSUFFICIENT_BUFFER;
8988                 goto out;
8989         }
8990
8991 out:
8992         if (!W_ERROR_IS_OK(result)) {
8993                 TALLOC_FREE(info);
8994                 *count = 0;
8995                 return result;
8996         }
8997
8998         *info_p = info;
8999
9000         return WERR_OK;
9001 }
9002
9003 /****************************************************************************
9004  enumprintmonitors level 2.
9005 ****************************************************************************/
9006
9007 static WERROR enumprintmonitors_level_2(TALLOC_CTX *mem_ctx,
9008                                         union spoolss_MonitorInfo **info_p,
9009                                         uint32_t offered,
9010                                         uint32_t *needed,
9011                                         uint32_t *count)
9012 {
9013         union spoolss_MonitorInfo *info;
9014         WERROR result = WERR_OK;
9015         int i;
9016
9017         info = TALLOC_ARRAY(mem_ctx, union spoolss_MonitorInfo, 2);
9018         W_ERROR_HAVE_NO_MEMORY(info);
9019
9020         *count = 2;
9021
9022         result = fill_monitor_2(info, &info[0].info2,
9023                                 SPL_LOCAL_PORT, /* FIXME */
9024                                 "Windows NT X86", /* FIXME */
9025                                 "localmon.dll");
9026         if (!W_ERROR_IS_OK(result)) {
9027                 goto out;
9028         }
9029
9030         result = fill_monitor_2(info, &info[1].info2,
9031                                 SPL_TCPIP_PORT, /* FIXME */
9032                                 "Windows NT X86", /* FIXME */
9033                                 "tcpmon.dll");
9034         if (!W_ERROR_IS_OK(result)) {
9035                 goto out;
9036         }
9037
9038         for (i=0; i<*count; i++) {
9039                 *needed += ndr_size_spoolss_MonitorInfo2(&info[i].info2, NULL, 0);
9040         }
9041
9042         if (*needed > offered) {
9043                 result = WERR_INSUFFICIENT_BUFFER;
9044                 goto out;
9045         }
9046
9047 out:
9048         if (!W_ERROR_IS_OK(result)) {
9049                 TALLOC_FREE(info);
9050                 *count = 0;
9051                 return result;
9052         }
9053
9054         *info_p = info;
9055
9056         return WERR_OK;
9057 }
9058
9059 /****************************************************************
9060  _spoolss_EnumMonitors
9061 ****************************************************************/
9062
9063 WERROR _spoolss_EnumMonitors(pipes_struct *p,
9064                              struct spoolss_EnumMonitors *r)
9065 {
9066         /* that's an [in out] buffer */
9067
9068         if (!r->in.buffer && (r->in.offered != 0)) {
9069                 return WERR_INVALID_PARAM;
9070         }
9071
9072         DEBUG(5,("_spoolss_EnumMonitors\n"));
9073
9074         /*
9075          * Enumerate the print monitors ...
9076          *
9077          * Just reply with "Local Port", to keep NT happy
9078          * and I can use my nice printer checker.
9079          */
9080
9081         *r->out.count = 0;
9082         *r->out.needed = 0;
9083         *r->out.info = NULL;
9084
9085         switch (r->in.level) {
9086         case 1:
9087                 return enumprintmonitors_level_1(p->mem_ctx, r->out.info,
9088                                                  r->in.offered, r->out.needed,
9089                                                  r->out.count);
9090         case 2:
9091                 return enumprintmonitors_level_2(p->mem_ctx, r->out.info,
9092                                                  r->in.offered, r->out.needed,
9093                                                  r->out.count);
9094         default:
9095                 return WERR_UNKNOWN_LEVEL;
9096         }
9097 }
9098
9099 /****************************************************************************
9100 ****************************************************************************/
9101
9102 static WERROR getjob_level_1(print_queue_struct **queue, int count, int snum,
9103                              NT_PRINTER_INFO_LEVEL *ntprinter,
9104                              uint32 jobid, RPC_BUFFER *buffer, uint32 offered,
9105                              uint32 *needed)
9106 {
9107         int i=0;
9108         bool found=False;
9109         JOB_INFO_1 *info_1=NULL;
9110         WERROR result = WERR_OK;
9111
9112         info_1=SMB_MALLOC_P(JOB_INFO_1);
9113
9114         if (info_1 == NULL) {
9115                 return WERR_NOMEM;
9116         }
9117
9118         for (i=0; i<count && found==False; i++) {
9119                 if ((*queue)[i].job==(int)jobid)
9120                         found=True;
9121         }
9122
9123         if (found==False) {
9124                 SAFE_FREE(info_1);
9125                 /* NT treats not found as bad param... yet another bad choice */
9126                 return WERR_INVALID_PARAM;
9127         }
9128
9129         fill_job_info_1( info_1, &((*queue)[i-1]), i, snum, ntprinter );
9130
9131         *needed += spoolss_size_job_info_1(info_1);
9132
9133         if (*needed > offered) {
9134                 result = WERR_INSUFFICIENT_BUFFER;
9135                 goto out;
9136         }
9137
9138         if (!rpcbuf_alloc_size(buffer, *needed)) {
9139                 result = WERR_NOMEM;
9140                 goto out;
9141         }
9142
9143         smb_io_job_info_1("", buffer, info_1, 0);
9144
9145 out:
9146         SAFE_FREE(info_1);
9147
9148         return result;
9149 }
9150
9151 /****************************************************************************
9152 ****************************************************************************/
9153
9154 static WERROR getjob_level_2(print_queue_struct **queue, int count, int snum,
9155                              NT_PRINTER_INFO_LEVEL *ntprinter,
9156                              uint32 jobid, RPC_BUFFER *buffer, uint32 offered,
9157                              uint32 *needed)
9158 {
9159         int             i = 0;
9160         bool            found = False;
9161         JOB_INFO_2      *info_2;
9162         WERROR          result;
9163         DEVICEMODE      *devmode = NULL;
9164         NT_DEVICEMODE   *nt_devmode = NULL;
9165
9166         if ( !(info_2=SMB_MALLOC_P(JOB_INFO_2)) )
9167                 return WERR_NOMEM;
9168
9169         ZERO_STRUCTP(info_2);
9170
9171         for ( i=0; i<count && found==False; i++ )
9172         {
9173                 if ((*queue)[i].job == (int)jobid)
9174                         found = True;
9175         }
9176
9177         if ( !found ) {
9178                 /* NT treats not found as bad param... yet another bad
9179                    choice */
9180                 result = WERR_INVALID_PARAM;
9181                 goto done;
9182         }
9183
9184         /*
9185          * if the print job does not have a DEVMODE associated with it,
9186          * just use the one for the printer. A NULL devicemode is not
9187          *  a failure condition
9188          */
9189
9190         if ( !(nt_devmode=print_job_devmode( lp_const_servicename(snum), jobid )) )
9191                 devmode = construct_dev_mode(lp_const_servicename(snum));
9192         else {
9193                 if ((devmode = SMB_MALLOC_P(DEVICEMODE)) != NULL) {
9194                         ZERO_STRUCTP( devmode );
9195                         convert_nt_devicemode( devmode, nt_devmode );
9196                 }
9197         }
9198
9199         fill_job_info_2(info_2, &((*queue)[i-1]), i, snum, ntprinter, devmode);
9200
9201         *needed += spoolss_size_job_info_2(info_2);
9202
9203         if (*needed > offered) {
9204                 result = WERR_INSUFFICIENT_BUFFER;
9205                 goto done;
9206         }
9207
9208         if (!rpcbuf_alloc_size(buffer, *needed)) {
9209                 result = WERR_NOMEM;
9210                 goto done;
9211         }
9212
9213         smb_io_job_info_2("", buffer, info_2, 0);
9214
9215         result = WERR_OK;
9216
9217  done:
9218         /* Cleanup allocated memory */
9219
9220         free_job_info_2(info_2);        /* Also frees devmode */
9221         SAFE_FREE(info_2);
9222
9223         return result;
9224 }
9225
9226 /****************************************************************************
9227 ****************************************************************************/
9228
9229 WERROR _spoolss_getjob( pipes_struct *p, SPOOL_Q_GETJOB *q_u, SPOOL_R_GETJOB *r_u)
9230 {
9231         POLICY_HND *handle = &q_u->handle;
9232         uint32 jobid = q_u->jobid;
9233         uint32 level = q_u->level;
9234         RPC_BUFFER *buffer = NULL;
9235         uint32 offered = q_u->offered;
9236         uint32 *needed = &r_u->needed;
9237         WERROR          wstatus = WERR_OK;
9238         NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
9239         int snum;
9240         int count;
9241         print_queue_struct      *queue = NULL;
9242         print_status_struct prt_status;
9243
9244         /* that's an [in out] buffer */
9245
9246         if (!q_u->buffer && (offered!=0)) {
9247                 return WERR_INVALID_PARAM;
9248         }
9249
9250         if (offered > MAX_RPC_DATA_SIZE) {
9251                 return WERR_INVALID_PARAM;
9252         }
9253
9254         rpcbuf_move(q_u->buffer, &r_u->buffer);
9255         buffer = r_u->buffer;
9256
9257         DEBUG(5,("spoolss_getjob\n"));
9258
9259         *needed = 0;
9260
9261         if (!get_printer_snum(p, handle, &snum, NULL))
9262                 return WERR_BADFID;
9263
9264         wstatus = get_a_printer(NULL, &ntprinter, 2, lp_servicename(snum));
9265         if ( !W_ERROR_IS_OK(wstatus) )
9266                 return wstatus;
9267
9268         count = print_queue_status(snum, &queue, &prt_status);
9269
9270         DEBUGADD(4,("count:[%d], prt_status:[%d], [%s]\n",
9271                      count, prt_status.status, prt_status.message));
9272
9273         switch ( level ) {
9274         case 1:
9275                         wstatus = getjob_level_1(&queue, count, snum, ntprinter, jobid,
9276                                 buffer, offered, needed);
9277                         break;
9278         case 2:
9279                         wstatus = getjob_level_2(&queue, count, snum, ntprinter, jobid,
9280                                 buffer, offered, needed);
9281                         break;
9282         default:
9283                         wstatus = WERR_UNKNOWN_LEVEL;
9284                         break;
9285         }
9286
9287         SAFE_FREE(queue);
9288         free_a_printer( &ntprinter, 2 );
9289
9290         return wstatus;
9291 }
9292
9293 /****************************************************************
9294  _spoolss_GetPrinterDataEx
9295
9296  From MSDN documentation of GetPrinterDataEx: pass request
9297  to GetPrinterData if key is "PrinterDriverData".
9298 ****************************************************************/
9299
9300 WERROR _spoolss_GetPrinterDataEx(pipes_struct *p,
9301                                  struct spoolss_GetPrinterDataEx *r)
9302 {
9303         POLICY_HND      *handle = r->in.handle;
9304         uint8           *data = NULL;
9305         const char      *keyname = r->in.key_name;
9306         const char      *valuename = r->in.value_name;
9307
9308         Printer_entry   *Printer = find_printer_index_by_hnd(p, handle);
9309
9310         NT_PRINTER_INFO_LEVEL   *printer = NULL;
9311         int                     snum = 0;
9312         WERROR                  status = WERR_OK;
9313
9314         DEBUG(4,("_spoolss_GetPrinterDataEx\n"));
9315
9316         DEBUG(10, ("_spoolss_GetPrinterDataEx: key => [%s], value => [%s]\n",
9317                 keyname, valuename));
9318
9319         /* in case of problem, return some default values */
9320
9321         *r->out.needed  = 0;
9322         *r->out.type    = 0;
9323
9324         if (!Printer) {
9325                 DEBUG(2,("_spoolss_GetPrinterDataEx: "
9326                         "Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
9327                 status = WERR_BADFID;
9328                 goto done;
9329         }
9330
9331         /* Is the handle to a printer or to the server? */
9332
9333         if (Printer->printer_type == SPLHND_SERVER) {
9334                 DEBUG(10,("_spoolss_GetPrinterDataEx: "
9335                         "Not implemented for server handles yet\n"));
9336                 status = WERR_INVALID_PARAM;
9337                 goto done;
9338         }
9339
9340         if ( !get_printer_snum(p,handle, &snum, NULL) )
9341                 return WERR_BADFID;
9342
9343         status = get_a_printer(Printer, &printer, 2, lp_servicename(snum));
9344         if ( !W_ERROR_IS_OK(status) )
9345                 goto done;
9346
9347         /* check to see if the keyname is valid */
9348         if ( !strlen(keyname) ) {
9349                 status = WERR_INVALID_PARAM;
9350                 goto done;
9351         }
9352
9353         if ( lookup_printerkey( printer->info_2->data, keyname ) == -1 ) {
9354                 DEBUG(4,("_spoolss_GetPrinterDataEx: "
9355                         "Invalid keyname [%s]\n", keyname ));
9356                 free_a_printer( &printer, 2 );
9357                 status = WERR_BADFILE;
9358                 goto done;
9359         }
9360
9361         /* When given a new keyname, we should just create it */
9362
9363         status = get_printer_dataex( p->mem_ctx, printer, keyname, valuename,
9364                                      r->out.type, &data, r->out.needed,
9365                                      r->in.offered );
9366
9367         if (*r->out.needed > r->in.offered) {
9368                 status = WERR_MORE_DATA;
9369         }
9370
9371         if (W_ERROR_IS_OK(status)) {
9372                 memcpy(r->out.buffer, data, r->in.offered);
9373         }
9374
9375 done:
9376         if ( printer )
9377         free_a_printer( &printer, 2 );
9378
9379         return status;
9380 }
9381
9382 /****************************************************************
9383  _spoolss_SetPrinterDataEx
9384 ****************************************************************/
9385
9386 WERROR _spoolss_SetPrinterDataEx(pipes_struct *p,
9387                                  struct spoolss_SetPrinterDataEx *r)
9388 {
9389         POLICY_HND              *handle = r->in.handle;
9390         NT_PRINTER_INFO_LEVEL   *printer = NULL;
9391         int                     snum = 0;
9392         WERROR                  status = WERR_OK;
9393         Printer_entry           *Printer = find_printer_index_by_hnd(p, handle);
9394         char                    *oid_string;
9395
9396         DEBUG(4,("_spoolss_SetPrinterDataEx\n"));
9397
9398         /* From MSDN documentation of SetPrinterDataEx: pass request to
9399            SetPrinterData if key is "PrinterDriverData" */
9400
9401         if (!Printer) {
9402                 DEBUG(2,("_spoolss_SetPrinterDataEx: "
9403                         "Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
9404                 return WERR_BADFID;
9405         }
9406
9407         if ( Printer->printer_type == SPLHND_SERVER ) {
9408                 DEBUG(10,("_spoolss_SetPrinterDataEx: "
9409                         "Not implemented for server handles yet\n"));
9410                 return WERR_INVALID_PARAM;
9411         }
9412
9413         if ( !get_printer_snum(p,handle, &snum, NULL) )
9414                 return WERR_BADFID;
9415
9416         /*
9417          * Access check : NT returns "access denied" if you make a
9418          * SetPrinterData call without the necessary privildge.
9419          * we were originally returning OK if nothing changed
9420          * which made Win2k issue **a lot** of SetPrinterData
9421          * when connecting to a printer  --jerry
9422          */
9423
9424         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER)
9425         {
9426                 DEBUG(3, ("_spoolss_SetPrinterDataEx: "
9427                         "change denied by handle access permissions\n"));
9428                 return WERR_ACCESS_DENIED;
9429         }
9430
9431         status = get_a_printer(Printer, &printer, 2, lp_servicename(snum));
9432         if (!W_ERROR_IS_OK(status))
9433                 return status;
9434
9435         /* check for OID in valuename */
9436
9437         if ( (oid_string = strchr( r->in.value_name, ',' )) != NULL )
9438         {
9439                 *oid_string = '\0';
9440                 oid_string++;
9441         }
9442
9443         /* save the registry data */
9444
9445         status = set_printer_dataex( printer, r->in.key_name, r->in.value_name,
9446                                      r->in.type, r->in.buffer, r->in.offered );
9447
9448         if ( W_ERROR_IS_OK(status) )
9449         {
9450                 /* save the OID if one was specified */
9451                 if ( oid_string ) {
9452                         char *str = talloc_asprintf(p->mem_ctx, "%s\\%s",
9453                                 r->in.key_name, SPOOL_OID_KEY);
9454                         if (!str) {
9455                                 return WERR_NOMEM;
9456                         }
9457
9458                         /*
9459                          * I'm not checking the status here on purpose.  Don't know
9460                          * if this is right, but I'm returning the status from the
9461                          * previous set_printer_dataex() call.  I have no idea if
9462                          * this is right.    --jerry
9463                          */
9464
9465                         set_printer_dataex( printer, str, r->in.value_name,
9466                                             REG_SZ, (uint8 *)oid_string,
9467                                             strlen(oid_string)+1 );
9468                 }
9469
9470                 status = mod_a_printer(printer, 2);
9471         }
9472
9473         free_a_printer(&printer, 2);
9474
9475         return status;
9476 }
9477
9478 /****************************************************************
9479  _spoolss_DeletePrinterDataEx
9480 ****************************************************************/
9481
9482 WERROR _spoolss_DeletePrinterDataEx(pipes_struct *p,
9483                                     struct spoolss_DeletePrinterDataEx *r)
9484 {
9485         POLICY_HND      *handle = r->in.handle;
9486         NT_PRINTER_INFO_LEVEL   *printer = NULL;
9487         int             snum=0;
9488         WERROR          status = WERR_OK;
9489         Printer_entry   *Printer=find_printer_index_by_hnd(p, handle);
9490
9491         DEBUG(5,("_spoolss_DeletePrinterDataEx\n"));
9492
9493         if (!Printer) {
9494                 DEBUG(2,("_spoolss_DeletePrinterDataEx: "
9495                         "Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
9496                 return WERR_BADFID;
9497         }
9498
9499         if (!get_printer_snum(p, handle, &snum, NULL))
9500                 return WERR_BADFID;
9501
9502         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
9503                 DEBUG(3, ("_spoolss_DeletePrinterDataEx: "
9504                         "printer properties change denied by handle\n"));
9505                 return WERR_ACCESS_DENIED;
9506         }
9507
9508         if (!r->in.value_name || !r->in.key_name) {
9509                 return WERR_NOMEM;
9510         }
9511
9512         status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
9513         if (!W_ERROR_IS_OK(status))
9514                 return status;
9515
9516         status = delete_printer_dataex( printer, r->in.key_name, r->in.value_name );
9517
9518         if ( W_ERROR_IS_OK(status) )
9519                 mod_a_printer( printer, 2 );
9520
9521         free_a_printer(&printer, 2);
9522
9523         return status;
9524 }
9525
9526 /********************************************************************
9527  * spoolss_enumprinterkey
9528  ********************************************************************/
9529
9530
9531 WERROR _spoolss_enumprinterkey(pipes_struct *p, SPOOL_Q_ENUMPRINTERKEY *q_u, SPOOL_R_ENUMPRINTERKEY *r_u)
9532 {
9533         fstring         key;
9534         fstring         *keynames = NULL;
9535         uint16          *enumkeys = NULL;
9536         int             num_keys;
9537         int             printerkey_len;
9538         POLICY_HND      *handle = &q_u->handle;
9539         Printer_entry   *Printer = find_printer_index_by_hnd(p, handle);
9540         NT_PRINTER_DATA *data;
9541         NT_PRINTER_INFO_LEVEL   *printer = NULL;
9542         int             snum = 0;
9543         WERROR          status = WERR_BADFILE;
9544
9545
9546         DEBUG(4,("_spoolss_enumprinterkey\n"));
9547
9548         if (!Printer) {
9549                 DEBUG(2,("_spoolss_enumprinterkey: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
9550                 return WERR_BADFID;
9551         }
9552
9553         if ( !get_printer_snum(p,handle, &snum, NULL) )
9554                 return WERR_BADFID;
9555
9556         status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
9557         if (!W_ERROR_IS_OK(status))
9558                 return status;
9559
9560         /* get the list of subkey names */
9561
9562         unistr2_to_ascii(key, &q_u->key, sizeof(key));
9563         data = printer->info_2->data;
9564
9565         num_keys = get_printer_subkeys( data, key, &keynames );
9566
9567         if ( num_keys == -1 ) {
9568                 status = WERR_BADFILE;
9569                 goto done;
9570         }
9571
9572         printerkey_len = init_unistr_array( &enumkeys,  keynames, NULL );
9573
9574         r_u->needed = printerkey_len*2;
9575
9576         if ( q_u->size < r_u->needed ) {
9577                 status = WERR_MORE_DATA;
9578                 goto done;
9579         }
9580
9581         if (!make_spoolss_buffer5(p->mem_ctx, &r_u->keys, printerkey_len, enumkeys)) {
9582                 status = WERR_NOMEM;
9583                 goto done;
9584         }
9585
9586         status = WERR_OK;
9587
9588         if ( q_u->size < r_u->needed )
9589                 status = WERR_MORE_DATA;
9590
9591 done:
9592         free_a_printer( &printer, 2 );
9593         SAFE_FREE( keynames );
9594
9595         return status;
9596 }
9597
9598 /****************************************************************
9599  _spoolss_DeletePrinterKey
9600 ****************************************************************/
9601
9602 WERROR _spoolss_DeletePrinterKey(pipes_struct *p,
9603                                  struct spoolss_DeletePrinterKey *r)
9604 {
9605         POLICY_HND              *handle = r->in.handle;
9606         Printer_entry           *Printer = find_printer_index_by_hnd(p, handle);
9607         NT_PRINTER_INFO_LEVEL   *printer = NULL;
9608         int                     snum=0;
9609         WERROR                  status;
9610
9611         DEBUG(5,("_spoolss_DeletePrinterKey\n"));
9612
9613         if (!Printer) {
9614                 DEBUG(2,("_spoolss_DeletePrinterKey: Invalid handle (%s:%u:%u).\n",
9615                         OUR_HANDLE(handle)));
9616                 return WERR_BADFID;
9617         }
9618
9619         /* if keyname == NULL, return error */
9620
9621         if ( !r->in.key_name )
9622                 return WERR_INVALID_PARAM;
9623
9624         if (!get_printer_snum(p, handle, &snum, NULL))
9625                 return WERR_BADFID;
9626
9627         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
9628                 DEBUG(3, ("_spoolss_DeletePrinterKey: "
9629                         "printer properties change denied by handle\n"));
9630                 return WERR_ACCESS_DENIED;
9631         }
9632
9633         status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
9634         if (!W_ERROR_IS_OK(status))
9635                 return status;
9636
9637         /* delete the key and all subneys */
9638
9639         status = delete_all_printer_data( printer->info_2, r->in.key_name );
9640
9641         if ( W_ERROR_IS_OK(status) )
9642                 status = mod_a_printer(printer, 2);
9643
9644         free_a_printer( &printer, 2 );
9645
9646         return status;
9647 }
9648
9649
9650 /********************************************************************
9651  * spoolss_enumprinterdataex
9652  ********************************************************************/
9653
9654 WERROR _spoolss_enumprinterdataex(pipes_struct *p, SPOOL_Q_ENUMPRINTERDATAEX *q_u, SPOOL_R_ENUMPRINTERDATAEX *r_u)
9655 {
9656         POLICY_HND      *handle = &q_u->handle;
9657         uint32          in_size = q_u->size;
9658         uint32          num_entries,
9659                         needed;
9660         NT_PRINTER_INFO_LEVEL   *printer = NULL;
9661         PRINTER_ENUM_VALUES     *enum_values = NULL;
9662         NT_PRINTER_DATA         *p_data;
9663         fstring         key;
9664         Printer_entry   *Printer = find_printer_index_by_hnd(p, handle);
9665         int             snum;
9666         WERROR          result;
9667         int             key_index;
9668         int             i;
9669         REGISTRY_VALUE  *val;
9670         char            *value_name;
9671         uint32          data_len;
9672
9673
9674         DEBUG(4,("_spoolss_enumprinterdataex\n"));
9675
9676         if (!Printer) {
9677                 DEBUG(2,("_spoolss_enumprinterdataex: Invalid handle (%s:%u:%u1<).\n", OUR_HANDLE(handle)));
9678                 return WERR_BADFID;
9679         }
9680
9681         /*
9682          * first check for a keyname of NULL or "".  Win2k seems to send
9683          * this a lot and we should send back WERR_INVALID_PARAM
9684          * no need to spend time looking up the printer in this case.
9685          * --jerry
9686          */
9687
9688         unistr2_to_ascii(key, &q_u->key, sizeof(key));
9689         if ( !strlen(key) ) {
9690                 result = WERR_INVALID_PARAM;
9691                 goto done;
9692         }
9693
9694         /* get the printer off of disk */
9695
9696         if (!get_printer_snum(p,handle, &snum, NULL))
9697                 return WERR_BADFID;
9698
9699         ZERO_STRUCT(printer);
9700         result = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
9701         if (!W_ERROR_IS_OK(result))
9702                 return result;
9703
9704         /* now look for a match on the key name */
9705
9706         p_data = printer->info_2->data;
9707
9708         unistr2_to_ascii(key, &q_u->key, sizeof(key));
9709         if ( (key_index = lookup_printerkey( p_data, key)) == -1  )
9710         {
9711                 DEBUG(10,("_spoolss_enumprinterdataex: Unknown keyname [%s]\n", key));
9712                 result = WERR_INVALID_PARAM;
9713                 goto done;
9714         }
9715
9716         result = WERR_OK;
9717         needed = 0;
9718
9719         /* allocate the memory for the array of pointers -- if necessary */
9720
9721         num_entries = regval_ctr_numvals( p_data->keys[key_index].values );
9722         if ( num_entries )
9723         {
9724                 if ( (enum_values=TALLOC_ARRAY(p->mem_ctx, PRINTER_ENUM_VALUES, num_entries)) == NULL )
9725                 {
9726                         DEBUG(0,("_spoolss_enumprinterdataex: talloc() failed to allocate memory for [%lu] bytes!\n",
9727                                 (unsigned long)num_entries*sizeof(PRINTER_ENUM_VALUES)));
9728                         result = WERR_NOMEM;
9729                         goto done;
9730                 }
9731
9732                 memset( enum_values, 0x0, num_entries*sizeof(PRINTER_ENUM_VALUES) );
9733         }
9734
9735         /*
9736          * loop through all params and build the array to pass
9737          * back to the  client
9738          */
9739
9740         for ( i=0; i<num_entries; i++ )
9741         {
9742                 /* lookup the registry value */
9743
9744                 val = regval_ctr_specific_value( p_data->keys[key_index].values, i );
9745                 DEBUG(10,("retrieved value number [%d] [%s]\n", i, regval_name(val) ));
9746
9747                 /* copy the data */
9748
9749                 value_name = regval_name( val );
9750                 init_unistr( &enum_values[i].valuename, value_name );
9751                 enum_values[i].value_len = (strlen(value_name)+1) * 2;
9752                 enum_values[i].type      = regval_type( val );
9753
9754                 data_len = regval_size( val );
9755                 if ( data_len ) {
9756                         if ( !(enum_values[i].data = (uint8 *)TALLOC_MEMDUP(p->mem_ctx, regval_data_p(val), data_len)) )
9757                         {
9758                                 DEBUG(0,("TALLOC_MEMDUP failed to allocate memory [data_len=%d] for data!\n",
9759                                         data_len ));
9760                                 result = WERR_NOMEM;
9761                                 goto done;
9762                         }
9763                 }
9764                 enum_values[i].data_len = data_len;
9765
9766                 /* keep track of the size of the array in bytes */
9767
9768                 needed += spoolss_size_printer_enum_values(&enum_values[i]);
9769         }
9770
9771         /* housekeeping information in the reply */
9772
9773         /* Fix from Martin Zielinski <mz@seh.de> - ensure
9774          * the hand marshalled container size is a multiple
9775          * of 4 bytes for RPC alignment.
9776          */
9777
9778         if (needed % 4) {
9779                 needed += 4-(needed % 4);
9780         }
9781
9782         r_u->needed     = needed;
9783         r_u->returned   = num_entries;
9784
9785         if (needed > in_size) {
9786                 result = WERR_MORE_DATA;
9787                 goto done;
9788         }
9789
9790         /* copy data into the reply */
9791
9792         /* mz: Vista x64 returns 0x6f7 (The stub received bad data), if the
9793            response buffer size is != the offered buffer size
9794
9795                 r_u->ctr.size           = r_u->needed;
9796         */
9797         r_u->ctr.size           = in_size;
9798
9799         r_u->ctr.size_of_array  = r_u->returned;
9800         r_u->ctr.values         = enum_values;
9801
9802 done:
9803         if ( printer )
9804         free_a_printer(&printer, 2);
9805
9806         return result;
9807 }
9808
9809 /****************************************************************************
9810 ****************************************************************************/
9811
9812 static WERROR getprintprocessordirectory_level_1(TALLOC_CTX *mem_ctx,
9813                                                  const char *servername,
9814                                                  const char *environment,
9815                                                  struct spoolss_PrintProcessorDirectoryInfo1 *r,
9816                                                  uint32_t offered,
9817                                                  uint32_t *needed)
9818 {
9819         WERROR werr;
9820         char *path = NULL;
9821
9822         werr = compose_spoolss_server_path(mem_ctx,
9823                                            servername,
9824                                            environment,
9825                                            SPOOLSS_PRTPROCS_PATH,
9826                                            &path);
9827         if (!W_ERROR_IS_OK(werr)) {
9828                 return werr;
9829         }
9830
9831         DEBUG(4,("print processor directory: [%s]\n", path));
9832
9833         r->directory_name = path;
9834
9835         *needed += ndr_size_spoolss_PrintProcessorDirectoryInfo1(r, NULL, 0);
9836
9837         if (*needed > offered) {
9838                 talloc_free(path);
9839                 return WERR_INSUFFICIENT_BUFFER;
9840         }
9841
9842         return WERR_OK;
9843 }
9844
9845 /****************************************************************
9846  _spoolss_GetPrintProcessorDirectory
9847 ****************************************************************/
9848
9849 WERROR _spoolss_GetPrintProcessorDirectory(pipes_struct *p,
9850                                            struct spoolss_GetPrintProcessorDirectory *r)
9851 {
9852         WERROR result;
9853
9854         /* that's an [in out] buffer */
9855
9856         if (!r->in.buffer && (r->in.offered != 0)) {
9857                 return WERR_INVALID_PARAM;
9858         }
9859
9860         DEBUG(5,("_spoolss_GetPrintProcessorDirectory: level %d\n",
9861                 r->in.level));
9862
9863         *r->out.needed = 0;
9864
9865         /* r->in.level is ignored */
9866
9867         result = getprintprocessordirectory_level_1(p->mem_ctx,
9868                                                     r->in.server,
9869                                                     r->in.environment,
9870                                                     &r->out.info->info1,
9871                                                     r->in.offered,
9872                                                     r->out.needed);
9873         if (!W_ERROR_IS_OK(result)) {
9874                 TALLOC_FREE(r->out.info);
9875         }
9876
9877         return result;
9878 }
9879
9880 /*******************************************************************
9881  ********************************************************************/
9882
9883 static bool push_monitorui_buf(TALLOC_CTX *mem_ctx, DATA_BLOB *buf,
9884                                const char *dllname)
9885 {
9886         enum ndr_err_code ndr_err;
9887         struct spoolss_MonitorUi ui;
9888
9889         ui.dll_name = dllname;
9890
9891         ndr_err = ndr_push_struct_blob(buf, mem_ctx, NULL, &ui,
9892                        (ndr_push_flags_fn_t)ndr_push_spoolss_MonitorUi);
9893         if (NDR_ERR_CODE_IS_SUCCESS(ndr_err) && (DEBUGLEVEL >= 10)) {
9894                 NDR_PRINT_DEBUG(spoolss_MonitorUi, &ui);
9895         }
9896         return NDR_ERR_CODE_IS_SUCCESS(ndr_err);
9897 }
9898
9899 /*******************************************************************
9900  Streams the monitor UI DLL name in UNICODE
9901 *******************************************************************/
9902
9903 static WERROR xcvtcp_monitorui(TALLOC_CTX *mem_ctx,
9904                                NT_USER_TOKEN *token, DATA_BLOB *in,
9905                                DATA_BLOB *out, uint32_t *needed)
9906 {
9907         const char *dllname = "tcpmonui.dll";
9908
9909         *needed = (strlen(dllname)+1) * 2;
9910
9911         if (out->length < *needed) {
9912                 return WERR_INSUFFICIENT_BUFFER;
9913         }
9914
9915         if (!push_monitorui_buf(mem_ctx, out, dllname)) {
9916                 return WERR_NOMEM;
9917         }
9918
9919         return WERR_OK;
9920 }
9921
9922 /*******************************************************************
9923  ********************************************************************/
9924
9925 static bool pull_port_data_1(TALLOC_CTX *mem_ctx,
9926                              struct spoolss_PortData1 *port1,
9927                              const DATA_BLOB *buf)
9928 {
9929         enum ndr_err_code ndr_err;
9930         ndr_err = ndr_pull_struct_blob(buf, mem_ctx, NULL, port1,
9931                        (ndr_pull_flags_fn_t)ndr_pull_spoolss_PortData1);
9932         if (NDR_ERR_CODE_IS_SUCCESS(ndr_err) && (DEBUGLEVEL >= 10)) {
9933                 NDR_PRINT_DEBUG(spoolss_PortData1, port1);
9934         }
9935         return NDR_ERR_CODE_IS_SUCCESS(ndr_err);
9936 }
9937
9938 /*******************************************************************
9939  ********************************************************************/
9940
9941 static bool pull_port_data_2(TALLOC_CTX *mem_ctx,
9942                              struct spoolss_PortData2 *port2,
9943                              const DATA_BLOB *buf)
9944 {
9945         enum ndr_err_code ndr_err;
9946         ndr_err = ndr_pull_struct_blob(buf, mem_ctx, NULL, port2,
9947                        (ndr_pull_flags_fn_t)ndr_pull_spoolss_PortData2);
9948         if (NDR_ERR_CODE_IS_SUCCESS(ndr_err) && (DEBUGLEVEL >= 10)) {
9949                 NDR_PRINT_DEBUG(spoolss_PortData2, port2);
9950         }
9951         return NDR_ERR_CODE_IS_SUCCESS(ndr_err);
9952 }
9953
9954 /*******************************************************************
9955  Create a new TCP/IP port
9956 *******************************************************************/
9957
9958 static WERROR xcvtcp_addport(TALLOC_CTX *mem_ctx,
9959                              NT_USER_TOKEN *token, DATA_BLOB *in,
9960                              DATA_BLOB *out, uint32_t *needed)
9961 {
9962         struct spoolss_PortData1 port1;
9963         struct spoolss_PortData2 port2;
9964         char *device_uri = NULL;
9965         uint32_t version;
9966
9967         const char *portname;
9968         const char *hostaddress;
9969         const char *queue;
9970         uint32_t port_number;
9971         uint32_t protocol;
9972
9973         /* peek for spoolss_PortData version */
9974
9975         if (!in || (in->length < (128 + 4))) {
9976                 return WERR_GENERAL_FAILURE;
9977         }
9978
9979         version = IVAL(in->data, 128);
9980
9981         switch (version) {
9982                 case 1:
9983                         ZERO_STRUCT(port1);
9984
9985                         if (!pull_port_data_1(mem_ctx, &port1, in)) {
9986                                 return WERR_NOMEM;
9987                         }
9988
9989                         portname        = port1.portname;
9990                         hostaddress     = port1.hostaddress;
9991                         queue           = port1.queue;
9992                         protocol        = port1.protocol;
9993                         port_number     = port1.port_number;
9994
9995                         break;
9996                 case 2:
9997                         ZERO_STRUCT(port2);
9998
9999                         if (!pull_port_data_2(mem_ctx, &port2, in)) {
10000                                 return WERR_NOMEM;
10001                         }
10002
10003                         portname        = port2.portname;
10004                         hostaddress     = port2.hostaddress;
10005                         queue           = port2.queue;
10006                         protocol        = port2.protocol;
10007                         port_number     = port2.port_number;
10008
10009                         break;
10010                 default:
10011                         DEBUG(1,("xcvtcp_addport: "
10012                                 "unknown version of port_data: %d\n", version));
10013                         return WERR_UNKNOWN_PORT;
10014         }
10015
10016         /* create the device URI and call the add_port_hook() */
10017
10018         switch (protocol) {
10019         case PROTOCOL_RAWTCP_TYPE:
10020                 device_uri = talloc_asprintf(mem_ctx,
10021                                 "socket://%s:%d/", hostaddress,
10022                                 port_number);
10023                 break;
10024
10025         case PROTOCOL_LPR_TYPE:
10026                 device_uri = talloc_asprintf(mem_ctx,
10027                         "lpr://%s/%s", hostaddress, queue );
10028                 break;
10029
10030         default:
10031                 return WERR_UNKNOWN_PORT;
10032         }
10033
10034         if (!device_uri) {
10035                 return WERR_NOMEM;
10036         }
10037
10038         return add_port_hook(mem_ctx, token, portname, device_uri);
10039 }
10040
10041 /*******************************************************************
10042 *******************************************************************/
10043
10044 struct xcv_api_table xcvtcp_cmds[] = {
10045         { "MonitorUI",  xcvtcp_monitorui },
10046         { "AddPort",    xcvtcp_addport},
10047         { NULL,         NULL }
10048 };
10049
10050 static WERROR process_xcvtcp_command(TALLOC_CTX *mem_ctx,
10051                                      NT_USER_TOKEN *token, const char *command,
10052                                      DATA_BLOB *inbuf,
10053                                      DATA_BLOB *outbuf,
10054                                      uint32_t *needed )
10055 {
10056         int i;
10057
10058         DEBUG(10,("process_xcvtcp_command: Received command \"%s\"\n", command));
10059
10060         for ( i=0; xcvtcp_cmds[i].name; i++ ) {
10061                 if ( strcmp( command, xcvtcp_cmds[i].name ) == 0 )
10062                         return xcvtcp_cmds[i].fn(mem_ctx, token, inbuf, outbuf, needed);
10063         }
10064
10065         return WERR_BADFUNC;
10066 }
10067
10068 /*******************************************************************
10069 *******************************************************************/
10070 #if 0   /* don't support management using the "Local Port" monitor */
10071
10072 static WERROR xcvlocal_monitorui(TALLOC_CTX *mem_ctx,
10073                                  NT_USER_TOKEN *token, DATA_BLOB *in,
10074                                  DATA_BLOB *out, uint32_t *needed)
10075 {
10076         const char *dllname = "localui.dll";
10077
10078         *needed = (strlen(dllname)+1) * 2;
10079
10080         if (out->length < *needed) {
10081                 return WERR_INSUFFICIENT_BUFFER;
10082         }
10083
10084         if (!push_monitorui_buf(mem_ctx, out, dllname)) {
10085                 return WERR_NOMEM;
10086         }
10087
10088         return WERR_OK;
10089 }
10090
10091 /*******************************************************************
10092 *******************************************************************/
10093
10094 struct xcv_api_table xcvlocal_cmds[] = {
10095         { "MonitorUI",  xcvlocal_monitorui },
10096         { NULL,         NULL }
10097 };
10098 #else
10099 struct xcv_api_table xcvlocal_cmds[] = {
10100         { NULL,         NULL }
10101 };
10102 #endif
10103
10104
10105
10106 /*******************************************************************
10107 *******************************************************************/
10108
10109 static WERROR process_xcvlocal_command(TALLOC_CTX *mem_ctx,
10110                                        NT_USER_TOKEN *token, const char *command,
10111                                        DATA_BLOB *inbuf, DATA_BLOB *outbuf,
10112                                        uint32_t *needed)
10113 {
10114         int i;
10115
10116         DEBUG(10,("process_xcvlocal_command: Received command \"%s\"\n", command));
10117
10118         for ( i=0; xcvlocal_cmds[i].name; i++ ) {
10119                 if ( strcmp( command, xcvlocal_cmds[i].name ) == 0 )
10120                         return xcvlocal_cmds[i].fn(mem_ctx, token, inbuf, outbuf, needed);
10121         }
10122         return WERR_BADFUNC;
10123 }
10124
10125 /****************************************************************
10126  _spoolss_XcvData
10127 ****************************************************************/
10128
10129 WERROR _spoolss_XcvData(pipes_struct *p,
10130                         struct spoolss_XcvData *r)
10131 {
10132         Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
10133         DATA_BLOB out_data = data_blob_null;
10134         WERROR werror;
10135
10136         if (!Printer) {
10137                 DEBUG(2,("_spoolss_XcvData: Invalid handle (%s:%u:%u).\n",
10138                         OUR_HANDLE(r->in.handle)));
10139                 return WERR_BADFID;
10140         }
10141
10142         /* Has to be a handle to the TCP/IP port monitor */
10143
10144         if ( !(Printer->printer_type & (SPLHND_PORTMON_LOCAL|SPLHND_PORTMON_TCP)) ) {
10145                 DEBUG(2,("_spoolss_XcvData: Call only valid for Port Monitors\n"));
10146                 return WERR_BADFID;
10147         }
10148
10149         /* requires administrative access to the server */
10150
10151         if ( !(Printer->access_granted & SERVER_ACCESS_ADMINISTER) ) {
10152                 DEBUG(2,("_spoolss_XcvData: denied by handle permissions.\n"));
10153                 return WERR_ACCESS_DENIED;
10154         }
10155
10156         /* Allocate the outgoing buffer */
10157
10158         if (r->in.out_data_size) {
10159                 out_data = data_blob_talloc_zero(p->mem_ctx, r->in.out_data_size);
10160                 if (out_data.data == NULL) {
10161                         return WERR_NOMEM;
10162                 }
10163         }
10164
10165         switch ( Printer->printer_type ) {
10166         case SPLHND_PORTMON_TCP:
10167                 werror = process_xcvtcp_command(p->mem_ctx,
10168                                                 p->server_info->ptok,
10169                                                 r->in.function_name,
10170                                                 &r->in.in_data, &out_data,
10171                                                 r->out.needed);
10172                 break;
10173         case SPLHND_PORTMON_LOCAL:
10174                 werror = process_xcvlocal_command(p->mem_ctx,
10175                                                   p->server_info->ptok,
10176                                                   r->in.function_name,
10177                                                   &r->in.in_data, &out_data,
10178                                                   r->out.needed);
10179                 break;
10180         default:
10181                 werror = WERR_INVALID_PRINT_MONITOR;
10182         }
10183
10184         if (!W_ERROR_IS_OK(werror)) {
10185                 return werror;
10186         }
10187
10188         *r->out.status_code = 0;
10189
10190         memcpy(r->out.out_data, out_data.data, out_data.length);
10191
10192         return WERR_OK;
10193 }
10194
10195 /****************************************************************
10196  _spoolss_AddPrintProcessor
10197 ****************************************************************/
10198
10199 WERROR _spoolss_AddPrintProcessor(pipes_struct *p,
10200                                   struct spoolss_AddPrintProcessor *r)
10201 {
10202         /* for now, just indicate success and ignore the add.  We'll
10203            automatically set the winprint processor for printer
10204            entries later.  Used to debug the LexMark Optra S 1855 PCL
10205            driver --jerry */
10206
10207         return WERR_OK;
10208 }
10209
10210 /****************************************************************
10211  _spoolss_EnumPrinters
10212 ****************************************************************/
10213
10214 WERROR _spoolss_EnumPrinters(pipes_struct *p,
10215                              struct spoolss_EnumPrinters *r)
10216 {
10217         p->rng_fault_state = true;
10218         return WERR_NOT_SUPPORTED;
10219 }
10220
10221 /****************************************************************
10222  _spoolss_GetJob
10223 ****************************************************************/
10224
10225 WERROR _spoolss_GetJob(pipes_struct *p,
10226                        struct spoolss_GetJob *r)
10227 {
10228         p->rng_fault_state = true;
10229         return WERR_NOT_SUPPORTED;
10230 }
10231
10232 /****************************************************************
10233  _spoolss_EnumJobs
10234 ****************************************************************/
10235
10236 WERROR _spoolss_EnumJobs(pipes_struct *p,
10237                          struct spoolss_EnumJobs *r)
10238 {
10239         p->rng_fault_state = true;
10240         return WERR_NOT_SUPPORTED;
10241 }
10242
10243 /****************************************************************
10244  _spoolss_AddPrinter
10245 ****************************************************************/
10246
10247 WERROR _spoolss_AddPrinter(pipes_struct *p,
10248                            struct spoolss_AddPrinter *r)
10249 {
10250         p->rng_fault_state = true;
10251         return WERR_NOT_SUPPORTED;
10252 }
10253
10254 /****************************************************************
10255  _spoolss_GetPrinter
10256 ****************************************************************/
10257
10258 WERROR _spoolss_GetPrinter(pipes_struct *p,
10259                            struct spoolss_GetPrinter *r)
10260 {
10261         p->rng_fault_state = true;
10262         return WERR_NOT_SUPPORTED;
10263 }
10264
10265 /****************************************************************
10266  _spoolss_EnumPrinterDrivers
10267 ****************************************************************/
10268
10269 WERROR _spoolss_EnumPrinterDrivers(pipes_struct *p,
10270                                    struct spoolss_EnumPrinterDrivers *r)
10271 {
10272         p->rng_fault_state = true;
10273         return WERR_NOT_SUPPORTED;
10274 }
10275
10276 /****************************************************************
10277  _spoolss_GetPrinterDriver
10278 ****************************************************************/
10279
10280 WERROR _spoolss_GetPrinterDriver(pipes_struct *p,
10281                                  struct spoolss_GetPrinterDriver *r)
10282 {
10283         p->rng_fault_state = true;
10284         return WERR_NOT_SUPPORTED;
10285 }
10286
10287 /****************************************************************
10288  _spoolss_ReadPrinter
10289 ****************************************************************/
10290
10291 WERROR _spoolss_ReadPrinter(pipes_struct *p,
10292                             struct spoolss_ReadPrinter *r)
10293 {
10294         p->rng_fault_state = true;
10295         return WERR_NOT_SUPPORTED;
10296 }
10297
10298 /****************************************************************
10299  _spoolss_GetPrinterData
10300 ****************************************************************/
10301
10302 WERROR _spoolss_GetPrinterData(pipes_struct *p,
10303                                struct spoolss_GetPrinterData *r)
10304 {
10305         p->rng_fault_state = true;
10306         return WERR_NOT_SUPPORTED;
10307 }
10308
10309 /****************************************************************
10310  _spoolss_SetPrinterData
10311 ****************************************************************/
10312
10313 WERROR _spoolss_SetPrinterData(pipes_struct *p,
10314                                struct spoolss_SetPrinterData *r)
10315 {
10316         p->rng_fault_state = true;
10317         return WERR_NOT_SUPPORTED;
10318 }
10319
10320 /****************************************************************
10321  _spoolss_WaitForPrinterChange
10322 ****************************************************************/
10323
10324 WERROR _spoolss_WaitForPrinterChange(pipes_struct *p,
10325                                      struct spoolss_WaitForPrinterChange *r)
10326 {
10327         p->rng_fault_state = true;
10328         return WERR_NOT_SUPPORTED;
10329 }
10330
10331 /****************************************************************
10332  _spoolss_AddPort
10333 ****************************************************************/
10334
10335 WERROR _spoolss_AddPort(pipes_struct *p,
10336                         struct spoolss_AddPort *r)
10337 {
10338         p->rng_fault_state = true;
10339         return WERR_NOT_SUPPORTED;
10340 }
10341
10342 /****************************************************************
10343  _spoolss_ConfigurePort
10344 ****************************************************************/
10345
10346 WERROR _spoolss_ConfigurePort(pipes_struct *p,
10347                               struct spoolss_ConfigurePort *r)
10348 {
10349         p->rng_fault_state = true;
10350         return WERR_NOT_SUPPORTED;
10351 }
10352
10353 /****************************************************************
10354  _spoolss_DeletePort
10355 ****************************************************************/
10356
10357 WERROR _spoolss_DeletePort(pipes_struct *p,
10358                            struct spoolss_DeletePort *r)
10359 {
10360         p->rng_fault_state = true;
10361         return WERR_NOT_SUPPORTED;
10362 }
10363
10364 /****************************************************************
10365  _spoolss_CreatePrinterIC
10366 ****************************************************************/
10367
10368 WERROR _spoolss_CreatePrinterIC(pipes_struct *p,
10369                                 struct spoolss_CreatePrinterIC *r)
10370 {
10371         p->rng_fault_state = true;
10372         return WERR_NOT_SUPPORTED;
10373 }
10374
10375 /****************************************************************
10376  _spoolss_PlayGDIScriptOnPrinterIC
10377 ****************************************************************/
10378
10379 WERROR _spoolss_PlayGDIScriptOnPrinterIC(pipes_struct *p,
10380                                          struct spoolss_PlayGDIScriptOnPrinterIC *r)
10381 {
10382         p->rng_fault_state = true;
10383         return WERR_NOT_SUPPORTED;
10384 }
10385
10386 /****************************************************************
10387  _spoolss_DeletePrinterIC
10388 ****************************************************************/
10389
10390 WERROR _spoolss_DeletePrinterIC(pipes_struct *p,
10391                                 struct spoolss_DeletePrinterIC *r)
10392 {
10393         p->rng_fault_state = true;
10394         return WERR_NOT_SUPPORTED;
10395 }
10396
10397 /****************************************************************
10398  _spoolss_AddPrinterConnection
10399 ****************************************************************/
10400
10401 WERROR _spoolss_AddPrinterConnection(pipes_struct *p,
10402                                      struct spoolss_AddPrinterConnection *r)
10403 {
10404         p->rng_fault_state = true;
10405         return WERR_NOT_SUPPORTED;
10406 }
10407
10408 /****************************************************************
10409  _spoolss_DeletePrinterConnection
10410 ****************************************************************/
10411
10412 WERROR _spoolss_DeletePrinterConnection(pipes_struct *p,
10413                                         struct spoolss_DeletePrinterConnection *r)
10414 {
10415         p->rng_fault_state = true;
10416         return WERR_NOT_SUPPORTED;
10417 }
10418
10419 /****************************************************************
10420  _spoolss_PrinterMessageBox
10421 ****************************************************************/
10422
10423 WERROR _spoolss_PrinterMessageBox(pipes_struct *p,
10424                                   struct spoolss_PrinterMessageBox *r)
10425 {
10426         p->rng_fault_state = true;
10427         return WERR_NOT_SUPPORTED;
10428 }
10429
10430 /****************************************************************
10431  _spoolss_AddMonitor
10432 ****************************************************************/
10433
10434 WERROR _spoolss_AddMonitor(pipes_struct *p,
10435                            struct spoolss_AddMonitor *r)
10436 {
10437         p->rng_fault_state = true;
10438         return WERR_NOT_SUPPORTED;
10439 }
10440
10441 /****************************************************************
10442  _spoolss_DeleteMonitor
10443 ****************************************************************/
10444
10445 WERROR _spoolss_DeleteMonitor(pipes_struct *p,
10446                               struct spoolss_DeleteMonitor *r)
10447 {
10448         p->rng_fault_state = true;
10449         return WERR_NOT_SUPPORTED;
10450 }
10451
10452 /****************************************************************
10453  _spoolss_DeletePrintProcessor
10454 ****************************************************************/
10455
10456 WERROR _spoolss_DeletePrintProcessor(pipes_struct *p,
10457                                      struct spoolss_DeletePrintProcessor *r)
10458 {
10459         p->rng_fault_state = true;
10460         return WERR_NOT_SUPPORTED;
10461 }
10462
10463 /****************************************************************
10464  _spoolss_AddPrintProvidor
10465 ****************************************************************/
10466
10467 WERROR _spoolss_AddPrintProvidor(pipes_struct *p,
10468                                  struct spoolss_AddPrintProvidor *r)
10469 {
10470         p->rng_fault_state = true;
10471         return WERR_NOT_SUPPORTED;
10472 }
10473
10474 /****************************************************************
10475  _spoolss_DeletePrintProvidor
10476 ****************************************************************/
10477
10478 WERROR _spoolss_DeletePrintProvidor(pipes_struct *p,
10479                                     struct spoolss_DeletePrintProvidor *r)
10480 {
10481         p->rng_fault_state = true;
10482         return WERR_NOT_SUPPORTED;
10483 }
10484
10485 /****************************************************************
10486  _spoolss_GetPrinterDriver2
10487 ****************************************************************/
10488
10489 WERROR _spoolss_GetPrinterDriver2(pipes_struct *p,
10490                                   struct spoolss_GetPrinterDriver2 *r)
10491 {
10492         p->rng_fault_state = true;
10493         return WERR_NOT_SUPPORTED;
10494 }
10495
10496 /****************************************************************
10497  _spoolss_FindFirstPrinterChangeNotification
10498 ****************************************************************/
10499
10500 WERROR _spoolss_FindFirstPrinterChangeNotification(pipes_struct *p,
10501                                                    struct spoolss_FindFirstPrinterChangeNotification *r)
10502 {
10503         p->rng_fault_state = true;
10504         return WERR_NOT_SUPPORTED;
10505 }
10506
10507 /****************************************************************
10508  _spoolss_FindNextPrinterChangeNotification
10509 ****************************************************************/
10510
10511 WERROR _spoolss_FindNextPrinterChangeNotification(pipes_struct *p,
10512                                                   struct spoolss_FindNextPrinterChangeNotification *r)
10513 {
10514         p->rng_fault_state = true;
10515         return WERR_NOT_SUPPORTED;
10516 }
10517
10518 /****************************************************************
10519  _spoolss_RouterFindFirstPrinterChangeNotificationOld
10520 ****************************************************************/
10521
10522 WERROR _spoolss_RouterFindFirstPrinterChangeNotificationOld(pipes_struct *p,
10523                                                             struct spoolss_RouterFindFirstPrinterChangeNotificationOld *r)
10524 {
10525         p->rng_fault_state = true;
10526         return WERR_NOT_SUPPORTED;
10527 }
10528
10529 /****************************************************************
10530  _spoolss_ReplyOpenPrinter
10531 ****************************************************************/
10532
10533 WERROR _spoolss_ReplyOpenPrinter(pipes_struct *p,
10534                                  struct spoolss_ReplyOpenPrinter *r)
10535 {
10536         p->rng_fault_state = true;
10537         return WERR_NOT_SUPPORTED;
10538 }
10539
10540 /****************************************************************
10541  _spoolss_RouterReplyPrinter
10542 ****************************************************************/
10543
10544 WERROR _spoolss_RouterReplyPrinter(pipes_struct *p,
10545                                    struct spoolss_RouterReplyPrinter *r)
10546 {
10547         p->rng_fault_state = true;
10548         return WERR_NOT_SUPPORTED;
10549 }
10550
10551 /****************************************************************
10552  _spoolss_ReplyClosePrinter
10553 ****************************************************************/
10554
10555 WERROR _spoolss_ReplyClosePrinter(pipes_struct *p,
10556                                   struct spoolss_ReplyClosePrinter *r)
10557 {
10558         p->rng_fault_state = true;
10559         return WERR_NOT_SUPPORTED;
10560 }
10561
10562 /****************************************************************
10563  _spoolss_AddPortEx
10564 ****************************************************************/
10565
10566 WERROR _spoolss_AddPortEx(pipes_struct *p,
10567                           struct spoolss_AddPortEx *r)
10568 {
10569         p->rng_fault_state = true;
10570         return WERR_NOT_SUPPORTED;
10571 }
10572
10573 /****************************************************************
10574  _spoolss_RouterFindFirstPrinterChangeNotification
10575 ****************************************************************/
10576
10577 WERROR _spoolss_RouterFindFirstPrinterChangeNotification(pipes_struct *p,
10578                                                          struct spoolss_RouterFindFirstPrinterChangeNotification *r)
10579 {
10580         p->rng_fault_state = true;
10581         return WERR_NOT_SUPPORTED;
10582 }
10583
10584 /****************************************************************
10585  _spoolss_SpoolerInit
10586 ****************************************************************/
10587
10588 WERROR _spoolss_SpoolerInit(pipes_struct *p,
10589                             struct spoolss_SpoolerInit *r)
10590 {
10591         p->rng_fault_state = true;
10592         return WERR_NOT_SUPPORTED;
10593 }
10594
10595 /****************************************************************
10596  _spoolss_ResetPrinterEx
10597 ****************************************************************/
10598
10599 WERROR _spoolss_ResetPrinterEx(pipes_struct *p,
10600                                struct spoolss_ResetPrinterEx *r)
10601 {
10602         p->rng_fault_state = true;
10603         return WERR_NOT_SUPPORTED;
10604 }
10605
10606 /****************************************************************
10607  _spoolss_RouterReplyPrinterEx
10608 ****************************************************************/
10609
10610 WERROR _spoolss_RouterReplyPrinterEx(pipes_struct *p,
10611                                      struct spoolss_RouterReplyPrinterEx *r)
10612 {
10613         p->rng_fault_state = true;
10614         return WERR_NOT_SUPPORTED;
10615 }
10616
10617 /****************************************************************
10618  _spoolss_44
10619 ****************************************************************/
10620
10621 WERROR _spoolss_44(pipes_struct *p,
10622                    struct spoolss_44 *r)
10623 {
10624         p->rng_fault_state = true;
10625         return WERR_NOT_SUPPORTED;
10626 }
10627
10628 /****************************************************************
10629  _spoolss_47
10630 ****************************************************************/
10631
10632 WERROR _spoolss_47(pipes_struct *p,
10633                    struct spoolss_47 *r)
10634 {
10635         p->rng_fault_state = true;
10636         return WERR_NOT_SUPPORTED;
10637 }
10638
10639 /****************************************************************
10640  _spoolss_EnumPrinterData
10641 ****************************************************************/
10642
10643 WERROR _spoolss_EnumPrinterData(pipes_struct *p,
10644                                 struct spoolss_EnumPrinterData *r)
10645 {
10646         p->rng_fault_state = true;
10647         return WERR_NOT_SUPPORTED;
10648 }
10649
10650 /****************************************************************
10651  _spoolss_4a
10652 ****************************************************************/
10653
10654 WERROR _spoolss_4a(pipes_struct *p,
10655                    struct spoolss_4a *r)
10656 {
10657         p->rng_fault_state = true;
10658         return WERR_NOT_SUPPORTED;
10659 }
10660
10661 /****************************************************************
10662  _spoolss_4b
10663 ****************************************************************/
10664
10665 WERROR _spoolss_4b(pipes_struct *p,
10666                    struct spoolss_4b *r)
10667 {
10668         p->rng_fault_state = true;
10669         return WERR_NOT_SUPPORTED;
10670 }
10671
10672 /****************************************************************
10673  _spoolss_4c
10674 ****************************************************************/
10675
10676 WERROR _spoolss_4c(pipes_struct *p,
10677                    struct spoolss_4c *r)
10678 {
10679         p->rng_fault_state = true;
10680         return WERR_NOT_SUPPORTED;
10681 }
10682
10683 /****************************************************************
10684  _spoolss_EnumPrinterDataEx
10685 ****************************************************************/
10686
10687 WERROR _spoolss_EnumPrinterDataEx(pipes_struct *p,
10688                                   struct spoolss_EnumPrinterDataEx *r)
10689 {
10690         p->rng_fault_state = true;
10691         return WERR_NOT_SUPPORTED;
10692 }
10693
10694 /****************************************************************
10695  _spoolss_EnumPrinterKey
10696 ****************************************************************/
10697
10698 WERROR _spoolss_EnumPrinterKey(pipes_struct *p,
10699                                struct spoolss_EnumPrinterKey *r)
10700 {
10701         p->rng_fault_state = true;
10702         return WERR_NOT_SUPPORTED;
10703 }
10704
10705 /****************************************************************
10706  _spoolss_53
10707 ****************************************************************/
10708
10709 WERROR _spoolss_53(pipes_struct *p,
10710                    struct spoolss_53 *r)
10711 {
10712         p->rng_fault_state = true;
10713         return WERR_NOT_SUPPORTED;
10714 }
10715
10716 /****************************************************************
10717  _spoolss_55
10718 ****************************************************************/
10719
10720 WERROR _spoolss_55(pipes_struct *p,
10721                    struct spoolss_55 *r)
10722 {
10723         p->rng_fault_state = true;
10724         return WERR_NOT_SUPPORTED;
10725 }
10726
10727 /****************************************************************
10728  _spoolss_56
10729 ****************************************************************/
10730
10731 WERROR _spoolss_56(pipes_struct *p,
10732                    struct spoolss_56 *r)
10733 {
10734         p->rng_fault_state = true;
10735         return WERR_NOT_SUPPORTED;
10736 }
10737
10738 /****************************************************************
10739  _spoolss_57
10740 ****************************************************************/
10741
10742 WERROR _spoolss_57(pipes_struct *p,
10743                    struct spoolss_57 *r)
10744 {
10745         p->rng_fault_state = true;
10746         return WERR_NOT_SUPPORTED;
10747 }
10748
10749 /****************************************************************
10750  _spoolss_5a
10751 ****************************************************************/
10752
10753 WERROR _spoolss_5a(pipes_struct *p,
10754                    struct spoolss_5a *r)
10755 {
10756         p->rng_fault_state = true;
10757         return WERR_NOT_SUPPORTED;
10758 }
10759
10760 /****************************************************************
10761  _spoolss_5b
10762 ****************************************************************/
10763
10764 WERROR _spoolss_5b(pipes_struct *p,
10765                    struct spoolss_5b *r)
10766 {
10767         p->rng_fault_state = true;
10768         return WERR_NOT_SUPPORTED;
10769 }
10770
10771 /****************************************************************
10772  _spoolss_5c
10773 ****************************************************************/
10774
10775 WERROR _spoolss_5c(pipes_struct *p,
10776                    struct spoolss_5c *r)
10777 {
10778         p->rng_fault_state = true;
10779         return WERR_NOT_SUPPORTED;
10780 }
10781
10782 /****************************************************************
10783  _spoolss_5d
10784 ****************************************************************/
10785
10786 WERROR _spoolss_5d(pipes_struct *p,
10787                    struct spoolss_5d *r)
10788 {
10789         p->rng_fault_state = true;
10790         return WERR_NOT_SUPPORTED;
10791 }
10792
10793 /****************************************************************
10794  _spoolss_5e
10795 ****************************************************************/
10796
10797 WERROR _spoolss_5e(pipes_struct *p,
10798                    struct spoolss_5e *r)
10799 {
10800         p->rng_fault_state = true;
10801         return WERR_NOT_SUPPORTED;
10802 }
10803
10804 /****************************************************************
10805  _spoolss_5f
10806 ****************************************************************/
10807
10808 WERROR _spoolss_5f(pipes_struct *p,
10809                    struct spoolss_5f *r)
10810 {
10811         p->rng_fault_state = true;
10812         return WERR_NOT_SUPPORTED;
10813 }
10814