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