s3-spoolss: make us pass the RPC-SPOOLSS torture test w.r.t. directory calls.
[vlendec/samba-autobuild/.git] / source3 / rpc_server / srv_spoolss_nt.c
1 /*
2  *  Unix SMB/CIFS implementation.
3  *  RPC Pipe client / server routines
4  *  Copyright (C) Andrew Tridgell              1992-2000,
5  *  Copyright (C) Luke Kenneth Casson Leighton 1996-2000,
6  *  Copyright (C) Jean François Micouleau      1998-2000,
7  *  Copyright (C) Jeremy Allison               2001-2002,
8  *  Copyright (C) Gerald Carter                2000-2004,
9  *  Copyright (C) Tim Potter                   2001-2002.
10  *
11  *  This program is free software; you can redistribute it and/or modify
12  *  it under the terms of the GNU General Public License as published by
13  *  the Free Software Foundation; either version 3 of the License, or
14  *  (at your option) any later version.
15  *
16  *  This program is distributed in the hope that it will be useful,
17  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
18  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19  *  GNU General Public License for more details.
20  *
21  *  You should have received a copy of the GNU General Public License
22  *  along with this program; if not, see <http://www.gnu.org/licenses/>.
23  */
24
25 /* Since the SPOOLSS rpc routines are basically DOS 16-bit calls wrapped
26    up, all the errors returned are DOS errors, not NT status codes. */
27
28 #include "includes.h"
29
30 extern userdom_struct current_user_info;
31
32 #undef DBGC_CLASS
33 #define DBGC_CLASS DBGC_RPC_SRV
34
35 #ifndef MAX_OPEN_PRINTER_EXS
36 #define MAX_OPEN_PRINTER_EXS 50
37 #endif
38
39 #define MAGIC_DISPLAY_FREQUENCY 0xfade2bad
40 #define PHANTOM_DEVMODE_KEY "_p_f_a_n_t_0_m_"
41
42 struct table_node {
43         const char    *long_archi;
44         const char    *short_archi;
45         int     version;
46 };
47
48 static Printer_entry *printers_list;
49
50 typedef struct _counter_printer_0 {
51         struct _counter_printer_0 *next;
52         struct _counter_printer_0 *prev;
53
54         int snum;
55         uint32 counter;
56 } counter_printer_0;
57
58 static counter_printer_0 *counter_list;
59
60 static struct rpc_pipe_client *notify_cli_pipe; /* print notify back-channel pipe handle*/
61 static uint32 smb_connections=0;
62
63
64 /* in printing/nt_printing.c */
65
66 extern struct standard_mapping printer_std_mapping, printserver_std_mapping;
67
68 /* API table for Xcv Monitor functions */
69
70 struct xcv_api_table {
71         const char *name;
72         WERROR(*fn) (TALLOC_CTX *mem_ctx, NT_USER_TOKEN *token, DATA_BLOB *in, DATA_BLOB *out, uint32_t *needed);
73 };
74
75 /********************************************************************
76  * Canonicalize servername.
77  ********************************************************************/
78
79 static const char *canon_servername(const char *servername)
80 {
81         const char *pservername = servername;
82         while (*pservername == '\\') {
83                 pservername++;
84         }
85         return pservername;
86 }
87
88 /* translate between internal status numbers and NT status numbers */
89 static int nt_printj_status(int v)
90 {
91         switch (v) {
92         case LPQ_QUEUED:
93                 return 0;
94         case LPQ_PAUSED:
95                 return JOB_STATUS_PAUSED;
96         case LPQ_SPOOLING:
97                 return JOB_STATUS_SPOOLING;
98         case LPQ_PRINTING:
99                 return JOB_STATUS_PRINTING;
100         case LPQ_ERROR:
101                 return JOB_STATUS_ERROR;
102         case LPQ_DELETING:
103                 return JOB_STATUS_DELETING;
104         case LPQ_OFFLINE:
105                 return JOB_STATUS_OFFLINE;
106         case LPQ_PAPEROUT:
107                 return JOB_STATUS_PAPEROUT;
108         case LPQ_PRINTED:
109                 return JOB_STATUS_PRINTED;
110         case LPQ_DELETED:
111                 return JOB_STATUS_DELETED;
112         case LPQ_BLOCKED:
113                 return JOB_STATUS_BLOCKED;
114         case LPQ_USER_INTERVENTION:
115                 return JOB_STATUS_USER_INTERVENTION;
116         }
117         return 0;
118 }
119
120 static int nt_printq_status(int v)
121 {
122         switch (v) {
123         case LPQ_PAUSED:
124                 return PRINTER_STATUS_PAUSED;
125         case LPQ_QUEUED:
126         case LPQ_SPOOLING:
127         case LPQ_PRINTING:
128                 return 0;
129         }
130         return 0;
131 }
132
133 /***************************************************************************
134  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 { PRINT_TABLE_END, 0x0, NULL, 0x0, NULL },
3490 };
3491
3492 /*******************************************************************
3493  Return the variable_type of info_data structure.
3494 ********************************************************************/
3495
3496 static uint32_t variable_type_of_notify_info_data(enum spoolss_NotifyType type,
3497                                                   enum spoolss_Field field)
3498 {
3499         int i=0;
3500
3501         for (i = 0; i < ARRAY_SIZE(notify_info_data_table); i++) {
3502                 if ( (notify_info_data_table[i].type == type) &&
3503                      (notify_info_data_table[i].field == field) ) {
3504                         return notify_info_data_table[i].variable_type;
3505                 }
3506         }
3507
3508         DEBUG(5, ("invalid notify data type %d/%d\n", type, field));
3509
3510         return 0;
3511 }
3512
3513 /****************************************************************************
3514 ****************************************************************************/
3515
3516 static bool search_notify(enum spoolss_NotifyType type,
3517                           enum spoolss_Field field,
3518                           int *value)
3519 {
3520         int i;
3521
3522         for (i = 0; notify_info_data_table[i].type != PRINT_TABLE_END; i++) {
3523                 if (notify_info_data_table[i].type == type &&
3524                     notify_info_data_table[i].field == field &&
3525                     notify_info_data_table[i].fn != NULL) {
3526                         *value = i;
3527                         return True;
3528                 }
3529         }
3530
3531         return False;
3532 }
3533
3534 /****************************************************************************
3535 ****************************************************************************/
3536
3537 void construct_info_data(struct spoolss_Notify *info_data,
3538                          enum spoolss_NotifyType type,
3539                          enum spoolss_Field field,
3540                          int id)
3541 {
3542         info_data->type                 = type;
3543         info_data->field                = field;
3544         info_data->variable_type        = variable_type_of_notify_info_data(type, field);
3545         info_data->job_id               = id;
3546 }
3547
3548 /*******************************************************************
3549  *
3550  * fill a notify_info struct with info asked
3551  *
3552  ********************************************************************/
3553
3554 static bool construct_notify_printer_info(Printer_entry *print_hnd,
3555                                           struct spoolss_NotifyInfo *info,
3556                                           int snum,
3557                                           const struct spoolss_NotifyOptionType *option_type,
3558                                           uint32_t id,
3559                                           TALLOC_CTX *mem_ctx)
3560 {
3561         int field_num,j;
3562         enum spoolss_NotifyType type;
3563         enum spoolss_Field field;
3564
3565         struct spoolss_Notify *current_data;
3566         NT_PRINTER_INFO_LEVEL *printer = NULL;
3567         print_queue_struct *queue=NULL;
3568
3569         type = option_type->type;
3570
3571         DEBUG(4,("construct_notify_printer_info: Notify type: [%s], number of notify info: [%d] on printer: [%s]\n",
3572                 (type == PRINTER_NOTIFY_TYPE ? "PRINTER_NOTIFY_TYPE" : "JOB_NOTIFY_TYPE"),
3573                 option_type->count, lp_servicename(snum)));
3574
3575         if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &printer, 2, lp_const_servicename(snum))))
3576                 return False;
3577
3578         for(field_num=0; field_num < option_type->count; field_num++) {
3579                 field = option_type->fields[field_num];
3580
3581                 DEBUG(4,("construct_notify_printer_info: notify [%d]: type [%x], field [%x]\n", field_num, type, field));
3582
3583                 if (!search_notify(type, field, &j) )
3584                         continue;
3585
3586                 info->notifies = TALLOC_REALLOC_ARRAY(info, info->notifies,
3587                                                       struct spoolss_Notify,
3588                                                       info->count + 1);
3589                 if (info->notifies == NULL) {
3590                         DEBUG(2,("construct_notify_printer_info: failed to enlarge buffer info->data!\n"));
3591                         free_a_printer(&printer, 2);
3592                         return False;
3593                 }
3594
3595                 current_data = &info->notifies[info->count];
3596
3597                 construct_info_data(current_data, type, field, id);
3598
3599                 DEBUG(10,("construct_notify_printer_info: calling [%s]  snum=%d  printername=[%s])\n",
3600                                 notify_info_data_table[j].name, snum, printer->info_2->printername ));
3601
3602                 notify_info_data_table[j].fn(snum, current_data, queue,
3603                                              printer, mem_ctx);
3604
3605                 info->count++;
3606         }
3607
3608         free_a_printer(&printer, 2);
3609         return True;
3610 }
3611
3612 /*******************************************************************
3613  *
3614  * fill a notify_info struct with info asked
3615  *
3616  ********************************************************************/
3617
3618 static bool construct_notify_jobs_info(print_queue_struct *queue,
3619                                        struct spoolss_NotifyInfo *info,
3620                                        NT_PRINTER_INFO_LEVEL *printer,
3621                                        int snum,
3622                                        const struct spoolss_NotifyOptionType *option_type,
3623                                        uint32_t id,
3624                                        TALLOC_CTX *mem_ctx)
3625 {
3626         int field_num,j;
3627         enum spoolss_NotifyType type;
3628         enum spoolss_Field field;
3629         struct spoolss_Notify *current_data;
3630
3631         DEBUG(4,("construct_notify_jobs_info\n"));
3632
3633         type = option_type->type;
3634
3635         DEBUGADD(4,("Notify type: [%s], number of notify info: [%d]\n",
3636                 (type == PRINTER_NOTIFY_TYPE ? "PRINTER_NOTIFY_TYPE" : "JOB_NOTIFY_TYPE"),
3637                 option_type->count));
3638
3639         for(field_num=0; field_num<option_type->count; field_num++) {
3640                 field = option_type->fields[field_num];
3641
3642                 if (!search_notify(type, field, &j) )
3643                         continue;
3644
3645                 info->notifies = TALLOC_REALLOC_ARRAY(info, info->notifies,
3646                                                       struct spoolss_Notify,
3647                                                       info->count + 1);
3648                 if (info->notifies == NULL) {
3649                         DEBUG(2,("construct_notify_jobs_info: failed to enlarg buffer info->data!\n"));
3650                         return False;
3651                 }
3652
3653                 current_data=&(info->notifies[info->count]);
3654
3655                 construct_info_data(current_data, type, field, id);
3656                 notify_info_data_table[j].fn(snum, current_data, queue,
3657                                              printer, mem_ctx);
3658                 info->count++;
3659         }
3660
3661         return True;
3662 }
3663
3664 /*
3665  * JFM: The enumeration is not that simple, it's even non obvious.
3666  *
3667  * let's take an example: I want to monitor the PRINTER SERVER for
3668  * the printer's name and the number of jobs currently queued.
3669  * So in the NOTIFY_OPTION, I have one NOTIFY_OPTION_TYPE structure.
3670  * Its type is PRINTER_NOTIFY_TYPE and it has 2 fields NAME and CJOBS.
3671  *
3672  * I have 3 printers on the back of my server.
3673  *
3674  * Now the response is a NOTIFY_INFO structure, with 6 NOTIFY_INFO_DATA
3675  * structures.
3676  *   Number     Data                    Id
3677  *      1       printer 1 name          1
3678  *      2       printer 1 cjob          1
3679  *      3       printer 2 name          2
3680  *      4       printer 2 cjob          2
3681  *      5       printer 3 name          3
3682  *      6       printer 3 name          3
3683  *
3684  * that's the print server case, the printer case is even worse.
3685  */
3686
3687 /*******************************************************************
3688  *
3689  * enumerate all printers on the printserver
3690  * fill a notify_info struct with info asked
3691  *
3692  ********************************************************************/
3693
3694 static WERROR printserver_notify_info(pipes_struct *p, POLICY_HND *hnd,
3695                                       struct spoolss_NotifyInfo *info,
3696                                       TALLOC_CTX *mem_ctx)
3697 {
3698         int snum;
3699         Printer_entry *Printer=find_printer_index_by_hnd(p, hnd);
3700         int n_services=lp_numservices();
3701         int i;
3702         struct spoolss_NotifyOption *option;
3703         struct spoolss_NotifyOptionType option_type;
3704
3705         DEBUG(4,("printserver_notify_info\n"));
3706
3707         if (!Printer)
3708                 return WERR_BADFID;
3709
3710         option = Printer->notify.option;
3711
3712         info->version   = 2;
3713         info->notifies  = NULL;
3714         info->count     = 0;
3715
3716         /* a bug in xp sp2 rc2 causes it to send a fnpcn request without
3717            sending a ffpcn() request first */
3718
3719         if ( !option )
3720                 return WERR_BADFID;
3721
3722         for (i=0; i<option->count; i++) {
3723                 option_type = option->types[i];
3724
3725                 if (option_type.type != PRINTER_NOTIFY_TYPE)
3726                         continue;
3727
3728                 for (snum=0; snum<n_services; snum++)
3729                 {
3730                         if ( lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) )
3731                                 construct_notify_printer_info ( Printer, info, snum, &option_type, snum, mem_ctx );
3732                 }
3733         }
3734
3735 #if 0
3736         /*
3737          * Debugging information, don't delete.
3738          */
3739
3740         DEBUG(1,("dumping the NOTIFY_INFO\n"));
3741         DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
3742         DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3743
3744         for (i=0; i<info->count; i++) {
3745                 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3746                 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
3747                 info->data[i].id, info->data[i].size, info->data[i].enc_type));
3748         }
3749 #endif
3750
3751         return WERR_OK;
3752 }
3753
3754 /*******************************************************************
3755  *
3756  * fill a notify_info struct with info asked
3757  *
3758  ********************************************************************/
3759
3760 static WERROR printer_notify_info(pipes_struct *p, POLICY_HND *hnd, struct spoolss_NotifyInfo *info,
3761                                   TALLOC_CTX *mem_ctx)
3762 {
3763         int snum;
3764         Printer_entry *Printer=find_printer_index_by_hnd(p, hnd);
3765         int i;
3766         uint32 id;
3767         struct spoolss_NotifyOption *option;
3768         struct spoolss_NotifyOptionType option_type;
3769         int count,j;
3770         print_queue_struct *queue=NULL;
3771         print_status_struct status;
3772
3773         DEBUG(4,("printer_notify_info\n"));
3774
3775         if (!Printer)
3776                 return WERR_BADFID;
3777
3778         option = Printer->notify.option;
3779         id = 0x0;
3780
3781         info->version   = 2;
3782         info->notifies  = NULL;
3783         info->count     = 0;
3784
3785         /* a bug in xp sp2 rc2 causes it to send a fnpcn request without
3786            sending a ffpcn() request first */
3787
3788         if ( !option )
3789                 return WERR_BADFID;
3790
3791         get_printer_snum(p, hnd, &snum, NULL);
3792
3793         for (i=0; i<option->count; i++) {
3794                 option_type = option->types[i];
3795
3796                 switch (option_type.type) {
3797                 case PRINTER_NOTIFY_TYPE:
3798                         if(construct_notify_printer_info(Printer, info, snum,
3799                                                          &option_type, id,
3800                                                          mem_ctx))
3801                                 id--;
3802                         break;
3803
3804                 case JOB_NOTIFY_TYPE: {
3805                         NT_PRINTER_INFO_LEVEL *printer = NULL;
3806
3807                         count = print_queue_status(snum, &queue, &status);
3808
3809                         if (!W_ERROR_IS_OK(get_a_printer(Printer, &printer, 2, lp_const_servicename(snum))))
3810                                 goto done;
3811
3812                         for (j=0; j<count; j++) {
3813                                 construct_notify_jobs_info(&queue[j], info,
3814                                                            printer, snum,
3815                                                            &option_type,
3816                                                            queue[j].job,
3817                                                            mem_ctx);
3818                         }
3819
3820                         free_a_printer(&printer, 2);
3821
3822                 done:
3823                         SAFE_FREE(queue);
3824                         break;
3825                 }
3826                 }
3827         }
3828
3829         /*
3830          * Debugging information, don't delete.
3831          */
3832         /*
3833         DEBUG(1,("dumping the NOTIFY_INFO\n"));
3834         DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
3835         DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3836
3837         for (i=0; i<info->count; i++) {
3838                 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3839                 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
3840                 info->data[i].id, info->data[i].size, info->data[i].enc_type));
3841         }
3842         */
3843         return WERR_OK;
3844 }
3845
3846 /****************************************************************
3847  _spoolss_RouterRefreshPrinterChangeNotify
3848 ****************************************************************/
3849
3850 WERROR _spoolss_RouterRefreshPrinterChangeNotify(pipes_struct *p,
3851                                                  struct spoolss_RouterRefreshPrinterChangeNotify *r)
3852 {
3853         POLICY_HND *handle = r->in.handle;
3854         struct spoolss_NotifyInfo *info;
3855
3856         Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
3857         WERROR result = WERR_BADFID;
3858
3859         /* we always have a spoolss_NotifyInfo struct */
3860         info = talloc_zero(p->mem_ctx, struct spoolss_NotifyInfo);
3861         if (!info) {
3862                 result = WERR_NOMEM;
3863                 goto done;
3864         }
3865
3866         *r->out.info = info;
3867
3868         if (!Printer) {
3869                 DEBUG(2,("_spoolss_RouterRefreshPrinterChangeNotify: "
3870                         "Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
3871                 goto done;
3872         }
3873
3874         DEBUG(4,("Printer type %x\n",Printer->printer_type));
3875
3876         /*
3877          *      We are now using the change value, and
3878          *      I should check for PRINTER_NOTIFY_OPTIONS_REFRESH but as
3879          *      I don't have a global notification system, I'm sending back all the
3880          *      informations even when _NOTHING_ has changed.
3881          */
3882
3883         /* We need to keep track of the change value to send back in
3884            RRPCN replies otherwise our updates are ignored. */
3885
3886         Printer->notify.fnpcn = True;
3887
3888         if (Printer->notify.client_connected) {
3889                 DEBUG(10,("_spoolss_RouterRefreshPrinterChangeNotify: "
3890                         "Saving change value in request [%x]\n",
3891                         r->in.change_low));
3892                 Printer->notify.change = r->in.change_low;
3893         }
3894
3895         /* just ignore the spoolss_NotifyOption */
3896
3897         switch (Printer->printer_type) {
3898                 case SPLHND_SERVER:
3899                         result = printserver_notify_info(p, handle, info, p->mem_ctx);
3900                         break;
3901
3902                 case SPLHND_PRINTER:
3903                         result = printer_notify_info(p, handle, info, p->mem_ctx);
3904                         break;
3905         }
3906
3907         Printer->notify.fnpcn = False;
3908
3909 done:
3910         return result;
3911 }
3912
3913 /********************************************************************
3914  * construct_printer_info_0
3915  * fill a printer_info_0 struct
3916  ********************************************************************/
3917
3918 static bool construct_printer_info_0(Printer_entry *print_hnd, PRINTER_INFO_0 *printer, int snum)
3919 {
3920         char *chaine = NULL;
3921         int count;
3922         NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
3923         counter_printer_0 *session_counter;
3924         uint32 global_counter;
3925         struct tm *t;
3926         time_t setuptime;
3927         print_status_struct status;
3928         TALLOC_CTX *ctx = talloc_tos();
3929
3930         if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
3931                 return False;
3932
3933         init_unistr(&printer->printername, ntprinter->info_2->printername);
3934
3935         chaine = talloc_asprintf(ctx, "\\\\%s", get_server_name(print_hnd));
3936         if (!chaine) {
3937                 free_a_printer(&ntprinter,2);
3938                 return false;
3939         }
3940
3941         count = print_queue_length(snum, &status);
3942
3943         /* check if we already have a counter for this printer */
3944         for(session_counter = counter_list; session_counter; session_counter = session_counter->next) {
3945                 if (session_counter->snum == snum)
3946                         break;
3947         }
3948
3949         init_unistr(&printer->servername, chaine);
3950
3951         /* it's the first time, add it to the list */
3952         if (session_counter==NULL) {
3953                 if((session_counter=SMB_MALLOC_P(counter_printer_0)) == NULL) {
3954                         free_a_printer(&ntprinter, 2);
3955                         return False;
3956                 }
3957                 ZERO_STRUCTP(session_counter);
3958                 session_counter->snum=snum;
3959                 session_counter->counter=0;
3960                 DLIST_ADD(counter_list, session_counter);
3961         }
3962
3963         /* increment it */
3964         session_counter->counter++;
3965
3966         /* JFM:
3967          * the global_counter should be stored in a TDB as it's common to all the clients
3968          * and should be zeroed on samba startup
3969          */
3970         global_counter=session_counter->counter;
3971         printer->cjobs = count;
3972         printer->total_jobs = 0;
3973         printer->total_bytes = 0;
3974
3975         setuptime = (time_t)ntprinter->info_2->setuptime;
3976         t=gmtime(&setuptime);
3977
3978         printer->year = t->tm_year+1900;
3979         printer->month = t->tm_mon+1;
3980         printer->dayofweek = t->tm_wday;
3981         printer->day = t->tm_mday;
3982         printer->hour = t->tm_hour;
3983         printer->minute = t->tm_min;
3984         printer->second = t->tm_sec;
3985         printer->milliseconds = 0;
3986
3987         printer->global_counter = global_counter;
3988         printer->total_pages = 0;
3989
3990         /* in 2.2 we reported ourselves as 0x0004 and 0x0565 */
3991         printer->major_version = 0x0005;        /* NT 5 */
3992         printer->build_version = 0x0893;        /* build 2195 */
3993
3994         printer->unknown7 = 0x1;
3995         printer->unknown8 = 0x0;
3996         printer->unknown9 = 0x0;
3997         printer->session_counter = session_counter->counter;
3998         printer->unknown11 = 0x0;
3999         printer->printer_errors = 0x0;          /* number of print failure */
4000         printer->unknown13 = 0x0;
4001         printer->unknown14 = 0x1;
4002         printer->unknown15 = 0x024a;            /* 586 Pentium ? */
4003         printer->unknown16 =  0x0;
4004         printer->change_id = ntprinter->info_2->changeid; /* ChangeID in milliseconds*/
4005         printer->unknown18 =  0x0;
4006         printer->status = nt_printq_status(status.status);
4007         printer->unknown20 =  0x0;
4008         printer->c_setprinter = get_c_setprinter(); /* monotonically increasing sum of delta printer counts */
4009         printer->unknown22 = 0x0;
4010         printer->unknown23 = 0x6;               /* 6  ???*/
4011         printer->unknown24 = 0;                 /* unknown 24 to 26 are always 0 */
4012         printer->unknown25 = 0;
4013         printer->unknown26 = 0;
4014         printer->unknown27 = 0;
4015         printer->unknown28 = 0;
4016         printer->unknown29 = 0;
4017
4018         free_a_printer(&ntprinter,2);
4019         return (True);
4020 }
4021
4022 /********************************************************************
4023  * construct_printer_info_1
4024  * fill a printer_info_1 struct
4025  ********************************************************************/
4026 static bool construct_printer_info_1(Printer_entry *print_hnd, uint32 flags, PRINTER_INFO_1 *printer, int snum)
4027 {
4028         char *chaine = NULL;
4029         NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4030         TALLOC_CTX *ctx = talloc_tos();
4031
4032         if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
4033                 return false;
4034
4035         printer->flags=flags;
4036
4037         if (*ntprinter->info_2->comment == '\0') {
4038                 init_unistr(&printer->comment, lp_comment(snum));
4039                 chaine = talloc_asprintf(ctx,
4040                                 "%s,%s,%s", ntprinter->info_2->printername,
4041                                 ntprinter->info_2->drivername, lp_comment(snum));
4042         }
4043         else {
4044                 init_unistr(&printer->comment, ntprinter->info_2->comment); /* saved comment. */
4045                 chaine = talloc_asprintf(ctx,
4046                                 "%s,%s,%s", ntprinter->info_2->printername,
4047                                 ntprinter->info_2->drivername, ntprinter->info_2->comment);
4048         }
4049
4050         if (!chaine) {
4051                 free_a_printer(&ntprinter,2);
4052                 return false;
4053         }
4054
4055         init_unistr(&printer->description, chaine);
4056         init_unistr(&printer->name, ntprinter->info_2->printername);
4057
4058         free_a_printer(&ntprinter,2);
4059
4060         return True;
4061 }
4062
4063 /****************************************************************************
4064  Free a DEVMODE struct.
4065 ****************************************************************************/
4066
4067 static void free_dev_mode(DEVICEMODE *dev)
4068 {
4069         if (dev == NULL)
4070                 return;
4071
4072         SAFE_FREE(dev->dev_private);
4073         SAFE_FREE(dev);
4074 }
4075
4076
4077 /****************************************************************************
4078  Convert an NT_DEVICEMODE to a DEVICEMODE structure.  Both pointers
4079  should be valid upon entry
4080 ****************************************************************************/
4081
4082 static bool convert_nt_devicemode( DEVICEMODE *devmode, NT_DEVICEMODE *ntdevmode )
4083 {
4084         if ( !devmode || !ntdevmode )
4085                 return False;
4086
4087         init_unistr(&devmode->devicename, ntdevmode->devicename);
4088
4089         init_unistr(&devmode->formname, ntdevmode->formname);
4090
4091         devmode->specversion      = ntdevmode->specversion;
4092         devmode->driverversion    = ntdevmode->driverversion;
4093         devmode->size             = ntdevmode->size;
4094         devmode->driverextra      = ntdevmode->driverextra;
4095         devmode->fields           = ntdevmode->fields;
4096
4097         devmode->orientation      = ntdevmode->orientation;
4098         devmode->papersize        = ntdevmode->papersize;
4099         devmode->paperlength      = ntdevmode->paperlength;
4100         devmode->paperwidth       = ntdevmode->paperwidth;
4101         devmode->scale            = ntdevmode->scale;
4102         devmode->copies           = ntdevmode->copies;
4103         devmode->defaultsource    = ntdevmode->defaultsource;
4104         devmode->printquality     = ntdevmode->printquality;
4105         devmode->color            = ntdevmode->color;
4106         devmode->duplex           = ntdevmode->duplex;
4107         devmode->yresolution      = ntdevmode->yresolution;
4108         devmode->ttoption         = ntdevmode->ttoption;
4109         devmode->collate          = ntdevmode->collate;
4110         devmode->icmmethod        = ntdevmode->icmmethod;
4111         devmode->icmintent        = ntdevmode->icmintent;
4112         devmode->mediatype        = ntdevmode->mediatype;
4113         devmode->dithertype       = ntdevmode->dithertype;
4114
4115         if (ntdevmode->nt_dev_private != NULL) {
4116                 if ((devmode->dev_private=(uint8 *)memdup(ntdevmode->nt_dev_private, ntdevmode->driverextra)) == NULL)
4117                         return False;
4118         }
4119
4120         return True;
4121 }
4122
4123 /****************************************************************************
4124  Create a DEVMODE struct. Returns malloced memory.
4125 ****************************************************************************/
4126
4127 DEVICEMODE *construct_dev_mode(const char *servicename)
4128 {
4129         NT_PRINTER_INFO_LEVEL   *printer = NULL;
4130         DEVICEMODE              *devmode = NULL;
4131
4132         DEBUG(7,("construct_dev_mode\n"));
4133
4134         DEBUGADD(8,("getting printer characteristics\n"));
4135
4136         if (!W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, servicename)))
4137                 return NULL;
4138
4139         if ( !printer->info_2->devmode ) {
4140                 DEBUG(5, ("BONG! There was no device mode!\n"));
4141                 goto done;
4142         }
4143
4144         if ((devmode = SMB_MALLOC_P(DEVICEMODE)) == NULL) {
4145                 DEBUG(2,("construct_dev_mode: malloc fail.\n"));
4146                 goto done;
4147         }
4148
4149         ZERO_STRUCTP(devmode);
4150
4151         DEBUGADD(8,("loading DEVICEMODE\n"));
4152
4153         if ( !convert_nt_devicemode( devmode, printer->info_2->devmode ) ) {
4154                 free_dev_mode( devmode );
4155                 devmode = NULL;
4156         }
4157
4158 done:
4159         free_a_printer(&printer,2);
4160
4161         return devmode;
4162 }
4163
4164 /********************************************************************
4165  * construct_printer_info_2
4166  * fill a printer_info_2 struct
4167  ********************************************************************/
4168
4169 static bool construct_printer_info_2(Printer_entry *print_hnd, PRINTER_INFO_2 *printer, int snum)
4170 {
4171         int count;
4172         NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4173
4174         print_status_struct status;
4175
4176         if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
4177                 return False;
4178
4179         count = print_queue_length(snum, &status);
4180
4181         init_unistr(&printer->servername, ntprinter->info_2->servername); /* servername*/
4182         init_unistr(&printer->printername, ntprinter->info_2->printername);                             /* printername*/
4183         init_unistr(&printer->sharename, lp_servicename(snum));                 /* sharename */
4184         init_unistr(&printer->portname, ntprinter->info_2->portname);                   /* port */
4185         init_unistr(&printer->drivername, ntprinter->info_2->drivername);       /* drivername */
4186
4187         if (*ntprinter->info_2->comment == '\0')
4188                 init_unistr(&printer->comment, lp_comment(snum));                       /* comment */
4189         else
4190                 init_unistr(&printer->comment, ntprinter->info_2->comment); /* saved comment. */
4191
4192         init_unistr(&printer->location, ntprinter->info_2->location);           /* location */
4193         init_unistr(&printer->sepfile, ntprinter->info_2->sepfile);             /* separator file */
4194         init_unistr(&printer->printprocessor, ntprinter->info_2->printprocessor);/* print processor */
4195         init_unistr(&printer->datatype, ntprinter->info_2->datatype);           /* datatype */
4196         init_unistr(&printer->parameters, ntprinter->info_2->parameters);       /* parameters (of print processor) */
4197
4198         printer->attributes = ntprinter->info_2->attributes;
4199
4200         printer->priority = ntprinter->info_2->priority;                                /* priority */
4201         printer->defaultpriority = ntprinter->info_2->default_priority;         /* default priority */
4202         printer->starttime = ntprinter->info_2->starttime;                      /* starttime */
4203         printer->untiltime = ntprinter->info_2->untiltime;                      /* untiltime */
4204         printer->status = nt_printq_status(status.status);                      /* status */
4205         printer->cjobs = count;                                                 /* jobs */
4206         printer->averageppm = ntprinter->info_2->averageppm;                    /* average pages per minute */
4207
4208         if ( !(printer->devmode = construct_dev_mode(
4209                        lp_const_servicename(snum))) )
4210                 DEBUG(8, ("Returning NULL Devicemode!\n"));
4211
4212         printer->secdesc = NULL;
4213
4214         if ( ntprinter->info_2->secdesc_buf
4215                 && ntprinter->info_2->secdesc_buf->sd_size != 0 )
4216         {
4217                 /* don't use talloc_steal() here unless you do a deep steal of all
4218                    the SEC_DESC members */
4219
4220                 printer->secdesc = dup_sec_desc( talloc_tos(),
4221                         ntprinter->info_2->secdesc_buf->sd );
4222         }
4223
4224         free_a_printer(&ntprinter, 2);
4225
4226         return True;
4227 }
4228
4229 /********************************************************************
4230  * construct_printer_info_3
4231  * fill a printer_info_3 struct
4232  ********************************************************************/
4233
4234 static bool construct_printer_info_3(Printer_entry *print_hnd, PRINTER_INFO_3 **pp_printer, int snum)
4235 {
4236         NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4237         PRINTER_INFO_3 *printer = NULL;
4238
4239         if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
4240                 return False;
4241
4242         *pp_printer = NULL;
4243         if ((printer = SMB_MALLOC_P(PRINTER_INFO_3)) == NULL) {
4244                 DEBUG(2,("construct_printer_info_3: malloc fail.\n"));
4245                 free_a_printer(&ntprinter, 2);
4246                 return False;
4247         }
4248
4249         ZERO_STRUCTP(printer);
4250
4251         /* These are the components of the SD we are returning. */
4252
4253         if (ntprinter->info_2->secdesc_buf && ntprinter->info_2->secdesc_buf->sd_size != 0) {
4254                 /* don't use talloc_steal() here unless you do a deep steal of all
4255                    the SEC_DESC members */
4256
4257                 printer->secdesc = dup_sec_desc( talloc_tos(),
4258                         ntprinter->info_2->secdesc_buf->sd );
4259         }
4260
4261         free_a_printer(&ntprinter, 2);
4262
4263         *pp_printer = printer;
4264         return True;
4265 }
4266
4267 /********************************************************************
4268  * construct_printer_info_4
4269  * fill a printer_info_4 struct
4270  ********************************************************************/
4271
4272 static bool construct_printer_info_4(Printer_entry *print_hnd, PRINTER_INFO_4 *printer, int snum)
4273 {
4274         NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4275
4276         if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
4277                 return False;
4278
4279         init_unistr(&printer->printername, ntprinter->info_2->printername);                             /* printername*/
4280         init_unistr(&printer->servername, ntprinter->info_2->servername); /* servername*/
4281         printer->attributes = ntprinter->info_2->attributes;
4282
4283         free_a_printer(&ntprinter, 2);
4284         return True;
4285 }
4286
4287 /********************************************************************
4288  * construct_printer_info_5
4289  * fill a printer_info_5 struct
4290  ********************************************************************/
4291
4292 static bool construct_printer_info_5(Printer_entry *print_hnd, PRINTER_INFO_5 *printer, int snum)
4293 {
4294         NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4295
4296         if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
4297                 return False;
4298
4299         init_unistr(&printer->printername, ntprinter->info_2->printername);
4300         init_unistr(&printer->portname, ntprinter->info_2->portname);
4301         printer->attributes = ntprinter->info_2->attributes;
4302
4303         /* these two are not used by NT+ according to MSDN */
4304
4305         printer->device_not_selected_timeout = 0x0;  /* have seen 0x3a98 */
4306         printer->transmission_retry_timeout  = 0x0;  /* have seen 0xafc8 */
4307
4308         free_a_printer(&ntprinter, 2);
4309
4310         return True;
4311 }
4312
4313 /********************************************************************
4314  * construct_printer_info_6
4315  * fill a printer_info_6 struct
4316  ********************************************************************/
4317
4318 static bool construct_printer_info_6(Printer_entry *print_hnd,
4319                                      PRINTER_INFO_6 *printer,
4320                                      int snum)
4321 {
4322         NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4323         int count;
4324         print_status_struct status;
4325
4326         if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2,
4327                                          lp_const_servicename(snum))))
4328                 return False;
4329
4330         count = print_queue_length(snum, &status);
4331
4332         printer->status = nt_printq_status(status.status);
4333
4334         free_a_printer(&ntprinter, 2);
4335
4336         return True;
4337 }
4338
4339 /********************************************************************
4340  * construct_printer_info_7
4341  * fill a printer_info_7 struct
4342  ********************************************************************/
4343
4344 static bool construct_printer_info_7(Printer_entry *print_hnd, PRINTER_INFO_7 *printer, int snum)
4345 {
4346         char *guid_str = NULL;
4347         struct GUID guid;
4348
4349         if (is_printer_published(print_hnd, snum, &guid)) {
4350                 if (asprintf(&guid_str, "{%s}",
4351                              GUID_string(talloc_tos(), &guid)) == -1) {
4352                         return false;
4353                 }
4354                 strupper_m(guid_str);
4355                 init_unistr(&printer->guid, guid_str);
4356                 SAFE_FREE(guid_str);
4357                 printer->action = SPOOL_DS_PUBLISH;
4358         } else {
4359                 init_unistr(&printer->guid, "");
4360                 printer->action = SPOOL_DS_UNPUBLISH;
4361         }
4362
4363         return True;
4364 }
4365
4366 /********************************************************************
4367  Spoolss_enumprinters.
4368 ********************************************************************/
4369
4370 static WERROR enum_all_printers_info_1(uint32 flags, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4371 {
4372         int snum;
4373         int i;
4374         int n_services=lp_numservices();
4375         PRINTER_INFO_1 *printers=NULL;
4376         PRINTER_INFO_1 current_prt;
4377         WERROR result = WERR_OK;
4378
4379         DEBUG(4,("enum_all_printers_info_1\n"));
4380
4381         for (snum=0; snum<n_services; snum++) {
4382                 if (lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) ) {
4383                         DEBUG(4,("Found a printer in smb.conf: %s[%x]\n", lp_servicename(snum), snum));
4384
4385                         if (construct_printer_info_1(NULL, flags, &current_prt, snum)) {
4386                                 if((printers=SMB_REALLOC_ARRAY(printers, PRINTER_INFO_1, *returned +1)) == NULL) {
4387                                         DEBUG(2,("enum_all_printers_info_1: failed to enlarge printers buffer!\n"));
4388                                         *returned=0;
4389                                         return WERR_NOMEM;
4390                                 }
4391                                 DEBUG(4,("ReAlloced memory for [%d] PRINTER_INFO_1\n", *returned));
4392
4393                                 memcpy(&printers[*returned], &current_prt, sizeof(PRINTER_INFO_1));
4394                                 (*returned)++;
4395                         }
4396                 }
4397         }
4398
4399         /* check the required size. */
4400         for (i=0; i<*returned; i++)
4401                 (*needed) += spoolss_size_printer_info_1(&printers[i]);
4402
4403         if (*needed > offered) {
4404                 result = WERR_INSUFFICIENT_BUFFER;
4405                 goto out;
4406         }
4407
4408         if (!rpcbuf_alloc_size(buffer, *needed)) {
4409                 result = WERR_NOMEM;
4410                 goto out;
4411         }
4412
4413         /* fill the buffer with the structures */
4414         for (i=0; i<*returned; i++)
4415                 smb_io_printer_info_1("", buffer, &printers[i], 0);
4416
4417 out:
4418         /* clear memory */
4419
4420         SAFE_FREE(printers);
4421
4422         if ( !W_ERROR_IS_OK(result) )
4423                 *returned = 0;
4424
4425         return result;
4426 }
4427
4428 /********************************************************************
4429  enum_all_printers_info_1_local.
4430 *********************************************************************/
4431
4432 static WERROR enum_all_printers_info_1_local(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4433 {
4434         DEBUG(4,("enum_all_printers_info_1_local\n"));
4435
4436         return enum_all_printers_info_1(PRINTER_ENUM_ICON8, buffer, offered, needed, returned);
4437 }
4438
4439 /********************************************************************
4440  enum_all_printers_info_1_name.
4441 *********************************************************************/
4442
4443 static WERROR enum_all_printers_info_1_name(fstring name, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4444 {
4445         char *s = name;
4446
4447         DEBUG(4,("enum_all_printers_info_1_name\n"));
4448
4449         if ((name[0] == '\\') && (name[1] == '\\'))
4450                 s = name + 2;
4451
4452         if (is_myname_or_ipaddr(s)) {
4453                 return enum_all_printers_info_1(PRINTER_ENUM_ICON8, buffer, offered, needed, returned);
4454         }
4455         else
4456                 return WERR_INVALID_NAME;
4457 }
4458
4459 #if 0   /* JERRY -- disabled for now.  Don't think this is used, tested, or correct */
4460 /********************************************************************
4461  enum_all_printers_info_1_remote.
4462 *********************************************************************/
4463
4464 static WERROR enum_all_printers_info_1_remote(fstring name, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4465 {
4466         PRINTER_INFO_1 *printer;
4467         fstring printername;
4468         fstring desc;
4469         fstring comment;
4470         DEBUG(4,("enum_all_printers_info_1_remote\n"));
4471         WERROR result = WERR_OK;
4472
4473         /* JFM: currently it's more a place holder than anything else.
4474          * In the spooler world there is a notion of server registration.
4475          * the print servers are registered on the PDC (in the same domain)
4476          *
4477          * We should have a TDB here. The registration is done thru an
4478          * undocumented RPC call.
4479          */
4480
4481         if((printer=SMB_MALLOC_P(PRINTER_INFO_1)) == NULL)
4482                 return WERR_NOMEM;
4483
4484         *returned=1;
4485
4486         slprintf(printername, sizeof(printername)-1,"Windows NT Remote Printers!!\\\\%s", name);
4487         slprintf(desc, sizeof(desc)-1,"%s", name);
4488         slprintf(comment, sizeof(comment)-1, "Logged on Domain");
4489
4490         init_unistr(&printer->description, desc);
4491         init_unistr(&printer->name, printername);
4492         init_unistr(&printer->comment, comment);
4493         printer->flags=PRINTER_ENUM_ICON3|PRINTER_ENUM_CONTAINER;
4494
4495         /* check the required size. */
4496         *needed += spoolss_size_printer_info_1(printer);
4497
4498         if (*needed > offered) {
4499                 result = WERR_INSUFFICIENT_BUFFER;
4500                 goto out;
4501         }
4502
4503         if (!rpcbuf_alloc_size(buffer, *needed)) {
4504                 result = WERR_NOMEM;
4505                 goto out;
4506         }
4507
4508         /* fill the buffer with the structures */
4509         smb_io_printer_info_1("", buffer, printer, 0);
4510
4511 out:
4512         /* clear memory */
4513         SAFE_FREE(printer);
4514
4515         if ( !W_ERROR_IS_OK(result) )
4516                 *returned = 0;
4517
4518         return result;
4519 }
4520
4521 #endif
4522
4523 /********************************************************************
4524  enum_all_printers_info_1_network.
4525 *********************************************************************/
4526
4527 static WERROR enum_all_printers_info_1_network(fstring name, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4528 {
4529         char *s = name;
4530
4531         DEBUG(4,("enum_all_printers_info_1_network\n"));
4532
4533         /* If we respond to a enum_printers level 1 on our name with flags
4534            set to PRINTER_ENUM_REMOTE with a list of printers then these
4535            printers incorrectly appear in the APW browse list.
4536            Specifically the printers for the server appear at the workgroup
4537            level where all the other servers in the domain are
4538            listed. Windows responds to this call with a
4539            WERR_CAN_NOT_COMPLETE so we should do the same. */
4540
4541         if (name[0] == '\\' && name[1] == '\\')
4542                  s = name + 2;
4543
4544         if (is_myname_or_ipaddr(s))
4545                  return WERR_CAN_NOT_COMPLETE;
4546
4547         return enum_all_printers_info_1(PRINTER_ENUM_NAME, buffer, offered, needed, returned);
4548 }
4549
4550 /********************************************************************
4551  * api_spoolss_enumprinters
4552  *
4553  * called from api_spoolss_enumprinters (see this to understand)
4554  ********************************************************************/
4555
4556 static WERROR enum_all_printers_info_2(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4557 {
4558         int snum;
4559         int i;
4560         int n_services=lp_numservices();
4561         PRINTER_INFO_2 *printers=NULL;
4562         PRINTER_INFO_2 current_prt;
4563         WERROR result = WERR_OK;
4564
4565         *returned = 0;
4566
4567         for (snum=0; snum<n_services; snum++) {
4568                 if (lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) ) {
4569                         DEBUG(4,("Found a printer in smb.conf: %s[%x]\n", lp_servicename(snum), snum));
4570
4571                         if (construct_printer_info_2(NULL, &current_prt, snum)) {
4572                                 if ( !(printers=SMB_REALLOC_ARRAY(printers, PRINTER_INFO_2, *returned +1)) ) {
4573                                         DEBUG(2,("enum_all_printers_info_2: failed to enlarge printers buffer!\n"));
4574                                         *returned = 0;
4575                                         return WERR_NOMEM;
4576                                 }
4577
4578                                 DEBUG(4,("ReAlloced memory for [%d] PRINTER_INFO_2\n", *returned + 1));
4579
4580                                 memcpy(&printers[*returned], &current_prt, sizeof(PRINTER_INFO_2));
4581
4582                                 (*returned)++;
4583                         }
4584                 }
4585         }
4586
4587         /* check the required size. */
4588         for (i=0; i<*returned; i++)
4589                 (*needed) += spoolss_size_printer_info_2(&printers[i]);
4590
4591         if (*needed > offered) {
4592                 result = WERR_INSUFFICIENT_BUFFER;
4593                 goto out;
4594         }
4595
4596         if (!rpcbuf_alloc_size(buffer, *needed)) {
4597                 result = WERR_NOMEM;
4598                 goto out;
4599         }
4600
4601         /* fill the buffer with the structures */
4602         for (i=0; i<*returned; i++)
4603                 smb_io_printer_info_2("", buffer, &(printers[i]), 0);
4604
4605 out:
4606         /* clear memory */
4607
4608         for (i=0; i<*returned; i++)
4609                 free_devmode(printers[i].devmode);
4610
4611         SAFE_FREE(printers);
4612
4613         if ( !W_ERROR_IS_OK(result) )
4614                 *returned = 0;
4615
4616         return result;
4617 }
4618
4619 /********************************************************************
4620  * handle enumeration of printers at level 1
4621  ********************************************************************/
4622
4623 static WERROR enumprinters_level1( uint32 flags, fstring name,
4624                                  RPC_BUFFER *buffer, uint32 offered,
4625                                  uint32 *needed, uint32 *returned)
4626 {
4627         /* Not all the flags are equals */
4628
4629         if (flags & PRINTER_ENUM_LOCAL)
4630                 return enum_all_printers_info_1_local(buffer, offered, needed, returned);
4631
4632         if (flags & PRINTER_ENUM_NAME)
4633                 return enum_all_printers_info_1_name(name, buffer, offered, needed, returned);
4634
4635 #if 0   /* JERRY - disabled for now */
4636         if (flags & PRINTER_ENUM_REMOTE)
4637                 return enum_all_printers_info_1_remote(name, buffer, offered, needed, returned);
4638 #endif
4639
4640         if (flags & PRINTER_ENUM_NETWORK)
4641                 return enum_all_printers_info_1_network(name, buffer, offered, needed, returned);
4642
4643         return WERR_OK; /* NT4sp5 does that */
4644 }
4645
4646 /********************************************************************
4647  * handle enumeration of printers at level 2
4648  ********************************************************************/
4649
4650 static WERROR enumprinters_level2( uint32 flags, const char *servername,
4651                                  RPC_BUFFER *buffer, uint32 offered,
4652                                  uint32 *needed, uint32 *returned)
4653 {
4654         if (flags & PRINTER_ENUM_LOCAL) {
4655                         return enum_all_printers_info_2(buffer, offered, needed, returned);
4656         }
4657
4658         if (flags & PRINTER_ENUM_NAME) {
4659                 if (is_myname_or_ipaddr(canon_servername(servername)))
4660                         return enum_all_printers_info_2(buffer, offered, needed, returned);
4661                 else
4662                         return WERR_INVALID_NAME;
4663         }
4664
4665         if (flags & PRINTER_ENUM_REMOTE)
4666                 return WERR_UNKNOWN_LEVEL;
4667
4668         return WERR_OK;
4669 }
4670
4671 /********************************************************************
4672  * handle enumeration of printers at level 5
4673  ********************************************************************/
4674
4675 static WERROR enumprinters_level5( uint32 flags, const char *servername,
4676                                  RPC_BUFFER *buffer, uint32 offered,
4677                                  uint32 *needed, uint32 *returned)
4678 {
4679 /*      return enum_all_printers_info_5(buffer, offered, needed, returned);*/
4680         return WERR_OK;
4681 }
4682
4683 /********************************************************************
4684  * api_spoolss_enumprinters
4685  *
4686  * called from api_spoolss_enumprinters (see this to understand)
4687  ********************************************************************/
4688
4689 WERROR _spoolss_enumprinters( pipes_struct *p, SPOOL_Q_ENUMPRINTERS *q_u, SPOOL_R_ENUMPRINTERS *r_u)
4690 {
4691         uint32 flags = q_u->flags;
4692         UNISTR2 *servername = &q_u->servername;
4693         uint32 level = q_u->level;
4694         RPC_BUFFER *buffer = NULL;
4695         uint32 offered = q_u->offered;
4696         uint32 *needed = &r_u->needed;
4697         uint32 *returned = &r_u->returned;
4698
4699         fstring name;
4700
4701         /* that's an [in out] buffer */
4702
4703         if (!q_u->buffer && (offered!=0)) {
4704                 return WERR_INVALID_PARAM;
4705         }
4706
4707         if (offered > MAX_RPC_DATA_SIZE) {
4708                 return WERR_INVALID_PARAM;
4709         }
4710
4711         rpcbuf_move(q_u->buffer, &r_u->buffer);
4712         buffer = r_u->buffer;
4713
4714         DEBUG(4,("_spoolss_enumprinters\n"));
4715
4716         *needed=0;
4717         *returned=0;
4718
4719         /*
4720          * Level 1:
4721          *          flags==PRINTER_ENUM_NAME
4722          *           if name=="" then enumerates all printers
4723          *           if name!="" then enumerate the printer
4724          *          flags==PRINTER_ENUM_REMOTE
4725          *          name is NULL, enumerate printers
4726          * Level 2: name!="" enumerates printers, name can't be NULL
4727          * Level 3: doesn't exist
4728          * Level 4: does a local registry lookup
4729          * Level 5: same as Level 2
4730          */
4731
4732         unistr2_to_ascii(name, servername, sizeof(name));
4733         strupper_m(name);
4734
4735         switch (level) {
4736         case 1:
4737                 return enumprinters_level1(flags, name, buffer, offered, needed, returned);
4738         case 2:
4739                 return enumprinters_level2(flags, name, buffer, offered, needed, returned);
4740         case 5:
4741                 return enumprinters_level5(flags, name, buffer, offered, needed, returned);
4742         case 3:
4743         case 4:
4744                 break;
4745         }
4746         return WERR_UNKNOWN_LEVEL;
4747 }
4748
4749 /****************************************************************************
4750 ****************************************************************************/
4751
4752 static WERROR getprinter_level_0(Printer_entry *print_hnd, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
4753 {
4754         PRINTER_INFO_0 *printer=NULL;
4755         WERROR result = WERR_OK;
4756
4757         if((printer=SMB_MALLOC_P(PRINTER_INFO_0)) == NULL)
4758                 return WERR_NOMEM;
4759
4760         construct_printer_info_0(print_hnd, printer, snum);
4761
4762         /* check the required size. */
4763         *needed += spoolss_size_printer_info_0(printer);
4764
4765         if (*needed > offered) {
4766                 result = WERR_INSUFFICIENT_BUFFER;
4767                 goto out;
4768         }
4769
4770         if (!rpcbuf_alloc_size(buffer, *needed)) {
4771                 result = WERR_NOMEM;
4772                 goto out;
4773         }
4774
4775         /* fill the buffer with the structures */
4776         smb_io_printer_info_0("", buffer, printer, 0);
4777
4778 out:
4779         /* clear memory */
4780
4781         SAFE_FREE(printer);
4782
4783         return result;
4784 }
4785
4786 /****************************************************************************
4787 ****************************************************************************/
4788
4789 static WERROR getprinter_level_1(Printer_entry *print_hnd, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
4790 {
4791         PRINTER_INFO_1 *printer=NULL;
4792         WERROR result = WERR_OK;
4793
4794         if((printer=SMB_MALLOC_P(PRINTER_INFO_1)) == NULL)
4795                 return WERR_NOMEM;
4796
4797         construct_printer_info_1(print_hnd, PRINTER_ENUM_ICON8, printer, snum);
4798
4799         /* check the required size. */
4800         *needed += spoolss_size_printer_info_1(printer);
4801
4802         if (*needed > offered) {
4803                 result = WERR_INSUFFICIENT_BUFFER;
4804                 goto out;
4805         }
4806
4807         if (!rpcbuf_alloc_size(buffer, *needed)) {
4808                 result = WERR_NOMEM;
4809                 goto out;
4810         }
4811
4812         /* fill the buffer with the structures */
4813         smb_io_printer_info_1("", buffer, printer, 0);
4814
4815 out:
4816         /* clear memory */
4817         SAFE_FREE(printer);
4818
4819         return result;
4820 }
4821
4822 /****************************************************************************
4823 ****************************************************************************/
4824
4825 static WERROR getprinter_level_2(Printer_entry *print_hnd, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
4826 {
4827         PRINTER_INFO_2 *printer=NULL;
4828         WERROR result = WERR_OK;
4829
4830         if((printer=SMB_MALLOC_P(PRINTER_INFO_2))==NULL)
4831                 return WERR_NOMEM;
4832
4833         construct_printer_info_2(print_hnd, printer, snum);
4834
4835         /* check the required size. */
4836         *needed += spoolss_size_printer_info_2(printer);
4837
4838         if (*needed > offered) {
4839                 result = WERR_INSUFFICIENT_BUFFER;
4840                 goto out;
4841         }
4842
4843         if (!rpcbuf_alloc_size(buffer, *needed)) {
4844                 result = WERR_NOMEM;
4845                 goto out;
4846         }
4847
4848         /* fill the buffer with the structures */
4849         if (!smb_io_printer_info_2("", buffer, printer, 0))
4850                 result = WERR_NOMEM;
4851
4852 out:
4853         /* clear memory */
4854         free_printer_info_2(printer);
4855
4856         return result;
4857 }
4858
4859 /****************************************************************************
4860 ****************************************************************************/
4861
4862 static WERROR getprinter_level_3(Printer_entry *print_hnd, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
4863 {
4864         PRINTER_INFO_3 *printer=NULL;
4865         WERROR result = WERR_OK;
4866
4867         if (!construct_printer_info_3(print_hnd, &printer, snum))
4868                 return WERR_NOMEM;
4869
4870         /* check the required size. */
4871         *needed += spoolss_size_printer_info_3(printer);
4872
4873         if (*needed > offered) {
4874                 result = WERR_INSUFFICIENT_BUFFER;
4875                 goto out;
4876         }
4877
4878         if (!rpcbuf_alloc_size(buffer, *needed)) {
4879                 result = WERR_NOMEM;
4880                 goto out;
4881         }
4882
4883         /* fill the buffer with the structures */
4884         smb_io_printer_info_3("", buffer, printer, 0);
4885
4886 out:
4887         /* clear memory */
4888         free_printer_info_3(printer);
4889
4890         return result;
4891 }
4892
4893 /****************************************************************************
4894 ****************************************************************************/
4895
4896 static WERROR getprinter_level_4(Printer_entry *print_hnd, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
4897 {
4898         PRINTER_INFO_4 *printer=NULL;
4899         WERROR result = WERR_OK;
4900
4901         if((printer=SMB_MALLOC_P(PRINTER_INFO_4))==NULL)
4902                 return WERR_NOMEM;
4903
4904         if (!construct_printer_info_4(print_hnd, printer, snum)) {
4905                 SAFE_FREE(printer);
4906                 return WERR_NOMEM;
4907         }
4908
4909         /* check the required size. */
4910         *needed += spoolss_size_printer_info_4(printer);
4911
4912         if (*needed > offered) {
4913                 result = WERR_INSUFFICIENT_BUFFER;
4914                 goto out;
4915         }
4916
4917         if (!rpcbuf_alloc_size(buffer, *needed)) {
4918                 result = WERR_NOMEM;
4919                 goto out;
4920         }
4921
4922         /* fill the buffer with the structures */
4923         smb_io_printer_info_4("", buffer, printer, 0);
4924
4925 out:
4926         /* clear memory */
4927         free_printer_info_4(printer);
4928
4929         return result;
4930 }
4931
4932 /****************************************************************************
4933 ****************************************************************************/
4934
4935 static WERROR getprinter_level_5(Printer_entry *print_hnd, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
4936 {
4937         PRINTER_INFO_5 *printer=NULL;
4938         WERROR result = WERR_OK;
4939
4940         if((printer=SMB_MALLOC_P(PRINTER_INFO_5))==NULL)
4941                 return WERR_NOMEM;
4942
4943         if (!construct_printer_info_5(print_hnd, printer, snum)) {
4944                 free_printer_info_5(printer);
4945                 return WERR_NOMEM;
4946         }
4947
4948         /* check the required size. */
4949         *needed += spoolss_size_printer_info_5(printer);
4950
4951         if (*needed > offered) {
4952                 result = WERR_INSUFFICIENT_BUFFER;
4953                 goto out;
4954         }
4955
4956         if (!rpcbuf_alloc_size(buffer, *needed)) {
4957                 result = WERR_NOMEM;
4958                 goto out;
4959         }
4960
4961         /* fill the buffer with the structures */
4962         smb_io_printer_info_5("", buffer, printer, 0);
4963
4964 out:
4965         /* clear memory */
4966         free_printer_info_5(printer);
4967
4968         return result;
4969 }
4970
4971 static WERROR getprinter_level_6(Printer_entry *print_hnd,
4972                                  int snum,
4973                                  RPC_BUFFER *buffer, uint32 offered,
4974                                  uint32 *needed)
4975 {
4976         PRINTER_INFO_6 *printer;
4977         WERROR result = WERR_OK;
4978
4979         if ((printer = SMB_MALLOC_P(PRINTER_INFO_6)) == NULL) {
4980                 return WERR_NOMEM;
4981         }
4982
4983         if (!construct_printer_info_6(print_hnd, printer, snum)) {
4984                 free_printer_info_6(printer);
4985                 return WERR_NOMEM;
4986         }
4987
4988         /* check the required size. */
4989         *needed += spoolss_size_printer_info_6(printer);
4990
4991         if (*needed > offered) {
4992                 result = WERR_INSUFFICIENT_BUFFER;
4993                 goto out;
4994         }
4995
4996         if (!rpcbuf_alloc_size(buffer, *needed)) {
4997                 result = WERR_NOMEM;
4998                 goto out;
4999         }
5000
5001         /* fill the buffer with the structures */
5002         smb_io_printer_info_6("", buffer, printer, 0);
5003
5004 out:
5005         /* clear memory */
5006         free_printer_info_6(printer);
5007
5008         return result;
5009 }
5010
5011 static WERROR getprinter_level_7(Printer_entry *print_hnd, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
5012 {
5013         PRINTER_INFO_7 *printer=NULL;
5014         WERROR result = WERR_OK;
5015
5016         if((printer=SMB_MALLOC_P(PRINTER_INFO_7))==NULL)
5017                 return WERR_NOMEM;
5018
5019         if (!construct_printer_info_7(print_hnd, printer, snum)) {
5020                 result = WERR_NOMEM;
5021                 goto out;
5022         }
5023
5024         /* check the required size. */
5025         *needed += spoolss_size_printer_info_7(printer);
5026
5027         if (*needed > offered) {
5028                 result = WERR_INSUFFICIENT_BUFFER;
5029                 goto out;
5030         }
5031
5032         if (!rpcbuf_alloc_size(buffer, *needed)) {
5033                 result = WERR_NOMEM;
5034                 goto out;
5035
5036         }
5037
5038         /* fill the buffer with the structures */
5039         smb_io_printer_info_7("", buffer, printer, 0);
5040
5041 out:
5042         /* clear memory */
5043         free_printer_info_7(printer);
5044
5045         return result;
5046 }
5047
5048 /****************************************************************************
5049 ****************************************************************************/
5050
5051 WERROR _spoolss_getprinter(pipes_struct *p, SPOOL_Q_GETPRINTER *q_u, SPOOL_R_GETPRINTER *r_u)
5052 {
5053         POLICY_HND *handle = &q_u->handle;
5054         uint32 level = q_u->level;
5055         RPC_BUFFER *buffer = NULL;
5056         uint32 offered = q_u->offered;
5057         uint32 *needed = &r_u->needed;
5058         Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
5059
5060         int snum;
5061
5062         /* that's an [in out] buffer */
5063
5064         if (!q_u->buffer && (offered!=0)) {
5065                 return WERR_INVALID_PARAM;
5066         }
5067
5068         if (offered > MAX_RPC_DATA_SIZE) {
5069                 return WERR_INVALID_PARAM;
5070         }
5071
5072         rpcbuf_move(q_u->buffer, &r_u->buffer);
5073         buffer = r_u->buffer;
5074
5075         *needed=0;
5076
5077         if (!get_printer_snum(p, handle, &snum, NULL))
5078                 return WERR_BADFID;
5079
5080         switch (level) {
5081         case 0:
5082                 return getprinter_level_0(Printer, snum, buffer, offered, needed);
5083         case 1:
5084                 return getprinter_level_1(Printer, snum, buffer, offered, needed);
5085         case 2:
5086                 return getprinter_level_2(Printer, snum, buffer, offered, needed);
5087         case 3:
5088                 return getprinter_level_3(Printer, snum, buffer, offered, needed);
5089         case 4:
5090                 return getprinter_level_4(Printer, snum, buffer, offered, needed);
5091         case 5:
5092                 return getprinter_level_5(Printer, snum, buffer, offered, needed);
5093         case 6:
5094                 return getprinter_level_6(Printer, snum, buffer, offered, needed);
5095         case 7:
5096                 return getprinter_level_7(Printer, snum, buffer, offered, needed);
5097         }
5098         return WERR_UNKNOWN_LEVEL;
5099 }
5100
5101 /********************************************************************
5102  * fill a DRIVER_INFO_1 struct
5103  ********************************************************************/
5104
5105 static void fill_printer_driver_info_1(DRIVER_INFO_1 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, const char *servername, fstring architecture)
5106 {
5107         init_unistr( &info->name, driver.info_3->name);
5108 }
5109
5110 /********************************************************************
5111  * construct_printer_driver_info_1
5112  ********************************************************************/
5113
5114 static WERROR construct_printer_driver_info_1(DRIVER_INFO_1 *info, int snum, const char *servername, fstring architecture, uint32 version)
5115 {
5116         NT_PRINTER_INFO_LEVEL *printer = NULL;
5117         NT_PRINTER_DRIVER_INFO_LEVEL driver;
5118
5119         ZERO_STRUCT(driver);
5120
5121         if (!W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, lp_const_servicename(snum))))
5122                 return WERR_INVALID_PRINTER_NAME;
5123
5124         if (!W_ERROR_IS_OK(get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version))) {
5125                 free_a_printer(&printer, 2);
5126                 return WERR_UNKNOWN_PRINTER_DRIVER;
5127         }
5128
5129         fill_printer_driver_info_1(info, driver, servername, architecture);
5130
5131         free_a_printer(&printer,2);
5132
5133         return WERR_OK;
5134 }
5135
5136 /********************************************************************
5137  * construct_printer_driver_info_2
5138  * fill a printer_info_2 struct
5139  ********************************************************************/
5140
5141 static void fill_printer_driver_info_2(DRIVER_INFO_2 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, const char *servername)
5142 {
5143         TALLOC_CTX *ctx = talloc_tos();
5144         char *temp = NULL;
5145         const char *cservername = canon_servername(servername);
5146
5147         info->version=driver.info_3->cversion;
5148
5149         init_unistr( &info->name, driver.info_3->name );
5150         init_unistr( &info->architecture, driver.info_3->environment );
5151
5152         if (strlen(driver.info_3->driverpath)) {
5153                 temp = talloc_asprintf(ctx,
5154                                 "\\\\%s%s",
5155                                 cservername,
5156                                 driver.info_3->driverpath);
5157                 init_unistr( &info->driverpath, temp );
5158         } else {
5159                 init_unistr( &info->driverpath, "" );
5160         }
5161
5162         TALLOC_FREE(temp);
5163         if (strlen(driver.info_3->datafile)) {
5164                 temp = talloc_asprintf(ctx,
5165                                 "\\\\%s%s",
5166                                 cservername,
5167                                 driver.info_3->datafile);
5168                 init_unistr( &info->datafile, temp );
5169         } else
5170                 init_unistr( &info->datafile, "" );
5171
5172         TALLOC_FREE(temp);
5173         if (strlen(driver.info_3->configfile)) {
5174                 temp = talloc_asprintf(ctx,
5175                                 "\\\\%s%s",
5176                                 cservername,
5177                                 driver.info_3->configfile);
5178                 init_unistr( &info->configfile, temp );
5179         } else
5180                 init_unistr( &info->configfile, "" );
5181 }
5182
5183 /********************************************************************
5184  * construct_printer_driver_info_2
5185  * fill a printer_info_2 struct
5186  ********************************************************************/
5187
5188 static WERROR construct_printer_driver_info_2(DRIVER_INFO_2 *info, int snum, const char *servername, fstring architecture, uint32 version)
5189 {
5190         NT_PRINTER_INFO_LEVEL *printer = NULL;
5191         NT_PRINTER_DRIVER_INFO_LEVEL driver;
5192
5193         ZERO_STRUCT(printer);
5194         ZERO_STRUCT(driver);
5195
5196         if (!W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, lp_const_servicename(snum))))
5197                 return WERR_INVALID_PRINTER_NAME;
5198
5199         if (!W_ERROR_IS_OK(get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version))) {
5200                 free_a_printer(&printer, 2);
5201                 return WERR_UNKNOWN_PRINTER_DRIVER;
5202         }
5203
5204         fill_printer_driver_info_2(info, driver, servername);
5205
5206         free_a_printer(&printer,2);
5207
5208         return WERR_OK;
5209 }
5210
5211 /********************************************************************
5212  * copy a strings array and convert to UNICODE
5213  *
5214  * convert an array of ascii string to a UNICODE string
5215  ********************************************************************/
5216
5217 static uint32 init_unistr_array(uint16 **uni_array, fstring *char_array, const char *servername)
5218 {
5219         int i=0;
5220         int j=0;
5221         const char *v;
5222         char *line = NULL;
5223         TALLOC_CTX *ctx = talloc_tos();
5224
5225         DEBUG(6,("init_unistr_array\n"));
5226         *uni_array=NULL;
5227
5228         while (true) {
5229                 if ( !char_array ) {
5230                         v = "";
5231                 } else {
5232                         v = char_array[i];
5233                         if (!v)
5234                                 v = ""; /* hack to handle null lists */
5235                 }
5236
5237                 /* hack to allow this to be used in places other than when generating
5238                    the list of dependent files */
5239
5240                 TALLOC_FREE(line);
5241                 if ( servername ) {
5242                         line = talloc_asprintf(ctx,
5243                                         "\\\\%s%s",
5244                                         canon_servername(servername),
5245                                         v);
5246                 } else {
5247                         line = talloc_strdup(ctx, v);
5248                 }
5249
5250                 if (!line) {
5251                         SAFE_FREE(*uni_array);
5252                         return 0;
5253                 }
5254                 DEBUGADD(6,("%d:%s:%lu\n", i, line, (unsigned long)strlen(line)));
5255
5256                 /* add one extra unit16 for the second terminating NULL */
5257
5258                 if ( (*uni_array=SMB_REALLOC_ARRAY(*uni_array, uint16, j+1+strlen(line)+2)) == NULL ) {
5259                         DEBUG(2,("init_unistr_array: Realloc error\n" ));
5260                         return 0;
5261                 }
5262
5263                 if ( !strlen(v) )
5264                         break;
5265
5266                 j += (rpcstr_push((*uni_array+j), line, sizeof(uint16)*strlen(line)+2, STR_TERMINATE) / sizeof(uint16));
5267                 i++;
5268         }
5269
5270         if (*uni_array) {
5271                 /* special case for ""; we need to add both NULL's here */
5272                 if (!j)
5273                         (*uni_array)[j++]=0x0000;
5274                 (*uni_array)[j]=0x0000;
5275         }
5276
5277         DEBUGADD(6,("last one:done\n"));
5278
5279         /* return size of array in uint16's */
5280
5281         return j+1;
5282 }
5283
5284 /********************************************************************
5285  * construct_printer_info_3
5286  * fill a printer_info_3 struct
5287  ********************************************************************/
5288
5289 static void fill_printer_driver_info_3(DRIVER_INFO_3 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, const char *servername)
5290 {
5291         char *temp = NULL;
5292         TALLOC_CTX *ctx = talloc_tos();
5293         const char *cservername = canon_servername(servername);
5294
5295         ZERO_STRUCTP(info);
5296
5297         info->version=driver.info_3->cversion;
5298
5299         init_unistr( &info->name, driver.info_3->name );
5300         init_unistr( &info->architecture, driver.info_3->environment );
5301
5302         if (strlen(driver.info_3->driverpath)) {
5303                 temp = talloc_asprintf(ctx,
5304                                 "\\\\%s%s",
5305                                 cservername,
5306                                 driver.info_3->driverpath);
5307                 init_unistr( &info->driverpath, temp );
5308         } else
5309                 init_unistr( &info->driverpath, "" );
5310
5311         TALLOC_FREE(temp);
5312         if (strlen(driver.info_3->datafile)) {
5313                 temp = talloc_asprintf(ctx,
5314                                 "\\\\%s%s",
5315                                 cservername,
5316                                 driver.info_3->datafile);
5317                 init_unistr( &info->datafile, temp );
5318         } else
5319                 init_unistr( &info->datafile, "" );
5320
5321         TALLOC_FREE(temp);
5322         if (strlen(driver.info_3->configfile)) {
5323                 temp = talloc_asprintf(ctx,
5324                                 "\\\\%s%s",
5325                                 cservername,
5326                                 driver.info_3->configfile);
5327                 init_unistr( &info->configfile, temp );
5328         } else
5329                 init_unistr( &info->configfile, "" );
5330
5331         TALLOC_FREE(temp);
5332         if (strlen(driver.info_3->helpfile)) {
5333                 temp = talloc_asprintf(ctx,
5334                                 "\\\\%s%s",
5335                                 cservername,
5336                                 driver.info_3->helpfile);
5337                 init_unistr( &info->helpfile, temp );
5338         } else
5339                 init_unistr( &info->helpfile, "" );
5340
5341         TALLOC_FREE(temp);
5342         init_unistr( &info->monitorname, driver.info_3->monitorname );
5343         init_unistr( &info->defaultdatatype, driver.info_3->defaultdatatype );
5344
5345         info->dependentfiles=NULL;
5346         init_unistr_array(&info->dependentfiles, driver.info_3->dependentfiles, cservername);
5347 }
5348
5349 /********************************************************************
5350  * construct_printer_info_3
5351  * fill a printer_info_3 struct
5352  ********************************************************************/
5353
5354 static WERROR construct_printer_driver_info_3(DRIVER_INFO_3 *info, int snum, const char *servername, fstring architecture, uint32 version)
5355 {
5356         NT_PRINTER_INFO_LEVEL *printer = NULL;
5357         NT_PRINTER_DRIVER_INFO_LEVEL driver;
5358         WERROR status;
5359         ZERO_STRUCT(driver);
5360
5361         status=get_a_printer(NULL, &printer, 2, lp_const_servicename(snum) );
5362         DEBUG(8,("construct_printer_driver_info_3: status: %s\n", win_errstr(status)));
5363         if (!W_ERROR_IS_OK(status))
5364                 return WERR_INVALID_PRINTER_NAME;
5365
5366         status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
5367         DEBUG(8,("construct_printer_driver_info_3: status: %s\n", win_errstr(status)));
5368
5369 #if 0   /* JERRY */
5370
5371         /*
5372          * I put this code in during testing.  Helpful when commenting out the
5373          * support for DRIVER_INFO_6 in regards to win2k.  Not needed in general
5374          * as win2k always queries the driver using an infor level of 6.
5375          * I've left it in (but ifdef'd out) because I'll probably
5376          * use it in experimentation again in the future.   --jerry 22/01/2002
5377          */
5378
5379         if (!W_ERROR_IS_OK(status)) {
5380                 /*
5381                  * Is this a W2k client ?
5382                  */
5383                 if (version == 3) {
5384                         /* Yes - try again with a WinNT driver. */
5385                         version = 2;
5386                         status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
5387                         DEBUG(8,("construct_printer_driver_info_3: status: %s\n", win_errstr(status)));
5388                 }
5389 #endif
5390
5391                 if (!W_ERROR_IS_OK(status)) {
5392                         free_a_printer(&printer,2);
5393                         return WERR_UNKNOWN_PRINTER_DRIVER;
5394                 }
5395
5396 #if 0   /* JERRY */
5397         }
5398 #endif
5399
5400
5401         fill_printer_driver_info_3(info, driver, servername);
5402
5403         free_a_printer(&printer,2);
5404
5405         return WERR_OK;
5406 }
5407
5408 /********************************************************************
5409  * construct_printer_info_6
5410  * fill a printer_info_6 struct - we know that driver is really level 3. This sucks. JRA.
5411  ********************************************************************/
5412
5413 static void fill_printer_driver_info_6(DRIVER_INFO_6 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, const char *servername)
5414 {
5415         char *temp = NULL;
5416         fstring nullstr;
5417         TALLOC_CTX *ctx = talloc_tos();
5418         const char *cservername = canon_servername(servername);
5419
5420         ZERO_STRUCTP(info);
5421         memset(&nullstr, '\0', sizeof(fstring));
5422
5423         info->version=driver.info_3->cversion;
5424
5425         init_unistr( &info->name, driver.info_3->name );
5426         init_unistr( &info->architecture, driver.info_3->environment );
5427
5428         if (strlen(driver.info_3->driverpath)) {
5429                 temp = talloc_asprintf(ctx,
5430                                 "\\\\%s%s",
5431                                 cservername,
5432                                 driver.info_3->driverpath);
5433                 init_unistr( &info->driverpath, temp );
5434         } else
5435                 init_unistr( &info->driverpath, "" );
5436
5437         TALLOC_FREE(temp);
5438         if (strlen(driver.info_3->datafile)) {
5439                 temp = talloc_asprintf(ctx,
5440                                 "\\\\%s%s",
5441                                 cservername,
5442                                 driver.info_3->datafile);
5443                 init_unistr( &info->datafile, temp );
5444         } else
5445                 init_unistr( &info->datafile, "" );
5446
5447         TALLOC_FREE(temp);
5448         if (strlen(driver.info_3->configfile)) {
5449                 temp = talloc_asprintf(ctx,
5450                                 "\\\\%s%s",
5451                                 cservername,
5452                                 driver.info_3->configfile);
5453                 init_unistr( &info->configfile, temp );
5454         } else
5455                 init_unistr( &info->configfile, "" );
5456
5457         TALLOC_FREE(temp);
5458         if (strlen(driver.info_3->helpfile)) {
5459                 temp = talloc_asprintf(ctx,
5460                                 "\\\\%s%s",
5461                                 cservername,
5462                                 driver.info_3->helpfile);
5463                 init_unistr( &info->helpfile, temp );
5464         } else
5465                 init_unistr( &info->helpfile, "" );
5466
5467         TALLOC_FREE(temp);
5468         init_unistr( &info->monitorname, driver.info_3->monitorname );
5469         init_unistr( &info->defaultdatatype, driver.info_3->defaultdatatype );
5470
5471         info->dependentfiles = NULL;
5472         init_unistr_array( &info->dependentfiles, driver.info_3->dependentfiles, servername );
5473
5474         info->previousdrivernames=NULL;
5475         init_unistr_array(&info->previousdrivernames, &nullstr, servername);
5476
5477         info->driver_date=0;
5478
5479         info->padding=0;
5480         info->driver_version_low=0;
5481         info->driver_version_high=0;
5482
5483         init_unistr( &info->mfgname, "");
5484         init_unistr( &info->oem_url, "");
5485         init_unistr( &info->hardware_id, "");
5486         init_unistr( &info->provider, "");
5487 }
5488
5489 /********************************************************************
5490  * construct_printer_info_6
5491  * fill a printer_info_6 struct
5492  ********************************************************************/
5493
5494 static WERROR construct_printer_driver_info_6(DRIVER_INFO_6 *info, int snum,
5495               const char *servername, fstring architecture, uint32 version)
5496 {
5497         NT_PRINTER_INFO_LEVEL           *printer = NULL;
5498         NT_PRINTER_DRIVER_INFO_LEVEL    driver;
5499         WERROR                          status;
5500
5501         ZERO_STRUCT(driver);
5502
5503         status=get_a_printer(NULL, &printer, 2, lp_const_servicename(snum) );
5504
5505         DEBUG(8,("construct_printer_driver_info_6: status: %s\n", win_errstr(status)));
5506
5507         if (!W_ERROR_IS_OK(status))
5508                 return WERR_INVALID_PRINTER_NAME;
5509
5510         status = get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
5511
5512         DEBUG(8,("construct_printer_driver_info_6: status: %s\n", win_errstr(status)));
5513
5514         if (!W_ERROR_IS_OK(status))
5515         {
5516                 /*
5517                  * Is this a W2k client ?
5518                  */
5519
5520                 if (version < 3) {
5521                         free_a_printer(&printer,2);
5522                         return WERR_UNKNOWN_PRINTER_DRIVER;
5523                 }
5524
5525                 /* Yes - try again with a WinNT driver. */
5526                 version = 2;
5527                 status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
5528                 DEBUG(8,("construct_printer_driver_info_6: status: %s\n", win_errstr(status)));
5529                 if (!W_ERROR_IS_OK(status)) {
5530                         free_a_printer(&printer,2);
5531                         return WERR_UNKNOWN_PRINTER_DRIVER;
5532                 }
5533         }
5534
5535         fill_printer_driver_info_6(info, driver, servername);
5536
5537         free_a_printer(&printer,2);
5538         free_a_printer_driver(driver, 3);
5539
5540         return WERR_OK;
5541 }
5542
5543 /****************************************************************************
5544 ****************************************************************************/
5545
5546 static void free_printer_driver_info_3(DRIVER_INFO_3 *info)
5547 {
5548         SAFE_FREE(info->dependentfiles);
5549 }
5550
5551 /****************************************************************************
5552 ****************************************************************************/
5553
5554 static void free_printer_driver_info_6(DRIVER_INFO_6 *info)
5555 {
5556         SAFE_FREE(info->dependentfiles);
5557 }
5558
5559 /****************************************************************************
5560 ****************************************************************************/
5561
5562 static WERROR getprinterdriver2_level1(const char *servername, fstring architecture, uint32 version, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
5563 {
5564         DRIVER_INFO_1 *info=NULL;
5565         WERROR result;
5566
5567         if((info=SMB_MALLOC_P(DRIVER_INFO_1)) == NULL)
5568                 return WERR_NOMEM;
5569
5570         result = construct_printer_driver_info_1(info, snum, servername, architecture, version);
5571         if (!W_ERROR_IS_OK(result))
5572                 goto out;
5573
5574         /* check the required size. */
5575         *needed += spoolss_size_printer_driver_info_1(info);
5576
5577         if (*needed > offered) {
5578                 result = WERR_INSUFFICIENT_BUFFER;
5579                 goto out;
5580         }
5581
5582         if (!rpcbuf_alloc_size(buffer, *needed)) {
5583                 result = WERR_NOMEM;
5584                 goto out;
5585         }
5586
5587         /* fill the buffer with the structures */
5588         smb_io_printer_driver_info_1("", buffer, info, 0);
5589
5590 out:
5591         /* clear memory */
5592         SAFE_FREE(info);
5593
5594         return result;
5595 }
5596
5597 /****************************************************************************
5598 ****************************************************************************/
5599
5600 static WERROR getprinterdriver2_level2(const char *servername, fstring architecture, uint32 version, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
5601 {
5602         DRIVER_INFO_2 *info=NULL;
5603         WERROR result;
5604
5605         if((info=SMB_MALLOC_P(DRIVER_INFO_2)) == NULL)
5606                 return WERR_NOMEM;
5607
5608         result = construct_printer_driver_info_2(info, snum, servername, architecture, version);
5609         if (!W_ERROR_IS_OK(result))
5610                 goto out;
5611
5612         /* check the required size. */
5613         *needed += spoolss_size_printer_driver_info_2(info);
5614
5615         if (*needed > offered) {
5616                 result = WERR_INSUFFICIENT_BUFFER;
5617                 goto out;
5618         }
5619
5620         if (!rpcbuf_alloc_size(buffer, *needed)) {
5621                 result = WERR_NOMEM;
5622                 goto out;
5623         }
5624
5625         /* fill the buffer with the structures */
5626         smb_io_printer_driver_info_2("", buffer, info, 0);
5627
5628 out:
5629         /* clear memory */
5630         SAFE_FREE(info);
5631
5632         return result;
5633 }
5634
5635 /****************************************************************************
5636 ****************************************************************************/
5637
5638 static WERROR getprinterdriver2_level3(const char *servername, fstring architecture, uint32 version, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
5639 {
5640         DRIVER_INFO_3 info;
5641         WERROR result;
5642
5643         ZERO_STRUCT(info);
5644
5645         result = construct_printer_driver_info_3(&info, snum, servername, architecture, version);
5646         if (!W_ERROR_IS_OK(result))
5647                 goto out;
5648
5649         /* check the required size. */
5650         *needed += spoolss_size_printer_driver_info_3(&info);
5651
5652         if (*needed > offered) {
5653                 result = WERR_INSUFFICIENT_BUFFER;
5654                 goto out;
5655         }
5656
5657         if (!rpcbuf_alloc_size(buffer, *needed)) {
5658                 result = WERR_NOMEM;
5659                 goto out;
5660         }
5661
5662         /* fill the buffer with the structures */
5663         smb_io_printer_driver_info_3("", buffer, &info, 0);
5664
5665 out:
5666         free_printer_driver_info_3(&info);
5667
5668         return result;
5669 }
5670
5671 /****************************************************************************
5672 ****************************************************************************/
5673
5674 static WERROR getprinterdriver2_level6(const char *servername, fstring architecture, uint32 version, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
5675 {
5676         DRIVER_INFO_6 info;
5677         WERROR result;
5678
5679         ZERO_STRUCT(info);
5680
5681         result = construct_printer_driver_info_6(&info, snum, servername, architecture, version);
5682         if (!W_ERROR_IS_OK(result))
5683                 goto out;
5684
5685         /* check the required size. */
5686         *needed += spoolss_size_printer_driver_info_6(&info);
5687
5688         if (*needed > offered) {
5689                 result = WERR_INSUFFICIENT_BUFFER;
5690                 goto out;
5691         }
5692
5693         if (!rpcbuf_alloc_size(buffer, *needed)) {
5694                 result = WERR_NOMEM;
5695                 goto out;
5696         }
5697
5698         /* fill the buffer with the structures */
5699         smb_io_printer_driver_info_6("", buffer, &info, 0);
5700
5701 out:
5702         free_printer_driver_info_6(&info);
5703
5704         return result;
5705 }
5706
5707 /****************************************************************************
5708 ****************************************************************************/
5709
5710 WERROR _spoolss_getprinterdriver2(pipes_struct *p, SPOOL_Q_GETPRINTERDRIVER2 *q_u, SPOOL_R_GETPRINTERDRIVER2 *r_u)
5711 {
5712         POLICY_HND *handle = &q_u->handle;
5713         UNISTR2 *uni_arch = &q_u->architecture;
5714         uint32 level = q_u->level;
5715         uint32 clientmajorversion = q_u->clientmajorversion;
5716         RPC_BUFFER *buffer = NULL;
5717         uint32 offered = q_u->offered;
5718         uint32 *needed = &r_u->needed;
5719         uint32 *servermajorversion = &r_u->servermajorversion;
5720         uint32 *serverminorversion = &r_u->serverminorversion;
5721         Printer_entry *printer;
5722
5723         fstring servername;
5724         fstring architecture;
5725         int snum;
5726
5727         /* that's an [in out] buffer */
5728
5729         if (!q_u->buffer && (offered!=0)) {
5730                 return WERR_INVALID_PARAM;
5731         }
5732
5733         if (offered > MAX_RPC_DATA_SIZE) {
5734                 return WERR_INVALID_PARAM;
5735         }
5736
5737         rpcbuf_move(q_u->buffer, &r_u->buffer);
5738         buffer = r_u->buffer;
5739
5740         DEBUG(4,("_spoolss_getprinterdriver2\n"));
5741
5742         if ( !(printer = find_printer_index_by_hnd( p, handle )) ) {
5743                 DEBUG(0,("_spoolss_getprinterdriver2: invalid printer handle!\n"));
5744                 return WERR_INVALID_PRINTER_NAME;
5745         }
5746
5747         *needed = 0;
5748         *servermajorversion = 0;
5749         *serverminorversion = 0;
5750
5751         fstrcpy(servername, get_server_name( printer ));
5752         unistr2_to_ascii(architecture, uni_arch, sizeof(architecture));
5753
5754         if (!get_printer_snum(p, handle, &snum, NULL))
5755                 return WERR_BADFID;
5756
5757         switch (level) {
5758         case 1:
5759                 return getprinterdriver2_level1(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
5760         case 2:
5761                 return getprinterdriver2_level2(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
5762         case 3:
5763                 return getprinterdriver2_level3(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
5764         case 6:
5765                 return getprinterdriver2_level6(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
5766 #if 0   /* JERRY */
5767         case 101:
5768                 /* apparently this call is the equivalent of
5769                    EnumPrinterDataEx() for the DsDriver key */
5770                 break;
5771 #endif
5772         }
5773
5774         return WERR_UNKNOWN_LEVEL;
5775 }
5776
5777
5778 /****************************************************************
5779  _spoolss_StartPagePrinter
5780 ****************************************************************/
5781
5782 WERROR _spoolss_StartPagePrinter(pipes_struct *p,
5783                                  struct spoolss_StartPagePrinter *r)
5784 {
5785         POLICY_HND *handle = r->in.handle;
5786
5787         Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5788
5789         if (!Printer) {
5790                 DEBUG(3,("_spoolss_StartPagePrinter: "
5791                         "Error in startpageprinter printer handle\n"));
5792                 return WERR_BADFID;
5793         }
5794
5795         Printer->page_started=True;
5796         return WERR_OK;
5797 }
5798
5799 /****************************************************************
5800  _spoolss_EndPagePrinter
5801 ****************************************************************/
5802
5803 WERROR _spoolss_EndPagePrinter(pipes_struct *p,
5804                                struct spoolss_EndPagePrinter *r)
5805 {
5806         POLICY_HND *handle = r->in.handle;
5807         int snum;
5808
5809         Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5810
5811         if (!Printer) {
5812                 DEBUG(2,("_spoolss_EndPagePrinter: Invalid handle (%s:%u:%u).\n",
5813                         OUR_HANDLE(handle)));
5814                 return WERR_BADFID;
5815         }
5816
5817         if (!get_printer_snum(p, handle, &snum, NULL))
5818                 return WERR_BADFID;
5819
5820         Printer->page_started=False;
5821         print_job_endpage(snum, Printer->jobid);
5822
5823         return WERR_OK;
5824 }
5825
5826 /****************************************************************
5827  _spoolss_StartDocPrinter
5828 ****************************************************************/
5829
5830 WERROR _spoolss_StartDocPrinter(pipes_struct *p,
5831                                 struct spoolss_StartDocPrinter *r)
5832 {
5833         POLICY_HND *handle = r->in.handle;
5834         uint32_t *jobid = r->out.job_id;
5835         struct spoolss_DocumentInfo1 *info_1;
5836         int snum;
5837         Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5838
5839         if (!Printer) {
5840                 DEBUG(2,("_spoolss_StartDocPrinter: "
5841                         "Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
5842                 return WERR_BADFID;
5843         }
5844
5845         if (r->in.level != 1) {
5846                 return WERR_UNKNOWN_LEVEL;
5847         }
5848
5849         info_1 = r->in.info.info1;
5850
5851         /*
5852          * a nice thing with NT is it doesn't listen to what you tell it.
5853          * when asked to send _only_ RAW datas, it tries to send datas
5854          * in EMF format.
5855          *
5856          * So I add checks like in NT Server ...
5857          */
5858
5859         if (info_1->datatype) {
5860                 if (strcmp(info_1->datatype, "RAW") != 0) {
5861                         (*jobid)=0;
5862                         return WERR_INVALID_DATATYPE;
5863                 }
5864         }
5865
5866         /* get the share number of the printer */
5867         if (!get_printer_snum(p, handle, &snum, NULL)) {
5868                 return WERR_BADFID;
5869         }
5870
5871         Printer->jobid = print_job_start(p->server_info, snum,
5872                                          CONST_DISCARD(char *,info_1->document_name),
5873                                          Printer->nt_devmode);
5874
5875         /* An error occured in print_job_start() so return an appropriate
5876            NT error code. */
5877
5878         if (Printer->jobid == -1) {
5879                 return map_werror_from_unix(errno);
5880         }
5881
5882         Printer->document_started=True;
5883         (*jobid) = Printer->jobid;
5884
5885         return WERR_OK;
5886 }
5887
5888 /****************************************************************
5889  _spoolss_EndDocPrinter
5890 ****************************************************************/
5891
5892 WERROR _spoolss_EndDocPrinter(pipes_struct *p,
5893                               struct spoolss_EndDocPrinter *r)
5894 {
5895         POLICY_HND *handle = r->in.handle;
5896
5897         return _spoolss_enddocprinter_internal(p, handle);
5898 }
5899
5900 /****************************************************************
5901  _spoolss_WritePrinter
5902 ****************************************************************/
5903
5904 WERROR _spoolss_WritePrinter(pipes_struct *p,
5905                              struct spoolss_WritePrinter *r)
5906 {
5907         POLICY_HND *handle = r->in.handle;
5908         uint32 buffer_size = r->in._data_size;
5909         uint8 *buffer = r->in.data.data;
5910         uint32 *buffer_written = &r->in._data_size;
5911         int snum;
5912         Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5913
5914         if (!Printer) {
5915                 DEBUG(2,("_spoolss_WritePrinter: Invalid handle (%s:%u:%u)\n",
5916                         OUR_HANDLE(handle)));
5917                 *r->out.num_written = r->in._data_size;
5918                 return WERR_BADFID;
5919         }
5920
5921         if (!get_printer_snum(p, handle, &snum, NULL))
5922                 return WERR_BADFID;
5923
5924         (*buffer_written) = (uint32)print_job_write(snum, Printer->jobid, (const char *)buffer,
5925                                         (SMB_OFF_T)-1, (size_t)buffer_size);
5926         if (*buffer_written == (uint32)-1) {
5927                 *r->out.num_written = 0;
5928                 if (errno == ENOSPC)
5929                         return WERR_NO_SPOOL_SPACE;
5930                 else
5931                         return WERR_ACCESS_DENIED;
5932         }
5933
5934         *r->out.num_written = r->in._data_size;
5935
5936         return WERR_OK;
5937 }
5938
5939 /********************************************************************
5940  * api_spoolss_getprinter
5941  * called from the spoolss dispatcher
5942  *
5943  ********************************************************************/
5944
5945 static WERROR control_printer(POLICY_HND *handle, uint32 command,
5946                               pipes_struct *p)
5947 {
5948         int snum;
5949         WERROR errcode = WERR_BADFUNC;
5950         Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5951
5952         if (!Printer) {
5953                 DEBUG(2,("control_printer: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
5954                 return WERR_BADFID;
5955         }
5956
5957         if (!get_printer_snum(p, handle, &snum, NULL))
5958                 return WERR_BADFID;
5959
5960         switch (command) {
5961         case SPOOLSS_PRINTER_CONTROL_PAUSE:
5962                 if (print_queue_pause(p->server_info, snum, &errcode)) {
5963                         errcode = WERR_OK;
5964                 }
5965                 break;
5966         case SPOOLSS_PRINTER_CONTROL_RESUME:
5967         case SPOOLSS_PRINTER_CONTROL_UNPAUSE:
5968                 if (print_queue_resume(p->server_info, snum, &errcode)) {
5969                         errcode = WERR_OK;
5970                 }
5971                 break;
5972         case SPOOLSS_PRINTER_CONTROL_PURGE:
5973                 if (print_queue_purge(p->server_info, snum, &errcode)) {
5974                         errcode = WERR_OK;
5975                 }
5976                 break;
5977         default:
5978                 return WERR_UNKNOWN_LEVEL;
5979         }
5980
5981         return errcode;
5982 }
5983
5984
5985 /****************************************************************
5986  _spoolss_AbortPrinter
5987  * From MSDN: "Deletes printer's spool file if printer is configured
5988  * for spooling"
5989 ****************************************************************/
5990
5991 WERROR _spoolss_AbortPrinter(pipes_struct *p,
5992                              struct spoolss_AbortPrinter *r)
5993 {
5994         POLICY_HND      *handle = r->in.handle;
5995         Printer_entry   *Printer = find_printer_index_by_hnd(p, handle);
5996         int             snum;
5997         WERROR          errcode = WERR_OK;
5998
5999         if (!Printer) {
6000                 DEBUG(2,("_spoolss_AbortPrinter: Invalid handle (%s:%u:%u)\n",
6001                         OUR_HANDLE(handle)));
6002                 return WERR_BADFID;
6003         }
6004
6005         if (!get_printer_snum(p, handle, &snum, NULL))
6006                 return WERR_BADFID;
6007
6008         print_job_delete(p->server_info, snum, Printer->jobid, &errcode );
6009
6010         return errcode;
6011 }
6012
6013 /********************************************************************
6014  * called by spoolss_api_setprinter
6015  * when updating a printer description
6016  ********************************************************************/
6017
6018 static WERROR update_printer_sec(POLICY_HND *handle,
6019                                  pipes_struct *p, SEC_DESC_BUF *secdesc_ctr)
6020 {
6021         SEC_DESC_BUF *new_secdesc_ctr = NULL, *old_secdesc_ctr = NULL;
6022         WERROR result;
6023         int snum;
6024
6025         Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
6026
6027         if (!Printer || !get_printer_snum(p, handle, &snum, NULL)) {
6028                 DEBUG(2,("update_printer_sec: Invalid handle (%s:%u:%u)\n",
6029                          OUR_HANDLE(handle)));
6030
6031                 result = WERR_BADFID;
6032                 goto done;
6033         }
6034
6035         if (!secdesc_ctr) {
6036                 DEBUG(10,("update_printer_sec: secdesc_ctr is NULL !\n"));
6037                 result = WERR_INVALID_PARAM;
6038                 goto done;
6039         }
6040
6041         /* Check the user has permissions to change the security
6042            descriptor.  By experimentation with two NT machines, the user
6043            requires Full Access to the printer to change security
6044            information. */
6045
6046         if ( Printer->access_granted != PRINTER_ACCESS_ADMINISTER ) {
6047                 DEBUG(4,("update_printer_sec: updated denied by printer permissions\n"));
6048                 result = WERR_ACCESS_DENIED;
6049                 goto done;
6050         }
6051
6052         /* NT seems to like setting the security descriptor even though
6053            nothing may have actually changed. */
6054
6055         if ( !nt_printing_getsec(p->mem_ctx, Printer->sharename, &old_secdesc_ctr)) {
6056                 DEBUG(2,("update_printer_sec: nt_printing_getsec() failed\n"));
6057                 result = WERR_BADFID;
6058                 goto done;
6059         }
6060
6061         if (DEBUGLEVEL >= 10) {
6062                 SEC_ACL *the_acl;
6063                 int i;
6064
6065                 the_acl = old_secdesc_ctr->sd->dacl;
6066                 DEBUG(10, ("old_secdesc_ctr for %s has %d aces:\n",
6067                            PRINTERNAME(snum), the_acl->num_aces));
6068
6069                 for (i = 0; i < the_acl->num_aces; i++) {
6070                         DEBUG(10, ("%s 0x%08x\n", sid_string_dbg(
6071                                            &the_acl->aces[i].trustee),
6072                                   the_acl->aces[i].access_mask));
6073                 }
6074
6075                 the_acl = secdesc_ctr->sd->dacl;
6076
6077                 if (the_acl) {
6078                         DEBUG(10, ("secdesc_ctr for %s has %d aces:\n",
6079                                    PRINTERNAME(snum), the_acl->num_aces));
6080
6081                         for (i = 0; i < the_acl->num_aces; i++) {
6082                                 DEBUG(10, ("%s 0x%08x\n", sid_string_dbg(
6083                                                    &the_acl->aces[i].trustee),
6084                                            the_acl->aces[i].access_mask));
6085                         }
6086                 } else {
6087                         DEBUG(10, ("dacl for secdesc_ctr is NULL\n"));
6088                 }
6089         }
6090
6091         new_secdesc_ctr = sec_desc_merge(p->mem_ctx, secdesc_ctr, old_secdesc_ctr);
6092         if (!new_secdesc_ctr) {
6093                 result = WERR_NOMEM;
6094                 goto done;
6095         }
6096
6097         if (sec_desc_equal(new_secdesc_ctr->sd, old_secdesc_ctr->sd)) {
6098                 result = WERR_OK;
6099                 goto done;
6100         }
6101
6102         result = nt_printing_setsec(Printer->sharename, new_secdesc_ctr);
6103
6104  done:
6105
6106         return result;
6107 }
6108
6109 /********************************************************************
6110  Canonicalize printer info from a client
6111
6112  ATTN: It does not matter what we set the servername to hear
6113  since we do the necessary work in get_a_printer() to set it to
6114  the correct value based on what the client sent in the
6115  _spoolss_open_printer_ex().
6116  ********************************************************************/
6117
6118 static bool check_printer_ok(NT_PRINTER_INFO_LEVEL_2 *info, int snum)
6119 {
6120         fstring printername;
6121         const char *p;
6122
6123         DEBUG(5,("check_printer_ok: servername=%s printername=%s sharename=%s "
6124                 "portname=%s drivername=%s comment=%s location=%s\n",
6125                 info->servername, info->printername, info->sharename,
6126                 info->portname, info->drivername, info->comment, info->location));
6127
6128         /* we force some elements to "correct" values */
6129         slprintf(info->servername, sizeof(info->servername)-1, "\\\\%s", global_myname());
6130         fstrcpy(info->sharename, lp_servicename(snum));
6131
6132         /* check to see if we allow printername != sharename */
6133
6134         if ( lp_force_printername(snum) ) {
6135                 slprintf(info->printername, sizeof(info->printername)-1, "\\\\%s\\%s",
6136                         global_myname(), info->sharename );
6137         } else {
6138
6139                 /* make sure printername is in \\server\printername format */
6140
6141                 fstrcpy( printername, info->printername );
6142                 p = printername;
6143                 if ( printername[0] == '\\' && printername[1] == '\\' ) {
6144                         if ( (p = strchr_m( &printername[2], '\\' )) != NULL )
6145                                 p++;
6146                 }
6147
6148                 slprintf(info->printername, sizeof(info->printername)-1, "\\\\%s\\%s",
6149                          global_myname(), p );
6150         }
6151
6152         info->attributes |= PRINTER_ATTRIBUTE_SAMBA;
6153         info->attributes &= ~PRINTER_ATTRIBUTE_NOT_SAMBA;
6154
6155
6156
6157         return True;
6158 }
6159
6160 /****************************************************************************
6161 ****************************************************************************/
6162
6163 WERROR add_port_hook(TALLOC_CTX *ctx, NT_USER_TOKEN *token, const char *portname, const char *uri )
6164 {
6165         char *cmd = lp_addport_cmd();
6166         char *command = NULL;
6167         int ret;
6168         SE_PRIV se_printop = SE_PRINT_OPERATOR;
6169         bool is_print_op = False;
6170
6171         if ( !*cmd ) {
6172                 return WERR_ACCESS_DENIED;
6173         }
6174
6175         command = talloc_asprintf(ctx,
6176                         "%s \"%s\" \"%s\"", cmd, portname, uri );
6177         if (!command) {
6178                 return WERR_NOMEM;
6179         }
6180
6181         if ( token )
6182                 is_print_op = user_has_privileges( token, &se_printop );
6183
6184         DEBUG(10,("Running [%s]\n", command));
6185
6186         /********* BEGIN SePrintOperatorPrivilege **********/
6187
6188         if ( is_print_op )
6189                 become_root();
6190
6191         ret = smbrun(command, NULL);
6192
6193         if ( is_print_op )
6194                 unbecome_root();
6195
6196         /********* END SePrintOperatorPrivilege **********/
6197
6198         DEBUGADD(10,("returned [%d]\n", ret));
6199
6200         TALLOC_FREE(command);
6201
6202         if ( ret != 0 ) {
6203                 return WERR_ACCESS_DENIED;
6204         }
6205
6206         return WERR_OK;
6207 }
6208
6209 /****************************************************************************
6210 ****************************************************************************/
6211
6212 bool add_printer_hook(TALLOC_CTX *ctx, NT_USER_TOKEN *token, NT_PRINTER_INFO_LEVEL *printer)
6213 {
6214         char *cmd = lp_addprinter_cmd();
6215         char **qlines;
6216         char *command = NULL;
6217         int numlines;
6218         int ret;
6219         int fd;
6220         SE_PRIV se_printop = SE_PRINT_OPERATOR;
6221         bool is_print_op = False;
6222         char *remote_machine = talloc_strdup(ctx, "%m");
6223
6224         if (!remote_machine) {
6225                 return false;
6226         }
6227         remote_machine = talloc_sub_basic(ctx,
6228                                 current_user_info.smb_name,
6229                                 current_user_info.domain,
6230                                 remote_machine);
6231         if (!remote_machine) {
6232                 return false;
6233         }
6234
6235         command = talloc_asprintf(ctx,
6236                         "%s \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\"",
6237                         cmd, printer->info_2->printername, printer->info_2->sharename,
6238                         printer->info_2->portname, printer->info_2->drivername,
6239                         printer->info_2->location, printer->info_2->comment, remote_machine);
6240         if (!command) {
6241                 return false;
6242         }
6243
6244         if ( token )
6245                 is_print_op = user_has_privileges( token, &se_printop );
6246
6247         DEBUG(10,("Running [%s]\n", command));
6248
6249         /********* BEGIN SePrintOperatorPrivilege **********/
6250
6251         if ( is_print_op )
6252                 become_root();
6253
6254         if ( (ret = smbrun(command, &fd)) == 0 ) {
6255                 /* Tell everyone we updated smb.conf. */
6256                 message_send_all(smbd_messaging_context(),
6257                                  MSG_SMB_CONF_UPDATED, NULL, 0, NULL);
6258         }
6259
6260         if ( is_print_op )
6261                 unbecome_root();
6262
6263         /********* END SePrintOperatorPrivilege **********/
6264
6265         DEBUGADD(10,("returned [%d]\n", ret));
6266
6267         TALLOC_FREE(command);
6268         TALLOC_FREE(remote_machine);
6269
6270         if ( ret != 0 ) {
6271                 if (fd != -1)
6272                         close(fd);
6273                 return False;
6274         }
6275
6276         /* reload our services immediately */
6277         reload_services( False );
6278
6279         numlines = 0;
6280         /* Get lines and convert them back to dos-codepage */
6281         qlines = fd_lines_load(fd, &numlines, 0, NULL);
6282         DEBUGADD(10,("Lines returned = [%d]\n", numlines));
6283         close(fd);
6284
6285         /* Set the portname to what the script says the portname should be. */
6286         /* but don't require anything to be return from the script exit a good error code */
6287
6288         if (numlines) {
6289                 /* Set the portname to what the script says the portname should be. */
6290                 strncpy(printer->info_2->portname, qlines[0], sizeof(printer->info_2->portname));
6291                 DEBUGADD(6,("Line[0] = [%s]\n", qlines[0]));
6292         }
6293
6294         TALLOC_FREE(qlines);
6295         return True;
6296 }
6297
6298
6299 /********************************************************************
6300  * Called by spoolss_api_setprinter
6301  * when updating a printer description.
6302  ********************************************************************/
6303
6304 static WERROR update_printer(pipes_struct *p, POLICY_HND *handle,
6305                              struct spoolss_SetPrinterInfoCtr *info_ctr,
6306                              struct spoolss_DeviceMode *devmode)
6307 {
6308         int snum;
6309         NT_PRINTER_INFO_LEVEL *printer = NULL, *old_printer = NULL;
6310         Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
6311         WERROR result;
6312         UNISTR2 buffer;
6313         fstring asc_buffer;
6314
6315         DEBUG(8,("update_printer\n"));
6316
6317         result = WERR_OK;
6318
6319         if (!Printer) {
6320                 result = WERR_BADFID;
6321                 goto done;
6322         }
6323
6324         if (!get_printer_snum(p, handle, &snum, NULL)) {
6325                 result = WERR_BADFID;
6326                 goto done;
6327         }
6328
6329         if (!W_ERROR_IS_OK(get_a_printer(Printer, &printer, 2, lp_const_servicename(snum))) ||
6330             (!W_ERROR_IS_OK(get_a_printer(Printer, &old_printer, 2, lp_const_servicename(snum))))) {
6331                 result = WERR_BADFID;
6332                 goto done;
6333         }
6334
6335         DEBUGADD(8,("Converting info_2 struct\n"));
6336
6337         /*
6338          * convert_printer_info converts the incoming
6339          * info from the client and overwrites the info
6340          * just read from the tdb in the pointer 'printer'.
6341          */
6342
6343         if (!convert_printer_info_new(info_ctr, printer)) {
6344                 result =  WERR_NOMEM;
6345                 goto done;
6346         }
6347
6348         if (devmode) {
6349                 /* we have a valid devmode
6350                    convert it and link it*/
6351
6352                 DEBUGADD(8,("update_printer: Converting the devicemode struct\n"));
6353                 if (!convert_devicemode_new(printer->info_2->printername,
6354                                             devmode,
6355                                             &printer->info_2->devmode)) {
6356                         result =  WERR_NOMEM;
6357                         goto done;
6358                 }
6359         }
6360
6361         /* Do sanity check on the requested changes for Samba */
6362
6363         if (!check_printer_ok(printer->info_2, snum)) {
6364                 result = WERR_INVALID_PARAM;
6365                 goto done;
6366         }
6367
6368         /* FIXME!!! If the driver has changed we really should verify that
6369            it is installed before doing much else   --jerry */
6370
6371         /* Check calling user has permission to update printer description */
6372
6373         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
6374                 DEBUG(3, ("update_printer: printer property change denied by handle\n"));
6375                 result = WERR_ACCESS_DENIED;
6376                 goto done;
6377         }
6378
6379         /* Call addprinter hook */
6380         /* Check changes to see if this is really needed */
6381
6382         if ( *lp_addprinter_cmd()
6383                 && (!strequal(printer->info_2->drivername, old_printer->info_2->drivername)
6384                         || !strequal(printer->info_2->comment, old_printer->info_2->comment)
6385                         || !strequal(printer->info_2->portname, old_printer->info_2->portname)
6386                         || !strequal(printer->info_2->location, old_printer->info_2->location)) )
6387         {
6388                 /* add_printer_hook() will call reload_services() */
6389
6390                 if ( !add_printer_hook(p->mem_ctx, p->server_info->ptok,
6391                                        printer) ) {
6392                         result = WERR_ACCESS_DENIED;
6393                         goto done;
6394                 }
6395         }
6396
6397         /*
6398          * When a *new* driver is bound to a printer, the drivername is used to
6399          * lookup previously saved driver initialization info, which is then
6400          * bound to the printer, simulating what happens in the Windows arch.
6401          */
6402         if (!strequal(printer->info_2->drivername, old_printer->info_2->drivername))
6403         {
6404                 if (!set_driver_init(printer, 2))
6405                 {
6406                         DEBUG(5,("update_printer: Error restoring driver initialization data for driver [%s]!\n",
6407                                 printer->info_2->drivername));
6408                 }
6409
6410                 DEBUG(10,("update_printer: changing driver [%s]!  Sending event!\n",
6411                         printer->info_2->drivername));
6412
6413                 notify_printer_driver(snum, printer->info_2->drivername);
6414         }
6415
6416         /*
6417          * flag which changes actually occured.  This is a small subset of
6418          * all the possible changes.  We also have to update things in the
6419          * DsSpooler key.
6420          */
6421
6422         if (!strequal(printer->info_2->comment, old_printer->info_2->comment)) {
6423                 init_unistr2( &buffer, printer->info_2->comment, UNI_STR_TERMINATE);
6424                 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "description",
6425                         REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6426
6427                 notify_printer_comment(snum, printer->info_2->comment);
6428         }
6429
6430         if (!strequal(printer->info_2->sharename, old_printer->info_2->sharename)) {
6431                 init_unistr2( &buffer, printer->info_2->sharename, UNI_STR_TERMINATE);
6432                 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "shareName",
6433                         REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6434
6435                 notify_printer_sharename(snum, printer->info_2->sharename);
6436         }
6437
6438         if (!strequal(printer->info_2->printername, old_printer->info_2->printername)) {
6439                 char *pname;
6440
6441                 if ( (pname = strchr_m( printer->info_2->printername+2, '\\' )) != NULL )
6442                         pname++;
6443                 else
6444                         pname = printer->info_2->printername;
6445
6446
6447                 init_unistr2( &buffer, pname, UNI_STR_TERMINATE);
6448                 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "printerName",
6449                         REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6450
6451                 notify_printer_printername( snum, pname );
6452         }
6453
6454         if (!strequal(printer->info_2->portname, old_printer->info_2->portname)) {
6455                 init_unistr2( &buffer, printer->info_2->portname, UNI_STR_TERMINATE);
6456                 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "portName",
6457                         REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6458
6459                 notify_printer_port(snum, printer->info_2->portname);
6460         }
6461
6462         if (!strequal(printer->info_2->location, old_printer->info_2->location)) {
6463                 init_unistr2( &buffer, printer->info_2->location, UNI_STR_TERMINATE);
6464                 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "location",
6465                         REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6466
6467                 notify_printer_location(snum, printer->info_2->location);
6468         }
6469
6470         /* here we need to update some more DsSpooler keys */
6471         /* uNCName, serverName, shortServerName */
6472
6473         init_unistr2( &buffer, global_myname(), UNI_STR_TERMINATE);
6474         set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "serverName",
6475                 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6476         set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "shortServerName",
6477                 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6478
6479         slprintf( asc_buffer, sizeof(asc_buffer)-1, "\\\\%s\\%s",
6480                  global_myname(), printer->info_2->sharename );
6481         init_unistr2( &buffer, asc_buffer, UNI_STR_TERMINATE);
6482         set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "uNCName",
6483                 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6484
6485         /* Update printer info */
6486         result = mod_a_printer(printer, 2);
6487
6488 done:
6489         free_a_printer(&printer, 2);
6490         free_a_printer(&old_printer, 2);
6491
6492
6493         return result;
6494 }
6495
6496 /****************************************************************************
6497 ****************************************************************************/
6498 static WERROR publish_or_unpublish_printer(pipes_struct *p, POLICY_HND *handle,
6499                                            struct spoolss_SetPrinterInfo7 *info7)
6500 {
6501 #ifdef HAVE_ADS
6502         int snum;
6503         Printer_entry *Printer;
6504
6505         if ( lp_security() != SEC_ADS ) {
6506                 return WERR_UNKNOWN_LEVEL;
6507         }
6508
6509         Printer = find_printer_index_by_hnd(p, handle);
6510
6511         DEBUG(5,("publish_or_unpublish_printer, action = %d\n",info7->action));
6512
6513         if (!Printer)
6514                 return WERR_BADFID;
6515
6516         if (!get_printer_snum(p, handle, &snum, NULL))
6517                 return WERR_BADFID;
6518
6519         nt_printer_publish(Printer, snum, info7->action);
6520
6521         return WERR_OK;
6522 #else
6523         return WERR_UNKNOWN_LEVEL;
6524 #endif
6525 }
6526
6527 /****************************************************************
6528  _spoolss_SetPrinter
6529 ****************************************************************/
6530
6531 WERROR _spoolss_SetPrinter(pipes_struct *p,
6532                            struct spoolss_SetPrinter *r)
6533 {
6534         POLICY_HND *handle = r->in.handle;
6535         WERROR result;
6536
6537         Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
6538
6539         if (!Printer) {
6540                 DEBUG(2,("_spoolss_SetPrinter: Invalid handle (%s:%u:%u)\n",
6541                         OUR_HANDLE(handle)));
6542                 return WERR_BADFID;
6543         }
6544
6545         /* check the level */
6546         switch (r->in.info_ctr->level) {
6547                 case 0:
6548                         return control_printer(handle, r->in.command, p);
6549                 case 2:
6550                         result = update_printer(p, handle,
6551                                                 r->in.info_ctr,
6552                                                 r->in.devmode_ctr->devmode);
6553                         if (!W_ERROR_IS_OK(result))
6554                                 return result;
6555                         if (r->in.secdesc_ctr->sd)
6556                                 result = update_printer_sec(handle, p,
6557                                                             r->in.secdesc_ctr);
6558                         return result;
6559                 case 3:
6560                         return update_printer_sec(handle, p,
6561                                                   r->in.secdesc_ctr);
6562                 case 7:
6563                         return publish_or_unpublish_printer(p, handle,
6564                                                             r->in.info_ctr->info.info7);
6565                 default:
6566                         return WERR_UNKNOWN_LEVEL;
6567         }
6568 }
6569
6570 /****************************************************************
6571  _spoolss_FindClosePrinterNotify
6572 ****************************************************************/
6573
6574 WERROR _spoolss_FindClosePrinterNotify(pipes_struct *p,
6575                                        struct spoolss_FindClosePrinterNotify *r)
6576 {
6577         POLICY_HND *handle = r->in.handle;
6578         Printer_entry *Printer= find_printer_index_by_hnd(p, handle);
6579
6580         if (!Printer) {
6581                 DEBUG(2,("_spoolss_FindClosePrinterNotify: "
6582                         "Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
6583                 return WERR_BADFID;
6584         }
6585
6586         if (Printer->notify.client_connected==True) {
6587                 int snum = -1;
6588
6589                 if ( Printer->printer_type == SPLHND_SERVER)
6590                         snum = -1;
6591                 else if ( (Printer->printer_type == SPLHND_PRINTER) &&
6592                                 !get_printer_snum(p, handle, &snum, NULL) )
6593                         return WERR_BADFID;
6594
6595                 srv_spoolss_replycloseprinter(snum, &Printer->notify.client_hnd);
6596         }
6597
6598         Printer->notify.flags=0;
6599         Printer->notify.options=0;
6600         Printer->notify.localmachine[0]='\0';
6601         Printer->notify.printerlocal=0;
6602         TALLOC_FREE(Printer->notify.option);
6603         Printer->notify.client_connected=False;
6604
6605         return WERR_OK;
6606 }
6607
6608 /****************************************************************
6609  _spoolss_AddJob
6610 ****************************************************************/
6611
6612 WERROR _spoolss_AddJob(pipes_struct *p,
6613                        struct spoolss_AddJob *r)
6614 {
6615         if (!r->in.buffer && (r->in.offered != 0)) {
6616                 return WERR_INVALID_PARAM;
6617         }
6618
6619         /* this is what a NT server returns for AddJob. AddJob must fail on
6620          * non-local printers */
6621
6622         return WERR_INVALID_PARAM;
6623 }
6624
6625 /****************************************************************************
6626 ****************************************************************************/
6627
6628 static void fill_job_info_1(JOB_INFO_1 *job_info, const print_queue_struct *queue,
6629                             int position, int snum,
6630                             const NT_PRINTER_INFO_LEVEL *ntprinter)
6631 {
6632         struct tm *t;
6633
6634         t=gmtime(&queue->time);
6635
6636         job_info->jobid=queue->job;
6637         init_unistr(&job_info->printername, lp_servicename(snum));
6638         init_unistr(&job_info->machinename, ntprinter->info_2->servername);
6639         init_unistr(&job_info->username, queue->fs_user);
6640         init_unistr(&job_info->document, queue->fs_file);
6641         init_unistr(&job_info->datatype, "RAW");
6642         init_unistr(&job_info->text_status, "");
6643         job_info->status=nt_printj_status(queue->status);
6644         job_info->priority=queue->priority;
6645         job_info->position=position;
6646         job_info->totalpages=queue->page_count;
6647         job_info->pagesprinted=0;
6648
6649         make_systemtime(&job_info->submitted, t);
6650 }
6651
6652 /****************************************************************************
6653 ****************************************************************************/
6654
6655 static bool fill_job_info_2(JOB_INFO_2 *job_info, const print_queue_struct *queue,
6656                             int position, int snum,
6657                             const NT_PRINTER_INFO_LEVEL *ntprinter,
6658                             DEVICEMODE *devmode)
6659 {
6660         struct tm *t;
6661
6662         t=gmtime(&queue->time);
6663
6664         job_info->jobid=queue->job;
6665
6666         init_unistr(&job_info->printername, ntprinter->info_2->printername);
6667
6668         init_unistr(&job_info->machinename, ntprinter->info_2->servername);
6669         init_unistr(&job_info->username, queue->fs_user);
6670         init_unistr(&job_info->document, queue->fs_file);
6671         init_unistr(&job_info->notifyname, queue->fs_user);
6672         init_unistr(&job_info->datatype, "RAW");
6673         init_unistr(&job_info->printprocessor, "winprint");
6674         init_unistr(&job_info->parameters, "");
6675         init_unistr(&job_info->drivername, ntprinter->info_2->drivername);
6676         init_unistr(&job_info->text_status, "");
6677
6678 /* and here the security descriptor */
6679
6680         job_info->status=nt_printj_status(queue->status);
6681         job_info->priority=queue->priority;
6682         job_info->position=position;
6683         job_info->starttime=0;
6684         job_info->untiltime=0;
6685         job_info->totalpages=queue->page_count;
6686         job_info->size=queue->size;
6687         make_systemtime(&(job_info->submitted), t);
6688         job_info->timeelapsed=0;
6689         job_info->pagesprinted=0;
6690
6691         job_info->devmode = devmode;
6692
6693         return (True);
6694 }
6695
6696 /****************************************************************************
6697  Enumjobs at level 1.
6698 ****************************************************************************/
6699
6700 static WERROR enumjobs_level1(const print_queue_struct *queue, int snum,
6701                               const NT_PRINTER_INFO_LEVEL *ntprinter,
6702                               RPC_BUFFER *buffer, uint32 offered,
6703                               uint32 *needed, uint32 *returned)
6704 {
6705         JOB_INFO_1 *info;
6706         int i;
6707         WERROR result = WERR_OK;
6708
6709         info=SMB_MALLOC_ARRAY(JOB_INFO_1,*returned);
6710         if (info==NULL) {
6711                 *returned=0;
6712                 return WERR_NOMEM;
6713         }
6714
6715         for (i=0; i<*returned; i++)
6716                 fill_job_info_1( &info[i], &queue[i], i, snum, ntprinter );
6717
6718         /* check the required size. */
6719         for (i=0; i<*returned; i++)
6720                 (*needed) += spoolss_size_job_info_1(&info[i]);
6721
6722         if (*needed > offered) {
6723                 result = WERR_INSUFFICIENT_BUFFER;
6724                 goto out;
6725         }
6726
6727         if (!rpcbuf_alloc_size(buffer, *needed)) {
6728                 result = WERR_NOMEM;
6729                 goto out;
6730         }
6731
6732         /* fill the buffer with the structures */
6733         for (i=0; i<*returned; i++)
6734                 smb_io_job_info_1("", buffer, &info[i], 0);
6735
6736 out:
6737         /* clear memory */
6738         SAFE_FREE(info);
6739
6740         if ( !W_ERROR_IS_OK(result) )
6741                 *returned = 0;
6742
6743         return result;
6744 }
6745
6746 /****************************************************************************
6747  Enumjobs at level 2.
6748 ****************************************************************************/
6749
6750 static WERROR enumjobs_level2(const print_queue_struct *queue, int snum,
6751                               const NT_PRINTER_INFO_LEVEL *ntprinter,
6752                               RPC_BUFFER *buffer, uint32 offered,
6753                               uint32 *needed, uint32 *returned)
6754 {
6755         JOB_INFO_2 *info = NULL;
6756         int i;
6757         WERROR result = WERR_OK;
6758         DEVICEMODE *devmode = NULL;
6759
6760         if ( !(info = SMB_MALLOC_ARRAY(JOB_INFO_2,*returned)) ) {
6761                 *returned=0;
6762                 return WERR_NOMEM;
6763         }
6764
6765         /* this should not be a failure condition if the devmode is NULL */
6766
6767         devmode = construct_dev_mode(lp_const_servicename(snum));
6768
6769         for (i=0; i<*returned; i++)
6770                 fill_job_info_2(&(info[i]), &queue[i], i, snum, ntprinter, devmode);
6771
6772         /* check the required size. */
6773         for (i=0; i<*returned; i++)
6774                 (*needed) += spoolss_size_job_info_2(&info[i]);
6775
6776         if (*needed > offered) {
6777                 result = WERR_INSUFFICIENT_BUFFER;
6778                 goto out;
6779         }
6780
6781         if (!rpcbuf_alloc_size(buffer, *needed)) {
6782                 result = WERR_NOMEM;
6783                 goto out;
6784         }
6785
6786         /* fill the buffer with the structures */
6787         for (i=0; i<*returned; i++)
6788                 smb_io_job_info_2("", buffer, &info[i], 0);
6789
6790 out:
6791         free_devmode(devmode);
6792         SAFE_FREE(info);
6793
6794         if ( !W_ERROR_IS_OK(result) )
6795                 *returned = 0;
6796
6797         return result;
6798
6799 }
6800
6801 /****************************************************************************
6802  Enumjobs.
6803 ****************************************************************************/
6804
6805 WERROR _spoolss_enumjobs( pipes_struct *p, SPOOL_Q_ENUMJOBS *q_u, SPOOL_R_ENUMJOBS *r_u)
6806 {
6807         POLICY_HND *handle = &q_u->handle;
6808         uint32 level = q_u->level;
6809         RPC_BUFFER *buffer = NULL;
6810         uint32 offered = q_u->offered;
6811         uint32 *needed = &r_u->needed;
6812         uint32 *returned = &r_u->returned;
6813         WERROR wret;
6814         NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
6815         int snum;
6816         print_status_struct prt_status;
6817         print_queue_struct *queue=NULL;
6818
6819         /* that's an [in out] buffer */
6820
6821         if (!q_u->buffer && (offered!=0)) {
6822                 return WERR_INVALID_PARAM;
6823         }
6824
6825         if (offered > MAX_RPC_DATA_SIZE) {
6826                 return WERR_INVALID_PARAM;
6827         }
6828
6829         rpcbuf_move(q_u->buffer, &r_u->buffer);
6830         buffer = r_u->buffer;
6831
6832         DEBUG(4,("_spoolss_enumjobs\n"));
6833
6834         *needed=0;
6835         *returned=0;
6836
6837         /* lookup the printer snum and tdb entry */
6838
6839         if (!get_printer_snum(p, handle, &snum, NULL))
6840                 return WERR_BADFID;
6841
6842         wret = get_a_printer(NULL, &ntprinter, 2, lp_servicename(snum));
6843         if ( !W_ERROR_IS_OK(wret) )
6844                 return wret;
6845
6846         *returned = print_queue_status(snum, &queue, &prt_status);
6847         DEBUGADD(4,("count:[%d], status:[%d], [%s]\n", *returned, prt_status.status, prt_status.message));
6848
6849         if (*returned == 0) {
6850                 SAFE_FREE(queue);
6851                 free_a_printer(&ntprinter, 2);
6852                 return WERR_OK;
6853         }
6854
6855         switch (level) {
6856         case 1:
6857                 wret = enumjobs_level1(queue, snum, ntprinter, buffer, offered, needed, returned);
6858                 break;
6859         case 2:
6860                 wret = enumjobs_level2(queue, snum, ntprinter, buffer, offered, needed, returned);
6861                 break;
6862         default:
6863                 *returned=0;
6864                 wret = WERR_UNKNOWN_LEVEL;
6865                 break;
6866         }
6867
6868         SAFE_FREE(queue);
6869         free_a_printer( &ntprinter, 2 );
6870         return wret;
6871 }
6872
6873 /****************************************************************
6874  _spoolss_ScheduleJob
6875 ****************************************************************/
6876
6877 WERROR _spoolss_ScheduleJob(pipes_struct *p,
6878                             struct spoolss_ScheduleJob *r)
6879 {
6880         return WERR_OK;
6881 }
6882
6883 /****************************************************************
6884  _spoolss_SetJob
6885 ****************************************************************/
6886
6887 WERROR _spoolss_SetJob(pipes_struct *p,
6888                        struct spoolss_SetJob *r)
6889 {
6890         POLICY_HND *handle = r->in.handle;
6891         uint32 jobid = r->in.job_id;
6892         uint32 command = r->in.command;
6893
6894         int snum;
6895         WERROR errcode = WERR_BADFUNC;
6896
6897         if (!get_printer_snum(p, handle, &snum, NULL)) {
6898                 return WERR_BADFID;
6899         }
6900
6901         if (!print_job_exists(lp_const_servicename(snum), jobid)) {
6902                 return WERR_INVALID_PRINTER_NAME;
6903         }
6904
6905         switch (command) {
6906         case SPOOLSS_JOB_CONTROL_CANCEL:
6907         case SPOOLSS_JOB_CONTROL_DELETE:
6908                 if (print_job_delete(p->server_info, snum, jobid, &errcode)) {
6909                         errcode = WERR_OK;
6910                 }
6911                 break;
6912         case SPOOLSS_JOB_CONTROL_PAUSE:
6913                 if (print_job_pause(p->server_info, snum, jobid, &errcode)) {
6914                         errcode = WERR_OK;
6915                 }
6916                 break;
6917         case SPOOLSS_JOB_CONTROL_RESTART:
6918         case SPOOLSS_JOB_CONTROL_RESUME:
6919                 if (print_job_resume(p->server_info, snum, jobid, &errcode)) {
6920                         errcode = WERR_OK;
6921                 }
6922                 break;
6923         default:
6924                 return WERR_UNKNOWN_LEVEL;
6925         }
6926
6927         return errcode;
6928 }
6929
6930 /****************************************************************************
6931  Enumerates all printer drivers at level 1.
6932 ****************************************************************************/
6933
6934 static WERROR enumprinterdrivers_level1(const char *servername, fstring architecture, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
6935 {
6936         int i;
6937         int ndrivers;
6938         uint32 version;
6939         fstring *list = NULL;
6940         NT_PRINTER_DRIVER_INFO_LEVEL driver;
6941         DRIVER_INFO_1 *driver_info_1=NULL;
6942         WERROR result = WERR_OK;
6943
6944         *returned=0;
6945
6946         for (version=0; version<DRIVER_MAX_VERSION; version++) {
6947                 list=NULL;
6948                 ndrivers=get_ntdrivers(&list, architecture, version);
6949                 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
6950
6951                 if(ndrivers == -1) {
6952                         SAFE_FREE(driver_info_1);
6953                         return WERR_NOMEM;
6954                 }
6955
6956                 if(ndrivers != 0) {
6957                         if((driver_info_1=SMB_REALLOC_ARRAY(driver_info_1, DRIVER_INFO_1, *returned+ndrivers )) == NULL) {
6958                                 DEBUG(0,("enumprinterdrivers_level1: failed to enlarge driver info buffer!\n"));
6959                                 SAFE_FREE(list);
6960                                 return WERR_NOMEM;
6961                         }
6962                 }
6963
6964                 for (i=0; i<ndrivers; i++) {
6965                         WERROR status;
6966                         DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
6967                         ZERO_STRUCT(driver);
6968                         status = get_a_printer_driver(&driver, 3, list[i],
6969                                                       architecture, version);
6970                         if (!W_ERROR_IS_OK(status)) {
6971                                 SAFE_FREE(list);
6972                                 SAFE_FREE(driver_info_1);
6973                                 return status;
6974                         }
6975                         fill_printer_driver_info_1(&driver_info_1[*returned+i], driver, servername, architecture );
6976                         free_a_printer_driver(driver, 3);
6977                 }
6978
6979                 *returned+=ndrivers;
6980                 SAFE_FREE(list);
6981         }
6982
6983         /* check the required size. */
6984         for (i=0; i<*returned; i++) {
6985                 DEBUGADD(6,("adding driver [%d]'s size\n",i));
6986                 *needed += spoolss_size_printer_driver_info_1(&driver_info_1[i]);
6987         }
6988
6989         if (*needed > offered) {
6990                 result = WERR_INSUFFICIENT_BUFFER;
6991                 goto out;
6992         }
6993
6994         if (!rpcbuf_alloc_size(buffer, *needed)) {
6995                 result = WERR_NOMEM;
6996                 goto out;
6997         }
6998
6999         /* fill the buffer with the driver structures */
7000         for (i=0; i<*returned; i++) {
7001                 DEBUGADD(6,("adding driver [%d] to buffer\n",i));
7002                 smb_io_printer_driver_info_1("", buffer, &driver_info_1[i], 0);
7003         }
7004
7005 out:
7006         SAFE_FREE(driver_info_1);
7007
7008         if ( !W_ERROR_IS_OK(result) )
7009                 *returned = 0;
7010
7011         return result;
7012 }
7013
7014 /****************************************************************************
7015  Enumerates all printer drivers at level 2.
7016 ****************************************************************************/
7017
7018 static WERROR enumprinterdrivers_level2(const char *servername, fstring architecture, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
7019 {
7020         int i;
7021         int ndrivers;
7022         uint32 version;
7023         fstring *list = NULL;
7024         NT_PRINTER_DRIVER_INFO_LEVEL driver;
7025         DRIVER_INFO_2 *driver_info_2=NULL;
7026         WERROR result = WERR_OK;
7027
7028         *returned=0;
7029
7030         for (version=0; version<DRIVER_MAX_VERSION; version++) {
7031                 list=NULL;
7032                 ndrivers=get_ntdrivers(&list, architecture, version);
7033                 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
7034
7035                 if(ndrivers == -1) {
7036                         SAFE_FREE(driver_info_2);
7037                         return WERR_NOMEM;
7038                 }
7039
7040                 if(ndrivers != 0) {
7041                         if((driver_info_2=SMB_REALLOC_ARRAY(driver_info_2, DRIVER_INFO_2, *returned+ndrivers )) == NULL) {
7042                                 DEBUG(0,("enumprinterdrivers_level2: failed to enlarge driver info buffer!\n"));
7043                                 SAFE_FREE(list);
7044                                 return WERR_NOMEM;
7045                         }
7046                 }
7047
7048                 for (i=0; i<ndrivers; i++) {
7049                         WERROR status;
7050
7051                         DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
7052                         ZERO_STRUCT(driver);
7053                         status = get_a_printer_driver(&driver, 3, list[i],
7054                                                       architecture, version);
7055                         if (!W_ERROR_IS_OK(status)) {
7056                                 SAFE_FREE(list);
7057                                 SAFE_FREE(driver_info_2);
7058                                 return status;
7059                         }
7060                         fill_printer_driver_info_2(&driver_info_2[*returned+i], driver, servername);
7061                         free_a_printer_driver(driver, 3);
7062                 }
7063
7064                 *returned+=ndrivers;
7065                 SAFE_FREE(list);
7066         }
7067
7068         /* check the required size. */
7069         for (i=0; i<*returned; i++) {
7070                 DEBUGADD(6,("adding driver [%d]'s size\n",i));
7071                 *needed += spoolss_size_printer_driver_info_2(&(driver_info_2[i]));
7072         }
7073
7074         if (*needed > offered) {
7075                 result = WERR_INSUFFICIENT_BUFFER;
7076                 goto out;
7077         }
7078
7079         if (!rpcbuf_alloc_size(buffer, *needed)) {
7080                 result = WERR_NOMEM;
7081                 goto out;
7082         }
7083
7084         /* fill the buffer with the form structures */
7085         for (i=0; i<*returned; i++) {
7086                 DEBUGADD(6,("adding driver [%d] to buffer\n",i));
7087                 smb_io_printer_driver_info_2("", buffer, &(driver_info_2[i]), 0);
7088         }
7089
7090 out:
7091         SAFE_FREE(driver_info_2);
7092
7093         if ( !W_ERROR_IS_OK(result) )
7094                 *returned = 0;
7095
7096         return result;
7097 }
7098
7099 /****************************************************************************
7100  Enumerates all printer drivers at level 3.
7101 ****************************************************************************/
7102
7103 static WERROR enumprinterdrivers_level3(const char *servername, fstring architecture, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
7104 {
7105         int i;
7106         int ndrivers;
7107         uint32 version;
7108         fstring *list = NULL;
7109         DRIVER_INFO_3 *driver_info_3=NULL;
7110         NT_PRINTER_DRIVER_INFO_LEVEL driver;
7111         WERROR result = WERR_OK;
7112
7113         *returned=0;
7114
7115         for (version=0; version<DRIVER_MAX_VERSION; version++) {
7116                 list=NULL;
7117                 ndrivers=get_ntdrivers(&list, architecture, version);
7118                 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
7119
7120                 if(ndrivers == -1) {
7121                         SAFE_FREE(driver_info_3);
7122                         return WERR_NOMEM;
7123                 }
7124
7125                 if(ndrivers != 0) {
7126                         if((driver_info_3=SMB_REALLOC_ARRAY(driver_info_3, DRIVER_INFO_3, *returned+ndrivers )) == NULL) {
7127                                 DEBUG(0,("enumprinterdrivers_level3: failed to enlarge driver info buffer!\n"));
7128                                 SAFE_FREE(list);
7129                                 return WERR_NOMEM;
7130                         }
7131                 }
7132
7133                 for (i=0; i<ndrivers; i++) {
7134                         WERROR status;
7135
7136                         DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
7137                         ZERO_STRUCT(driver);
7138                         status = get_a_printer_driver(&driver, 3, list[i],
7139                                                       architecture, version);
7140                         if (!W_ERROR_IS_OK(status)) {
7141                                 SAFE_FREE(list);
7142                                 SAFE_FREE(driver_info_3);
7143                                 return status;
7144                         }
7145                         fill_printer_driver_info_3(&driver_info_3[*returned+i], driver, servername);
7146                         free_a_printer_driver(driver, 3);
7147                 }
7148
7149                 *returned+=ndrivers;
7150                 SAFE_FREE(list);
7151         }
7152
7153         /* check the required size. */
7154         for (i=0; i<*returned; i++) {
7155                 DEBUGADD(6,("adding driver [%d]'s size\n",i));
7156                 *needed += spoolss_size_printer_driver_info_3(&driver_info_3[i]);
7157         }
7158
7159         if (*needed > offered) {
7160                 result = WERR_INSUFFICIENT_BUFFER;
7161                 goto out;
7162         }
7163
7164         if (!rpcbuf_alloc_size(buffer, *needed)) {
7165                 result = WERR_NOMEM;
7166                 goto out;
7167         }
7168
7169         /* fill the buffer with the driver structures */
7170         for (i=0; i<*returned; i++) {
7171                 DEBUGADD(6,("adding driver [%d] to buffer\n",i));
7172                 smb_io_printer_driver_info_3("", buffer, &driver_info_3[i], 0);
7173         }
7174
7175 out:
7176         for (i=0; i<*returned; i++) {
7177                 SAFE_FREE(driver_info_3[i].dependentfiles);
7178         }
7179
7180         SAFE_FREE(driver_info_3);
7181
7182         if ( !W_ERROR_IS_OK(result) )
7183                 *returned = 0;
7184
7185         return result;
7186 }
7187
7188 /****************************************************************************
7189  Enumerates all printer drivers.
7190 ****************************************************************************/
7191
7192 WERROR _spoolss_enumprinterdrivers( pipes_struct *p, SPOOL_Q_ENUMPRINTERDRIVERS *q_u, SPOOL_R_ENUMPRINTERDRIVERS *r_u)
7193 {
7194         uint32 level = q_u->level;
7195         RPC_BUFFER *buffer = NULL;
7196         uint32 offered = q_u->offered;
7197         uint32 *needed = &r_u->needed;
7198         uint32 *returned = &r_u->returned;
7199         const char *cservername;
7200         fstring servername;
7201         fstring architecture;
7202
7203         /* that's an [in out] buffer */
7204
7205         if (!q_u->buffer && (offered!=0)) {
7206                 return WERR_INVALID_PARAM;
7207         }
7208
7209         if (offered > MAX_RPC_DATA_SIZE) {
7210                 return WERR_INVALID_PARAM;
7211         }
7212
7213         rpcbuf_move(q_u->buffer, &r_u->buffer);
7214         buffer = r_u->buffer;
7215
7216         DEBUG(4,("_spoolss_enumprinterdrivers\n"));
7217
7218         *needed   = 0;
7219         *returned = 0;
7220
7221         unistr2_to_ascii(architecture, &q_u->environment, sizeof(architecture));
7222         unistr2_to_ascii(servername, &q_u->name, sizeof(servername));
7223
7224         cservername = canon_servername(servername);
7225
7226         if (!is_myname_or_ipaddr(cservername))
7227                 return WERR_UNKNOWN_PRINTER_DRIVER;
7228
7229         switch (level) {
7230         case 1:
7231                 return enumprinterdrivers_level1(cservername, architecture, buffer, offered, needed, returned);
7232         case 2:
7233                 return enumprinterdrivers_level2(cservername, architecture, buffer, offered, needed, returned);
7234         case 3:
7235                 return enumprinterdrivers_level3(cservername, architecture, buffer, offered, needed, returned);
7236         default:
7237                 return WERR_UNKNOWN_LEVEL;
7238         }
7239 }
7240
7241 /****************************************************************************
7242 ****************************************************************************/
7243
7244 static void fill_form_1(FORM_1 *form, nt_forms_struct *list)
7245 {
7246         form->flag=list->flag;
7247         init_unistr(&form->name, list->name);
7248         form->width=list->width;
7249         form->length=list->length;
7250         form->left=list->left;
7251         form->top=list->top;
7252         form->right=list->right;
7253         form->bottom=list->bottom;
7254 }
7255
7256 /****************************************************************************
7257 ****************************************************************************/
7258
7259 static WERROR fill_form_info_1(TALLOC_CTX *mem_ctx,
7260                                struct spoolss_FormInfo1 *form,
7261                                nt_forms_struct *list)
7262 {
7263         form->form_name         = talloc_strdup(mem_ctx, list->name);
7264         W_ERROR_HAVE_NO_MEMORY(form->form_name);
7265
7266         form->flags             = list->flag;
7267         form->size.width        = list->width;
7268         form->size.height       = list->length;
7269         form->area.left         = list->left;
7270         form->area.top          = list->top;
7271         form->area.right        = list->right;
7272         form->area.bottom       = list->bottom;
7273
7274         return WERR_OK;
7275 }
7276
7277 /****************************************************************************
7278 ****************************************************************************/
7279
7280 WERROR _spoolss_enumforms(pipes_struct *p, SPOOL_Q_ENUMFORMS *q_u, SPOOL_R_ENUMFORMS *r_u)
7281 {
7282         uint32 level = q_u->level;
7283         RPC_BUFFER *buffer = NULL;
7284         uint32 offered = q_u->offered;
7285         uint32 *needed = &r_u->needed;
7286         uint32 *numofforms = &r_u->numofforms;
7287         uint32 numbuiltinforms;
7288
7289         nt_forms_struct *list=NULL;
7290         nt_forms_struct *builtinlist=NULL;
7291         FORM_1 *forms_1;
7292         int buffer_size=0;
7293         int i;
7294
7295         /* that's an [in out] buffer */
7296
7297         if (!q_u->buffer && (offered!=0) ) {
7298                 return WERR_INVALID_PARAM;
7299         }
7300
7301         if (offered > MAX_RPC_DATA_SIZE) {
7302                 return WERR_INVALID_PARAM;
7303         }
7304
7305         rpcbuf_move(q_u->buffer, &r_u->buffer);
7306         buffer = r_u->buffer;
7307
7308         DEBUG(4,("_spoolss_enumforms\n"));
7309         DEBUGADD(5,("Offered buffer size [%d]\n", offered));
7310         DEBUGADD(5,("Info level [%d]\n",          level));
7311
7312         numbuiltinforms = get_builtin_ntforms(&builtinlist);
7313         DEBUGADD(5,("Number of builtin forms [%d]\n",     numbuiltinforms));
7314         *numofforms = get_ntforms(&list);
7315         DEBUGADD(5,("Number of user forms [%d]\n",     *numofforms));
7316         *numofforms += numbuiltinforms;
7317
7318         if (*numofforms == 0) {
7319                 SAFE_FREE(builtinlist);
7320                 SAFE_FREE(list);
7321                 return WERR_NO_MORE_ITEMS;
7322         }
7323
7324         switch (level) {
7325         case 1:
7326                 if ((forms_1=SMB_MALLOC_ARRAY(FORM_1, *numofforms)) == NULL) {
7327                         SAFE_FREE(builtinlist);
7328                         SAFE_FREE(list);
7329                         *numofforms=0;
7330                         return WERR_NOMEM;
7331                 }
7332
7333                 /* construct the list of form structures */
7334                 for (i=0; i<numbuiltinforms; i++) {
7335                         DEBUGADD(6,("Filling form number [%d]\n",i));
7336                         fill_form_1(&forms_1[i], &builtinlist[i]);
7337                 }
7338
7339                 SAFE_FREE(builtinlist);
7340
7341                 for (; i<*numofforms; i++) {
7342                         DEBUGADD(6,("Filling form number [%d]\n",i));
7343                         fill_form_1(&forms_1[i], &list[i-numbuiltinforms]);
7344                 }
7345
7346                 SAFE_FREE(list);
7347
7348                 /* check the required size. */
7349                 for (i=0; i<numbuiltinforms; i++) {
7350                         DEBUGADD(6,("adding form [%d]'s size\n",i));
7351                         buffer_size += spoolss_size_form_1(&forms_1[i]);
7352                 }
7353                 for (; i<*numofforms; i++) {
7354                         DEBUGADD(6,("adding form [%d]'s size\n",i));
7355                         buffer_size += spoolss_size_form_1(&forms_1[i]);
7356                 }
7357
7358                 *needed=buffer_size;
7359
7360                 if (*needed > offered) {
7361                         SAFE_FREE(forms_1);
7362                         *numofforms=0;
7363                         return WERR_INSUFFICIENT_BUFFER;
7364                 }
7365
7366                 if (!rpcbuf_alloc_size(buffer, buffer_size)){
7367                         SAFE_FREE(forms_1);
7368                         *numofforms=0;
7369                         return WERR_NOMEM;
7370                 }
7371
7372                 /* fill the buffer with the form structures */
7373                 for (i=0; i<numbuiltinforms; i++) {
7374                         DEBUGADD(6,("adding form [%d] to buffer\n",i));
7375                         smb_io_form_1("", buffer, &forms_1[i], 0);
7376                 }
7377                 for (; i<*numofforms; i++) {
7378                         DEBUGADD(6,("adding form [%d] to buffer\n",i));
7379                         smb_io_form_1("", buffer, &forms_1[i], 0);
7380                 }
7381
7382                 SAFE_FREE(forms_1);
7383
7384                 return WERR_OK;
7385
7386         default:
7387                 SAFE_FREE(list);
7388                 SAFE_FREE(builtinlist);
7389                 return WERR_UNKNOWN_LEVEL;
7390         }
7391 }
7392
7393 /****************************************************************
7394  _spoolss_GetForm
7395 ****************************************************************/
7396
7397 WERROR _spoolss_GetForm(pipes_struct *p,
7398                         struct spoolss_GetForm *r)
7399 {
7400         uint32 level = r->in.level;
7401         uint32 offered = r->in.offered;
7402         uint32 *needed = r->out.needed;
7403
7404         nt_forms_struct *list=NULL;
7405         nt_forms_struct builtin_form;
7406         bool foundBuiltin;
7407         union spoolss_FormInfo info;
7408         struct spoolss_FormInfo1 form_1;
7409         int numofforms=0, i=0;
7410
7411         /* that's an [in out] buffer */
7412
7413         if (!r->in.buffer && (offered!=0)) {
7414                 return WERR_INVALID_PARAM;
7415         }
7416
7417         DEBUG(4,("_spoolss_GetForm\n"));
7418         DEBUGADD(5,("Offered buffer size [%d]\n", offered));
7419         DEBUGADD(5,("Info level [%d]\n",          level));
7420
7421         foundBuiltin = get_a_builtin_ntform_by_string(r->in.form_name, &builtin_form);
7422         if (!foundBuiltin) {
7423                 numofforms = get_ntforms(&list);
7424                 DEBUGADD(5,("Number of forms [%d]\n",     numofforms));
7425
7426                 if (numofforms == 0)
7427                         return WERR_BADFID;
7428         }
7429
7430         ZERO_STRUCT(form_1);
7431
7432         switch (level) {
7433         case 1:
7434                 if (foundBuiltin) {
7435                         fill_form_info_1(p->mem_ctx, &form_1, &builtin_form);
7436                 } else {
7437
7438                         /* Check if the requested name is in the list of form structures */
7439                         for (i=0; i<numofforms; i++) {
7440
7441                                 DEBUG(4,("_spoolss_GetForm: checking form %s (want %s)\n",
7442                                         list[i].name, r->in.form_name));
7443
7444                                 if (strequal(r->in.form_name, list[i].name)) {
7445                                         DEBUGADD(6,("Found form %s number [%d]\n",
7446                                                 r->in.form_name, i));
7447                                         fill_form_info_1(p->mem_ctx, &form_1, &list[i]);
7448                                         break;
7449                                 }
7450                         }
7451
7452                         SAFE_FREE(list);
7453                         if (i == numofforms) {
7454                                 return WERR_BADFID;
7455                         }
7456                 }
7457                 /* check the required size. */
7458
7459                 info.info1 = form_1;
7460
7461                 *needed = ndr_size_spoolss_FormInfo(&info, 1, NULL, 0);
7462
7463                 if (*needed > offered) {
7464                         r->out.info = NULL;
7465                         return WERR_INSUFFICIENT_BUFFER;
7466                 }
7467
7468                 r->out.info->info1 = form_1;
7469
7470                 /* fill the buffer with the form structures */
7471                 DEBUGADD(6,("adding form %s [%d] to buffer\n",
7472                         r->in.form_name, i));
7473
7474                 return WERR_OK;
7475
7476         default:
7477                 SAFE_FREE(list);
7478                 return WERR_UNKNOWN_LEVEL;
7479         }
7480 }
7481
7482 /****************************************************************************
7483 ****************************************************************************/
7484
7485 static void fill_port_1(PORT_INFO_1 *port, const char *name)
7486 {
7487         init_unistr(&port->port_name, name);
7488 }
7489
7490 /****************************************************************************
7491  TODO: This probably needs distinguish between TCP/IP and Local ports
7492  somehow.
7493 ****************************************************************************/
7494
7495 static void fill_port_2(PORT_INFO_2 *port, const char *name)
7496 {
7497         init_unistr(&port->port_name, name);
7498         init_unistr(&port->monitor_name, "Local Monitor");
7499         init_unistr(&port->description, SPL_LOCAL_PORT );
7500         port->port_type=PORT_TYPE_WRITE;
7501         port->reserved=0x0;
7502 }
7503
7504
7505 /****************************************************************************
7506  wrapper around the enumer ports command
7507 ****************************************************************************/
7508
7509 WERROR enumports_hook(TALLOC_CTX *ctx, int *count, char ***lines )
7510 {
7511         char *cmd = lp_enumports_cmd();
7512         char **qlines = NULL;
7513         char *command = NULL;
7514         int numlines;
7515         int ret;
7516         int fd;
7517
7518         *count = 0;
7519         *lines = NULL;
7520
7521         /* if no hook then just fill in the default port */
7522
7523         if ( !*cmd ) {
7524                 if (!(qlines = TALLOC_ARRAY( NULL, char*, 2 ))) {
7525                         return WERR_NOMEM;
7526                 }
7527                 if (!(qlines[0] = talloc_strdup(qlines, SAMBA_PRINTER_PORT_NAME ))) {
7528                         TALLOC_FREE(qlines);
7529                         return WERR_NOMEM;
7530                 }
7531                 qlines[1] = NULL;
7532                 numlines = 1;
7533         }
7534         else {
7535                 /* we have a valid enumport command */
7536
7537                 command = talloc_asprintf(ctx, "%s \"%d\"", cmd, 1);
7538                 if (!command) {
7539                         return WERR_NOMEM;
7540                 }
7541
7542                 DEBUG(10,("Running [%s]\n", command));
7543                 ret = smbrun(command, &fd);
7544                 DEBUG(10,("Returned [%d]\n", ret));
7545                 TALLOC_FREE(command);
7546                 if (ret != 0) {
7547                         if (fd != -1) {
7548                                 close(fd);
7549                         }
7550                         return WERR_ACCESS_DENIED;
7551                 }
7552
7553                 numlines = 0;
7554                 qlines = fd_lines_load(fd, &numlines, 0, NULL);
7555                 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
7556                 close(fd);
7557         }
7558
7559         *count = numlines;
7560         *lines = qlines;
7561
7562         return WERR_OK;
7563 }
7564
7565 /****************************************************************************
7566  enumports level 1.
7567 ****************************************************************************/
7568
7569 static WERROR enumports_level_1(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
7570 {
7571         PORT_INFO_1 *ports=NULL;
7572         int i=0;
7573         WERROR result = WERR_OK;
7574         char **qlines = NULL;
7575         int numlines = 0;
7576
7577         result = enumports_hook(talloc_tos(), &numlines, &qlines );
7578         if (!W_ERROR_IS_OK(result)) {
7579                 TALLOC_FREE(qlines);
7580                 return result;
7581         }
7582
7583         if(numlines) {
7584                 if((ports=SMB_MALLOC_ARRAY( PORT_INFO_1, numlines )) == NULL) {
7585                         DEBUG(10,("Returning WERR_NOMEM [%s]\n",
7586                                   win_errstr(WERR_NOMEM)));
7587                         TALLOC_FREE(qlines);
7588                         return WERR_NOMEM;
7589                 }
7590
7591                 for (i=0; i<numlines; i++) {
7592                         DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
7593                         fill_port_1(&ports[i], qlines[i]);
7594                 }
7595         }
7596         TALLOC_FREE(qlines);
7597
7598         *returned = numlines;
7599
7600         /* check the required size. */
7601         for (i=0; i<*returned; i++) {
7602                 DEBUGADD(6,("adding port [%d]'s size\n", i));
7603                 *needed += spoolss_size_port_info_1(&ports[i]);
7604         }
7605
7606         if (*needed > offered) {
7607                 result = WERR_INSUFFICIENT_BUFFER;
7608                 goto out;
7609         }
7610
7611         if (!rpcbuf_alloc_size(buffer, *needed)) {
7612                 result = WERR_NOMEM;
7613                 goto out;
7614         }
7615
7616         /* fill the buffer with the ports structures */
7617         for (i=0; i<*returned; i++) {
7618                 DEBUGADD(6,("adding port [%d] to buffer\n", i));
7619                 smb_io_port_1("", buffer, &ports[i], 0);
7620         }
7621
7622 out:
7623         SAFE_FREE(ports);
7624
7625         if ( !W_ERROR_IS_OK(result) )
7626                 *returned = 0;
7627
7628         return result;
7629 }
7630
7631 /****************************************************************************
7632  enumports level 2.
7633 ****************************************************************************/
7634
7635 static WERROR enumports_level_2(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
7636 {
7637         PORT_INFO_2 *ports=NULL;
7638         int i=0;
7639         WERROR result = WERR_OK;
7640         char **qlines = NULL;
7641         int numlines = 0;
7642
7643         result = enumports_hook(talloc_tos(), &numlines, &qlines );
7644         if ( !W_ERROR_IS_OK(result)) {
7645                 TALLOC_FREE(qlines);
7646                 return result;
7647         }
7648
7649         if(numlines) {
7650                 if((ports=SMB_MALLOC_ARRAY( PORT_INFO_2, numlines)) == NULL) {
7651                         TALLOC_FREE(qlines);
7652                         return WERR_NOMEM;
7653                 }
7654
7655                 for (i=0; i<numlines; i++) {
7656                         DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
7657                         fill_port_2(&(ports[i]), qlines[i]);
7658                 }
7659         }
7660
7661         TALLOC_FREE(qlines);
7662
7663         *returned = numlines;
7664
7665         /* check the required size. */
7666         for (i=0; i<*returned; i++) {
7667                 DEBUGADD(6,("adding port [%d]'s size\n", i));
7668                 *needed += spoolss_size_port_info_2(&ports[i]);
7669         }
7670
7671         if (*needed > offered) {
7672                 result = WERR_INSUFFICIENT_BUFFER;
7673                 goto out;
7674         }
7675
7676         if (!rpcbuf_alloc_size(buffer, *needed)) {
7677                 result = WERR_NOMEM;
7678                 goto out;
7679         }
7680
7681         /* fill the buffer with the ports structures */
7682         for (i=0; i<*returned; i++) {
7683                 DEBUGADD(6,("adding port [%d] to buffer\n", i));
7684                 smb_io_port_2("", buffer, &ports[i], 0);
7685         }
7686
7687 out:
7688         SAFE_FREE(ports);
7689
7690         if ( !W_ERROR_IS_OK(result) )
7691                 *returned = 0;
7692
7693         return result;
7694 }
7695
7696 /****************************************************************************
7697  enumports.
7698 ****************************************************************************/
7699
7700 WERROR _spoolss_enumports( pipes_struct *p, SPOOL_Q_ENUMPORTS *q_u, SPOOL_R_ENUMPORTS *r_u)
7701 {
7702         uint32 level = q_u->level;
7703         RPC_BUFFER *buffer = NULL;
7704         uint32 offered = q_u->offered;
7705         uint32 *needed = &r_u->needed;
7706         uint32 *returned = &r_u->returned;
7707
7708         /* that's an [in out] buffer */
7709
7710         if (!q_u->buffer && (offered!=0)) {
7711                 return WERR_INVALID_PARAM;
7712         }
7713
7714         if (offered > MAX_RPC_DATA_SIZE) {
7715                 return WERR_INVALID_PARAM;
7716         }
7717
7718         rpcbuf_move(q_u->buffer, &r_u->buffer);
7719         buffer = r_u->buffer;
7720
7721         DEBUG(4,("_spoolss_enumports\n"));
7722
7723         *returned=0;
7724         *needed=0;
7725
7726         switch (level) {
7727         case 1:
7728                 return enumports_level_1(buffer, offered, needed, returned);
7729         case 2:
7730                 return enumports_level_2(buffer, offered, needed, returned);
7731         default:
7732                 return WERR_UNKNOWN_LEVEL;
7733         }
7734 }
7735
7736 /****************************************************************************
7737 ****************************************************************************/
7738
7739 static WERROR spoolss_addprinterex_level_2(pipes_struct *p,
7740                                            const char *server,
7741                                            struct spoolss_SetPrinterInfoCtr *info_ctr,
7742                                            struct spoolss_DeviceMode *devmode,
7743                                            struct security_descriptor *sec_desc,
7744                                            struct spoolss_UserLevelCtr *user_ctr,
7745                                            POLICY_HND *handle)
7746 {
7747         NT_PRINTER_INFO_LEVEL *printer = NULL;
7748         fstring name;
7749         int     snum;
7750         WERROR err = WERR_OK;
7751
7752         if ( !(printer = TALLOC_ZERO_P(NULL, NT_PRINTER_INFO_LEVEL)) ) {
7753                 DEBUG(0,("spoolss_addprinterex_level_2: malloc fail.\n"));
7754                 return WERR_NOMEM;
7755         }
7756
7757         /* convert from UNICODE to ASCII - this allocates the info_2 struct inside *printer.*/
7758         if (!convert_printer_info_new(info_ctr, printer)) {
7759                 free_a_printer(&printer, 2);
7760                 return WERR_NOMEM;
7761         }
7762
7763         /* check to see if the printer already exists */
7764
7765         if ((snum = print_queue_snum(printer->info_2->sharename)) != -1) {
7766                 DEBUG(5, ("spoolss_addprinterex_level_2: Attempted to add a printer named [%s] when one already existed!\n",
7767                         printer->info_2->sharename));
7768                 free_a_printer(&printer, 2);
7769                 return WERR_PRINTER_ALREADY_EXISTS;
7770         }
7771
7772         /* FIXME!!!  smbd should check to see if the driver is installed before
7773            trying to add a printer like this  --jerry */
7774
7775         if (*lp_addprinter_cmd() ) {
7776                 if ( !add_printer_hook(p->mem_ctx, p->server_info->ptok,
7777                                        printer) ) {
7778                         free_a_printer(&printer,2);
7779                         return WERR_ACCESS_DENIED;
7780                 }
7781         } else {
7782                 DEBUG(0,("spoolss_addprinterex_level_2: add printer for printer %s called and no"
7783                         "smb.conf parameter \"addprinter command\" is defined. This"
7784                         "parameter must exist for this call to succeed\n",
7785                         printer->info_2->sharename ));
7786         }
7787
7788         /* use our primary netbios name since get_a_printer() will convert
7789            it to what the client expects on a case by case basis */
7790
7791         slprintf(name, sizeof(name)-1, "\\\\%s\\%s", global_myname(),
7792              printer->info_2->sharename);
7793
7794
7795         if ((snum = print_queue_snum(printer->info_2->sharename)) == -1) {
7796                 free_a_printer(&printer,2);
7797                 return WERR_ACCESS_DENIED;
7798         }
7799
7800         /* you must be a printer admin to add a new printer */
7801         if (!print_access_check(NULL, snum, PRINTER_ACCESS_ADMINISTER)) {
7802                 free_a_printer(&printer,2);
7803                 return WERR_ACCESS_DENIED;
7804         }
7805
7806         /*
7807          * Do sanity check on the requested changes for Samba.
7808          */
7809
7810         if (!check_printer_ok(printer->info_2, snum)) {
7811                 free_a_printer(&printer,2);
7812                 return WERR_INVALID_PARAM;
7813         }
7814
7815         /*
7816          * When a printer is created, the drivername bound to the printer is used
7817          * to lookup previously saved driver initialization info, which is then
7818          * bound to the new printer, simulating what happens in the Windows arch.
7819          */
7820
7821         if (!devmode)
7822         {
7823                 set_driver_init(printer, 2);
7824         }
7825         else
7826         {
7827                 /* A valid devmode was included, convert and link it
7828                 */
7829                 DEBUGADD(10, ("spoolss_addprinterex_level_2: devmode included, converting\n"));
7830
7831                 if (!convert_devicemode_new(printer->info_2->printername,
7832                                             devmode,
7833                                             &printer->info_2->devmode))
7834                         return  WERR_NOMEM;
7835         }
7836
7837         /* write the ASCII on disk */
7838         err = mod_a_printer(printer, 2);
7839         if (!W_ERROR_IS_OK(err)) {
7840                 free_a_printer(&printer,2);
7841                 return err;
7842         }
7843
7844         if (!open_printer_hnd(p, handle, name, PRINTER_ACCESS_ADMINISTER)) {
7845                 /* Handle open failed - remove addition. */
7846                 del_a_printer(printer->info_2->sharename);
7847                 free_a_printer(&printer,2);
7848                 ZERO_STRUCTP(handle);
7849                 return WERR_ACCESS_DENIED;
7850         }
7851
7852         update_c_setprinter(False);
7853         free_a_printer(&printer,2);
7854
7855         return WERR_OK;
7856 }
7857
7858 /****************************************************************
7859  _spoolss_AddPrinterEx
7860 ****************************************************************/
7861
7862 WERROR _spoolss_AddPrinterEx(pipes_struct *p,
7863                              struct spoolss_AddPrinterEx *r)
7864 {
7865         switch (r->in.info_ctr->level) {
7866         case 1:
7867                 /* we don't handle yet */
7868                 /* but I know what to do ... */
7869                 return WERR_UNKNOWN_LEVEL;
7870         case 2:
7871                 return spoolss_addprinterex_level_2(p, r->in.server,
7872                                                     r->in.info_ctr,
7873                                                     r->in.devmode_ctr->devmode,
7874                                                     r->in.secdesc_ctr->sd,
7875                                                     r->in.userlevel_ctr,
7876                                                     r->out.handle);
7877         default:
7878                 return WERR_UNKNOWN_LEVEL;
7879         }
7880 }
7881
7882 /****************************************************************
7883  _spoolss_AddPrinterDriver
7884 ****************************************************************/
7885
7886 WERROR _spoolss_AddPrinterDriver(pipes_struct *p,
7887                                  struct spoolss_AddPrinterDriver *r)
7888 {
7889         uint32_t level = r->in.info_ctr->level;
7890         struct spoolss_AddDriverInfoCtr *info = r->in.info_ctr;
7891         WERROR err = WERR_OK;
7892         NT_PRINTER_DRIVER_INFO_LEVEL driver;
7893         fstring driver_name;
7894         uint32 version;
7895         const char *fn;
7896
7897         switch (p->hdr_req.opnum) {
7898                 case NDR_SPOOLSS_ADDPRINTERDRIVER:
7899                         fn = "_spoolss_AddPrinterDriver";
7900                         break;
7901                 case NDR_SPOOLSS_ADDPRINTERDRIVEREX:
7902                         fn = "_spoolss_AddPrinterDriverEx";
7903                         break;
7904                 default:
7905                         return WERR_INVALID_PARAM;
7906         }
7907
7908
7909         /* FIXME */
7910         if (level != 3 && level != 6) {
7911                 /* Clever hack from Martin Zielinski <mz@seh.de>
7912                  * to allow downgrade from level 8 (Vista).
7913                  */
7914                 DEBUG(0,("%s: level %d not yet implemented\n", fn, level));
7915                 return WERR_UNKNOWN_LEVEL;
7916         }
7917
7918         ZERO_STRUCT(driver);
7919
7920         if (!convert_printer_driver_info(info, &driver, level)) {
7921                 err = WERR_NOMEM;
7922                 goto done;
7923         }
7924
7925         DEBUG(5,("Cleaning driver's information\n"));
7926         err = clean_up_driver_struct(p, driver, level);
7927         if (!W_ERROR_IS_OK(err))
7928                 goto done;
7929
7930         DEBUG(5,("Moving driver to final destination\n"));
7931         if( !W_ERROR_IS_OK(err = move_driver_to_download_area(p, driver, level,
7932                                                               &err)) ) {
7933                 goto done;
7934         }
7935
7936         if (add_a_printer_driver(driver, level)!=0) {
7937                 err = WERR_ACCESS_DENIED;
7938                 goto done;
7939         }
7940
7941         switch(level) {
7942         case 3:
7943                 fstrcpy(driver_name,
7944                         driver.info_3->name ? driver.info_3->name : "");
7945                 break;
7946         case 6:
7947                 fstrcpy(driver_name,
7948                         driver.info_6->name ?  driver.info_6->name : "");
7949                 break;
7950         }
7951
7952         /*
7953          * I think this is where he DrvUpgradePrinter() hook would be
7954          * be called in a driver's interface DLL on a Windows NT 4.0/2k
7955          * server.  Right now, we just need to send ourselves a message
7956          * to update each printer bound to this driver.   --jerry
7957          */
7958
7959         if (!srv_spoolss_drv_upgrade_printer(driver_name)) {
7960                 DEBUG(0,("%s: Failed to send message about upgrading driver [%s]!\n",
7961                         fn, driver_name));
7962         }
7963
7964         /*
7965          * Based on the version (e.g. driver destination dir: 0=9x,2=Nt/2k,3=2k/Xp),
7966          * decide if the driver init data should be deleted. The rules are:
7967          *  1) never delete init data if it is a 9x driver, they don't use it anyway
7968          *  2) delete init data only if there is no 2k/Xp driver
7969          *  3) always delete init data
7970          * The generalized rule is always use init data from the highest order driver.
7971          * It is necessary to follow the driver install by an initialization step to
7972          * finish off this process.
7973         */
7974         if (level == 3)
7975                 version = driver.info_3->cversion;
7976         else if (level == 6)
7977                 version = driver.info_6->version;
7978         else
7979                 version = -1;
7980         switch (version) {
7981                 /*
7982                  * 9x printer driver - never delete init data
7983                 */
7984                 case 0:
7985                         DEBUG(10,("%s: init data not deleted for 9x driver [%s]\n",
7986                                 fn, driver_name));
7987                         break;
7988
7989                 /*
7990                  * Nt or 2k (compatiblity mode) printer driver - only delete init data if
7991                  * there is no 2k/Xp driver init data for this driver name.
7992                 */
7993                 case 2:
7994                 {
7995                         NT_PRINTER_DRIVER_INFO_LEVEL driver1;
7996
7997                         if (!W_ERROR_IS_OK(get_a_printer_driver(&driver1, 3, driver_name, "Windows NT x86", 3))) {
7998                                 /*
7999                                  * No 2k/Xp driver found, delete init data (if any) for the new Nt driver.
8000                                 */
8001                                 if (!del_driver_init(driver_name))
8002                                         DEBUG(6,("%s: del_driver_init(%s) Nt failed!\n",
8003                                                 fn, driver_name));
8004                         } else {
8005                                 /*
8006                                  * a 2k/Xp driver was found, don't delete init data because Nt driver will use it.
8007                                 */
8008                                 free_a_printer_driver(driver1,3);
8009                                 DEBUG(10,("%s: init data not deleted for Nt driver [%s]\n",
8010                                         fn, driver_name));
8011                         }
8012                 }
8013                 break;
8014
8015                 /*
8016                  * 2k or Xp printer driver - always delete init data
8017                 */
8018                 case 3:
8019                         if (!del_driver_init(driver_name))
8020                                 DEBUG(6,("%s: del_driver_init(%s) 2k/Xp failed!\n",
8021                                         fn, driver_name));
8022                         break;
8023
8024                 default:
8025                         DEBUG(0,("%s: invalid level=%d\n", fn, level));
8026                         break;
8027         }
8028
8029
8030 done:
8031         free_a_printer_driver(driver, level);
8032         return err;
8033 }
8034
8035 /****************************************************************
8036  _spoolss_AddPrinterDriverEx
8037 ****************************************************************/
8038
8039 WERROR _spoolss_AddPrinterDriverEx(pipes_struct *p,
8040                                    struct spoolss_AddPrinterDriverEx *r)
8041 {
8042         struct spoolss_AddPrinterDriver a;
8043
8044         /*
8045          * we only support the semantics of AddPrinterDriver()
8046          * i.e. only copy files that are newer than existing ones
8047          */
8048
8049         if (r->in.flags != APD_COPY_NEW_FILES) {
8050                 return WERR_ACCESS_DENIED;
8051         }
8052
8053         a.in.servername         = r->in.servername;
8054         a.in.info_ctr           = r->in.info_ctr;
8055
8056         return _spoolss_AddPrinterDriver(p, &a);
8057 }
8058
8059 /****************************************************************************
8060 ****************************************************************************/
8061
8062 struct _spoolss_paths {
8063         int type;
8064         const char *share;
8065         const char *dir;
8066 };
8067
8068 enum { SPOOLSS_DRIVER_PATH, SPOOLSS_PRTPROCS_PATH };
8069
8070 static const struct _spoolss_paths spoolss_paths[]= {
8071         { SPOOLSS_DRIVER_PATH,          "print$",       "DRIVERS" },
8072         { SPOOLSS_PRTPROCS_PATH,        "prnproc$",     "PRTPROCS" }
8073 };
8074
8075 static WERROR compose_spoolss_server_path(TALLOC_CTX *mem_ctx,
8076                                           const char *servername,
8077                                           const char *environment,
8078                                           int component,
8079                                           char **path)
8080 {
8081         const char *pservername = NULL;
8082         const char *long_archi = SPOOLSS_ARCHITECTURE_NT_X86;
8083         const char *short_archi;
8084
8085         *path = NULL;
8086
8087         /* environment may be empty */
8088         if (environment && strlen(environment)) {
8089                 long_archi = environment;
8090         }
8091
8092         /* servername may be empty */
8093         if (servername && strlen(servername)) {
8094                 pservername = canon_servername(servername);
8095
8096                 if (!is_myname_or_ipaddr(pservername)) {
8097                         return WERR_INVALID_PARAM;
8098                 }
8099         }
8100
8101         if (!(short_archi = get_short_archi(long_archi))) {
8102                 return WERR_INVALID_ENVIRONMENT;
8103         }
8104
8105         switch (component) {
8106         case SPOOLSS_PRTPROCS_PATH:
8107         case SPOOLSS_DRIVER_PATH:
8108                 if (pservername) {
8109                         *path = talloc_asprintf(mem_ctx,
8110                                         "\\\\%s\\%s\\%s",
8111                                         pservername,
8112                                         spoolss_paths[component].share,
8113                                         short_archi);
8114                 } else {
8115                         *path = talloc_asprintf(mem_ctx, "%s\\%s\\%s",
8116                                         SPOOLSS_DEFAULT_SERVER_PATH,
8117                                         spoolss_paths[component].dir,
8118                                         short_archi);
8119                 }
8120                 break;
8121         default:
8122                 return WERR_INVALID_PARAM;
8123         }
8124
8125         if (!*path) {
8126                 return WERR_NOMEM;
8127         }
8128
8129         return WERR_OK;
8130 }
8131
8132 /****************************************************************************
8133 ****************************************************************************/
8134
8135 static WERROR getprinterdriverdir_level_1(TALLOC_CTX *mem_ctx,
8136                                           const char *servername,
8137                                           const char *environment,
8138                                           struct spoolss_DriverDirectoryInfo1 *r,
8139                                           uint32_t offered,
8140                                           uint32_t *needed)
8141 {
8142         WERROR werr;
8143         char *path = NULL;
8144
8145         werr = compose_spoolss_server_path(mem_ctx,
8146                                            servername,
8147                                            environment,
8148                                            SPOOLSS_DRIVER_PATH,
8149                                            &path);
8150         if (!W_ERROR_IS_OK(werr)) {
8151                 return werr;
8152         }
8153
8154         DEBUG(4,("printer driver directory: [%s]\n", path));
8155
8156         r->directory_name = path;
8157
8158         *needed += ndr_size_spoolss_DriverDirectoryInfo1(r, NULL, 0);
8159
8160         if (*needed > offered) {
8161                 talloc_free(path);
8162                 return WERR_INSUFFICIENT_BUFFER;
8163         }
8164
8165         return WERR_OK;
8166 }
8167
8168 /****************************************************************
8169  _spoolss_GetPrinterDriverDirectory
8170 ****************************************************************/
8171
8172 WERROR _spoolss_GetPrinterDriverDirectory(pipes_struct *p,
8173                                           struct spoolss_GetPrinterDriverDirectory *r)
8174 {
8175         WERROR werror;
8176
8177         /* that's an [in out] buffer */
8178
8179         if (!r->in.buffer && (r->in.offered != 0)) {
8180                 return WERR_INVALID_PARAM;
8181         }
8182
8183         DEBUG(5,("_spoolss_GetPrinterDriverDirectory: level %d\n",
8184                 r->in.level));
8185
8186         *r->out.needed = 0;
8187
8188         /* r->in.level is ignored */
8189
8190         werror = getprinterdriverdir_level_1(p->mem_ctx,
8191                                              r->in.server,
8192                                              r->in.environment,
8193                                              &r->out.info->info1,
8194                                              r->in.offered,
8195                                              r->out.needed);
8196         if (!W_ERROR_IS_OK(werror)) {
8197                 TALLOC_FREE(r->out.info);
8198         }
8199
8200         return werror;
8201 }
8202
8203 /****************************************************************************
8204 ****************************************************************************/
8205
8206 WERROR _spoolss_enumprinterdata(pipes_struct *p, SPOOL_Q_ENUMPRINTERDATA *q_u, SPOOL_R_ENUMPRINTERDATA *r_u)
8207 {
8208         POLICY_HND *handle = &q_u->handle;
8209         uint32 idx               = q_u->index;
8210         uint32 in_value_len      = q_u->valuesize;
8211         uint32 in_data_len       = q_u->datasize;
8212         uint32 *out_max_value_len = &r_u->valuesize;
8213         uint16 **out_value       = &r_u->value;
8214         uint32 *out_value_len    = &r_u->realvaluesize;
8215         uint32 *out_type         = &r_u->type;
8216         uint32 *out_max_data_len = &r_u->datasize;
8217         uint8  **data_out        = &r_u->data;
8218         uint32 *out_data_len     = &r_u->realdatasize;
8219
8220         NT_PRINTER_INFO_LEVEL *printer = NULL;
8221
8222         uint32          biggest_valuesize;
8223         uint32          biggest_datasize;
8224         uint32          data_len;
8225         Printer_entry   *Printer = find_printer_index_by_hnd(p, handle);
8226         int             snum;
8227         WERROR          result;
8228         REGISTRY_VALUE  *val = NULL;
8229         NT_PRINTER_DATA *p_data;
8230         int             i, key_index, num_values;
8231         int             name_length;
8232
8233         *out_type = 0;
8234
8235         *out_max_data_len = 0;
8236         *data_out         = NULL;
8237         *out_data_len     = 0;
8238
8239         DEBUG(5,("spoolss_enumprinterdata\n"));
8240
8241         if (!Printer) {
8242                 DEBUG(2,("_spoolss_enumprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8243                 return WERR_BADFID;
8244         }
8245
8246         if (!get_printer_snum(p,handle, &snum, NULL))
8247                 return WERR_BADFID;
8248
8249         result = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8250         if (!W_ERROR_IS_OK(result))
8251                 return result;
8252
8253         p_data = printer->info_2->data;
8254         key_index = lookup_printerkey( p_data, SPOOL_PRINTERDATA_KEY );
8255
8256         result = WERR_OK;
8257
8258         /*
8259          * The NT machine wants to know the biggest size of value and data
8260          *
8261          * cf: MSDN EnumPrinterData remark section
8262          */
8263
8264         if ( !in_value_len && !in_data_len && (key_index != -1) )
8265         {
8266                 DEBUGADD(6,("Activating NT mega-hack to find sizes\n"));
8267
8268                 biggest_valuesize = 0;
8269                 biggest_datasize  = 0;
8270
8271                 num_values = regval_ctr_numvals( p_data->keys[key_index].values );
8272
8273                 for ( i=0; i<num_values; i++ )
8274                 {
8275                         val = regval_ctr_specific_value( p_data->keys[key_index].values, i );
8276
8277                         name_length = strlen(val->valuename);
8278                         if ( strlen(val->valuename) > biggest_valuesize )
8279                                 biggest_valuesize = name_length;
8280
8281                         if ( val->size > biggest_datasize )
8282                                 biggest_datasize = val->size;
8283
8284                         DEBUG(6,("current values: [%d], [%d]\n", biggest_valuesize,
8285                                 biggest_datasize));
8286                 }
8287
8288                 /* the value is an UNICODE string but real_value_size is the length
8289                    in bytes including the trailing 0 */
8290
8291                 *out_value_len = 2 * (1+biggest_valuesize);
8292                 *out_data_len  = biggest_datasize;
8293
8294                 DEBUG(6,("final values: [%d], [%d]\n", *out_value_len, *out_data_len));
8295
8296                 goto done;
8297         }
8298
8299         /*
8300          * the value len is wrong in NT sp3
8301          * that's the number of bytes not the number of unicode chars
8302          */
8303
8304         if ( key_index != -1 )
8305                 val = regval_ctr_specific_value( p_data->keys[key_index].values, idx );
8306
8307         if ( !val )
8308         {
8309
8310                 /* out_value should default to "" or else NT4 has
8311                    problems unmarshalling the response */
8312
8313                 *out_max_value_len=(in_value_len/sizeof(uint16));
8314
8315                 if (in_value_len) {
8316                         if((*out_value=(uint16 *)TALLOC_ZERO(p->mem_ctx, in_value_len*sizeof(uint8))) == NULL)
8317                         {
8318                                 result = WERR_NOMEM;
8319                                 goto done;
8320                         }
8321                         *out_value_len = (uint32)rpcstr_push((char *)*out_value, "", in_value_len, 0);
8322                 } else {
8323                         *out_value=NULL;
8324                         *out_value_len = 0;
8325                 }
8326
8327                 /* the data is counted in bytes */
8328
8329                 *out_max_data_len = in_data_len;
8330                 *out_data_len     = in_data_len;
8331
8332                 /* only allocate when given a non-zero data_len */
8333
8334                 if ( in_data_len && ((*data_out=(uint8 *)TALLOC_ZERO(p->mem_ctx, in_data_len*sizeof(uint8))) == NULL) )
8335                 {
8336                         result = WERR_NOMEM;
8337                         goto done;
8338                 }
8339
8340                 result = WERR_NO_MORE_ITEMS;
8341         }
8342         else
8343         {
8344                 /*
8345                  * the value is:
8346                  * - counted in bytes in the request
8347                  * - counted in UNICODE chars in the max reply
8348                  * - counted in bytes in the real size
8349                  *
8350                  * take a pause *before* coding not *during* coding
8351                  */
8352
8353                 /* name */
8354                 *out_max_value_len=(in_value_len/sizeof(uint16));
8355                 if (in_value_len) {
8356                         if ( (*out_value = (uint16 *)TALLOC_ZERO(p->mem_ctx, in_value_len*sizeof(uint8))) == NULL )
8357                         {
8358                                 result = WERR_NOMEM;
8359                                 goto done;
8360                         }
8361
8362                         *out_value_len = (uint32)rpcstr_push((char *)*out_value, regval_name(val), (size_t)in_value_len, 0);
8363                 } else {
8364                         *out_value = NULL;
8365                         *out_value_len = 0;
8366                 }
8367
8368                 /* type */
8369
8370                 *out_type = regval_type( val );
8371
8372                 /* data - counted in bytes */
8373
8374                 *out_max_data_len = in_data_len;
8375                 if ( in_data_len && (*data_out = (uint8 *)TALLOC_ZERO(p->mem_ctx, in_data_len*sizeof(uint8))) == NULL)
8376                 {
8377                         result = WERR_NOMEM;
8378                         goto done;
8379                 }
8380                 data_len = regval_size(val);
8381                 if ( *data_out && data_len )
8382                         memcpy( *data_out, regval_data_p(val), data_len );
8383                 *out_data_len = data_len;
8384         }
8385
8386 done:
8387         free_a_printer(&printer, 2);
8388         return result;
8389 }
8390
8391 /****************************************************************************
8392 ****************************************************************************/
8393
8394 WERROR _spoolss_setprinterdata( pipes_struct *p, SPOOL_Q_SETPRINTERDATA *q_u, SPOOL_R_SETPRINTERDATA *r_u)
8395 {
8396         POLICY_HND              *handle = &q_u->handle;
8397         UNISTR2                 *value = &q_u->value;
8398         uint32                  type = q_u->type;
8399         uint8                   *data = q_u->data;
8400         uint32                  real_len = q_u->real_len;
8401
8402         NT_PRINTER_INFO_LEVEL   *printer = NULL;
8403         int                     snum=0;
8404         WERROR                  status = WERR_OK;
8405         Printer_entry           *Printer=find_printer_index_by_hnd(p, handle);
8406         fstring                 valuename;
8407
8408         DEBUG(5,("spoolss_setprinterdata\n"));
8409
8410         if (!Printer) {
8411                 DEBUG(2,("_spoolss_setprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8412                 return WERR_BADFID;
8413         }
8414
8415         if ( Printer->printer_type == SPLHND_SERVER ) {
8416                 DEBUG(10,("_spoolss_setprinterdata: Not implemented for server handles yet\n"));
8417                 return WERR_INVALID_PARAM;
8418         }
8419
8420         if (!get_printer_snum(p,handle, &snum, NULL))
8421                 return WERR_BADFID;
8422
8423         /*
8424          * Access check : NT returns "access denied" if you make a
8425          * SetPrinterData call without the necessary privildge.
8426          * we were originally returning OK if nothing changed
8427          * which made Win2k issue **a lot** of SetPrinterData
8428          * when connecting to a printer  --jerry
8429          */
8430
8431         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER)
8432         {
8433                 DEBUG(3, ("_spoolss_setprinterdata: change denied by handle access permissions\n"));
8434                 status = WERR_ACCESS_DENIED;
8435                 goto done;
8436         }
8437
8438         status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8439         if (!W_ERROR_IS_OK(status))
8440                 return status;
8441
8442         unistr2_to_ascii(valuename, value, sizeof(valuename));
8443
8444         /*
8445          * When client side code sets a magic printer data key, detect it and save
8446          * the current printer data and the magic key's data (its the DEVMODE) for
8447          * future printer/driver initializations.
8448          */
8449         if ( (type == REG_BINARY) && strequal( valuename, PHANTOM_DEVMODE_KEY))
8450         {
8451                 /* Set devmode and printer initialization info */
8452                 status = save_driver_init( printer, 2, data, real_len );
8453
8454                 srv_spoolss_reset_printerdata( printer->info_2->drivername );
8455         }
8456         else
8457         {
8458         status = set_printer_dataex( printer, SPOOL_PRINTERDATA_KEY, valuename,
8459                                         type, data, real_len );
8460                 if ( W_ERROR_IS_OK(status) )
8461                         status = mod_a_printer(printer, 2);
8462         }
8463
8464 done:
8465         free_a_printer(&printer, 2);
8466
8467         return status;
8468 }
8469
8470 /****************************************************************
8471  _spoolss_ResetPrinter
8472 ****************************************************************/
8473
8474 WERROR _spoolss_ResetPrinter(pipes_struct *p,
8475                              struct spoolss_ResetPrinter *r)
8476 {
8477         POLICY_HND      *handle = r->in.handle;
8478         Printer_entry   *Printer=find_printer_index_by_hnd(p, handle);
8479         int             snum;
8480
8481         DEBUG(5,("_spoolss_ResetPrinter\n"));
8482
8483         /*
8484          * All we do is to check to see if the handle and queue is valid.
8485          * This call really doesn't mean anything to us because we only
8486          * support RAW printing.   --jerry
8487          */
8488
8489         if (!Printer) {
8490                 DEBUG(2,("_spoolss_ResetPrinter: 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
8499         /* blindly return success */
8500         return WERR_OK;
8501 }
8502
8503 /****************************************************************
8504  _spoolss_DeletePrinterData
8505 ****************************************************************/
8506
8507 WERROR _spoolss_DeletePrinterData(pipes_struct *p,
8508                                   struct spoolss_DeletePrinterData *r)
8509 {
8510         POLICY_HND      *handle = r->in.handle;
8511         NT_PRINTER_INFO_LEVEL   *printer = NULL;
8512         int             snum=0;
8513         WERROR          status = WERR_OK;
8514         Printer_entry   *Printer=find_printer_index_by_hnd(p, handle);
8515
8516         DEBUG(5,("_spoolss_DeletePrinterData\n"));
8517
8518         if (!Printer) {
8519                 DEBUG(2,("_spoolss_DeletePrinterData: Invalid handle (%s:%u:%u).\n",
8520                         OUR_HANDLE(handle)));
8521                 return WERR_BADFID;
8522         }
8523
8524         if (!get_printer_snum(p, handle, &snum, NULL))
8525                 return WERR_BADFID;
8526
8527         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
8528                 DEBUG(3, ("_spoolss_DeletePrinterData: "
8529                         "printer properties change denied by handle\n"));
8530                 return WERR_ACCESS_DENIED;
8531         }
8532
8533         status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8534         if (!W_ERROR_IS_OK(status))
8535                 return status;
8536
8537         if (!r->in.value_name) {
8538                 free_a_printer(&printer, 2);
8539                 return WERR_NOMEM;
8540         }
8541
8542         status = delete_printer_dataex( printer, SPOOL_PRINTERDATA_KEY,
8543                                         r->in.value_name );
8544
8545         if ( W_ERROR_IS_OK(status) )
8546                 mod_a_printer( printer, 2 );
8547
8548         free_a_printer(&printer, 2);
8549
8550         return status;
8551 }
8552
8553 /****************************************************************
8554  _spoolss_AddForm
8555 ****************************************************************/
8556
8557 WERROR _spoolss_AddForm(pipes_struct *p,
8558                         struct spoolss_AddForm *r)
8559 {
8560         POLICY_HND *handle = r->in.handle;
8561         struct spoolss_AddFormInfo1 *form = r->in.info.info1;
8562         nt_forms_struct tmpForm;
8563         int snum;
8564         WERROR status = WERR_OK;
8565         NT_PRINTER_INFO_LEVEL *printer = NULL;
8566
8567         int count=0;
8568         nt_forms_struct *list=NULL;
8569         Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8570
8571         DEBUG(5,("_spoolss_AddForm\n"));
8572
8573         if (!Printer) {
8574                 DEBUG(2,("_spoolss_AddForm: Invalid handle (%s:%u:%u).\n",
8575                         OUR_HANDLE(handle)));
8576                 return WERR_BADFID;
8577         }
8578
8579
8580         /* forms can be added on printer of on the print server handle */
8581
8582         if ( Printer->printer_type == SPLHND_PRINTER )
8583         {
8584                 if (!get_printer_snum(p,handle, &snum, NULL))
8585                         return WERR_BADFID;
8586
8587                 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8588                 if (!W_ERROR_IS_OK(status))
8589                         goto done;
8590         }
8591
8592         if ( !(Printer->access_granted & (PRINTER_ACCESS_ADMINISTER|SERVER_ACCESS_ADMINISTER)) ) {
8593                 DEBUG(2,("_spoolss_addform: denied by handle permissions.\n"));
8594                 status = WERR_ACCESS_DENIED;
8595                 goto done;
8596         }
8597
8598         /* can't add if builtin */
8599
8600         if (get_a_builtin_ntform_by_string(form->form_name, &tmpForm)) {
8601                 status = WERR_FILE_EXISTS;
8602                 goto done;
8603         }
8604
8605         count = get_ntforms(&list);
8606
8607         if(!add_a_form(&list, form, &count)) {
8608                 status =  WERR_NOMEM;
8609                 goto done;
8610         }
8611
8612         write_ntforms(&list, count);
8613
8614         /*
8615          * ChangeID must always be set if this is a printer
8616          */
8617
8618         if ( Printer->printer_type == SPLHND_PRINTER )
8619                 status = mod_a_printer(printer, 2);
8620
8621 done:
8622         if ( printer )
8623                 free_a_printer(&printer, 2);
8624         SAFE_FREE(list);
8625
8626         return status;
8627 }
8628
8629 /****************************************************************
8630  _spoolss_DeleteForm
8631 ****************************************************************/
8632
8633 WERROR _spoolss_DeleteForm(pipes_struct *p,
8634                            struct spoolss_DeleteForm *r)
8635 {
8636         POLICY_HND *handle = r->in.handle;
8637         const char *form_name = r->in.form_name;
8638         nt_forms_struct tmpForm;
8639         int count=0;
8640         nt_forms_struct *list=NULL;
8641         Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8642         int snum;
8643         WERROR status = WERR_OK;
8644         NT_PRINTER_INFO_LEVEL *printer = NULL;
8645
8646         DEBUG(5,("_spoolss_DeleteForm\n"));
8647
8648         if (!Printer) {
8649                 DEBUG(2,("_spoolss_DeleteForm: Invalid handle (%s:%u:%u).\n",
8650                         OUR_HANDLE(handle)));
8651                 return WERR_BADFID;
8652         }
8653
8654         /* forms can be deleted on printer of on the print server handle */
8655
8656         if ( Printer->printer_type == SPLHND_PRINTER )
8657         {
8658                 if (!get_printer_snum(p,handle, &snum, NULL))
8659                         return WERR_BADFID;
8660
8661                 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8662                 if (!W_ERROR_IS_OK(status))
8663                         goto done;
8664         }
8665
8666         if ( !(Printer->access_granted & (PRINTER_ACCESS_ADMINISTER|SERVER_ACCESS_ADMINISTER)) ) {
8667                 DEBUG(2,("_spoolss_DeleteForm: denied by handle permissions.\n"));
8668                 status = WERR_ACCESS_DENIED;
8669                 goto done;
8670         }
8671
8672         /* can't delete if builtin */
8673
8674         if (get_a_builtin_ntform_by_string(form_name,&tmpForm)) {
8675                 status = WERR_INVALID_PARAM;
8676                 goto done;
8677         }
8678
8679         count = get_ntforms(&list);
8680
8681         if ( !delete_a_form(&list, form_name, &count, &status ))
8682                 goto done;
8683
8684         /*
8685          * ChangeID must always be set if this is a printer
8686          */
8687
8688         if ( Printer->printer_type == SPLHND_PRINTER )
8689                 status = mod_a_printer(printer, 2);
8690
8691 done:
8692         if ( printer )
8693                 free_a_printer(&printer, 2);
8694         SAFE_FREE(list);
8695
8696         return status;
8697 }
8698
8699 /****************************************************************
8700  _spoolss_SetForm
8701 ****************************************************************/
8702
8703 WERROR _spoolss_SetForm(pipes_struct *p,
8704                         struct spoolss_SetForm *r)
8705 {
8706         POLICY_HND *handle = r->in.handle;
8707         struct spoolss_AddFormInfo1 *form = r->in.info.info1;
8708         nt_forms_struct tmpForm;
8709         int snum;
8710         WERROR status = WERR_OK;
8711         NT_PRINTER_INFO_LEVEL *printer = NULL;
8712
8713         int count=0;
8714         nt_forms_struct *list=NULL;
8715         Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8716
8717         DEBUG(5,("_spoolss_SetForm\n"));
8718
8719         if (!Printer) {
8720                 DEBUG(2,("_spoolss_SetForm: Invalid handle (%s:%u:%u).\n",
8721                         OUR_HANDLE(handle)));
8722                 return WERR_BADFID;
8723         }
8724
8725         /* forms can be modified on printer of on the print server handle */
8726
8727         if ( Printer->printer_type == SPLHND_PRINTER )
8728         {
8729                 if (!get_printer_snum(p,handle, &snum, NULL))
8730                         return WERR_BADFID;
8731
8732                 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8733                 if (!W_ERROR_IS_OK(status))
8734                         goto done;
8735         }
8736
8737         if ( !(Printer->access_granted & (PRINTER_ACCESS_ADMINISTER|SERVER_ACCESS_ADMINISTER)) ) {
8738                 DEBUG(2,("_spoolss_SetForm: denied by handle permissions\n"));
8739                 status = WERR_ACCESS_DENIED;
8740                 goto done;
8741         }
8742
8743         /* can't set if builtin */
8744         if (get_a_builtin_ntform_by_string(form->form_name, &tmpForm)) {
8745                 status = WERR_INVALID_PARAM;
8746                 goto done;
8747         }
8748
8749         count = get_ntforms(&list);
8750         update_a_form(&list, form, count);
8751         write_ntforms(&list, count);
8752
8753         /*
8754          * ChangeID must always be set if this is a printer
8755          */
8756
8757         if ( Printer->printer_type == SPLHND_PRINTER )
8758                 status = mod_a_printer(printer, 2);
8759
8760
8761 done:
8762         if ( printer )
8763                 free_a_printer(&printer, 2);
8764         SAFE_FREE(list);
8765
8766         return status;
8767 }
8768
8769 /****************************************************************************
8770  enumprintprocessors level 1.
8771 ****************************************************************************/
8772
8773 static WERROR enumprintprocessors_level_1(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
8774 {
8775         PRINTPROCESSOR_1 *info_1=NULL;
8776         WERROR result = WERR_OK;
8777
8778         if((info_1 = SMB_MALLOC_P(PRINTPROCESSOR_1)) == NULL)
8779                 return WERR_NOMEM;
8780
8781         (*returned) = 0x1;
8782
8783         init_unistr(&info_1->name, "winprint");
8784
8785         *needed += spoolss_size_printprocessor_info_1(info_1);
8786
8787         if (*needed > offered) {
8788                 result = WERR_INSUFFICIENT_BUFFER;
8789                 goto out;
8790         }
8791
8792         if (!rpcbuf_alloc_size(buffer, *needed)) {
8793                 result = WERR_NOMEM;
8794                 goto out;
8795         }
8796
8797         smb_io_printprocessor_info_1("", buffer, info_1, 0);
8798
8799 out:
8800         SAFE_FREE(info_1);
8801
8802         if ( !W_ERROR_IS_OK(result) )
8803                 *returned = 0;
8804
8805         return result;
8806 }
8807
8808 /****************************************************************************
8809 ****************************************************************************/
8810
8811 WERROR _spoolss_enumprintprocessors(pipes_struct *p, SPOOL_Q_ENUMPRINTPROCESSORS *q_u, SPOOL_R_ENUMPRINTPROCESSORS *r_u)
8812 {
8813         uint32 level = q_u->level;
8814         RPC_BUFFER *buffer = NULL;
8815         uint32 offered = q_u->offered;
8816         uint32 *needed = &r_u->needed;
8817         uint32 *returned = &r_u->returned;
8818
8819         /* that's an [in out] buffer */
8820
8821         if (!q_u->buffer && (offered!=0)) {
8822                 return WERR_INVALID_PARAM;
8823         }
8824
8825         if (offered > MAX_RPC_DATA_SIZE) {
8826                 return WERR_INVALID_PARAM;
8827         }
8828
8829         rpcbuf_move(q_u->buffer, &r_u->buffer);
8830         buffer = r_u->buffer;
8831
8832         DEBUG(5,("spoolss_enumprintprocessors\n"));
8833
8834         /*
8835          * Enumerate the print processors ...
8836          *
8837          * Just reply with "winprint", to keep NT happy
8838          * and I can use my nice printer checker.
8839          */
8840
8841         *returned=0;
8842         *needed=0;
8843
8844         switch (level) {
8845         case 1:
8846                 return enumprintprocessors_level_1(buffer, offered, needed, returned);
8847         default:
8848                 return WERR_UNKNOWN_LEVEL;
8849         }
8850 }
8851
8852 /****************************************************************************
8853  enumprintprocdatatypes level 1.
8854 ****************************************************************************/
8855
8856 static WERROR enumprintprocdatatypes_level_1(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
8857 {
8858         PRINTPROCDATATYPE_1 *info_1=NULL;
8859         WERROR result = WERR_OK;
8860
8861         if((info_1 = SMB_MALLOC_P(PRINTPROCDATATYPE_1)) == NULL)
8862                 return WERR_NOMEM;
8863
8864         (*returned) = 0x1;
8865
8866         init_unistr(&info_1->name, "RAW");
8867
8868         *needed += spoolss_size_printprocdatatype_info_1(info_1);
8869
8870         if (*needed > offered) {
8871                 result = WERR_INSUFFICIENT_BUFFER;
8872                 goto out;
8873         }
8874
8875         if (!rpcbuf_alloc_size(buffer, *needed)) {
8876                 result = WERR_NOMEM;
8877                 goto out;
8878         }
8879
8880         smb_io_printprocdatatype_info_1("", buffer, info_1, 0);
8881
8882 out:
8883         SAFE_FREE(info_1);
8884
8885         if ( !W_ERROR_IS_OK(result) )
8886                 *returned = 0;
8887
8888         return result;
8889 }
8890
8891 /****************************************************************************
8892 ****************************************************************************/
8893
8894 WERROR _spoolss_enumprintprocdatatypes(pipes_struct *p, SPOOL_Q_ENUMPRINTPROCDATATYPES *q_u, SPOOL_R_ENUMPRINTPROCDATATYPES *r_u)
8895 {
8896         uint32 level = q_u->level;
8897         RPC_BUFFER *buffer = NULL;
8898         uint32 offered = q_u->offered;
8899         uint32 *needed = &r_u->needed;
8900         uint32 *returned = &r_u->returned;
8901
8902         /* that's an [in out] buffer */
8903
8904         if (!q_u->buffer && (offered!=0)) {
8905                 return WERR_INVALID_PARAM;
8906         }
8907
8908         if (offered > MAX_RPC_DATA_SIZE) {
8909                 return WERR_INVALID_PARAM;
8910         }
8911
8912         rpcbuf_move(q_u->buffer, &r_u->buffer);
8913         buffer = r_u->buffer;
8914
8915         DEBUG(5,("_spoolss_enumprintprocdatatypes\n"));
8916
8917         *returned=0;
8918         *needed=0;
8919
8920         switch (level) {
8921         case 1:
8922                 return enumprintprocdatatypes_level_1(buffer, offered, needed, returned);
8923         default:
8924                 return WERR_UNKNOWN_LEVEL;
8925         }
8926 }
8927
8928 /****************************************************************************
8929  enumprintmonitors level 1.
8930 ****************************************************************************/
8931
8932 static WERROR enumprintmonitors_level_1(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
8933 {
8934         PRINTMONITOR_1 *info_1;
8935         WERROR result = WERR_OK;
8936         int i;
8937
8938         if((info_1 = SMB_MALLOC_ARRAY(PRINTMONITOR_1, 2)) == NULL)
8939                 return WERR_NOMEM;
8940
8941         *returned = 2;
8942
8943         init_unistr(&(info_1[0].name), SPL_LOCAL_PORT );
8944         init_unistr(&(info_1[1].name), SPL_TCPIP_PORT );
8945
8946         for ( i=0; i<*returned; i++ ) {
8947                 *needed += spoolss_size_printmonitor_info_1(&info_1[i]);
8948         }
8949
8950         if (*needed > offered) {
8951                 result = WERR_INSUFFICIENT_BUFFER;
8952                 goto out;
8953         }
8954
8955         if (!rpcbuf_alloc_size(buffer, *needed)) {
8956                 result = WERR_NOMEM;
8957                 goto out;
8958         }
8959
8960         for ( i=0; i<*returned; i++ ) {
8961                 smb_io_printmonitor_info_1("", buffer, &info_1[i], 0);
8962         }
8963
8964 out:
8965         SAFE_FREE(info_1);
8966
8967         if ( !W_ERROR_IS_OK(result) )
8968                 *returned = 0;
8969
8970         return result;
8971 }
8972
8973 /****************************************************************************
8974  enumprintmonitors level 2.
8975 ****************************************************************************/
8976
8977 static WERROR enumprintmonitors_level_2(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
8978 {
8979         PRINTMONITOR_2 *info_2;
8980         WERROR result = WERR_OK;
8981         int i;
8982
8983         if((info_2 = SMB_MALLOC_ARRAY(PRINTMONITOR_2, 2)) == NULL)
8984                 return WERR_NOMEM;
8985
8986         *returned = 2;
8987
8988         init_unistr( &(info_2[0].name), SPL_LOCAL_PORT );
8989         init_unistr( &(info_2[0].environment), "Windows NT X86" );
8990         init_unistr( &(info_2[0].dll_name), "localmon.dll" );
8991
8992         init_unistr( &(info_2[1].name), SPL_TCPIP_PORT );
8993         init_unistr( &(info_2[1].environment), "Windows NT X86" );
8994         init_unistr( &(info_2[1].dll_name), "tcpmon.dll" );
8995
8996         for ( i=0; i<*returned; i++ ) {
8997                 *needed += spoolss_size_printmonitor_info_2(&info_2[i]);
8998         }
8999
9000         if (*needed > offered) {
9001                 result = WERR_INSUFFICIENT_BUFFER;
9002                 goto out;
9003         }
9004
9005         if (!rpcbuf_alloc_size(buffer, *needed)) {
9006                 result = WERR_NOMEM;
9007                 goto out;
9008         }
9009
9010         for ( i=0; i<*returned; i++ ) {
9011                 smb_io_printmonitor_info_2("", buffer, &info_2[i], 0);
9012         }
9013
9014 out:
9015         SAFE_FREE(info_2);
9016
9017         if ( !W_ERROR_IS_OK(result) )
9018                 *returned = 0;
9019
9020         return result;
9021 }
9022
9023 /****************************************************************************
9024 ****************************************************************************/
9025
9026 WERROR _spoolss_enumprintmonitors(pipes_struct *p, SPOOL_Q_ENUMPRINTMONITORS *q_u, SPOOL_R_ENUMPRINTMONITORS *r_u)
9027 {
9028         uint32 level = q_u->level;
9029         RPC_BUFFER *buffer = NULL;
9030         uint32 offered = q_u->offered;
9031         uint32 *needed = &r_u->needed;
9032         uint32 *returned = &r_u->returned;
9033
9034         /* that's an [in out] buffer */
9035
9036         if (!q_u->buffer && (offered!=0)) {
9037                 return WERR_INVALID_PARAM;
9038         }
9039
9040         if (offered > MAX_RPC_DATA_SIZE) {
9041                 return WERR_INVALID_PARAM;
9042         }
9043
9044         rpcbuf_move(q_u->buffer, &r_u->buffer);
9045         buffer = r_u->buffer;
9046
9047         DEBUG(5,("spoolss_enumprintmonitors\n"));
9048
9049         /*
9050          * Enumerate the print monitors ...
9051          *
9052          * Just reply with "Local Port", to keep NT happy
9053          * and I can use my nice printer checker.
9054          */
9055
9056         *returned=0;
9057         *needed=0;
9058
9059         switch (level) {
9060         case 1:
9061                 return enumprintmonitors_level_1(buffer, offered, needed, returned);
9062         case 2:
9063                 return enumprintmonitors_level_2(buffer, offered, needed, returned);
9064         default:
9065                 return WERR_UNKNOWN_LEVEL;
9066         }
9067 }
9068
9069 /****************************************************************************
9070 ****************************************************************************/
9071
9072 static WERROR getjob_level_1(print_queue_struct **queue, int count, int snum,
9073                              NT_PRINTER_INFO_LEVEL *ntprinter,
9074                              uint32 jobid, RPC_BUFFER *buffer, uint32 offered,
9075                              uint32 *needed)
9076 {
9077         int i=0;
9078         bool found=False;
9079         JOB_INFO_1 *info_1=NULL;
9080         WERROR result = WERR_OK;
9081
9082         info_1=SMB_MALLOC_P(JOB_INFO_1);
9083
9084         if (info_1 == NULL) {
9085                 return WERR_NOMEM;
9086         }
9087
9088         for (i=0; i<count && found==False; i++) {
9089                 if ((*queue)[i].job==(int)jobid)
9090                         found=True;
9091         }
9092
9093         if (found==False) {
9094                 SAFE_FREE(info_1);
9095                 /* NT treats not found as bad param... yet another bad choice */
9096                 return WERR_INVALID_PARAM;
9097         }
9098
9099         fill_job_info_1( info_1, &((*queue)[i-1]), i, snum, ntprinter );
9100
9101         *needed += spoolss_size_job_info_1(info_1);
9102
9103         if (*needed > offered) {
9104                 result = WERR_INSUFFICIENT_BUFFER;
9105                 goto out;
9106         }
9107
9108         if (!rpcbuf_alloc_size(buffer, *needed)) {
9109                 result = WERR_NOMEM;
9110                 goto out;
9111         }
9112
9113         smb_io_job_info_1("", buffer, info_1, 0);
9114
9115 out:
9116         SAFE_FREE(info_1);
9117
9118         return result;
9119 }
9120
9121 /****************************************************************************
9122 ****************************************************************************/
9123
9124 static WERROR getjob_level_2(print_queue_struct **queue, int count, int snum,
9125                              NT_PRINTER_INFO_LEVEL *ntprinter,
9126                              uint32 jobid, RPC_BUFFER *buffer, uint32 offered,
9127                              uint32 *needed)
9128 {
9129         int             i = 0;
9130         bool            found = False;
9131         JOB_INFO_2      *info_2;
9132         WERROR          result;
9133         DEVICEMODE      *devmode = NULL;
9134         NT_DEVICEMODE   *nt_devmode = NULL;
9135
9136         if ( !(info_2=SMB_MALLOC_P(JOB_INFO_2)) )
9137                 return WERR_NOMEM;
9138
9139         ZERO_STRUCTP(info_2);
9140
9141         for ( i=0; i<count && found==False; i++ )
9142         {
9143                 if ((*queue)[i].job == (int)jobid)
9144                         found = True;
9145         }
9146
9147         if ( !found ) {
9148                 /* NT treats not found as bad param... yet another bad
9149                    choice */
9150                 result = WERR_INVALID_PARAM;
9151                 goto done;
9152         }
9153
9154         /*
9155          * if the print job does not have a DEVMODE associated with it,
9156          * just use the one for the printer. A NULL devicemode is not
9157          *  a failure condition
9158          */
9159
9160         if ( !(nt_devmode=print_job_devmode( lp_const_servicename(snum), jobid )) )
9161                 devmode = construct_dev_mode(lp_const_servicename(snum));
9162         else {
9163                 if ((devmode = SMB_MALLOC_P(DEVICEMODE)) != NULL) {
9164                         ZERO_STRUCTP( devmode );
9165                         convert_nt_devicemode( devmode, nt_devmode );
9166                 }
9167         }
9168
9169         fill_job_info_2(info_2, &((*queue)[i-1]), i, snum, ntprinter, devmode);
9170
9171         *needed += spoolss_size_job_info_2(info_2);
9172
9173         if (*needed > offered) {
9174                 result = WERR_INSUFFICIENT_BUFFER;
9175                 goto done;
9176         }
9177
9178         if (!rpcbuf_alloc_size(buffer, *needed)) {
9179                 result = WERR_NOMEM;
9180                 goto done;
9181         }
9182
9183         smb_io_job_info_2("", buffer, info_2, 0);
9184
9185         result = WERR_OK;
9186
9187  done:
9188         /* Cleanup allocated memory */
9189
9190         free_job_info_2(info_2);        /* Also frees devmode */
9191         SAFE_FREE(info_2);
9192
9193         return result;
9194 }
9195
9196 /****************************************************************************
9197 ****************************************************************************/
9198
9199 WERROR _spoolss_getjob( pipes_struct *p, SPOOL_Q_GETJOB *q_u, SPOOL_R_GETJOB *r_u)
9200 {
9201         POLICY_HND *handle = &q_u->handle;
9202         uint32 jobid = q_u->jobid;
9203         uint32 level = q_u->level;
9204         RPC_BUFFER *buffer = NULL;
9205         uint32 offered = q_u->offered;
9206         uint32 *needed = &r_u->needed;
9207         WERROR          wstatus = WERR_OK;
9208         NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
9209         int snum;
9210         int count;
9211         print_queue_struct      *queue = NULL;
9212         print_status_struct prt_status;
9213
9214         /* that's an [in out] buffer */
9215
9216         if (!q_u->buffer && (offered!=0)) {
9217                 return WERR_INVALID_PARAM;
9218         }
9219
9220         if (offered > MAX_RPC_DATA_SIZE) {
9221                 return WERR_INVALID_PARAM;
9222         }
9223
9224         rpcbuf_move(q_u->buffer, &r_u->buffer);
9225         buffer = r_u->buffer;
9226
9227         DEBUG(5,("spoolss_getjob\n"));
9228
9229         *needed = 0;
9230
9231         if (!get_printer_snum(p, handle, &snum, NULL))
9232                 return WERR_BADFID;
9233
9234         wstatus = get_a_printer(NULL, &ntprinter, 2, lp_servicename(snum));
9235         if ( !W_ERROR_IS_OK(wstatus) )
9236                 return wstatus;
9237
9238         count = print_queue_status(snum, &queue, &prt_status);
9239
9240         DEBUGADD(4,("count:[%d], prt_status:[%d], [%s]\n",
9241                      count, prt_status.status, prt_status.message));
9242
9243         switch ( level ) {
9244         case 1:
9245                         wstatus = getjob_level_1(&queue, count, snum, ntprinter, jobid,
9246                                 buffer, offered, needed);
9247                         break;
9248         case 2:
9249                         wstatus = getjob_level_2(&queue, count, snum, ntprinter, jobid,
9250                                 buffer, offered, needed);
9251                         break;
9252         default:
9253                         wstatus = WERR_UNKNOWN_LEVEL;
9254                         break;
9255         }
9256
9257         SAFE_FREE(queue);
9258         free_a_printer( &ntprinter, 2 );
9259
9260         return wstatus;
9261 }
9262
9263 /****************************************************************
9264  _spoolss_GetPrinterDataEx
9265
9266  From MSDN documentation of GetPrinterDataEx: pass request
9267  to GetPrinterData if key is "PrinterDriverData".
9268 ****************************************************************/
9269
9270 WERROR _spoolss_GetPrinterDataEx(pipes_struct *p,
9271                                  struct spoolss_GetPrinterDataEx *r)
9272 {
9273         POLICY_HND      *handle = r->in.handle;
9274         uint8           *data = NULL;
9275         const char      *keyname = r->in.key_name;
9276         const char      *valuename = r->in.value_name;
9277
9278         Printer_entry   *Printer = find_printer_index_by_hnd(p, handle);
9279
9280         NT_PRINTER_INFO_LEVEL   *printer = NULL;
9281         int                     snum = 0;
9282         WERROR                  status = WERR_OK;
9283
9284         DEBUG(4,("_spoolss_GetPrinterDataEx\n"));
9285
9286         DEBUG(10, ("_spoolss_GetPrinterDataEx: key => [%s], value => [%s]\n",
9287                 keyname, valuename));
9288
9289         /* in case of problem, return some default values */
9290
9291         *r->out.needed  = 0;
9292         *r->out.type    = 0;
9293
9294         if (!Printer) {
9295                 DEBUG(2,("_spoolss_GetPrinterDataEx: "
9296                         "Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
9297                 status = WERR_BADFID;
9298                 goto done;
9299         }
9300
9301         /* Is the handle to a printer or to the server? */
9302
9303         if (Printer->printer_type == SPLHND_SERVER) {
9304                 DEBUG(10,("_spoolss_GetPrinterDataEx: "
9305                         "Not implemented for server handles yet\n"));
9306                 status = WERR_INVALID_PARAM;
9307                 goto done;
9308         }
9309
9310         if ( !get_printer_snum(p,handle, &snum, NULL) )
9311                 return WERR_BADFID;
9312
9313         status = get_a_printer(Printer, &printer, 2, lp_servicename(snum));
9314         if ( !W_ERROR_IS_OK(status) )
9315                 goto done;
9316
9317         /* check to see if the keyname is valid */
9318         if ( !strlen(keyname) ) {
9319                 status = WERR_INVALID_PARAM;
9320                 goto done;
9321         }
9322
9323         if ( lookup_printerkey( printer->info_2->data, keyname ) == -1 ) {
9324                 DEBUG(4,("_spoolss_GetPrinterDataEx: "
9325                         "Invalid keyname [%s]\n", keyname ));
9326                 free_a_printer( &printer, 2 );
9327                 status = WERR_BADFILE;
9328                 goto done;
9329         }
9330
9331         /* When given a new keyname, we should just create it */
9332
9333         status = get_printer_dataex( p->mem_ctx, printer, keyname, valuename,
9334                                      r->out.type, &data, r->out.needed,
9335                                      r->in.offered );
9336
9337         if (*r->out.needed > r->in.offered) {
9338                 status = WERR_MORE_DATA;
9339         }
9340
9341         if (W_ERROR_IS_OK(status)) {
9342                 memcpy(r->out.buffer, data, r->in.offered);
9343         }
9344
9345 done:
9346         if ( printer )
9347         free_a_printer( &printer, 2 );
9348
9349         return status;
9350 }
9351
9352 /****************************************************************
9353  _spoolss_SetPrinterDataEx
9354 ****************************************************************/
9355
9356 WERROR _spoolss_SetPrinterDataEx(pipes_struct *p,
9357                                  struct spoolss_SetPrinterDataEx *r)
9358 {
9359         POLICY_HND              *handle = r->in.handle;
9360         NT_PRINTER_INFO_LEVEL   *printer = NULL;
9361         int                     snum = 0;
9362         WERROR                  status = WERR_OK;
9363         Printer_entry           *Printer = find_printer_index_by_hnd(p, handle);
9364         char                    *oid_string;
9365
9366         DEBUG(4,("_spoolss_SetPrinterDataEx\n"));
9367
9368         /* From MSDN documentation of SetPrinterDataEx: pass request to
9369            SetPrinterData if key is "PrinterDriverData" */
9370
9371         if (!Printer) {
9372                 DEBUG(2,("_spoolss_SetPrinterDataEx: "
9373                         "Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
9374                 return WERR_BADFID;
9375         }
9376
9377         if ( Printer->printer_type == SPLHND_SERVER ) {
9378                 DEBUG(10,("_spoolss_SetPrinterDataEx: "
9379                         "Not implemented for server handles yet\n"));
9380                 return WERR_INVALID_PARAM;
9381         }
9382
9383         if ( !get_printer_snum(p,handle, &snum, NULL) )
9384                 return WERR_BADFID;
9385
9386         /*
9387          * Access check : NT returns "access denied" if you make a
9388          * SetPrinterData call without the necessary privildge.
9389          * we were originally returning OK if nothing changed
9390          * which made Win2k issue **a lot** of SetPrinterData
9391          * when connecting to a printer  --jerry
9392          */
9393
9394         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER)
9395         {
9396                 DEBUG(3, ("_spoolss_SetPrinterDataEx: "
9397                         "change denied by handle access permissions\n"));
9398                 return WERR_ACCESS_DENIED;
9399         }
9400
9401         status = get_a_printer(Printer, &printer, 2, lp_servicename(snum));
9402         if (!W_ERROR_IS_OK(status))
9403                 return status;
9404
9405         /* check for OID in valuename */
9406
9407         if ( (oid_string = strchr( r->in.value_name, ',' )) != NULL )
9408         {
9409                 *oid_string = '\0';
9410                 oid_string++;
9411         }
9412
9413         /* save the registry data */
9414
9415         status = set_printer_dataex( printer, r->in.key_name, r->in.value_name,
9416                                      r->in.type, r->in.buffer, r->in.offered );
9417
9418         if ( W_ERROR_IS_OK(status) )
9419         {
9420                 /* save the OID if one was specified */
9421                 if ( oid_string ) {
9422                         char *str = talloc_asprintf(p->mem_ctx, "%s\\%s",
9423                                 r->in.key_name, SPOOL_OID_KEY);
9424                         if (!str) {
9425                                 return WERR_NOMEM;
9426                         }
9427
9428                         /*
9429                          * I'm not checking the status here on purpose.  Don't know
9430                          * if this is right, but I'm returning the status from the
9431                          * previous set_printer_dataex() call.  I have no idea if
9432                          * this is right.    --jerry
9433                          */
9434
9435                         set_printer_dataex( printer, str, r->in.value_name,
9436                                             REG_SZ, (uint8 *)oid_string,
9437                                             strlen(oid_string)+1 );
9438                 }
9439
9440                 status = mod_a_printer(printer, 2);
9441         }
9442
9443         free_a_printer(&printer, 2);
9444
9445         return status;
9446 }
9447
9448 /****************************************************************
9449  _spoolss_DeletePrinterDataEx
9450 ****************************************************************/
9451
9452 WERROR _spoolss_DeletePrinterDataEx(pipes_struct *p,
9453                                     struct spoolss_DeletePrinterDataEx *r)
9454 {
9455         POLICY_HND      *handle = r->in.handle;
9456         NT_PRINTER_INFO_LEVEL   *printer = NULL;
9457         int             snum=0;
9458         WERROR          status = WERR_OK;
9459         Printer_entry   *Printer=find_printer_index_by_hnd(p, handle);
9460
9461         DEBUG(5,("_spoolss_DeletePrinterDataEx\n"));
9462
9463         if (!Printer) {
9464                 DEBUG(2,("_spoolss_DeletePrinterDataEx: "
9465                         "Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
9466                 return WERR_BADFID;
9467         }
9468
9469         if (!get_printer_snum(p, handle, &snum, NULL))
9470                 return WERR_BADFID;
9471
9472         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
9473                 DEBUG(3, ("_spoolss_DeletePrinterDataEx: "
9474                         "printer properties change denied by handle\n"));
9475                 return WERR_ACCESS_DENIED;
9476         }
9477
9478         if (!r->in.value_name || !r->in.key_name) {
9479                 return WERR_NOMEM;
9480         }
9481
9482         status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
9483         if (!W_ERROR_IS_OK(status))
9484                 return status;
9485
9486         status = delete_printer_dataex( printer, r->in.key_name, r->in.value_name );
9487
9488         if ( W_ERROR_IS_OK(status) )
9489                 mod_a_printer( printer, 2 );
9490
9491         free_a_printer(&printer, 2);
9492
9493         return status;
9494 }
9495
9496 /********************************************************************
9497  * spoolss_enumprinterkey
9498  ********************************************************************/
9499
9500
9501 WERROR _spoolss_enumprinterkey(pipes_struct *p, SPOOL_Q_ENUMPRINTERKEY *q_u, SPOOL_R_ENUMPRINTERKEY *r_u)
9502 {
9503         fstring         key;
9504         fstring         *keynames = NULL;
9505         uint16          *enumkeys = NULL;
9506         int             num_keys;
9507         int             printerkey_len;
9508         POLICY_HND      *handle = &q_u->handle;
9509         Printer_entry   *Printer = find_printer_index_by_hnd(p, handle);
9510         NT_PRINTER_DATA *data;
9511         NT_PRINTER_INFO_LEVEL   *printer = NULL;
9512         int             snum = 0;
9513         WERROR          status = WERR_BADFILE;
9514
9515
9516         DEBUG(4,("_spoolss_enumprinterkey\n"));
9517
9518         if (!Printer) {
9519                 DEBUG(2,("_spoolss_enumprinterkey: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
9520                 return WERR_BADFID;
9521         }
9522
9523         if ( !get_printer_snum(p,handle, &snum, NULL) )
9524                 return WERR_BADFID;
9525
9526         status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
9527         if (!W_ERROR_IS_OK(status))
9528                 return status;
9529
9530         /* get the list of subkey names */
9531
9532         unistr2_to_ascii(key, &q_u->key, sizeof(key));
9533         data = printer->info_2->data;
9534
9535         num_keys = get_printer_subkeys( data, key, &keynames );
9536
9537         if ( num_keys == -1 ) {
9538                 status = WERR_BADFILE;
9539                 goto done;
9540         }
9541
9542         printerkey_len = init_unistr_array( &enumkeys,  keynames, NULL );
9543
9544         r_u->needed = printerkey_len*2;
9545
9546         if ( q_u->size < r_u->needed ) {
9547                 status = WERR_MORE_DATA;
9548                 goto done;
9549         }
9550
9551         if (!make_spoolss_buffer5(p->mem_ctx, &r_u->keys, printerkey_len, enumkeys)) {
9552                 status = WERR_NOMEM;
9553                 goto done;
9554         }
9555
9556         status = WERR_OK;
9557
9558         if ( q_u->size < r_u->needed )
9559                 status = WERR_MORE_DATA;
9560
9561 done:
9562         free_a_printer( &printer, 2 );
9563         SAFE_FREE( keynames );
9564
9565         return status;
9566 }
9567
9568 /****************************************************************
9569  _spoolss_DeletePrinterKey
9570 ****************************************************************/
9571
9572 WERROR _spoolss_DeletePrinterKey(pipes_struct *p,
9573                                  struct spoolss_DeletePrinterKey *r)
9574 {
9575         POLICY_HND              *handle = r->in.handle;
9576         Printer_entry           *Printer = find_printer_index_by_hnd(p, handle);
9577         NT_PRINTER_INFO_LEVEL   *printer = NULL;
9578         int                     snum=0;
9579         WERROR                  status;
9580
9581         DEBUG(5,("_spoolss_DeletePrinterKey\n"));
9582
9583         if (!Printer) {
9584                 DEBUG(2,("_spoolss_DeletePrinterKey: Invalid handle (%s:%u:%u).\n",
9585                         OUR_HANDLE(handle)));
9586                 return WERR_BADFID;
9587         }
9588
9589         /* if keyname == NULL, return error */
9590
9591         if ( !r->in.key_name )
9592                 return WERR_INVALID_PARAM;
9593
9594         if (!get_printer_snum(p, handle, &snum, NULL))
9595                 return WERR_BADFID;
9596
9597         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
9598                 DEBUG(3, ("_spoolss_DeletePrinterKey: "
9599                         "printer properties change denied by handle\n"));
9600                 return WERR_ACCESS_DENIED;
9601         }
9602
9603         status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
9604         if (!W_ERROR_IS_OK(status))
9605                 return status;
9606
9607         /* delete the key and all subneys */
9608
9609         status = delete_all_printer_data( printer->info_2, r->in.key_name );
9610
9611         if ( W_ERROR_IS_OK(status) )
9612                 status = mod_a_printer(printer, 2);
9613
9614         free_a_printer( &printer, 2 );
9615
9616         return status;
9617 }
9618
9619
9620 /********************************************************************
9621  * spoolss_enumprinterdataex
9622  ********************************************************************/
9623
9624 WERROR _spoolss_enumprinterdataex(pipes_struct *p, SPOOL_Q_ENUMPRINTERDATAEX *q_u, SPOOL_R_ENUMPRINTERDATAEX *r_u)
9625 {
9626         POLICY_HND      *handle = &q_u->handle;
9627         uint32          in_size = q_u->size;
9628         uint32          num_entries,
9629                         needed;
9630         NT_PRINTER_INFO_LEVEL   *printer = NULL;
9631         PRINTER_ENUM_VALUES     *enum_values = NULL;
9632         NT_PRINTER_DATA         *p_data;
9633         fstring         key;
9634         Printer_entry   *Printer = find_printer_index_by_hnd(p, handle);
9635         int             snum;
9636         WERROR          result;
9637         int             key_index;
9638         int             i;
9639         REGISTRY_VALUE  *val;
9640         char            *value_name;
9641         uint32          data_len;
9642
9643
9644         DEBUG(4,("_spoolss_enumprinterdataex\n"));
9645
9646         if (!Printer) {
9647                 DEBUG(2,("_spoolss_enumprinterdataex: Invalid handle (%s:%u:%u1<).\n", OUR_HANDLE(handle)));
9648                 return WERR_BADFID;
9649         }
9650
9651         /*
9652          * first check for a keyname of NULL or "".  Win2k seems to send
9653          * this a lot and we should send back WERR_INVALID_PARAM
9654          * no need to spend time looking up the printer in this case.
9655          * --jerry
9656          */
9657
9658         unistr2_to_ascii(key, &q_u->key, sizeof(key));
9659         if ( !strlen(key) ) {
9660                 result = WERR_INVALID_PARAM;
9661                 goto done;
9662         }
9663
9664         /* get the printer off of disk */
9665
9666         if (!get_printer_snum(p,handle, &snum, NULL))
9667                 return WERR_BADFID;
9668
9669         ZERO_STRUCT(printer);
9670         result = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
9671         if (!W_ERROR_IS_OK(result))
9672                 return result;
9673
9674         /* now look for a match on the key name */
9675
9676         p_data = printer->info_2->data;
9677
9678         unistr2_to_ascii(key, &q_u->key, sizeof(key));
9679         if ( (key_index = lookup_printerkey( p_data, key)) == -1  )
9680         {
9681                 DEBUG(10,("_spoolss_enumprinterdataex: Unknown keyname [%s]\n", key));
9682                 result = WERR_INVALID_PARAM;
9683                 goto done;
9684         }
9685
9686         result = WERR_OK;
9687         needed = 0;
9688
9689         /* allocate the memory for the array of pointers -- if necessary */
9690
9691         num_entries = regval_ctr_numvals( p_data->keys[key_index].values );
9692         if ( num_entries )
9693         {
9694                 if ( (enum_values=TALLOC_ARRAY(p->mem_ctx, PRINTER_ENUM_VALUES, num_entries)) == NULL )
9695                 {
9696                         DEBUG(0,("_spoolss_enumprinterdataex: talloc() failed to allocate memory for [%lu] bytes!\n",
9697                                 (unsigned long)num_entries*sizeof(PRINTER_ENUM_VALUES)));
9698                         result = WERR_NOMEM;
9699                         goto done;
9700                 }
9701
9702                 memset( enum_values, 0x0, num_entries*sizeof(PRINTER_ENUM_VALUES) );
9703         }
9704
9705         /*
9706          * loop through all params and build the array to pass
9707          * back to the  client
9708          */
9709
9710         for ( i=0; i<num_entries; i++ )
9711         {
9712                 /* lookup the registry value */
9713
9714                 val = regval_ctr_specific_value( p_data->keys[key_index].values, i );
9715                 DEBUG(10,("retrieved value number [%d] [%s]\n", i, regval_name(val) ));
9716
9717                 /* copy the data */
9718
9719                 value_name = regval_name( val );
9720                 init_unistr( &enum_values[i].valuename, value_name );
9721                 enum_values[i].value_len = (strlen(value_name)+1) * 2;
9722                 enum_values[i].type      = regval_type( val );
9723
9724                 data_len = regval_size( val );
9725                 if ( data_len ) {
9726                         if ( !(enum_values[i].data = (uint8 *)TALLOC_MEMDUP(p->mem_ctx, regval_data_p(val), data_len)) )
9727                         {
9728                                 DEBUG(0,("TALLOC_MEMDUP failed to allocate memory [data_len=%d] for data!\n",
9729                                         data_len ));
9730                                 result = WERR_NOMEM;
9731                                 goto done;
9732                         }
9733                 }
9734                 enum_values[i].data_len = data_len;
9735
9736                 /* keep track of the size of the array in bytes */
9737
9738                 needed += spoolss_size_printer_enum_values(&enum_values[i]);
9739         }
9740
9741         /* housekeeping information in the reply */
9742
9743         /* Fix from Martin Zielinski <mz@seh.de> - ensure
9744          * the hand marshalled container size is a multiple
9745          * of 4 bytes for RPC alignment.
9746          */
9747
9748         if (needed % 4) {
9749                 needed += 4-(needed % 4);
9750         }
9751
9752         r_u->needed     = needed;
9753         r_u->returned   = num_entries;
9754
9755         if (needed > in_size) {
9756                 result = WERR_MORE_DATA;
9757                 goto done;
9758         }
9759
9760         /* copy data into the reply */
9761
9762         /* mz: Vista x64 returns 0x6f7 (The stub received bad data), if the
9763            response buffer size is != the offered buffer size
9764
9765                 r_u->ctr.size           = r_u->needed;
9766         */
9767         r_u->ctr.size           = in_size;
9768
9769         r_u->ctr.size_of_array  = r_u->returned;
9770         r_u->ctr.values         = enum_values;
9771
9772 done:
9773         if ( printer )
9774         free_a_printer(&printer, 2);
9775
9776         return result;
9777 }
9778
9779 /****************************************************************************
9780 ****************************************************************************/
9781
9782 static WERROR getprintprocessordirectory_level_1(TALLOC_CTX *mem_ctx,
9783                                                  const char *servername,
9784                                                  const char *environment,
9785                                                  struct spoolss_PrintProcessorDirectoryInfo1 *r,
9786                                                  uint32_t offered,
9787                                                  uint32_t *needed)
9788 {
9789         WERROR werr;
9790         char *path = NULL;
9791
9792         werr = compose_spoolss_server_path(mem_ctx,
9793                                            servername,
9794                                            environment,
9795                                            SPOOLSS_PRTPROCS_PATH,
9796                                            &path);
9797         if (!W_ERROR_IS_OK(werr)) {
9798                 return werr;
9799         }
9800
9801         DEBUG(4,("print processor directory: [%s]\n", path));
9802
9803         r->directory_name = path;
9804
9805         *needed += ndr_size_spoolss_PrintProcessorDirectoryInfo1(r, NULL, 0);
9806
9807         if (*needed > offered) {
9808                 talloc_free(path);
9809                 return WERR_INSUFFICIENT_BUFFER;
9810         }
9811
9812         return WERR_OK;
9813 }
9814
9815 /****************************************************************
9816  _spoolss_GetPrintProcessorDirectory
9817 ****************************************************************/
9818
9819 WERROR _spoolss_GetPrintProcessorDirectory(pipes_struct *p,
9820                                            struct spoolss_GetPrintProcessorDirectory *r)
9821 {
9822         WERROR result;
9823
9824         /* that's an [in out] buffer */
9825
9826         if (!r->in.buffer && (r->in.offered != 0)) {
9827                 return WERR_INVALID_PARAM;
9828         }
9829
9830         DEBUG(5,("_spoolss_GetPrintProcessorDirectory: level %d\n",
9831                 r->in.level));
9832
9833         *r->out.needed = 0;
9834
9835         /* r->in.level is ignored */
9836
9837         result = getprintprocessordirectory_level_1(p->mem_ctx,
9838                                                     r->in.server,
9839                                                     r->in.environment,
9840                                                     &r->out.info->info1,
9841                                                     r->in.offered,
9842                                                     r->out.needed);
9843         if (!W_ERROR_IS_OK(result)) {
9844                 TALLOC_FREE(r->out.info);
9845         }
9846
9847         return result;
9848 }
9849
9850 /*******************************************************************
9851  ********************************************************************/
9852
9853 static bool push_monitorui_buf(TALLOC_CTX *mem_ctx, DATA_BLOB *buf,
9854                                const char *dllname)
9855 {
9856         enum ndr_err_code ndr_err;
9857         struct spoolss_MonitorUi ui;
9858
9859         ui.dll_name = dllname;
9860
9861         ndr_err = ndr_push_struct_blob(buf, mem_ctx, NULL, &ui,
9862                        (ndr_push_flags_fn_t)ndr_push_spoolss_MonitorUi);
9863         if (NDR_ERR_CODE_IS_SUCCESS(ndr_err) && (DEBUGLEVEL >= 10)) {
9864                 NDR_PRINT_DEBUG(spoolss_MonitorUi, &ui);
9865         }
9866         return NDR_ERR_CODE_IS_SUCCESS(ndr_err);
9867 }
9868
9869 /*******************************************************************
9870  Streams the monitor UI DLL name in UNICODE
9871 *******************************************************************/
9872
9873 static WERROR xcvtcp_monitorui(TALLOC_CTX *mem_ctx,
9874                                NT_USER_TOKEN *token, DATA_BLOB *in,
9875                                DATA_BLOB *out, uint32_t *needed)
9876 {
9877         const char *dllname = "tcpmonui.dll";
9878
9879         *needed = (strlen(dllname)+1) * 2;
9880
9881         if (out->length < *needed) {
9882                 return WERR_INSUFFICIENT_BUFFER;
9883         }
9884
9885         if (!push_monitorui_buf(mem_ctx, out, dllname)) {
9886                 return WERR_NOMEM;
9887         }
9888
9889         return WERR_OK;
9890 }
9891
9892 /*******************************************************************
9893  ********************************************************************/
9894
9895 static bool pull_port_data_1(TALLOC_CTX *mem_ctx,
9896                              struct spoolss_PortData1 *port1,
9897                              const DATA_BLOB *buf)
9898 {
9899         enum ndr_err_code ndr_err;
9900         ndr_err = ndr_pull_struct_blob(buf, mem_ctx, NULL, port1,
9901                        (ndr_pull_flags_fn_t)ndr_pull_spoolss_PortData1);
9902         if (NDR_ERR_CODE_IS_SUCCESS(ndr_err) && (DEBUGLEVEL >= 10)) {
9903                 NDR_PRINT_DEBUG(spoolss_PortData1, port1);
9904         }
9905         return NDR_ERR_CODE_IS_SUCCESS(ndr_err);
9906 }
9907
9908 /*******************************************************************
9909  ********************************************************************/
9910
9911 static bool pull_port_data_2(TALLOC_CTX *mem_ctx,
9912                              struct spoolss_PortData2 *port2,
9913                              const DATA_BLOB *buf)
9914 {
9915         enum ndr_err_code ndr_err;
9916         ndr_err = ndr_pull_struct_blob(buf, mem_ctx, NULL, port2,
9917                        (ndr_pull_flags_fn_t)ndr_pull_spoolss_PortData2);
9918         if (NDR_ERR_CODE_IS_SUCCESS(ndr_err) && (DEBUGLEVEL >= 10)) {
9919                 NDR_PRINT_DEBUG(spoolss_PortData2, port2);
9920         }
9921         return NDR_ERR_CODE_IS_SUCCESS(ndr_err);
9922 }
9923
9924 /*******************************************************************
9925  Create a new TCP/IP port
9926 *******************************************************************/
9927
9928 static WERROR xcvtcp_addport(TALLOC_CTX *mem_ctx,
9929                              NT_USER_TOKEN *token, DATA_BLOB *in,
9930                              DATA_BLOB *out, uint32_t *needed)
9931 {
9932         struct spoolss_PortData1 port1;
9933         struct spoolss_PortData2 port2;
9934         char *device_uri = NULL;
9935         uint32_t version;
9936
9937         const char *portname;
9938         const char *hostaddress;
9939         const char *queue;
9940         uint32_t port_number;
9941         uint32_t protocol;
9942
9943         /* peek for spoolss_PortData version */
9944
9945         if (!in || (in->length < (128 + 4))) {
9946                 return WERR_GENERAL_FAILURE;
9947         }
9948
9949         version = IVAL(in->data, 128);
9950
9951         switch (version) {
9952                 case 1:
9953                         ZERO_STRUCT(port1);
9954
9955                         if (!pull_port_data_1(mem_ctx, &port1, in)) {
9956                                 return WERR_NOMEM;
9957                         }
9958
9959                         portname        = port1.portname;
9960                         hostaddress     = port1.hostaddress;
9961                         queue           = port1.queue;
9962                         protocol        = port1.protocol;
9963                         port_number     = port1.port_number;
9964
9965                         break;
9966                 case 2:
9967                         ZERO_STRUCT(port2);
9968
9969                         if (!pull_port_data_2(mem_ctx, &port2, in)) {
9970                                 return WERR_NOMEM;
9971                         }
9972
9973                         portname        = port2.portname;
9974                         hostaddress     = port2.hostaddress;
9975                         queue           = port2.queue;
9976                         protocol        = port2.protocol;
9977                         port_number     = port2.port_number;
9978
9979                         break;
9980                 default:
9981                         DEBUG(1,("xcvtcp_addport: "
9982                                 "unknown version of port_data: %d\n", version));
9983                         return WERR_UNKNOWN_PORT;
9984         }
9985
9986         /* create the device URI and call the add_port_hook() */
9987
9988         switch (protocol) {
9989         case PROTOCOL_RAWTCP_TYPE:
9990                 device_uri = talloc_asprintf(mem_ctx,
9991                                 "socket://%s:%d/", hostaddress,
9992                                 port_number);
9993                 break;
9994
9995         case PROTOCOL_LPR_TYPE:
9996                 device_uri = talloc_asprintf(mem_ctx,
9997                         "lpr://%s/%s", hostaddress, queue );
9998                 break;
9999
10000         default:
10001                 return WERR_UNKNOWN_PORT;
10002         }
10003
10004         if (!device_uri) {
10005                 return WERR_NOMEM;
10006         }
10007
10008         return add_port_hook(mem_ctx, token, portname, device_uri);
10009 }
10010
10011 /*******************************************************************
10012 *******************************************************************/
10013
10014 struct xcv_api_table xcvtcp_cmds[] = {
10015         { "MonitorUI",  xcvtcp_monitorui },
10016         { "AddPort",    xcvtcp_addport},
10017         { NULL,         NULL }
10018 };
10019
10020 static WERROR process_xcvtcp_command(TALLOC_CTX *mem_ctx,
10021                                      NT_USER_TOKEN *token, const char *command,
10022                                      DATA_BLOB *inbuf,
10023                                      DATA_BLOB *outbuf,
10024                                      uint32_t *needed )
10025 {
10026         int i;
10027
10028         DEBUG(10,("process_xcvtcp_command: Received command \"%s\"\n", command));
10029
10030         for ( i=0; xcvtcp_cmds[i].name; i++ ) {
10031                 if ( strcmp( command, xcvtcp_cmds[i].name ) == 0 )
10032                         return xcvtcp_cmds[i].fn(mem_ctx, token, inbuf, outbuf, needed);
10033         }
10034
10035         return WERR_BADFUNC;
10036 }
10037
10038 /*******************************************************************
10039 *******************************************************************/
10040 #if 0   /* don't support management using the "Local Port" monitor */
10041
10042 static WERROR xcvlocal_monitorui(TALLOC_CTX *mem_ctx,
10043                                  NT_USER_TOKEN *token, DATA_BLOB *in,
10044                                  DATA_BLOB *out, uint32_t *needed)
10045 {
10046         const char *dllname = "localui.dll";
10047
10048         *needed = (strlen(dllname)+1) * 2;
10049
10050         if (out->length < *needed) {
10051                 return WERR_INSUFFICIENT_BUFFER;
10052         }
10053
10054         if (!push_monitorui_buf(mem_ctx, out, dllname)) {
10055                 return WERR_NOMEM;
10056         }
10057
10058         return WERR_OK;
10059 }
10060
10061 /*******************************************************************
10062 *******************************************************************/
10063
10064 struct xcv_api_table xcvlocal_cmds[] = {
10065         { "MonitorUI",  xcvlocal_monitorui },
10066         { NULL,         NULL }
10067 };
10068 #else
10069 struct xcv_api_table xcvlocal_cmds[] = {
10070         { NULL,         NULL }
10071 };
10072 #endif
10073
10074
10075
10076 /*******************************************************************
10077 *******************************************************************/
10078
10079 static WERROR process_xcvlocal_command(TALLOC_CTX *mem_ctx,
10080                                        NT_USER_TOKEN *token, const char *command,
10081                                        DATA_BLOB *inbuf, DATA_BLOB *outbuf,
10082                                        uint32_t *needed)
10083 {
10084         int i;
10085
10086         DEBUG(10,("process_xcvlocal_command: Received command \"%s\"\n", command));
10087
10088         for ( i=0; xcvlocal_cmds[i].name; i++ ) {
10089                 if ( strcmp( command, xcvlocal_cmds[i].name ) == 0 )
10090                         return xcvlocal_cmds[i].fn(mem_ctx, token, inbuf, outbuf, needed);
10091         }
10092         return WERR_BADFUNC;
10093 }
10094
10095 /****************************************************************
10096  _spoolss_XcvData
10097 ****************************************************************/
10098
10099 WERROR _spoolss_XcvData(pipes_struct *p,
10100                         struct spoolss_XcvData *r)
10101 {
10102         Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
10103         DATA_BLOB out_data;
10104         WERROR werror;
10105
10106         if (!Printer) {
10107                 DEBUG(2,("_spoolss_XcvData: Invalid handle (%s:%u:%u).\n",
10108                         OUR_HANDLE(r->in.handle)));
10109                 return WERR_BADFID;
10110         }
10111
10112         /* Has to be a handle to the TCP/IP port monitor */
10113
10114         if ( !(Printer->printer_type & (SPLHND_PORTMON_LOCAL|SPLHND_PORTMON_TCP)) ) {
10115                 DEBUG(2,("_spoolss_XcvData: Call only valid for Port Monitors\n"));
10116                 return WERR_BADFID;
10117         }
10118
10119         /* requires administrative access to the server */
10120
10121         if ( !(Printer->access_granted & SERVER_ACCESS_ADMINISTER) ) {
10122                 DEBUG(2,("_spoolss_XcvData: denied by handle permissions.\n"));
10123                 return WERR_ACCESS_DENIED;
10124         }
10125
10126         /* Allocate the outgoing buffer */
10127
10128         if (r->in.out_data_size) {
10129                 out_data = data_blob_talloc_zero(p->mem_ctx, r->in.out_data_size);
10130                 if (out_data.data == NULL) {
10131                         return WERR_NOMEM;
10132                 }
10133         }
10134
10135         switch ( Printer->printer_type ) {
10136         case SPLHND_PORTMON_TCP:
10137                 werror = process_xcvtcp_command(p->mem_ctx,
10138                                                 p->server_info->ptok,
10139                                                 r->in.function_name,
10140                                                 &r->in.in_data, &out_data,
10141                                                 r->out.needed);
10142                 break;
10143         case SPLHND_PORTMON_LOCAL:
10144                 werror = process_xcvlocal_command(p->mem_ctx,
10145                                                   p->server_info->ptok,
10146                                                   r->in.function_name,
10147                                                   &r->in.in_data, &out_data,
10148                                                   r->out.needed);
10149                 break;
10150         default:
10151                 werror = WERR_INVALID_PRINT_MONITOR;
10152         }
10153
10154         if (!W_ERROR_IS_OK(werror)) {
10155                 return werror;
10156         }
10157
10158         *r->out.status_code = 0;
10159
10160         memcpy(r->out.out_data, out_data.data, out_data.length);
10161
10162         return WERR_OK;
10163 }
10164
10165 /****************************************************************
10166  _spoolss_AddPrintProcessor
10167 ****************************************************************/
10168
10169 WERROR _spoolss_AddPrintProcessor(pipes_struct *p,
10170                                   struct spoolss_AddPrintProcessor *r)
10171 {
10172         /* for now, just indicate success and ignore the add.  We'll
10173            automatically set the winprint processor for printer
10174            entries later.  Used to debug the LexMark Optra S 1855 PCL
10175            driver --jerry */
10176
10177         return WERR_OK;
10178 }
10179
10180 /****************************************************************
10181  _spoolss_EnumPrinters
10182 ****************************************************************/
10183
10184 WERROR _spoolss_EnumPrinters(pipes_struct *p,
10185                              struct spoolss_EnumPrinters *r)
10186 {
10187         p->rng_fault_state = true;
10188         return WERR_NOT_SUPPORTED;
10189 }
10190
10191 /****************************************************************
10192  _spoolss_GetJob
10193 ****************************************************************/
10194
10195 WERROR _spoolss_GetJob(pipes_struct *p,
10196                        struct spoolss_GetJob *r)
10197 {
10198         p->rng_fault_state = true;
10199         return WERR_NOT_SUPPORTED;
10200 }
10201
10202 /****************************************************************
10203  _spoolss_EnumJobs
10204 ****************************************************************/
10205
10206 WERROR _spoolss_EnumJobs(pipes_struct *p,
10207                          struct spoolss_EnumJobs *r)
10208 {
10209         p->rng_fault_state = true;
10210         return WERR_NOT_SUPPORTED;
10211 }
10212
10213 /****************************************************************
10214  _spoolss_AddPrinter
10215 ****************************************************************/
10216
10217 WERROR _spoolss_AddPrinter(pipes_struct *p,
10218                            struct spoolss_AddPrinter *r)
10219 {
10220         p->rng_fault_state = true;
10221         return WERR_NOT_SUPPORTED;
10222 }
10223
10224 /****************************************************************
10225  _spoolss_GetPrinter
10226 ****************************************************************/
10227
10228 WERROR _spoolss_GetPrinter(pipes_struct *p,
10229                            struct spoolss_GetPrinter *r)
10230 {
10231         p->rng_fault_state = true;
10232         return WERR_NOT_SUPPORTED;
10233 }
10234
10235 /****************************************************************
10236  _spoolss_EnumPrinterDrivers
10237 ****************************************************************/
10238
10239 WERROR _spoolss_EnumPrinterDrivers(pipes_struct *p,
10240                                    struct spoolss_EnumPrinterDrivers *r)
10241 {
10242         p->rng_fault_state = true;
10243         return WERR_NOT_SUPPORTED;
10244 }
10245
10246 /****************************************************************
10247  _spoolss_GetPrinterDriver
10248 ****************************************************************/
10249
10250 WERROR _spoolss_GetPrinterDriver(pipes_struct *p,
10251                                  struct spoolss_GetPrinterDriver *r)
10252 {
10253         p->rng_fault_state = true;
10254         return WERR_NOT_SUPPORTED;
10255 }
10256
10257 /****************************************************************
10258  _spoolss_EnumPrintProcessors
10259 ****************************************************************/
10260
10261 WERROR _spoolss_EnumPrintProcessors(pipes_struct *p,
10262                                     struct spoolss_EnumPrintProcessors *r)
10263 {
10264         p->rng_fault_state = true;
10265         return WERR_NOT_SUPPORTED;
10266 }
10267
10268 /****************************************************************
10269  _spoolss_ReadPrinter
10270 ****************************************************************/
10271
10272 WERROR _spoolss_ReadPrinter(pipes_struct *p,
10273                             struct spoolss_ReadPrinter *r)
10274 {
10275         p->rng_fault_state = true;
10276         return WERR_NOT_SUPPORTED;
10277 }
10278
10279 /****************************************************************
10280  _spoolss_GetPrinterData
10281 ****************************************************************/
10282
10283 WERROR _spoolss_GetPrinterData(pipes_struct *p,
10284                                struct spoolss_GetPrinterData *r)
10285 {
10286         p->rng_fault_state = true;
10287         return WERR_NOT_SUPPORTED;
10288 }
10289
10290 /****************************************************************
10291  _spoolss_SetPrinterData
10292 ****************************************************************/
10293
10294 WERROR _spoolss_SetPrinterData(pipes_struct *p,
10295                                struct spoolss_SetPrinterData *r)
10296 {
10297         p->rng_fault_state = true;
10298         return WERR_NOT_SUPPORTED;
10299 }
10300
10301 /****************************************************************
10302  _spoolss_WaitForPrinterChange
10303 ****************************************************************/
10304
10305 WERROR _spoolss_WaitForPrinterChange(pipes_struct *p,
10306                                      struct spoolss_WaitForPrinterChange *r)
10307 {
10308         p->rng_fault_state = true;
10309         return WERR_NOT_SUPPORTED;
10310 }
10311
10312 /****************************************************************
10313  _spoolss_EnumForms
10314 ****************************************************************/
10315
10316 WERROR _spoolss_EnumForms(pipes_struct *p,
10317                           struct spoolss_EnumForms *r)
10318 {
10319         p->rng_fault_state = true;
10320         return WERR_NOT_SUPPORTED;
10321 }
10322
10323 /****************************************************************
10324  _spoolss_EnumPorts
10325 ****************************************************************/
10326
10327 WERROR _spoolss_EnumPorts(pipes_struct *p,
10328                           struct spoolss_EnumPorts *r)
10329 {
10330         p->rng_fault_state = true;
10331         return WERR_NOT_SUPPORTED;
10332 }
10333
10334 /****************************************************************
10335  _spoolss_EnumMonitors
10336 ****************************************************************/
10337
10338 WERROR _spoolss_EnumMonitors(pipes_struct *p,
10339                              struct spoolss_EnumMonitors *r)
10340 {
10341         p->rng_fault_state = true;
10342         return WERR_NOT_SUPPORTED;
10343 }
10344
10345 /****************************************************************
10346  _spoolss_AddPort
10347 ****************************************************************/
10348
10349 WERROR _spoolss_AddPort(pipes_struct *p,
10350                         struct spoolss_AddPort *r)
10351 {
10352         p->rng_fault_state = true;
10353         return WERR_NOT_SUPPORTED;
10354 }
10355
10356 /****************************************************************
10357  _spoolss_ConfigurePort
10358 ****************************************************************/
10359
10360 WERROR _spoolss_ConfigurePort(pipes_struct *p,
10361                               struct spoolss_ConfigurePort *r)
10362 {
10363         p->rng_fault_state = true;
10364         return WERR_NOT_SUPPORTED;
10365 }
10366
10367 /****************************************************************
10368  _spoolss_DeletePort
10369 ****************************************************************/
10370
10371 WERROR _spoolss_DeletePort(pipes_struct *p,
10372                            struct spoolss_DeletePort *r)
10373 {
10374         p->rng_fault_state = true;
10375         return WERR_NOT_SUPPORTED;
10376 }
10377
10378 /****************************************************************
10379  _spoolss_CreatePrinterIC
10380 ****************************************************************/
10381
10382 WERROR _spoolss_CreatePrinterIC(pipes_struct *p,
10383                                 struct spoolss_CreatePrinterIC *r)
10384 {
10385         p->rng_fault_state = true;
10386         return WERR_NOT_SUPPORTED;
10387 }
10388
10389 /****************************************************************
10390  _spoolss_PlayGDIScriptOnPrinterIC
10391 ****************************************************************/
10392
10393 WERROR _spoolss_PlayGDIScriptOnPrinterIC(pipes_struct *p,
10394                                          struct spoolss_PlayGDIScriptOnPrinterIC *r)
10395 {
10396         p->rng_fault_state = true;
10397         return WERR_NOT_SUPPORTED;
10398 }
10399
10400 /****************************************************************
10401  _spoolss_DeletePrinterIC
10402 ****************************************************************/
10403
10404 WERROR _spoolss_DeletePrinterIC(pipes_struct *p,
10405                                 struct spoolss_DeletePrinterIC *r)
10406 {
10407         p->rng_fault_state = true;
10408         return WERR_NOT_SUPPORTED;
10409 }
10410
10411 /****************************************************************
10412  _spoolss_AddPrinterConnection
10413 ****************************************************************/
10414
10415 WERROR _spoolss_AddPrinterConnection(pipes_struct *p,
10416                                      struct spoolss_AddPrinterConnection *r)
10417 {
10418         p->rng_fault_state = true;
10419         return WERR_NOT_SUPPORTED;
10420 }
10421
10422 /****************************************************************
10423  _spoolss_DeletePrinterConnection
10424 ****************************************************************/
10425
10426 WERROR _spoolss_DeletePrinterConnection(pipes_struct *p,
10427                                         struct spoolss_DeletePrinterConnection *r)
10428 {
10429         p->rng_fault_state = true;
10430         return WERR_NOT_SUPPORTED;
10431 }
10432
10433 /****************************************************************
10434  _spoolss_PrinterMessageBox
10435 ****************************************************************/
10436
10437 WERROR _spoolss_PrinterMessageBox(pipes_struct *p,
10438                                   struct spoolss_PrinterMessageBox *r)
10439 {
10440         p->rng_fault_state = true;
10441         return WERR_NOT_SUPPORTED;
10442 }
10443
10444 /****************************************************************
10445  _spoolss_AddMonitor
10446 ****************************************************************/
10447
10448 WERROR _spoolss_AddMonitor(pipes_struct *p,
10449                            struct spoolss_AddMonitor *r)
10450 {
10451         p->rng_fault_state = true;
10452         return WERR_NOT_SUPPORTED;
10453 }
10454
10455 /****************************************************************
10456  _spoolss_DeleteMonitor
10457 ****************************************************************/
10458
10459 WERROR _spoolss_DeleteMonitor(pipes_struct *p,
10460                               struct spoolss_DeleteMonitor *r)
10461 {
10462         p->rng_fault_state = true;
10463         return WERR_NOT_SUPPORTED;
10464 }
10465
10466 /****************************************************************
10467  _spoolss_DeletePrintProcessor
10468 ****************************************************************/
10469
10470 WERROR _spoolss_DeletePrintProcessor(pipes_struct *p,
10471                                      struct spoolss_DeletePrintProcessor *r)
10472 {
10473         p->rng_fault_state = true;
10474         return WERR_NOT_SUPPORTED;
10475 }
10476
10477 /****************************************************************
10478  _spoolss_AddPrintProvidor
10479 ****************************************************************/
10480
10481 WERROR _spoolss_AddPrintProvidor(pipes_struct *p,
10482                                  struct spoolss_AddPrintProvidor *r)
10483 {
10484         p->rng_fault_state = true;
10485         return WERR_NOT_SUPPORTED;
10486 }
10487
10488 /****************************************************************
10489  _spoolss_DeletePrintProvidor
10490 ****************************************************************/
10491
10492 WERROR _spoolss_DeletePrintProvidor(pipes_struct *p,
10493                                     struct spoolss_DeletePrintProvidor *r)
10494 {
10495         p->rng_fault_state = true;
10496         return WERR_NOT_SUPPORTED;
10497 }
10498
10499 /****************************************************************
10500  _spoolss_EnumPrintProcDataTypes
10501 ****************************************************************/
10502
10503 WERROR _spoolss_EnumPrintProcDataTypes(pipes_struct *p,
10504                                        struct spoolss_EnumPrintProcDataTypes *r)
10505 {
10506         p->rng_fault_state = true;
10507         return WERR_NOT_SUPPORTED;
10508 }
10509
10510 /****************************************************************
10511  _spoolss_GetPrinterDriver2
10512 ****************************************************************/
10513
10514 WERROR _spoolss_GetPrinterDriver2(pipes_struct *p,
10515                                   struct spoolss_GetPrinterDriver2 *r)
10516 {
10517         p->rng_fault_state = true;
10518         return WERR_NOT_SUPPORTED;
10519 }
10520
10521 /****************************************************************
10522  _spoolss_FindFirstPrinterChangeNotification
10523 ****************************************************************/
10524
10525 WERROR _spoolss_FindFirstPrinterChangeNotification(pipes_struct *p,
10526                                                    struct spoolss_FindFirstPrinterChangeNotification *r)
10527 {
10528         p->rng_fault_state = true;
10529         return WERR_NOT_SUPPORTED;
10530 }
10531
10532 /****************************************************************
10533  _spoolss_FindNextPrinterChangeNotification
10534 ****************************************************************/
10535
10536 WERROR _spoolss_FindNextPrinterChangeNotification(pipes_struct *p,
10537                                                   struct spoolss_FindNextPrinterChangeNotification *r)
10538 {
10539         p->rng_fault_state = true;
10540         return WERR_NOT_SUPPORTED;
10541 }
10542
10543 /****************************************************************
10544  _spoolss_RouterFindFirstPrinterChangeNotificationOld
10545 ****************************************************************/
10546
10547 WERROR _spoolss_RouterFindFirstPrinterChangeNotificationOld(pipes_struct *p,
10548                                                             struct spoolss_RouterFindFirstPrinterChangeNotificationOld *r)
10549 {
10550         p->rng_fault_state = true;
10551         return WERR_NOT_SUPPORTED;
10552 }
10553
10554 /****************************************************************
10555  _spoolss_ReplyOpenPrinter
10556 ****************************************************************/
10557
10558 WERROR _spoolss_ReplyOpenPrinter(pipes_struct *p,
10559                                  struct spoolss_ReplyOpenPrinter *r)
10560 {
10561         p->rng_fault_state = true;
10562         return WERR_NOT_SUPPORTED;
10563 }
10564
10565 /****************************************************************
10566  _spoolss_RouterReplyPrinter
10567 ****************************************************************/
10568
10569 WERROR _spoolss_RouterReplyPrinter(pipes_struct *p,
10570                                    struct spoolss_RouterReplyPrinter *r)
10571 {
10572         p->rng_fault_state = true;
10573         return WERR_NOT_SUPPORTED;
10574 }
10575
10576 /****************************************************************
10577  _spoolss_ReplyClosePrinter
10578 ****************************************************************/
10579
10580 WERROR _spoolss_ReplyClosePrinter(pipes_struct *p,
10581                                   struct spoolss_ReplyClosePrinter *r)
10582 {
10583         p->rng_fault_state = true;
10584         return WERR_NOT_SUPPORTED;
10585 }
10586
10587 /****************************************************************
10588  _spoolss_AddPortEx
10589 ****************************************************************/
10590
10591 WERROR _spoolss_AddPortEx(pipes_struct *p,
10592                           struct spoolss_AddPortEx *r)
10593 {
10594         p->rng_fault_state = true;
10595         return WERR_NOT_SUPPORTED;
10596 }
10597
10598 /****************************************************************
10599  _spoolss_RouterFindFirstPrinterChangeNotification
10600 ****************************************************************/
10601
10602 WERROR _spoolss_RouterFindFirstPrinterChangeNotification(pipes_struct *p,
10603                                                          struct spoolss_RouterFindFirstPrinterChangeNotification *r)
10604 {
10605         p->rng_fault_state = true;
10606         return WERR_NOT_SUPPORTED;
10607 }
10608
10609 /****************************************************************
10610  _spoolss_SpoolerInit
10611 ****************************************************************/
10612
10613 WERROR _spoolss_SpoolerInit(pipes_struct *p,
10614                             struct spoolss_SpoolerInit *r)
10615 {
10616         p->rng_fault_state = true;
10617         return WERR_NOT_SUPPORTED;
10618 }
10619
10620 /****************************************************************
10621  _spoolss_ResetPrinterEx
10622 ****************************************************************/
10623
10624 WERROR _spoolss_ResetPrinterEx(pipes_struct *p,
10625                                struct spoolss_ResetPrinterEx *r)
10626 {
10627         p->rng_fault_state = true;
10628         return WERR_NOT_SUPPORTED;
10629 }
10630
10631 /****************************************************************
10632  _spoolss_RouterReplyPrinterEx
10633 ****************************************************************/
10634
10635 WERROR _spoolss_RouterReplyPrinterEx(pipes_struct *p,
10636                                      struct spoolss_RouterReplyPrinterEx *r)
10637 {
10638         p->rng_fault_state = true;
10639         return WERR_NOT_SUPPORTED;
10640 }
10641
10642 /****************************************************************
10643  _spoolss_44
10644 ****************************************************************/
10645
10646 WERROR _spoolss_44(pipes_struct *p,
10647                    struct spoolss_44 *r)
10648 {
10649         p->rng_fault_state = true;
10650         return WERR_NOT_SUPPORTED;
10651 }
10652
10653 /****************************************************************
10654  _spoolss_47
10655 ****************************************************************/
10656
10657 WERROR _spoolss_47(pipes_struct *p,
10658                    struct spoolss_47 *r)
10659 {
10660         p->rng_fault_state = true;
10661         return WERR_NOT_SUPPORTED;
10662 }
10663
10664 /****************************************************************
10665  _spoolss_EnumPrinterData
10666 ****************************************************************/
10667
10668 WERROR _spoolss_EnumPrinterData(pipes_struct *p,
10669                                 struct spoolss_EnumPrinterData *r)
10670 {
10671         p->rng_fault_state = true;
10672         return WERR_NOT_SUPPORTED;
10673 }
10674
10675 /****************************************************************
10676  _spoolss_4a
10677 ****************************************************************/
10678
10679 WERROR _spoolss_4a(pipes_struct *p,
10680                    struct spoolss_4a *r)
10681 {
10682         p->rng_fault_state = true;
10683         return WERR_NOT_SUPPORTED;
10684 }
10685
10686 /****************************************************************
10687  _spoolss_4b
10688 ****************************************************************/
10689
10690 WERROR _spoolss_4b(pipes_struct *p,
10691                    struct spoolss_4b *r)
10692 {
10693         p->rng_fault_state = true;
10694         return WERR_NOT_SUPPORTED;
10695 }
10696
10697 /****************************************************************
10698  _spoolss_4c
10699 ****************************************************************/
10700
10701 WERROR _spoolss_4c(pipes_struct *p,
10702                    struct spoolss_4c *r)
10703 {
10704         p->rng_fault_state = true;
10705         return WERR_NOT_SUPPORTED;
10706 }
10707
10708 /****************************************************************
10709  _spoolss_EnumPrinterDataEx
10710 ****************************************************************/
10711
10712 WERROR _spoolss_EnumPrinterDataEx(pipes_struct *p,
10713                                   struct spoolss_EnumPrinterDataEx *r)
10714 {
10715         p->rng_fault_state = true;
10716         return WERR_NOT_SUPPORTED;
10717 }
10718
10719 /****************************************************************
10720  _spoolss_EnumPrinterKey
10721 ****************************************************************/
10722
10723 WERROR _spoolss_EnumPrinterKey(pipes_struct *p,
10724                                struct spoolss_EnumPrinterKey *r)
10725 {
10726         p->rng_fault_state = true;
10727         return WERR_NOT_SUPPORTED;
10728 }
10729
10730 /****************************************************************
10731  _spoolss_53
10732 ****************************************************************/
10733
10734 WERROR _spoolss_53(pipes_struct *p,
10735                    struct spoolss_53 *r)
10736 {
10737         p->rng_fault_state = true;
10738         return WERR_NOT_SUPPORTED;
10739 }
10740
10741 /****************************************************************
10742  _spoolss_55
10743 ****************************************************************/
10744
10745 WERROR _spoolss_55(pipes_struct *p,
10746                    struct spoolss_55 *r)
10747 {
10748         p->rng_fault_state = true;
10749         return WERR_NOT_SUPPORTED;
10750 }
10751
10752 /****************************************************************
10753  _spoolss_56
10754 ****************************************************************/
10755
10756 WERROR _spoolss_56(pipes_struct *p,
10757                    struct spoolss_56 *r)
10758 {
10759         p->rng_fault_state = true;
10760         return WERR_NOT_SUPPORTED;
10761 }
10762
10763 /****************************************************************
10764  _spoolss_57
10765 ****************************************************************/
10766
10767 WERROR _spoolss_57(pipes_struct *p,
10768                    struct spoolss_57 *r)
10769 {
10770         p->rng_fault_state = true;
10771         return WERR_NOT_SUPPORTED;
10772 }
10773
10774 /****************************************************************
10775  _spoolss_5a
10776 ****************************************************************/
10777
10778 WERROR _spoolss_5a(pipes_struct *p,
10779                    struct spoolss_5a *r)
10780 {
10781         p->rng_fault_state = true;
10782         return WERR_NOT_SUPPORTED;
10783 }
10784
10785 /****************************************************************
10786  _spoolss_5b
10787 ****************************************************************/
10788
10789 WERROR _spoolss_5b(pipes_struct *p,
10790                    struct spoolss_5b *r)
10791 {
10792         p->rng_fault_state = true;
10793         return WERR_NOT_SUPPORTED;
10794 }
10795
10796 /****************************************************************
10797  _spoolss_5c
10798 ****************************************************************/
10799
10800 WERROR _spoolss_5c(pipes_struct *p,
10801                    struct spoolss_5c *r)
10802 {
10803         p->rng_fault_state = true;
10804         return WERR_NOT_SUPPORTED;
10805 }
10806
10807 /****************************************************************
10808  _spoolss_5d
10809 ****************************************************************/
10810
10811 WERROR _spoolss_5d(pipes_struct *p,
10812                    struct spoolss_5d *r)
10813 {
10814         p->rng_fault_state = true;
10815         return WERR_NOT_SUPPORTED;
10816 }
10817
10818 /****************************************************************
10819  _spoolss_5e
10820 ****************************************************************/
10821
10822 WERROR _spoolss_5e(pipes_struct *p,
10823                    struct spoolss_5e *r)
10824 {
10825         p->rng_fault_state = true;
10826         return WERR_NOT_SUPPORTED;
10827 }
10828
10829 /****************************************************************
10830  _spoolss_5f
10831 ****************************************************************/
10832
10833 WERROR _spoolss_5f(pipes_struct *p,
10834                    struct spoolss_5f *r)
10835 {
10836         p->rng_fault_state = true;
10837         return WERR_NOT_SUPPORTED;
10838 }
10839