samba-spoolss: use spoolss_StringArray2 in spoolss_EnumPrinterKey.
[Samba/gbeck.git] / source3 / rpc_server / srv_spoolss_nt.c
blob1dfae32d07683056ab758ec52b88688feafade16
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 * Copyright (C) Guenther Deschner 2009.
12 * This program is free software; you can redistribute it and/or modify
13 * it under the terms of the GNU General Public License as published by
14 * the Free Software Foundation; either version 3 of the License, or
15 * (at your option) any later version.
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, see <http://www.gnu.org/licenses/>.
26 /* Since the SPOOLSS rpc routines are basically DOS 16-bit calls wrapped
27 up, all the errors returned are DOS errors, not NT status codes. */
29 #include "includes.h"
31 /* macros stolen from s4 spoolss server */
32 #define SPOOLSS_BUFFER_UNION(fn,ic,info,level) \
33 ((info)?ndr_size_##fn(info, level, ic, 0):0)
35 #define SPOOLSS_BUFFER_UNION_ARRAY(mem_ctx,fn,ic,info,level,count) \
36 ((info)?ndr_size_##fn##_info(mem_ctx, ic, level, count, info):0)
38 #define SPOOLSS_BUFFER_ARRAY(mem_ctx,fn,ic,info,count) \
39 ((info)?ndr_size_##fn##_info(mem_ctx, ic, count, info):0)
41 #define SPOOLSS_BUFFER_OK(val_true,val_false) ((r->in.offered >= *r->out.needed)?val_true:val_false)
44 extern userdom_struct current_user_info;
46 #undef DBGC_CLASS
47 #define DBGC_CLASS DBGC_RPC_SRV
49 #ifndef MAX_OPEN_PRINTER_EXS
50 #define MAX_OPEN_PRINTER_EXS 50
51 #endif
53 #define MAGIC_DISPLAY_FREQUENCY 0xfade2bad
54 #define PHANTOM_DEVMODE_KEY "_p_f_a_n_t_0_m_"
56 static Printer_entry *printers_list;
58 typedef struct _counter_printer_0 {
59 struct _counter_printer_0 *next;
60 struct _counter_printer_0 *prev;
62 int snum;
63 uint32_t counter;
64 } counter_printer_0;
66 static counter_printer_0 *counter_list;
68 static struct rpc_pipe_client *notify_cli_pipe; /* print notify back-channel pipe handle*/
69 static uint32_t smb_connections = 0;
72 /* in printing/nt_printing.c */
74 extern struct standard_mapping printer_std_mapping, printserver_std_mapping;
76 /* API table for Xcv Monitor functions */
78 struct xcv_api_table {
79 const char *name;
80 WERROR(*fn) (TALLOC_CTX *mem_ctx, NT_USER_TOKEN *token, DATA_BLOB *in, DATA_BLOB *out, uint32_t *needed);
83 /********************************************************************
84 * Canonicalize servername.
85 ********************************************************************/
87 static const char *canon_servername(const char *servername)
89 const char *pservername = servername;
90 while (*pservername == '\\') {
91 pservername++;
93 return pservername;
96 /* translate between internal status numbers and NT status numbers */
97 static int nt_printj_status(int v)
99 switch (v) {
100 case LPQ_QUEUED:
101 return 0;
102 case LPQ_PAUSED:
103 return JOB_STATUS_PAUSED;
104 case LPQ_SPOOLING:
105 return JOB_STATUS_SPOOLING;
106 case LPQ_PRINTING:
107 return JOB_STATUS_PRINTING;
108 case LPQ_ERROR:
109 return JOB_STATUS_ERROR;
110 case LPQ_DELETING:
111 return JOB_STATUS_DELETING;
112 case LPQ_OFFLINE:
113 return JOB_STATUS_OFFLINE;
114 case LPQ_PAPEROUT:
115 return JOB_STATUS_PAPEROUT;
116 case LPQ_PRINTED:
117 return JOB_STATUS_PRINTED;
118 case LPQ_DELETED:
119 return JOB_STATUS_DELETED;
120 case LPQ_BLOCKED:
121 return JOB_STATUS_BLOCKED_DEVQ;
122 case LPQ_USER_INTERVENTION:
123 return JOB_STATUS_USER_INTERVENTION;
125 return 0;
128 static int nt_printq_status(int v)
130 switch (v) {
131 case LPQ_PAUSED:
132 return PRINTER_STATUS_PAUSED;
133 case LPQ_QUEUED:
134 case LPQ_SPOOLING:
135 case LPQ_PRINTING:
136 return 0;
138 return 0;
141 /***************************************************************************
142 Disconnect from the client
143 ****************************************************************************/
145 static void srv_spoolss_replycloseprinter(int snum, struct policy_handle *handle)
147 WERROR result;
148 NTSTATUS status;
151 * Tell the specific printing tdb we no longer want messages for this printer
152 * by deregistering our PID.
155 if (!print_notify_deregister_pid(snum))
156 DEBUG(0,("print_notify_register_pid: Failed to register our pid for printer %s\n", lp_const_servicename(snum) ));
158 /* weird if the test succeds !!! */
159 if (smb_connections==0) {
160 DEBUG(0,("srv_spoolss_replycloseprinter:Trying to close non-existant notify backchannel !\n"));
161 return;
164 status = rpccli_spoolss_ReplyClosePrinter(notify_cli_pipe, talloc_tos(),
165 handle,
166 &result);
167 if (!NT_STATUS_IS_OK(status) || !W_ERROR_IS_OK(result))
168 DEBUG(0,("srv_spoolss_replycloseprinter: reply_close_printer failed [%s].\n",
169 win_errstr(result)));
171 /* if it's the last connection, deconnect the IPC$ share */
172 if (smb_connections==1) {
174 cli_shutdown( rpc_pipe_np_smb_conn(notify_cli_pipe) );
175 notify_cli_pipe = NULL; /* The above call shuts downn the pipe also. */
177 messaging_deregister(smbd_messaging_context(),
178 MSG_PRINTER_NOTIFY2, NULL);
180 /* Tell the connections db we're no longer interested in
181 * printer notify messages. */
183 register_message_flags(false, FLAG_MSG_PRINT_NOTIFY);
186 smb_connections--;
189 /****************************************************************************
190 Functions to free a printer entry datastruct.
191 ****************************************************************************/
193 static int printer_entry_destructor(Printer_entry *Printer)
195 if (Printer->notify.client_connected == true) {
196 int snum = -1;
198 if ( Printer->printer_type == SPLHND_SERVER) {
199 snum = -1;
200 srv_spoolss_replycloseprinter(snum, &Printer->notify.client_hnd);
201 } else if (Printer->printer_type == SPLHND_PRINTER) {
202 snum = print_queue_snum(Printer->sharename);
203 if (snum != -1)
204 srv_spoolss_replycloseprinter(snum,
205 &Printer->notify.client_hnd);
209 Printer->notify.flags=0;
210 Printer->notify.options=0;
211 Printer->notify.localmachine[0]='\0';
212 Printer->notify.printerlocal=0;
213 TALLOC_FREE(Printer->notify.option);
214 Printer->notify.client_connected = false;
216 free_nt_devicemode( &Printer->nt_devmode );
217 free_a_printer( &Printer->printer_info, 2 );
219 /* Remove from the internal list. */
220 DLIST_REMOVE(printers_list, Printer);
221 return 0;
224 /****************************************************************************
225 find printer index by handle
226 ****************************************************************************/
228 static Printer_entry *find_printer_index_by_hnd(pipes_struct *p,
229 struct policy_handle *hnd)
231 Printer_entry *find_printer = NULL;
233 if(!find_policy_by_hnd(p,hnd,(void **)(void *)&find_printer)) {
234 DEBUG(2,("find_printer_index_by_hnd: Printer handle not found: "));
235 return NULL;
238 return find_printer;
241 /****************************************************************************
242 Close printer index by handle.
243 ****************************************************************************/
245 static bool close_printer_handle(pipes_struct *p, struct policy_handle *hnd)
247 Printer_entry *Printer = find_printer_index_by_hnd(p, hnd);
249 if (!Printer) {
250 DEBUG(2,("close_printer_handle: Invalid handle (%s:%u:%u)\n",
251 OUR_HANDLE(hnd)));
252 return false;
255 close_policy_hnd(p, hnd);
257 return true;
260 /****************************************************************************
261 Delete a printer given a handle.
262 ****************************************************************************/
264 WERROR delete_printer_hook(TALLOC_CTX *ctx, NT_USER_TOKEN *token, const char *sharename )
266 char *cmd = lp_deleteprinter_cmd();
267 char *command = NULL;
268 int ret;
269 SE_PRIV se_printop = SE_PRINT_OPERATOR;
270 bool is_print_op = false;
272 /* can't fail if we don't try */
274 if ( !*cmd )
275 return WERR_OK;
277 command = talloc_asprintf(ctx,
278 "%s \"%s\"",
279 cmd, sharename);
280 if (!command) {
281 return WERR_NOMEM;
283 if ( token )
284 is_print_op = user_has_privileges( token, &se_printop );
286 DEBUG(10,("Running [%s]\n", command));
288 /********** BEGIN SePrintOperatorPrivlege BLOCK **********/
290 if ( is_print_op )
291 become_root();
293 if ( (ret = smbrun(command, NULL)) == 0 ) {
294 /* Tell everyone we updated smb.conf. */
295 message_send_all(smbd_messaging_context(),
296 MSG_SMB_CONF_UPDATED, NULL, 0, NULL);
299 if ( is_print_op )
300 unbecome_root();
302 /********** END SePrintOperatorPrivlege BLOCK **********/
304 DEBUGADD(10,("returned [%d]\n", ret));
306 TALLOC_FREE(command);
308 if (ret != 0)
309 return WERR_BADFID; /* What to return here? */
311 /* go ahead and re-read the services immediately */
312 become_root();
313 reload_services(false);
314 unbecome_root();
316 if ( lp_servicenumber( sharename ) < 0 )
317 return WERR_ACCESS_DENIED;
319 return WERR_OK;
322 /****************************************************************************
323 Delete a printer given a handle.
324 ****************************************************************************/
326 static WERROR delete_printer_handle(pipes_struct *p, struct policy_handle *hnd)
328 Printer_entry *Printer = find_printer_index_by_hnd(p, hnd);
330 if (!Printer) {
331 DEBUG(2,("delete_printer_handle: Invalid handle (%s:%u:%u)\n",
332 OUR_HANDLE(hnd)));
333 return WERR_BADFID;
337 * It turns out that Windows allows delete printer on a handle
338 * opened by an admin user, then used on a pipe handle created
339 * by an anonymous user..... but they're working on security.... riiight !
340 * JRA.
343 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
344 DEBUG(3, ("delete_printer_handle: denied by handle\n"));
345 return WERR_ACCESS_DENIED;
348 /* this does not need a become root since the access check has been
349 done on the handle already */
351 if (del_a_printer( Printer->sharename ) != 0) {
352 DEBUG(3,("Error deleting printer %s\n", Printer->sharename));
353 return WERR_BADFID;
356 return delete_printer_hook(p->mem_ctx, p->server_info->ptok,
357 Printer->sharename );
360 /****************************************************************************
361 Return the snum of a printer corresponding to an handle.
362 ****************************************************************************/
364 static bool get_printer_snum(pipes_struct *p, struct policy_handle *hnd,
365 int *number, struct share_params **params)
367 Printer_entry *Printer = find_printer_index_by_hnd(p, hnd);
369 if (!Printer) {
370 DEBUG(2,("get_printer_snum: Invalid handle (%s:%u:%u)\n",
371 OUR_HANDLE(hnd)));
372 return false;
375 switch (Printer->printer_type) {
376 case SPLHND_PRINTER:
377 DEBUG(4,("short name:%s\n", Printer->sharename));
378 *number = print_queue_snum(Printer->sharename);
379 return (*number != -1);
380 case SPLHND_SERVER:
381 return false;
382 default:
383 return false;
387 /****************************************************************************
388 Set printer handle type.
389 Check if it's \\server or \\server\printer
390 ****************************************************************************/
392 static bool set_printer_hnd_printertype(Printer_entry *Printer, const char *handlename)
394 DEBUG(3,("Setting printer type=%s\n", handlename));
396 if ( strlen(handlename) < 3 ) {
397 DEBUGADD(4,("A print server must have at least 1 char ! %s\n", handlename));
398 return false;
401 /* it's a print server */
402 if (*handlename=='\\' && *(handlename+1)=='\\' && !strchr_m(handlename+2, '\\')) {
403 DEBUGADD(4,("Printer is a print server\n"));
404 Printer->printer_type = SPLHND_SERVER;
406 /* it's a printer (set_printer_hnd_name() will handle port monitors */
407 else {
408 DEBUGADD(4,("Printer is a printer\n"));
409 Printer->printer_type = SPLHND_PRINTER;
412 return true;
415 /****************************************************************************
416 Set printer handle name.. Accept names like \\server, \\server\printer,
417 \\server\SHARE, & "\\server\,XcvMonitor Standard TCP/IP Port" See
418 the MSDN docs regarding OpenPrinter() for details on the XcvData() and
419 XcvDataPort() interface.
420 ****************************************************************************/
422 static bool set_printer_hnd_name(Printer_entry *Printer, const char *handlename)
424 int snum;
425 int n_services=lp_numservices();
426 char *aprinter, *printername;
427 const char *servername;
428 fstring sname;
429 bool found = false;
430 NT_PRINTER_INFO_LEVEL *printer = NULL;
431 WERROR result;
433 DEBUG(4,("Setting printer name=%s (len=%lu)\n", handlename,
434 (unsigned long)strlen(handlename)));
436 aprinter = CONST_DISCARD(char *, handlename);
437 if ( *handlename == '\\' ) {
438 servername = canon_servername(handlename);
439 if ( (aprinter = strchr_m( servername, '\\' )) != NULL ) {
440 *aprinter = '\0';
441 aprinter++;
443 } else {
444 servername = global_myname();
447 /* save the servername to fill in replies on this handle */
449 if ( !is_myname_or_ipaddr( servername ) )
450 return false;
452 fstrcpy( Printer->servername, servername );
454 if ( Printer->printer_type == SPLHND_SERVER )
455 return true;
457 if ( Printer->printer_type != SPLHND_PRINTER )
458 return false;
460 DEBUGADD(5, ("searching for [%s]\n", aprinter ));
462 /* check for the Port Monitor Interface */
464 if ( strequal( aprinter, SPL_XCV_MONITOR_TCPMON ) ) {
465 Printer->printer_type = SPLHND_PORTMON_TCP;
466 fstrcpy(sname, SPL_XCV_MONITOR_TCPMON);
467 found = true;
469 else if ( strequal( aprinter, SPL_XCV_MONITOR_LOCALMON ) ) {
470 Printer->printer_type = SPLHND_PORTMON_LOCAL;
471 fstrcpy(sname, SPL_XCV_MONITOR_LOCALMON);
472 found = true;
475 /* Search all sharenames first as this is easier than pulling
476 the printer_info_2 off of disk. Don't use find_service() since
477 that calls out to map_username() */
479 /* do another loop to look for printernames */
481 for (snum=0; !found && snum<n_services; snum++) {
483 /* no point going on if this is not a printer */
485 if ( !(lp_snum_ok(snum) && lp_print_ok(snum)) )
486 continue;
488 fstrcpy(sname, lp_servicename(snum));
489 if ( strequal( aprinter, sname ) ) {
490 found = true;
491 break;
494 /* no point looking up the printer object if
495 we aren't allowing printername != sharename */
497 if ( lp_force_printername(snum) )
498 continue;
500 fstrcpy(sname, lp_servicename(snum));
502 printer = NULL;
504 /* This call doesn't fill in the location or comment from
505 * a CUPS server for efficiency with large numbers of printers.
506 * JRA.
509 result = get_a_printer_search( NULL, &printer, 2, sname );
510 if ( !W_ERROR_IS_OK(result) ) {
511 DEBUG(0,("set_printer_hnd_name: failed to lookup printer [%s] -- result [%s]\n",
512 sname, win_errstr(result)));
513 continue;
516 /* printername is always returned as \\server\printername */
517 if ( !(printername = strchr_m(&printer->info_2->printername[2], '\\')) ) {
518 DEBUG(0,("set_printer_hnd_name: info2->printername in wrong format! [%s]\n",
519 printer->info_2->printername));
520 free_a_printer( &printer, 2);
521 continue;
524 printername++;
526 if ( strequal(printername, aprinter) ) {
527 free_a_printer( &printer, 2);
528 found = true;
529 break;
532 DEBUGADD(10, ("printername: %s\n", printername));
534 free_a_printer( &printer, 2);
537 free_a_printer( &printer, 2);
539 if ( !found ) {
540 DEBUGADD(4,("Printer not found\n"));
541 return false;
544 DEBUGADD(4,("set_printer_hnd_name: Printer found: %s -> %s\n", aprinter, sname));
546 fstrcpy(Printer->sharename, sname);
548 return true;
551 /****************************************************************************
552 Find first available printer slot. creates a printer handle for you.
553 ****************************************************************************/
555 static bool open_printer_hnd(pipes_struct *p, struct policy_handle *hnd,
556 const char *name, uint32_t access_granted)
558 Printer_entry *new_printer;
560 DEBUG(10,("open_printer_hnd: name [%s]\n", name));
562 new_printer = TALLOC_ZERO_P(NULL, Printer_entry);
563 if (new_printer == NULL) {
564 return false;
566 talloc_set_destructor(new_printer, printer_entry_destructor);
568 if (!create_policy_hnd(p, hnd, new_printer)) {
569 TALLOC_FREE(new_printer);
570 return false;
573 /* Add to the internal list. */
574 DLIST_ADD(printers_list, new_printer);
576 new_printer->notify.option=NULL;
578 if (!set_printer_hnd_printertype(new_printer, name)) {
579 close_printer_handle(p, hnd);
580 return false;
583 if (!set_printer_hnd_name(new_printer, name)) {
584 close_printer_handle(p, hnd);
585 return false;
588 new_printer->access_granted = access_granted;
590 DEBUG(5, ("%d printer handles active\n", (int)p->pipe_handles->count ));
592 return true;
595 /***************************************************************************
596 check to see if the client motify handle is monitoring the notification
597 given by (notify_type, notify_field).
598 **************************************************************************/
600 static bool is_monitoring_event_flags(uint32_t flags, uint16_t notify_type,
601 uint16_t notify_field)
603 return true;
606 static bool is_monitoring_event(Printer_entry *p, uint16_t notify_type,
607 uint16_t notify_field)
609 struct spoolss_NotifyOption *option = p->notify.option;
610 uint32_t i, j;
613 * Flags should always be zero when the change notify
614 * is registered by the client's spooler. A user Win32 app
615 * might use the flags though instead of the NOTIFY_OPTION_INFO
616 * --jerry
619 if (!option) {
620 return false;
623 if (p->notify.flags)
624 return is_monitoring_event_flags(
625 p->notify.flags, notify_type, notify_field);
627 for (i = 0; i < option->count; i++) {
629 /* Check match for notify_type */
631 if (option->types[i].type != notify_type)
632 continue;
634 /* Check match for field */
636 for (j = 0; j < option->types[i].count; j++) {
637 if (option->types[i].fields[j].field == notify_field) {
638 return true;
643 DEBUG(10, ("Open handle for \\\\%s\\%s is not monitoring 0x%02x/0x%02x\n",
644 p->servername, p->sharename, notify_type, notify_field));
646 return false;
649 #define SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(_data, _integer) \
650 _data->data.integer[0] = _integer; \
651 _data->data.integer[1] = 0;
654 #define SETUP_SPOOLSS_NOTIFY_DATA_STRING(_data, _p) \
655 _data->data.string.string = talloc_strdup(mem_ctx, _p); \
656 if (!_data->data.string.string) {\
657 _data->data.string.size = 0; \
659 _data->data.string.size = strlen_m_term(_p) * 2;
661 #define SETUP_SPOOLSS_NOTIFY_DATA_DEVMODE(_data, _devmode) \
662 _data->data.devmode.devmode = _devmode;
664 #define SETUP_SPOOLSS_NOTIFY_DATA_SECDESC(_data, _size, _sd) \
665 _data->data.sd.sd = dup_sec_desc(mem_ctx, _sd); \
666 if (!_data->data.sd.sd) { \
667 _data->data.sd.sd_size = 0; \
669 _data->data.sd.sd_size = _size;
671 static void init_systemtime_buffer(TALLOC_CTX *mem_ctx,
672 struct tm *t,
673 const char **pp,
674 uint32_t *plen)
676 struct spoolss_Time st;
677 uint32_t len = 16;
678 char *p;
680 if (!init_systemtime(&st, t)) {
681 return;
684 p = talloc_array(mem_ctx, char, len);
685 if (!p) {
686 return;
690 * Systemtime must be linearized as a set of UINT16's.
691 * Fix from Benjamin (Bj) Kuit bj@it.uts.edu.au
694 SSVAL(p, 0, st.year);
695 SSVAL(p, 2, st.month);
696 SSVAL(p, 4, st.day_of_week);
697 SSVAL(p, 6, st.day);
698 SSVAL(p, 8, st.hour);
699 SSVAL(p, 10, st.minute);
700 SSVAL(p, 12, st.second);
701 SSVAL(p, 14, st.millisecond);
703 *pp = p;
704 *plen = len;
707 /* Convert a notification message to a struct spoolss_Notify */
709 static void notify_one_value(struct spoolss_notify_msg *msg,
710 struct spoolss_Notify *data,
711 TALLOC_CTX *mem_ctx)
713 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, msg->notify.value[0]);
716 static void notify_string(struct spoolss_notify_msg *msg,
717 struct spoolss_Notify *data,
718 TALLOC_CTX *mem_ctx)
720 /* The length of the message includes the trailing \0 */
722 data->data.string.size = msg->len * 2;
723 data->data.string.string = talloc_strdup(mem_ctx, msg->notify.data);
724 if (!data->data.string.string) {
725 data->data.string.size = 0;
726 return;
730 static void notify_system_time(struct spoolss_notify_msg *msg,
731 struct spoolss_Notify *data,
732 TALLOC_CTX *mem_ctx)
734 data->data.string.string = NULL;
735 data->data.string.size = 0;
737 if (msg->len != sizeof(time_t)) {
738 DEBUG(5, ("notify_system_time: received wrong sized message (%d)\n",
739 msg->len));
740 return;
743 init_systemtime_buffer(mem_ctx, gmtime((time_t *)msg->notify.data),
744 &data->data.string.string,
745 &data->data.string.size);
748 struct notify2_message_table {
749 const char *name;
750 void (*fn)(struct spoolss_notify_msg *msg,
751 struct spoolss_Notify *data, TALLOC_CTX *mem_ctx);
754 static struct notify2_message_table printer_notify_table[] = {
755 /* 0x00 */ { "PRINTER_NOTIFY_FIELD_SERVER_NAME", notify_string },
756 /* 0x01 */ { "PRINTER_NOTIFY_FIELD_PRINTER_NAME", notify_string },
757 /* 0x02 */ { "PRINTER_NOTIFY_FIELD_SHARE_NAME", notify_string },
758 /* 0x03 */ { "PRINTER_NOTIFY_FIELD_PORT_NAME", notify_string },
759 /* 0x04 */ { "PRINTER_NOTIFY_FIELD_DRIVER_NAME", notify_string },
760 /* 0x05 */ { "PRINTER_NOTIFY_FIELD_COMMENT", notify_string },
761 /* 0x06 */ { "PRINTER_NOTIFY_FIELD_LOCATION", notify_string },
762 /* 0x07 */ { "PRINTER_NOTIFY_FIELD_DEVMODE", NULL },
763 /* 0x08 */ { "PRINTER_NOTIFY_FIELD_SEPFILE", notify_string },
764 /* 0x09 */ { "PRINTER_NOTIFY_FIELD_PRINT_PROCESSOR", notify_string },
765 /* 0x0a */ { "PRINTER_NOTIFY_FIELD_PARAMETERS", NULL },
766 /* 0x0b */ { "PRINTER_NOTIFY_FIELD_DATATYPE", notify_string },
767 /* 0x0c */ { "PRINTER_NOTIFY_FIELD_SECURITY_DESCRIPTOR", NULL },
768 /* 0x0d */ { "PRINTER_NOTIFY_FIELD_ATTRIBUTES", notify_one_value },
769 /* 0x0e */ { "PRINTER_NOTIFY_FIELD_PRIORITY", notify_one_value },
770 /* 0x0f */ { "PRINTER_NOTIFY_FIELD_DEFAULT_PRIORITY", NULL },
771 /* 0x10 */ { "PRINTER_NOTIFY_FIELD_START_TIME", NULL },
772 /* 0x11 */ { "PRINTER_NOTIFY_FIELD_UNTIL_TIME", NULL },
773 /* 0x12 */ { "PRINTER_NOTIFY_FIELD_STATUS", notify_one_value },
776 static struct notify2_message_table job_notify_table[] = {
777 /* 0x00 */ { "JOB_NOTIFY_FIELD_PRINTER_NAME", NULL },
778 /* 0x01 */ { "JOB_NOTIFY_FIELD_MACHINE_NAME", NULL },
779 /* 0x02 */ { "JOB_NOTIFY_FIELD_PORT_NAME", NULL },
780 /* 0x03 */ { "JOB_NOTIFY_FIELD_USER_NAME", notify_string },
781 /* 0x04 */ { "JOB_NOTIFY_FIELD_NOTIFY_NAME", NULL },
782 /* 0x05 */ { "JOB_NOTIFY_FIELD_DATATYPE", NULL },
783 /* 0x06 */ { "JOB_NOTIFY_FIELD_PRINT_PROCESSOR", NULL },
784 /* 0x07 */ { "JOB_NOTIFY_FIELD_PARAMETERS", NULL },
785 /* 0x08 */ { "JOB_NOTIFY_FIELD_DRIVER_NAME", NULL },
786 /* 0x09 */ { "JOB_NOTIFY_FIELD_DEVMODE", NULL },
787 /* 0x0a */ { "JOB_NOTIFY_FIELD_STATUS", notify_one_value },
788 /* 0x0b */ { "JOB_NOTIFY_FIELD_STATUS_STRING", NULL },
789 /* 0x0c */ { "JOB_NOTIFY_FIELD_SECURITY_DESCRIPTOR", NULL },
790 /* 0x0d */ { "JOB_NOTIFY_FIELD_DOCUMENT", notify_string },
791 /* 0x0e */ { "JOB_NOTIFY_FIELD_PRIORITY", NULL },
792 /* 0x0f */ { "JOB_NOTIFY_FIELD_POSITION", NULL },
793 /* 0x10 */ { "JOB_NOTIFY_FIELD_SUBMITTED", notify_system_time },
794 /* 0x11 */ { "JOB_NOTIFY_FIELD_START_TIME", NULL },
795 /* 0x12 */ { "JOB_NOTIFY_FIELD_UNTIL_TIME", NULL },
796 /* 0x13 */ { "JOB_NOTIFY_FIELD_TIME", NULL },
797 /* 0x14 */ { "JOB_NOTIFY_FIELD_TOTAL_PAGES", notify_one_value },
798 /* 0x15 */ { "JOB_NOTIFY_FIELD_PAGES_PRINTED", NULL },
799 /* 0x16 */ { "JOB_NOTIFY_FIELD_TOTAL_BYTES", notify_one_value },
800 /* 0x17 */ { "JOB_NOTIFY_FIELD_BYTES_PRINTED", NULL },
804 /***********************************************************************
805 Allocate talloc context for container object
806 **********************************************************************/
808 static void notify_msg_ctr_init( SPOOLSS_NOTIFY_MSG_CTR *ctr )
810 if ( !ctr )
811 return;
813 ctr->ctx = talloc_init("notify_msg_ctr_init %p", ctr);
815 return;
818 /***********************************************************************
819 release all allocated memory and zero out structure
820 **********************************************************************/
822 static void notify_msg_ctr_destroy( SPOOLSS_NOTIFY_MSG_CTR *ctr )
824 if ( !ctr )
825 return;
827 if ( ctr->ctx )
828 talloc_destroy(ctr->ctx);
830 ZERO_STRUCTP(ctr);
832 return;
835 /***********************************************************************
836 **********************************************************************/
838 static TALLOC_CTX* notify_ctr_getctx( SPOOLSS_NOTIFY_MSG_CTR *ctr )
840 if ( !ctr )
841 return NULL;
843 return ctr->ctx;
846 /***********************************************************************
847 **********************************************************************/
849 static SPOOLSS_NOTIFY_MSG_GROUP* notify_ctr_getgroup( SPOOLSS_NOTIFY_MSG_CTR *ctr, uint32_t idx )
851 if ( !ctr || !ctr->msg_groups )
852 return NULL;
854 if ( idx >= ctr->num_groups )
855 return NULL;
857 return &ctr->msg_groups[idx];
861 /***********************************************************************
862 How many groups of change messages do we have ?
863 **********************************************************************/
865 static int notify_msg_ctr_numgroups( SPOOLSS_NOTIFY_MSG_CTR *ctr )
867 if ( !ctr )
868 return 0;
870 return ctr->num_groups;
873 /***********************************************************************
874 Add a SPOOLSS_NOTIFY_MSG_CTR to the correct group
875 **********************************************************************/
877 static int notify_msg_ctr_addmsg( SPOOLSS_NOTIFY_MSG_CTR *ctr, SPOOLSS_NOTIFY_MSG *msg )
879 SPOOLSS_NOTIFY_MSG_GROUP *groups = NULL;
880 SPOOLSS_NOTIFY_MSG_GROUP *msg_grp = NULL;
881 SPOOLSS_NOTIFY_MSG *msg_list = NULL;
882 int i, new_slot;
884 if ( !ctr || !msg )
885 return 0;
887 /* loop over all groups looking for a matching printer name */
889 for ( i=0; i<ctr->num_groups; i++ ) {
890 if ( strcmp(ctr->msg_groups[i].printername, msg->printer) == 0 )
891 break;
894 /* add a new group? */
896 if ( i == ctr->num_groups ) {
897 ctr->num_groups++;
899 if ( !(groups = TALLOC_REALLOC_ARRAY( ctr->ctx, ctr->msg_groups, SPOOLSS_NOTIFY_MSG_GROUP, ctr->num_groups)) ) {
900 DEBUG(0,("notify_msg_ctr_addmsg: talloc_realloc() failed!\n"));
901 return 0;
903 ctr->msg_groups = groups;
905 /* clear the new entry and set the printer name */
907 ZERO_STRUCT( ctr->msg_groups[ctr->num_groups-1] );
908 fstrcpy( ctr->msg_groups[ctr->num_groups-1].printername, msg->printer );
911 /* add the change messages; 'i' is the correct index now regardless */
913 msg_grp = &ctr->msg_groups[i];
915 msg_grp->num_msgs++;
917 if ( !(msg_list = TALLOC_REALLOC_ARRAY( ctr->ctx, msg_grp->msgs, SPOOLSS_NOTIFY_MSG, msg_grp->num_msgs )) ) {
918 DEBUG(0,("notify_msg_ctr_addmsg: talloc_realloc() failed for new message [%d]!\n", msg_grp->num_msgs));
919 return 0;
921 msg_grp->msgs = msg_list;
923 new_slot = msg_grp->num_msgs-1;
924 memcpy( &msg_grp->msgs[new_slot], msg, sizeof(SPOOLSS_NOTIFY_MSG) );
926 /* need to allocate own copy of data */
928 if ( msg->len != 0 )
929 msg_grp->msgs[new_slot].notify.data = (char *)
930 TALLOC_MEMDUP( ctr->ctx, msg->notify.data, msg->len );
932 return ctr->num_groups;
935 /***********************************************************************
936 Send a change notication message on all handles which have a call
937 back registered
938 **********************************************************************/
940 static void send_notify2_changes( SPOOLSS_NOTIFY_MSG_CTR *ctr, uint32_t idx )
942 Printer_entry *p;
943 TALLOC_CTX *mem_ctx = notify_ctr_getctx( ctr );
944 SPOOLSS_NOTIFY_MSG_GROUP *msg_group = notify_ctr_getgroup( ctr, idx );
945 SPOOLSS_NOTIFY_MSG *messages;
946 int sending_msg_count;
948 if ( !msg_group ) {
949 DEBUG(5,("send_notify2_changes() called with no msg group!\n"));
950 return;
953 messages = msg_group->msgs;
955 if ( !messages ) {
956 DEBUG(5,("send_notify2_changes() called with no messages!\n"));
957 return;
960 DEBUG(8,("send_notify2_changes: Enter...[%s]\n", msg_group->printername));
962 /* loop over all printers */
964 for (p = printers_list; p; p = p->next) {
965 struct spoolss_Notify *notifies;
966 uint32_t count = 0;
967 uint32_t id;
968 int i;
970 /* Is there notification on this handle? */
972 if ( !p->notify.client_connected )
973 continue;
975 DEBUG(10,("Client connected! [\\\\%s\\%s]\n", p->servername, p->sharename));
977 /* For this printer? Print servers always receive
978 notifications. */
980 if ( ( p->printer_type == SPLHND_PRINTER ) &&
981 ( !strequal(msg_group->printername, p->sharename) ) )
982 continue;
984 DEBUG(10,("Our printer\n"));
986 /* allocate the max entries possible */
988 notifies = TALLOC_ZERO_ARRAY(mem_ctx, struct spoolss_Notify, msg_group->num_msgs);
989 if (!notifies) {
990 return;
993 /* build the array of change notifications */
995 sending_msg_count = 0;
997 for ( i=0; i<msg_group->num_msgs; i++ ) {
998 SPOOLSS_NOTIFY_MSG *msg = &messages[i];
1000 /* Are we monitoring this event? */
1002 if (!is_monitoring_event(p, msg->type, msg->field))
1003 continue;
1005 sending_msg_count++;
1008 DEBUG(10,("process_notify2_message: Sending message type [0x%x] field [0x%2x] for printer [%s]\n",
1009 msg->type, msg->field, p->sharename));
1012 * if the is a printer notification handle and not a job notification
1013 * type, then set the id to 0. Other wise just use what was specified
1014 * in the message.
1016 * When registering change notification on a print server handle
1017 * we always need to send back the id (snum) matching the printer
1018 * for which the change took place. For change notify registered
1019 * on a printer handle, this does not matter and the id should be 0.
1021 * --jerry
1024 if ( ( p->printer_type == SPLHND_PRINTER ) && ( msg->type == PRINTER_NOTIFY_TYPE ) )
1025 id = 0;
1026 else
1027 id = msg->id;
1030 /* Convert unix jobid to smb jobid */
1032 if (msg->flags & SPOOLSS_NOTIFY_MSG_UNIX_JOBID) {
1033 id = sysjob_to_jobid(msg->id);
1035 if (id == -1) {
1036 DEBUG(3, ("no such unix jobid %d\n", msg->id));
1037 goto done;
1041 construct_info_data( &notifies[count], msg->type, msg->field, id );
1043 switch(msg->type) {
1044 case PRINTER_NOTIFY_TYPE:
1045 if ( printer_notify_table[msg->field].fn )
1046 printer_notify_table[msg->field].fn(msg, &notifies[count], mem_ctx);
1047 break;
1049 case JOB_NOTIFY_TYPE:
1050 if ( job_notify_table[msg->field].fn )
1051 job_notify_table[msg->field].fn(msg, &notifies[count], mem_ctx);
1052 break;
1054 default:
1055 DEBUG(5, ("Unknown notification type %d\n", msg->type));
1056 goto done;
1059 count++;
1062 if ( sending_msg_count ) {
1063 NTSTATUS status;
1064 WERROR werr;
1065 union spoolss_ReplyPrinterInfo info;
1066 struct spoolss_NotifyInfo info0;
1067 uint32_t reply_result;
1069 info0.version = 0x2;
1070 info0.flags = count ? 0x00020000 /* ??? */ : PRINTER_NOTIFY_INFO_DISCARDED;
1071 info0.count = count;
1072 info0.notifies = notifies;
1074 info.info0 = &info0;
1076 status = rpccli_spoolss_RouterReplyPrinterEx(notify_cli_pipe, mem_ctx,
1077 &p->notify.client_hnd,
1078 p->notify.change, /* color */
1079 p->notify.flags,
1080 &reply_result,
1081 0, /* reply_type, must be 0 */
1082 info,
1083 &werr);
1084 if (!NT_STATUS_IS_OK(status) || !W_ERROR_IS_OK(werr)) {
1085 DEBUG(1,("RouterReplyPrinterEx to client: %s failed: %s\n",
1086 notify_cli_pipe->srv_name_slash,
1087 win_errstr(werr)));
1089 switch (reply_result) {
1090 case 0:
1091 break;
1092 case PRINTER_NOTIFY_INFO_DISCARDED:
1093 case PRINTER_NOTIFY_INFO_DISCARDNOTED:
1094 case PRINTER_NOTIFY_INFO_COLOR_MISMATCH:
1095 break;
1096 default:
1097 break;
1102 done:
1103 DEBUG(8,("send_notify2_changes: Exit...\n"));
1104 return;
1107 /***********************************************************************
1108 **********************************************************************/
1110 static bool notify2_unpack_msg( SPOOLSS_NOTIFY_MSG *msg, struct timeval *tv, void *buf, size_t len )
1113 uint32_t tv_sec, tv_usec;
1114 size_t offset = 0;
1116 /* Unpack message */
1118 offset += tdb_unpack((uint8_t *)buf + offset, len - offset, "f",
1119 msg->printer);
1121 offset += tdb_unpack((uint8_t *)buf + offset, len - offset, "ddddddd",
1122 &tv_sec, &tv_usec,
1123 &msg->type, &msg->field, &msg->id, &msg->len, &msg->flags);
1125 if (msg->len == 0)
1126 tdb_unpack((uint8_t *)buf + offset, len - offset, "dd",
1127 &msg->notify.value[0], &msg->notify.value[1]);
1128 else
1129 tdb_unpack((uint8_t *)buf + offset, len - offset, "B",
1130 &msg->len, &msg->notify.data);
1132 DEBUG(3, ("notify2_unpack_msg: got NOTIFY2 message for printer %s, jobid %u type %d, field 0x%02x, flags 0x%04x\n",
1133 msg->printer, (unsigned int)msg->id, msg->type, msg->field, msg->flags));
1135 tv->tv_sec = tv_sec;
1136 tv->tv_usec = tv_usec;
1138 if (msg->len == 0)
1139 DEBUG(3, ("notify2_unpack_msg: value1 = %d, value2 = %d\n", msg->notify.value[0],
1140 msg->notify.value[1]));
1141 else
1142 dump_data(3, (uint8_t *)msg->notify.data, msg->len);
1144 return true;
1147 /********************************************************************
1148 Receive a notify2 message list
1149 ********************************************************************/
1151 static void receive_notify2_message_list(struct messaging_context *msg,
1152 void *private_data,
1153 uint32_t msg_type,
1154 struct server_id server_id,
1155 DATA_BLOB *data)
1157 size_t msg_count, i;
1158 char *buf = (char *)data->data;
1159 char *msg_ptr;
1160 size_t msg_len;
1161 SPOOLSS_NOTIFY_MSG notify;
1162 SPOOLSS_NOTIFY_MSG_CTR messages;
1163 int num_groups;
1165 if (data->length < 4) {
1166 DEBUG(0,("receive_notify2_message_list: bad message format (len < 4)!\n"));
1167 return;
1170 msg_count = IVAL(buf, 0);
1171 msg_ptr = buf + 4;
1173 DEBUG(5, ("receive_notify2_message_list: got %lu messages in list\n", (unsigned long)msg_count));
1175 if (msg_count == 0) {
1176 DEBUG(0,("receive_notify2_message_list: bad message format (msg_count == 0) !\n"));
1177 return;
1180 /* initialize the container */
1182 ZERO_STRUCT( messages );
1183 notify_msg_ctr_init( &messages );
1186 * build message groups for each printer identified
1187 * in a change_notify msg. Remember that a PCN message
1188 * includes the handle returned for the srv_spoolss_replyopenprinter()
1189 * call. Therefore messages are grouped according to printer handle.
1192 for ( i=0; i<msg_count; i++ ) {
1193 struct timeval msg_tv;
1195 if (msg_ptr + 4 - buf > data->length) {
1196 DEBUG(0,("receive_notify2_message_list: bad message format (len > buf_size) !\n"));
1197 return;
1200 msg_len = IVAL(msg_ptr,0);
1201 msg_ptr += 4;
1203 if (msg_ptr + msg_len - buf > data->length) {
1204 DEBUG(0,("receive_notify2_message_list: bad message format (bad len) !\n"));
1205 return;
1208 /* unpack messages */
1210 ZERO_STRUCT( notify );
1211 notify2_unpack_msg( &notify, &msg_tv, msg_ptr, msg_len );
1212 msg_ptr += msg_len;
1214 /* add to correct list in container */
1216 notify_msg_ctr_addmsg( &messages, &notify );
1218 /* free memory that might have been allocated by notify2_unpack_msg() */
1220 if ( notify.len != 0 )
1221 SAFE_FREE( notify.notify.data );
1224 /* process each group of messages */
1226 num_groups = notify_msg_ctr_numgroups( &messages );
1227 for ( i=0; i<num_groups; i++ )
1228 send_notify2_changes( &messages, i );
1231 /* cleanup */
1233 DEBUG(10,("receive_notify2_message_list: processed %u messages\n",
1234 (uint32_t)msg_count ));
1236 notify_msg_ctr_destroy( &messages );
1238 return;
1241 /********************************************************************
1242 Send a message to ourself about new driver being installed
1243 so we can upgrade the information for each printer bound to this
1244 driver
1245 ********************************************************************/
1247 static bool srv_spoolss_drv_upgrade_printer(const char *drivername)
1249 int len = strlen(drivername);
1251 if (!len)
1252 return false;
1254 DEBUG(10,("srv_spoolss_drv_upgrade_printer: Sending message about driver upgrade [%s]\n",
1255 drivername));
1257 messaging_send_buf(smbd_messaging_context(), procid_self(),
1258 MSG_PRINTER_DRVUPGRADE,
1259 (uint8_t *)drivername, len+1);
1261 return true;
1264 /**********************************************************************
1265 callback to receive a MSG_PRINTER_DRVUPGRADE message and interate
1266 over all printers, upgrading ones as necessary
1267 **********************************************************************/
1269 void do_drv_upgrade_printer(struct messaging_context *msg,
1270 void *private_data,
1271 uint32_t msg_type,
1272 struct server_id server_id,
1273 DATA_BLOB *data)
1275 fstring drivername;
1276 int snum;
1277 int n_services = lp_numservices();
1278 size_t len;
1280 len = MIN(data->length,sizeof(drivername)-1);
1281 strncpy(drivername, (const char *)data->data, len);
1283 DEBUG(10,("do_drv_upgrade_printer: Got message for new driver [%s]\n", drivername ));
1285 /* Iterate the printer list */
1287 for (snum=0; snum<n_services; snum++)
1289 if (lp_snum_ok(snum) && lp_print_ok(snum) )
1291 WERROR result;
1292 NT_PRINTER_INFO_LEVEL *printer = NULL;
1294 result = get_a_printer(NULL, &printer, 2, lp_const_servicename(snum));
1295 if (!W_ERROR_IS_OK(result))
1296 continue;
1298 if (printer && printer->info_2 && !strcmp(drivername, printer->info_2->drivername))
1300 DEBUG(6,("Updating printer [%s]\n", printer->info_2->printername));
1302 /* all we care about currently is the change_id */
1304 result = mod_a_printer(printer, 2);
1305 if (!W_ERROR_IS_OK(result)) {
1306 DEBUG(3,("do_drv_upgrade_printer: mod_a_printer() failed with status [%s]\n",
1307 win_errstr(result)));
1311 free_a_printer(&printer, 2);
1315 /* all done */
1318 /********************************************************************
1319 Update the cache for all printq's with a registered client
1320 connection
1321 ********************************************************************/
1323 void update_monitored_printq_cache( void )
1325 Printer_entry *printer = printers_list;
1326 int snum;
1328 /* loop through all printers and update the cache where
1329 client_connected == true */
1330 while ( printer )
1332 if ( (printer->printer_type == SPLHND_PRINTER)
1333 && printer->notify.client_connected )
1335 snum = print_queue_snum(printer->sharename);
1336 print_queue_status( snum, NULL, NULL );
1339 printer = printer->next;
1342 return;
1344 /********************************************************************
1345 Send a message to ourself about new driver being installed
1346 so we can upgrade the information for each printer bound to this
1347 driver
1348 ********************************************************************/
1350 static bool srv_spoolss_reset_printerdata(char* drivername)
1352 int len = strlen(drivername);
1354 if (!len)
1355 return false;
1357 DEBUG(10,("srv_spoolss_reset_printerdata: Sending message about resetting printerdata [%s]\n",
1358 drivername));
1360 messaging_send_buf(smbd_messaging_context(), procid_self(),
1361 MSG_PRINTERDATA_INIT_RESET,
1362 (uint8_t *)drivername, len+1);
1364 return true;
1367 /**********************************************************************
1368 callback to receive a MSG_PRINTERDATA_INIT_RESET message and interate
1369 over all printers, resetting printer data as neessary
1370 **********************************************************************/
1372 void reset_all_printerdata(struct messaging_context *msg,
1373 void *private_data,
1374 uint32_t msg_type,
1375 struct server_id server_id,
1376 DATA_BLOB *data)
1378 fstring drivername;
1379 int snum;
1380 int n_services = lp_numservices();
1381 size_t len;
1383 len = MIN( data->length, sizeof(drivername)-1 );
1384 strncpy( drivername, (const char *)data->data, len );
1386 DEBUG(10,("reset_all_printerdata: Got message for new driver [%s]\n", drivername ));
1388 /* Iterate the printer list */
1390 for ( snum=0; snum<n_services; snum++ )
1392 if ( lp_snum_ok(snum) && lp_print_ok(snum) )
1394 WERROR result;
1395 NT_PRINTER_INFO_LEVEL *printer = NULL;
1397 result = get_a_printer( NULL, &printer, 2, lp_const_servicename(snum) );
1398 if ( !W_ERROR_IS_OK(result) )
1399 continue;
1402 * if the printer is bound to the driver,
1403 * then reset to the new driver initdata
1406 if ( printer && printer->info_2 && !strcmp(drivername, printer->info_2->drivername) )
1408 DEBUG(6,("reset_all_printerdata: Updating printer [%s]\n", printer->info_2->printername));
1410 if ( !set_driver_init(printer, 2) ) {
1411 DEBUG(5,("reset_all_printerdata: Error resetting printer data for printer [%s], driver [%s]!\n",
1412 printer->info_2->printername, printer->info_2->drivername));
1415 result = mod_a_printer( printer, 2 );
1416 if ( !W_ERROR_IS_OK(result) ) {
1417 DEBUG(3,("reset_all_printerdata: mod_a_printer() failed! (%s)\n",
1418 get_dos_error_msg(result)));
1422 free_a_printer( &printer, 2 );
1426 /* all done */
1428 return;
1431 /****************************************************************
1432 _spoolss_OpenPrinter
1433 ****************************************************************/
1435 WERROR _spoolss_OpenPrinter(pipes_struct *p,
1436 struct spoolss_OpenPrinter *r)
1438 struct spoolss_OpenPrinterEx e;
1439 WERROR werr;
1441 ZERO_STRUCT(e.in.userlevel);
1443 e.in.printername = r->in.printername;
1444 e.in.datatype = r->in.datatype;
1445 e.in.devmode_ctr = r->in.devmode_ctr;
1446 e.in.access_mask = r->in.access_mask;
1447 e.in.level = 0;
1449 e.out.handle = r->out.handle;
1451 werr = _spoolss_OpenPrinterEx(p, &e);
1453 if (W_ERROR_EQUAL(werr, WERR_INVALID_PARAM)) {
1454 /* OpenPrinterEx returns this for a bad
1455 * printer name. We must return WERR_INVALID_PRINTER_NAME
1456 * instead.
1458 werr = WERR_INVALID_PRINTER_NAME;
1461 return werr;
1464 /********************************************************************
1465 ********************************************************************/
1467 bool convert_devicemode(const char *printername,
1468 const struct spoolss_DeviceMode *devmode,
1469 NT_DEVICEMODE **pp_nt_devmode)
1471 NT_DEVICEMODE *nt_devmode = *pp_nt_devmode;
1474 * Ensure nt_devmode is a valid pointer
1475 * as we will be overwriting it.
1478 if (nt_devmode == NULL) {
1479 DEBUG(5, ("convert_devicemode: allocating a generic devmode\n"));
1480 if ((nt_devmode = construct_nt_devicemode(printername)) == NULL)
1481 return false;
1484 rpcstr_push(nt_devmode->devicename, devmode->devicename, 31, 0);
1485 rpcstr_push(nt_devmode->formname, devmode->formname, 31, 0);
1487 nt_devmode->specversion = devmode->specversion;
1488 nt_devmode->driverversion = devmode->driverversion;
1489 nt_devmode->size = devmode->size;
1490 nt_devmode->fields = devmode->fields;
1491 nt_devmode->orientation = devmode->orientation;
1492 nt_devmode->papersize = devmode->papersize;
1493 nt_devmode->paperlength = devmode->paperlength;
1494 nt_devmode->paperwidth = devmode->paperwidth;
1495 nt_devmode->scale = devmode->scale;
1496 nt_devmode->copies = devmode->copies;
1497 nt_devmode->defaultsource = devmode->defaultsource;
1498 nt_devmode->printquality = devmode->printquality;
1499 nt_devmode->color = devmode->color;
1500 nt_devmode->duplex = devmode->duplex;
1501 nt_devmode->yresolution = devmode->yresolution;
1502 nt_devmode->ttoption = devmode->ttoption;
1503 nt_devmode->collate = devmode->collate;
1505 nt_devmode->logpixels = devmode->logpixels;
1506 nt_devmode->bitsperpel = devmode->bitsperpel;
1507 nt_devmode->pelswidth = devmode->pelswidth;
1508 nt_devmode->pelsheight = devmode->pelsheight;
1509 nt_devmode->displayflags = devmode->displayflags;
1510 nt_devmode->displayfrequency = devmode->displayfrequency;
1511 nt_devmode->icmmethod = devmode->icmmethod;
1512 nt_devmode->icmintent = devmode->icmintent;
1513 nt_devmode->mediatype = devmode->mediatype;
1514 nt_devmode->dithertype = devmode->dithertype;
1515 nt_devmode->reserved1 = devmode->reserved1;
1516 nt_devmode->reserved2 = devmode->reserved2;
1517 nt_devmode->panningwidth = devmode->panningwidth;
1518 nt_devmode->panningheight = devmode->panningheight;
1521 * Only change private and driverextra if the incoming devmode
1522 * has a new one. JRA.
1525 if ((devmode->__driverextra_length != 0) && (devmode->driverextra_data.data != NULL)) {
1526 SAFE_FREE(nt_devmode->nt_dev_private);
1527 nt_devmode->driverextra = devmode->__driverextra_length;
1528 if((nt_devmode->nt_dev_private = SMB_MALLOC_ARRAY(uint8_t, nt_devmode->driverextra)) == NULL)
1529 return false;
1530 memcpy(nt_devmode->nt_dev_private, devmode->driverextra_data.data, nt_devmode->driverextra);
1533 *pp_nt_devmode = nt_devmode;
1535 return true;
1538 /****************************************************************
1539 _spoolss_OpenPrinterEx
1540 ****************************************************************/
1542 WERROR _spoolss_OpenPrinterEx(pipes_struct *p,
1543 struct spoolss_OpenPrinterEx *r)
1545 int snum;
1546 Printer_entry *Printer=NULL;
1548 if (!r->in.printername) {
1549 return WERR_INVALID_PARAM;
1552 /* some sanity check because you can open a printer or a print server */
1553 /* aka: \\server\printer or \\server */
1555 DEBUGADD(3,("checking name: %s\n", r->in.printername));
1557 if (!open_printer_hnd(p, r->out.handle, r->in.printername, 0)) {
1558 ZERO_STRUCTP(r->out.handle);
1559 return WERR_INVALID_PARAM;
1562 Printer = find_printer_index_by_hnd(p, r->out.handle);
1563 if ( !Printer ) {
1564 DEBUG(0,("_spoolss_OpenPrinterEx: logic error. Can't find printer "
1565 "handle we created for printer %s\n", r->in.printername));
1566 close_printer_handle(p, r->out.handle);
1567 ZERO_STRUCTP(r->out.handle);
1568 return WERR_INVALID_PARAM;
1572 * First case: the user is opening the print server:
1574 * Disallow MS AddPrinterWizard if parameter disables it. A Win2k
1575 * client 1st tries an OpenPrinterEx with access==0, MUST be allowed.
1577 * Then both Win2k and WinNT clients try an OpenPrinterEx with
1578 * SERVER_ALL_ACCESS, which we allow only if the user is root (uid=0)
1579 * or if the user is listed in the smb.conf printer admin parameter.
1581 * Then they try OpenPrinterEx with SERVER_READ which we allow. This lets the
1582 * client view printer folder, but does not show the MSAPW.
1584 * Note: this test needs code to check access rights here too. Jeremy
1585 * could you look at this?
1587 * Second case: the user is opening a printer:
1588 * NT doesn't let us connect to a printer if the connecting user
1589 * doesn't have print permission.
1591 * Third case: user is opening a Port Monitor
1592 * access checks same as opening a handle to the print server.
1595 switch (Printer->printer_type )
1597 case SPLHND_SERVER:
1598 case SPLHND_PORTMON_TCP:
1599 case SPLHND_PORTMON_LOCAL:
1600 /* Printserver handles use global struct... */
1602 snum = -1;
1604 /* Map standard access rights to object specific access rights */
1606 se_map_standard(&r->in.access_mask,
1607 &printserver_std_mapping);
1609 /* Deny any object specific bits that don't apply to print
1610 servers (i.e printer and job specific bits) */
1612 r->in.access_mask &= SPECIFIC_RIGHTS_MASK;
1614 if (r->in.access_mask &
1615 ~(SERVER_ACCESS_ADMINISTER | SERVER_ACCESS_ENUMERATE)) {
1616 DEBUG(3, ("access DENIED for non-printserver bits\n"));
1617 close_printer_handle(p, r->out.handle);
1618 ZERO_STRUCTP(r->out.handle);
1619 return WERR_ACCESS_DENIED;
1622 /* Allow admin access */
1624 if ( r->in.access_mask & SERVER_ACCESS_ADMINISTER )
1626 SE_PRIV se_printop = SE_PRINT_OPERATOR;
1628 if (!lp_ms_add_printer_wizard()) {
1629 close_printer_handle(p, r->out.handle);
1630 ZERO_STRUCTP(r->out.handle);
1631 return WERR_ACCESS_DENIED;
1634 /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
1635 and not a printer admin, then fail */
1637 if ((p->server_info->utok.uid != sec_initial_uid()) &&
1638 !user_has_privileges(p->server_info->ptok,
1639 &se_printop ) &&
1640 !token_contains_name_in_list(
1641 uidtoname(p->server_info->utok.uid),
1642 NULL, NULL,
1643 p->server_info->ptok,
1644 lp_printer_admin(snum))) {
1645 close_printer_handle(p, r->out.handle);
1646 ZERO_STRUCTP(r->out.handle);
1647 return WERR_ACCESS_DENIED;
1650 r->in.access_mask = SERVER_ACCESS_ADMINISTER;
1652 else
1654 r->in.access_mask = SERVER_ACCESS_ENUMERATE;
1657 DEBUG(4,("Setting print server access = %s\n", (r->in.access_mask == SERVER_ACCESS_ADMINISTER)
1658 ? "SERVER_ACCESS_ADMINISTER" : "SERVER_ACCESS_ENUMERATE" ));
1660 /* We fall through to return WERR_OK */
1661 break;
1663 case SPLHND_PRINTER:
1664 /* NT doesn't let us connect to a printer if the connecting user
1665 doesn't have print permission. */
1667 if (!get_printer_snum(p, r->out.handle, &snum, NULL)) {
1668 close_printer_handle(p, r->out.handle);
1669 ZERO_STRUCTP(r->out.handle);
1670 return WERR_BADFID;
1673 se_map_standard(&r->in.access_mask, &printer_std_mapping);
1675 /* map an empty access mask to the minimum access mask */
1676 if (r->in.access_mask == 0x0)
1677 r->in.access_mask = PRINTER_ACCESS_USE;
1680 * If we are not serving the printer driver for this printer,
1681 * map PRINTER_ACCESS_ADMINISTER to PRINTER_ACCESS_USE. This
1682 * will keep NT clients happy --jerry
1685 if (lp_use_client_driver(snum)
1686 && (r->in.access_mask & PRINTER_ACCESS_ADMINISTER))
1688 r->in.access_mask = PRINTER_ACCESS_USE;
1691 /* check smb.conf parameters and the the sec_desc */
1693 if ( !check_access(get_client_fd(), lp_hostsallow(snum), lp_hostsdeny(snum)) ) {
1694 DEBUG(3, ("access DENIED (hosts allow/deny) for printer open\n"));
1695 ZERO_STRUCTP(r->out.handle);
1696 return WERR_ACCESS_DENIED;
1699 if (!user_ok_token(uidtoname(p->server_info->utok.uid), NULL,
1700 p->server_info->ptok, snum) ||
1701 !print_access_check(p->server_info, snum,
1702 r->in.access_mask)) {
1703 DEBUG(3, ("access DENIED for printer open\n"));
1704 close_printer_handle(p, r->out.handle);
1705 ZERO_STRUCTP(r->out.handle);
1706 return WERR_ACCESS_DENIED;
1709 if ((r->in.access_mask & SPECIFIC_RIGHTS_MASK)& ~(PRINTER_ACCESS_ADMINISTER|PRINTER_ACCESS_USE)) {
1710 DEBUG(3, ("access DENIED for printer open - unknown bits\n"));
1711 close_printer_handle(p, r->out.handle);
1712 ZERO_STRUCTP(r->out.handle);
1713 return WERR_ACCESS_DENIED;
1716 if (r->in.access_mask & PRINTER_ACCESS_ADMINISTER)
1717 r->in.access_mask = PRINTER_ACCESS_ADMINISTER;
1718 else
1719 r->in.access_mask = PRINTER_ACCESS_USE;
1721 DEBUG(4,("Setting printer access = %s\n", (r->in.access_mask == PRINTER_ACCESS_ADMINISTER)
1722 ? "PRINTER_ACCESS_ADMINISTER" : "PRINTER_ACCESS_USE" ));
1724 break;
1726 default:
1727 /* sanity check to prevent programmer error */
1728 ZERO_STRUCTP(r->out.handle);
1729 return WERR_BADFID;
1732 Printer->access_granted = r->in.access_mask;
1735 * If the client sent a devmode in the OpenPrinter() call, then
1736 * save it here in case we get a job submission on this handle
1739 if ((Printer->printer_type != SPLHND_SERVER) &&
1740 r->in.devmode_ctr.devmode) {
1741 convert_devicemode(Printer->sharename,
1742 r->in.devmode_ctr.devmode,
1743 &Printer->nt_devmode);
1746 #if 0 /* JERRY -- I'm doubtful this is really effective */
1747 /* HACK ALERT!!! Sleep for 1/3 of a second to try trigger a LAN/WAN
1748 optimization in Windows 2000 clients --jerry */
1750 if ( (r->in.access_mask == PRINTER_ACCESS_ADMINISTER)
1751 && (RA_WIN2K == get_remote_arch()) )
1753 DEBUG(10,("_spoolss_OpenPrinterEx: Enabling LAN/WAN hack for Win2k clients.\n"));
1754 sys_usleep( 500000 );
1756 #endif
1758 return WERR_OK;
1761 /****************************************************************************
1762 ****************************************************************************/
1764 static bool printer_info2_to_nt_printer_info2(struct spoolss_SetPrinterInfo2 *r,
1765 NT_PRINTER_INFO_LEVEL_2 *d)
1767 DEBUG(7,("printer_info2_to_nt_printer_info2\n"));
1769 if (!r || !d) {
1770 return false;
1773 d->attributes = r->attributes;
1774 d->priority = r->priority;
1775 d->default_priority = r->defaultpriority;
1776 d->starttime = r->starttime;
1777 d->untiltime = r->untiltime;
1778 d->status = r->status;
1779 d->cjobs = r->cjobs;
1781 fstrcpy(d->servername, r->servername);
1782 fstrcpy(d->printername, r->printername);
1783 fstrcpy(d->sharename, r->sharename);
1784 fstrcpy(d->portname, r->portname);
1785 fstrcpy(d->drivername, r->drivername);
1786 slprintf(d->comment, sizeof(d->comment)-1, "%s", r->comment);
1787 fstrcpy(d->location, r->location);
1788 fstrcpy(d->sepfile, r->sepfile);
1789 fstrcpy(d->printprocessor, r->printprocessor);
1790 fstrcpy(d->datatype, r->datatype);
1791 fstrcpy(d->parameters, r->parameters);
1793 return true;
1796 /****************************************************************************
1797 ****************************************************************************/
1799 static bool convert_printer_info(struct spoolss_SetPrinterInfoCtr *info_ctr,
1800 NT_PRINTER_INFO_LEVEL *printer)
1802 bool ret;
1804 switch (info_ctr->level) {
1805 case 2:
1806 /* allocate memory if needed. Messy because
1807 convert_printer_info is used to update an existing
1808 printer or build a new one */
1810 if (!printer->info_2) {
1811 printer->info_2 = TALLOC_ZERO_P(printer, NT_PRINTER_INFO_LEVEL_2);
1812 if (!printer->info_2) {
1813 DEBUG(0,("convert_printer_info: "
1814 "talloc() failed!\n"));
1815 return false;
1819 ret = printer_info2_to_nt_printer_info2(info_ctr->info.info2,
1820 printer->info_2);
1821 printer->info_2->setuptime = time(NULL);
1822 return ret;
1825 return false;
1828 /*******************************************************************
1829 ********************************************************************/
1831 static bool string_array_to_fstring_array(const char **sarray, fstring **farray)
1833 int i;
1835 if (!sarray) {
1836 *farray = NULL;
1837 return true;
1840 *farray = SMB_MALLOC_ARRAY(fstring, 1);
1841 if (!*farray) {
1842 return false;
1845 for (i=0; sarray[i] != NULL; i++) {
1846 *farray = SMB_REALLOC_ARRAY(*farray, fstring, i+2);
1847 if (!*farray) {
1848 return false;
1850 fstrcpy((*farray)[i], sarray[i]);
1853 fstrcpy((*farray)[i], "");
1855 return true;
1858 /*******************************************************************
1859 ********************************************************************/
1861 static bool driver_info3_to_nt_driver_info3(struct spoolss_AddDriverInfo3 *r,
1862 NT_PRINTER_DRIVER_INFO_LEVEL_3 **p)
1864 NT_PRINTER_DRIVER_INFO_LEVEL_3 *d;
1866 DEBUG(7,("driver_info3_to_nt_driver_info3: Converting from UNICODE to ASCII\n"));
1868 if (*p == NULL) {
1869 *p = SMB_MALLOC_P(NT_PRINTER_DRIVER_INFO_LEVEL_3);
1870 if (*p == NULL) {
1871 return false;
1873 ZERO_STRUCTP(*p);
1876 d = *p;
1878 d->cversion = r->version;
1880 fstrcpy(d->name, r->driver_name);
1881 fstrcpy(d->environment, r->architecture);
1882 fstrcpy(d->driverpath, r->driver_path);
1883 fstrcpy(d->datafile, r->data_file);
1884 fstrcpy(d->configfile, r->config_file);
1885 fstrcpy(d->helpfile, r->help_file);
1886 fstrcpy(d->monitorname, r->monitor_name);
1887 fstrcpy(d->defaultdatatype, r->default_datatype);
1889 DEBUGADD(8,( "version: %d\n", d->cversion));
1890 DEBUGADD(8,( "name: %s\n", d->name));
1891 DEBUGADD(8,( "environment: %s\n", d->environment));
1892 DEBUGADD(8,( "driverpath: %s\n", d->driverpath));
1893 DEBUGADD(8,( "datafile: %s\n", d->datafile));
1894 DEBUGADD(8,( "configfile: %s\n", d->configfile));
1895 DEBUGADD(8,( "helpfile: %s\n", d->helpfile));
1896 DEBUGADD(8,( "monitorname: %s\n", d->monitorname));
1897 DEBUGADD(8,( "defaultdatatype: %s\n", d->defaultdatatype));
1899 if (r->dependent_files) {
1900 if (!string_array_to_fstring_array(r->dependent_files->string,
1901 &d->dependentfiles)) {
1902 SAFE_FREE(*p);
1903 return false;
1907 return true;
1910 /*******************************************************************
1911 ********************************************************************/
1913 static bool driver_info6_to_nt_driver_info6(struct spoolss_AddDriverInfo6 *r,
1914 NT_PRINTER_DRIVER_INFO_LEVEL_6 **p)
1916 NT_PRINTER_DRIVER_INFO_LEVEL_6 *d;
1918 DEBUG(7,("driver_info6_to_nt_driver_info6: Converting from UNICODE to ASCII\n"));
1920 if (*p == NULL) {
1921 *p = SMB_MALLOC_P(NT_PRINTER_DRIVER_INFO_LEVEL_6);
1922 if (*p == NULL) {
1923 return false;
1925 ZERO_STRUCTP(*p);
1928 d = *p;
1930 d->version = r->version;
1932 fstrcpy(d->name, r->driver_name);
1933 fstrcpy(d->environment, r->architecture);
1934 fstrcpy(d->driverpath, r->driver_path);
1935 fstrcpy(d->datafile, r->data_file);
1936 fstrcpy(d->configfile, r->config_file);
1937 fstrcpy(d->helpfile, r->help_file);
1938 fstrcpy(d->monitorname, r->monitor_name);
1939 fstrcpy(d->defaultdatatype, r->default_datatype);
1941 DEBUGADD(8,( "version: %d\n", d->version));
1942 DEBUGADD(8,( "name: %s\n", d->name));
1943 DEBUGADD(8,( "environment: %s\n", d->environment));
1944 DEBUGADD(8,( "driverpath: %s\n", d->driverpath));
1945 DEBUGADD(8,( "datafile: %s\n", d->datafile));
1946 DEBUGADD(8,( "configfile: %s\n", d->configfile));
1947 DEBUGADD(8,( "helpfile: %s\n", d->helpfile));
1948 DEBUGADD(8,( "monitorname: %s\n", d->monitorname));
1949 DEBUGADD(8,( "defaultdatatype: %s\n", d->defaultdatatype));
1951 if (r->dependent_files) {
1952 if (!string_array_to_fstring_array(r->dependent_files->string,
1953 &d->dependentfiles)) {
1954 goto error;
1958 if (r->previous_names) {
1959 if (!string_array_to_fstring_array(r->previous_names->string,
1960 &d->previousnames)) {
1961 goto error;
1965 return true;
1967 error:
1968 SAFE_FREE(*p);
1969 return false;
1972 /********************************************************************
1973 ********************************************************************/
1975 static bool convert_printer_driver_info(const struct spoolss_AddDriverInfoCtr *r,
1976 NT_PRINTER_DRIVER_INFO_LEVEL *printer,
1977 uint32_t level)
1979 switch (level) {
1980 case 3:
1981 printer->info_3 = NULL;
1982 if (!driver_info3_to_nt_driver_info3(r->info.info3, &printer->info_3)) {
1983 return false;
1985 break;
1986 case 6:
1987 printer->info_6 = NULL;
1988 if (!driver_info6_to_nt_driver_info6(r->info.info6, &printer->info_6)) {
1989 return false;
1991 break;
1992 default:
1993 return false;
1996 return true;
1999 /********************************************************************
2000 * _spoolss_enddocprinter_internal.
2001 ********************************************************************/
2003 static WERROR _spoolss_enddocprinter_internal(pipes_struct *p,
2004 struct policy_handle *handle)
2006 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
2007 int snum;
2009 if (!Printer) {
2010 DEBUG(2,("_spoolss_enddocprinter_internal: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
2011 return WERR_BADFID;
2014 if (!get_printer_snum(p, handle, &snum, NULL))
2015 return WERR_BADFID;
2017 Printer->document_started = false;
2018 print_job_end(snum, Printer->jobid,NORMAL_CLOSE);
2019 /* error codes unhandled so far ... */
2021 return WERR_OK;
2024 /****************************************************************
2025 _spoolss_ClosePrinter
2026 ****************************************************************/
2028 WERROR _spoolss_ClosePrinter(pipes_struct *p,
2029 struct spoolss_ClosePrinter *r)
2031 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
2033 if (Printer && Printer->document_started)
2034 _spoolss_enddocprinter_internal(p, r->in.handle); /* print job was not closed */
2036 if (!close_printer_handle(p, r->in.handle))
2037 return WERR_BADFID;
2039 /* clear the returned printer handle. Observed behavior
2040 from Win2k server. Don't think this really matters.
2041 Previous code just copied the value of the closed
2042 handle. --jerry */
2044 ZERO_STRUCTP(r->out.handle);
2046 return WERR_OK;
2049 /****************************************************************
2050 _spoolss_DeletePrinter
2051 ****************************************************************/
2053 WERROR _spoolss_DeletePrinter(pipes_struct *p,
2054 struct spoolss_DeletePrinter *r)
2056 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
2057 WERROR result;
2059 if (Printer && Printer->document_started)
2060 _spoolss_enddocprinter_internal(p, r->in.handle); /* print job was not closed */
2062 result = delete_printer_handle(p, r->in.handle);
2064 update_c_setprinter(false);
2066 return result;
2069 /*******************************************************************
2070 * static function to lookup the version id corresponding to an
2071 * long architecture string
2072 ******************************************************************/
2074 static int get_version_id(const char *arch)
2076 int i;
2077 struct print_architecture_table_node archi_table[]= {
2079 {"Windows 4.0", "WIN40", 0 },
2080 {"Windows NT x86", "W32X86", 2 },
2081 {"Windows NT R4000", "W32MIPS", 2 },
2082 {"Windows NT Alpha_AXP", "W32ALPHA", 2 },
2083 {"Windows NT PowerPC", "W32PPC", 2 },
2084 {"Windows IA64", "IA64", 3 },
2085 {"Windows x64", "x64", 3 },
2086 {NULL, "", -1 }
2089 for (i=0; archi_table[i].long_archi != NULL; i++)
2091 if (strcmp(arch, archi_table[i].long_archi) == 0)
2092 return (archi_table[i].version);
2095 return -1;
2098 /****************************************************************
2099 _spoolss_DeletePrinterDriver
2100 ****************************************************************/
2102 WERROR _spoolss_DeletePrinterDriver(pipes_struct *p,
2103 struct spoolss_DeletePrinterDriver *r)
2105 NT_PRINTER_DRIVER_INFO_LEVEL info;
2106 NT_PRINTER_DRIVER_INFO_LEVEL info_win2k;
2107 int version;
2108 WERROR status;
2109 WERROR status_win2k = WERR_ACCESS_DENIED;
2110 SE_PRIV se_printop = SE_PRINT_OPERATOR;
2112 /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
2113 and not a printer admin, then fail */
2115 if ( (p->server_info->utok.uid != sec_initial_uid())
2116 && !user_has_privileges(p->server_info->ptok, &se_printop )
2117 && !token_contains_name_in_list(
2118 uidtoname(p->server_info->utok.uid), NULL,
2119 NULL, p->server_info->ptok,
2120 lp_printer_admin(-1)) )
2122 return WERR_ACCESS_DENIED;
2125 /* check that we have a valid driver name first */
2127 if ((version = get_version_id(r->in.architecture)) == -1)
2128 return WERR_INVALID_ENVIRONMENT;
2130 ZERO_STRUCT(info);
2131 ZERO_STRUCT(info_win2k);
2133 if (!W_ERROR_IS_OK(get_a_printer_driver(&info, 3, r->in.driver,
2134 r->in.architecture,
2135 version)))
2137 /* try for Win2k driver if "Windows NT x86" */
2139 if ( version == 2 ) {
2140 version = 3;
2141 if (!W_ERROR_IS_OK(get_a_printer_driver(&info, 3,
2142 r->in.driver,
2143 r->in.architecture,
2144 version))) {
2145 status = WERR_UNKNOWN_PRINTER_DRIVER;
2146 goto done;
2149 /* otherwise it was a failure */
2150 else {
2151 status = WERR_UNKNOWN_PRINTER_DRIVER;
2152 goto done;
2157 if (printer_driver_in_use(info.info_3)) {
2158 status = WERR_PRINTER_DRIVER_IN_USE;
2159 goto done;
2162 if ( version == 2 )
2164 if (W_ERROR_IS_OK(get_a_printer_driver(&info_win2k, 3,
2165 r->in.driver,
2166 r->in.architecture, 3)))
2168 /* if we get to here, we now have 2 driver info structures to remove */
2169 /* remove the Win2k driver first*/
2171 status_win2k = delete_printer_driver(
2172 p, info_win2k.info_3, 3, false);
2173 free_a_printer_driver( info_win2k, 3 );
2175 /* this should not have failed---if it did, report to client */
2176 if ( !W_ERROR_IS_OK(status_win2k) )
2178 status = status_win2k;
2179 goto done;
2184 status = delete_printer_driver(p, info.info_3, version, false);
2186 /* if at least one of the deletes succeeded return OK */
2188 if ( W_ERROR_IS_OK(status) || W_ERROR_IS_OK(status_win2k) )
2189 status = WERR_OK;
2191 done:
2192 free_a_printer_driver( info, 3 );
2194 return status;
2197 /****************************************************************
2198 _spoolss_DeletePrinterDriverEx
2199 ****************************************************************/
2201 WERROR _spoolss_DeletePrinterDriverEx(pipes_struct *p,
2202 struct spoolss_DeletePrinterDriverEx *r)
2204 NT_PRINTER_DRIVER_INFO_LEVEL info;
2205 NT_PRINTER_DRIVER_INFO_LEVEL info_win2k;
2206 int version;
2207 bool delete_files;
2208 WERROR status;
2209 WERROR status_win2k = WERR_ACCESS_DENIED;
2210 SE_PRIV se_printop = SE_PRINT_OPERATOR;
2212 /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
2213 and not a printer admin, then fail */
2215 if ( (p->server_info->utok.uid != sec_initial_uid())
2216 && !user_has_privileges(p->server_info->ptok, &se_printop )
2217 && !token_contains_name_in_list(
2218 uidtoname(p->server_info->utok.uid), NULL, NULL,
2219 p->server_info->ptok, lp_printer_admin(-1)) )
2221 return WERR_ACCESS_DENIED;
2224 /* check that we have a valid driver name first */
2225 if ((version = get_version_id(r->in.architecture)) == -1) {
2226 /* this is what NT returns */
2227 return WERR_INVALID_ENVIRONMENT;
2230 if (r->in.delete_flags & DPD_DELETE_SPECIFIC_VERSION)
2231 version = r->in.version;
2233 ZERO_STRUCT(info);
2234 ZERO_STRUCT(info_win2k);
2236 status = get_a_printer_driver(&info, 3, r->in.driver,
2237 r->in.architecture, version);
2239 if ( !W_ERROR_IS_OK(status) )
2242 * if the client asked for a specific version,
2243 * or this is something other than Windows NT x86,
2244 * then we've failed
2247 if ( (r->in.delete_flags & DPD_DELETE_SPECIFIC_VERSION) || (version !=2) )
2248 goto done;
2250 /* try for Win2k driver if "Windows NT x86" */
2252 version = 3;
2253 if (!W_ERROR_IS_OK(get_a_printer_driver(&info, 3, r->in.driver,
2254 r->in.architecture,
2255 version))) {
2256 status = WERR_UNKNOWN_PRINTER_DRIVER;
2257 goto done;
2261 if ( printer_driver_in_use(info.info_3) ) {
2262 status = WERR_PRINTER_DRIVER_IN_USE;
2263 goto done;
2267 * we have a couple of cases to consider.
2268 * (1) Are any files in use? If so and DPD_DELTE_ALL_FILE is set,
2269 * then the delete should fail if **any** files overlap with
2270 * other drivers
2271 * (2) If DPD_DELTE_UNUSED_FILES is sert, then delete all
2272 * non-overlapping files
2273 * (3) If neither DPD_DELTE_ALL_FILE nor DPD_DELTE_ALL_FILES
2274 * is set, the do not delete any files
2275 * Refer to MSDN docs on DeletePrinterDriverEx() for details.
2278 delete_files = r->in.delete_flags & (DPD_DELETE_ALL_FILES|DPD_DELETE_UNUSED_FILES);
2280 /* fail if any files are in use and DPD_DELETE_ALL_FILES is set */
2282 if ( delete_files && printer_driver_files_in_use(info.info_3) & (r->in.delete_flags & DPD_DELETE_ALL_FILES) ) {
2283 /* no idea of the correct error here */
2284 status = WERR_ACCESS_DENIED;
2285 goto done;
2289 /* also check for W32X86/3 if necessary; maybe we already have? */
2291 if ( (version == 2) && ((r->in.delete_flags & DPD_DELETE_SPECIFIC_VERSION) != DPD_DELETE_SPECIFIC_VERSION) ) {
2292 if (W_ERROR_IS_OK(get_a_printer_driver(&info_win2k, 3,
2293 r->in.driver,
2294 r->in.architecture, 3)))
2297 if ( delete_files && printer_driver_files_in_use(info_win2k.info_3) & (r->in.delete_flags & DPD_DELETE_ALL_FILES) ) {
2298 /* no idea of the correct error here */
2299 free_a_printer_driver( info_win2k, 3 );
2300 status = WERR_ACCESS_DENIED;
2301 goto done;
2304 /* if we get to here, we now have 2 driver info structures to remove */
2305 /* remove the Win2k driver first*/
2307 status_win2k = delete_printer_driver(
2308 p, info_win2k.info_3, 3, delete_files);
2309 free_a_printer_driver( info_win2k, 3 );
2311 /* this should not have failed---if it did, report to client */
2313 if ( !W_ERROR_IS_OK(status_win2k) )
2314 goto done;
2318 status = delete_printer_driver(p, info.info_3, version, delete_files);
2320 if ( W_ERROR_IS_OK(status) || W_ERROR_IS_OK(status_win2k) )
2321 status = WERR_OK;
2322 done:
2323 free_a_printer_driver( info, 3 );
2325 return status;
2329 /****************************************************************************
2330 Internal routine for removing printerdata
2331 ***************************************************************************/
2333 static WERROR delete_printer_dataex( NT_PRINTER_INFO_LEVEL *printer, const char *key, const char *value )
2335 return delete_printer_data( printer->info_2, key, value );
2338 /****************************************************************************
2339 Internal routine for storing printerdata
2340 ***************************************************************************/
2342 WERROR set_printer_dataex(NT_PRINTER_INFO_LEVEL *printer,
2343 const char *key, const char *value,
2344 uint32_t type, uint8_t *data, int real_len)
2346 /* the registry objects enforce uniqueness based on value name */
2348 return add_printer_data( printer->info_2, key, value, type, data, real_len );
2351 /********************************************************************
2352 GetPrinterData on a printer server Handle.
2353 ********************************************************************/
2355 static WERROR getprinterdata_printer_server(TALLOC_CTX *mem_ctx,
2356 const char *value,
2357 enum winreg_Type *type,
2358 union spoolss_PrinterData *data)
2360 DEBUG(8,("getprinterdata_printer_server:%s\n", value));
2362 if (!StrCaseCmp(value, "W3SvcInstalled")) {
2363 *type = REG_DWORD;
2364 data->value = 0x00;
2365 return WERR_OK;
2368 if (!StrCaseCmp(value, "BeepEnabled")) {
2369 *type = REG_DWORD;
2370 data->value = 0x00;
2371 return WERR_OK;
2374 if (!StrCaseCmp(value, "EventLog")) {
2375 *type = REG_DWORD;
2376 /* formally was 0x1b */
2377 data->value = 0x00;
2378 return WERR_OK;
2381 if (!StrCaseCmp(value, "NetPopup")) {
2382 *type = REG_DWORD;
2383 data->value = 0x00;
2384 return WERR_OK;
2387 if (!StrCaseCmp(value, "MajorVersion")) {
2388 *type = REG_DWORD;
2390 /* Windows NT 4.0 seems to not allow uploading of drivers
2391 to a server that reports 0x3 as the MajorVersion.
2392 need to investigate more how Win2k gets around this .
2393 -- jerry */
2395 if (RA_WINNT == get_remote_arch()) {
2396 data->value = 0x02;
2397 } else {
2398 data->value = 0x03;
2401 return WERR_OK;
2404 if (!StrCaseCmp(value, "MinorVersion")) {
2405 *type = REG_DWORD;
2406 data->value = 0x00;
2407 return WERR_OK;
2410 /* REG_BINARY
2411 * uint32_t size = 0x114
2412 * uint32_t major = 5
2413 * uint32_t minor = [0|1]
2414 * uint32_t build = [2195|2600]
2415 * extra unicode string = e.g. "Service Pack 3"
2417 if (!StrCaseCmp(value, "OSVersion")) {
2418 DATA_BLOB blob;
2419 enum ndr_err_code ndr_err;
2420 struct spoolss_OSVersion os;
2422 os.major = 5; /* Windows 2000 == 5.0 */
2423 os.minor = 0;
2424 os.build = 2195; /* build */
2425 os.extra_string = ""; /* leave extra string empty */
2427 ndr_err = ndr_push_struct_blob(&blob, mem_ctx, NULL, &os,
2428 (ndr_push_flags_fn_t)ndr_push_spoolss_OSVersion);
2429 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
2430 return WERR_GENERAL_FAILURE;
2433 *type = REG_BINARY;
2434 data->binary = blob;
2436 return WERR_OK;
2440 if (!StrCaseCmp(value, "DefaultSpoolDirectory")) {
2441 *type = REG_SZ;
2443 data->string = talloc_strdup(mem_ctx, "C:\\PRINTERS");
2444 W_ERROR_HAVE_NO_MEMORY(data->string);
2446 return WERR_OK;
2449 if (!StrCaseCmp(value, "Architecture")) {
2450 *type = REG_SZ;
2452 data->string = talloc_strdup(mem_ctx, "Windows NT x86");
2453 W_ERROR_HAVE_NO_MEMORY(data->string);
2455 return WERR_OK;
2458 if (!StrCaseCmp(value, "DsPresent")) {
2459 *type = REG_DWORD;
2461 /* only show the publish check box if we are a
2462 member of a AD domain */
2464 if (lp_security() == SEC_ADS) {
2465 data->value = 0x01;
2466 } else {
2467 data->value = 0x00;
2469 return WERR_OK;
2472 if (!StrCaseCmp(value, "DNSMachineName")) {
2473 const char *hostname = get_mydnsfullname();
2475 if (!hostname) {
2476 return WERR_BADFILE;
2479 *type = REG_SZ;
2480 data->string = talloc_strdup(mem_ctx, hostname);
2481 W_ERROR_HAVE_NO_MEMORY(data->string);
2483 return WERR_OK;
2486 return WERR_INVALID_PARAM;
2489 /****************************************************************
2490 _spoolss_GetPrinterData
2491 ****************************************************************/
2493 WERROR _spoolss_GetPrinterData(pipes_struct *p,
2494 struct spoolss_GetPrinterData *r)
2496 WERROR result;
2497 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
2498 NT_PRINTER_INFO_LEVEL *printer = NULL;
2499 int snum = 0;
2502 * Reminder: when it's a string, the length is in BYTES
2503 * even if UNICODE is negociated.
2505 * JFM, 4/19/1999
2508 /* in case of problem, return some default values */
2510 *r->out.needed = 0;
2511 *r->out.type = 0;
2513 DEBUG(4,("_spoolss_GetPrinterData\n"));
2515 if (!Printer) {
2516 DEBUG(2,("_spoolss_GetPrinterData: Invalid handle (%s:%u:%u).\n",
2517 OUR_HANDLE(r->in.handle)));
2518 result = WERR_BADFID;
2519 goto done;
2522 if (Printer->printer_type == SPLHND_SERVER) {
2523 result = getprinterdata_printer_server(p->mem_ctx,
2524 r->in.value_name,
2525 r->out.type,
2526 r->out.data);
2527 } else {
2528 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
2529 result = WERR_BADFID;
2530 goto done;
2533 result = get_a_printer(Printer, &printer, 2, lp_servicename(snum));
2534 if (!W_ERROR_IS_OK(result)) {
2535 goto done;
2538 /* XP sends this and wants to change id value from the PRINTER_INFO_0 */
2540 if (strequal(r->in.value_name, "ChangeId")) {
2541 *r->out.type = REG_DWORD;
2542 r->out.data->value = printer->info_2->changeid;
2543 result = WERR_OK;
2544 } else {
2545 REGISTRY_VALUE *v;
2546 DATA_BLOB blob;
2548 v = get_printer_data(printer->info_2,
2549 SPOOL_PRINTERDATA_KEY,
2550 r->in.value_name);
2551 if (!v) {
2552 result = WERR_BADFILE;
2553 goto done;
2556 *r->out.type = v->type;
2558 blob = data_blob_const(v->data_p, v->size);
2560 result = pull_spoolss_PrinterData(p->mem_ctx, &blob,
2561 r->out.data,
2562 *r->out.type);
2566 done:
2567 /* cleanup & exit */
2569 if (printer) {
2570 free_a_printer(&printer, 2);
2573 if (!W_ERROR_IS_OK(result)) {
2574 return result;
2577 *r->out.needed = ndr_size_spoolss_PrinterData(r->out.data, *r->out.type, NULL, 0);
2578 *r->out.type = SPOOLSS_BUFFER_OK(*r->out.type, REG_NONE);
2579 r->out.data = SPOOLSS_BUFFER_OK(r->out.data, r->out.data);
2581 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_MORE_DATA);
2584 /*********************************************************
2585 Connect to the client machine.
2586 **********************************************************/
2588 static bool spoolss_connect_to_client(struct rpc_pipe_client **pp_pipe,
2589 struct sockaddr_storage *client_ss, const char *remote_machine)
2591 NTSTATUS ret;
2592 struct cli_state *the_cli;
2593 struct sockaddr_storage rm_addr;
2595 if ( is_zero_addr((struct sockaddr *)client_ss) ) {
2596 if ( !resolve_name( remote_machine, &rm_addr, 0x20) ) {
2597 DEBUG(2,("spoolss_connect_to_client: Can't resolve address for %s\n", remote_machine));
2598 return false;
2601 if (ismyaddr((struct sockaddr *)&rm_addr)) {
2602 DEBUG(0,("spoolss_connect_to_client: Machine %s is one of our addresses. Cannot add to ourselves.\n", remote_machine));
2603 return false;
2605 } else {
2606 char addr[INET6_ADDRSTRLEN];
2607 rm_addr = *client_ss;
2608 print_sockaddr(addr, sizeof(addr), &rm_addr);
2609 DEBUG(5,("spoolss_connect_to_client: Using address %s (no name resolution necessary)\n",
2610 addr));
2613 /* setup the connection */
2615 ret = cli_full_connection( &the_cli, global_myname(), remote_machine,
2616 &rm_addr, 0, "IPC$", "IPC",
2617 "", /* username */
2618 "", /* domain */
2619 "", /* password */
2620 0, lp_client_signing(), NULL );
2622 if ( !NT_STATUS_IS_OK( ret ) ) {
2623 DEBUG(2,("spoolss_connect_to_client: connection to [%s] failed!\n",
2624 remote_machine ));
2625 return false;
2628 if ( the_cli->protocol != PROTOCOL_NT1 ) {
2629 DEBUG(0,("spoolss_connect_to_client: machine %s didn't negotiate NT protocol.\n", remote_machine));
2630 cli_shutdown(the_cli);
2631 return false;
2635 * Ok - we have an anonymous connection to the IPC$ share.
2636 * Now start the NT Domain stuff :-).
2639 ret = cli_rpc_pipe_open_noauth(the_cli, &ndr_table_spoolss.syntax_id, pp_pipe);
2640 if (!NT_STATUS_IS_OK(ret)) {
2641 DEBUG(2,("spoolss_connect_to_client: unable to open the spoolss pipe on machine %s. Error was : %s.\n",
2642 remote_machine, nt_errstr(ret)));
2643 cli_shutdown(the_cli);
2644 return false;
2647 return true;
2650 /***************************************************************************
2651 Connect to the client.
2652 ****************************************************************************/
2654 static bool srv_spoolss_replyopenprinter(int snum, const char *printer,
2655 uint32_t localprinter, uint32_t type,
2656 struct policy_handle *handle,
2657 struct sockaddr_storage *client_ss)
2659 WERROR result;
2660 NTSTATUS status;
2663 * If it's the first connection, contact the client
2664 * and connect to the IPC$ share anonymously
2666 if (smb_connections==0) {
2667 fstring unix_printer;
2669 fstrcpy(unix_printer, printer+2); /* the +2 is to strip the leading 2 backslashs */
2671 if ( !spoolss_connect_to_client( &notify_cli_pipe, client_ss, unix_printer ))
2672 return false;
2674 messaging_register(smbd_messaging_context(), NULL,
2675 MSG_PRINTER_NOTIFY2,
2676 receive_notify2_message_list);
2677 /* Tell the connections db we're now interested in printer
2678 * notify messages. */
2679 register_message_flags(true, FLAG_MSG_PRINT_NOTIFY);
2683 * Tell the specific printing tdb we want messages for this printer
2684 * by registering our PID.
2687 if (!print_notify_register_pid(snum))
2688 DEBUG(0,("print_notify_register_pid: Failed to register our pid for printer %s\n", printer ));
2690 smb_connections++;
2692 status = rpccli_spoolss_ReplyOpenPrinter(notify_cli_pipe, talloc_tos(),
2693 printer,
2694 localprinter,
2695 type,
2697 NULL,
2698 handle,
2699 &result);
2700 if (!NT_STATUS_IS_OK(status) || !W_ERROR_IS_OK(result))
2701 DEBUG(5,("srv_spoolss_reply_open_printer: Client RPC returned [%s]\n",
2702 win_errstr(result)));
2704 return (W_ERROR_IS_OK(result));
2707 /****************************************************************
2708 ****************************************************************/
2710 static struct spoolss_NotifyOption *dup_spoolss_NotifyOption(TALLOC_CTX *mem_ctx,
2711 const struct spoolss_NotifyOption *r)
2713 struct spoolss_NotifyOption *option;
2714 uint32_t i,k;
2716 if (!r) {
2717 return NULL;
2720 option = talloc_zero(mem_ctx, struct spoolss_NotifyOption);
2721 if (!option) {
2722 return NULL;
2725 *option = *r;
2727 if (!option->count) {
2728 return option;
2731 option->types = talloc_zero_array(option,
2732 struct spoolss_NotifyOptionType, option->count);
2733 if (!option->types) {
2734 talloc_free(option);
2735 return NULL;
2738 for (i=0; i < option->count; i++) {
2739 option->types[i] = r->types[i];
2741 if (option->types[i].count) {
2742 option->types[i].fields = talloc_zero_array(option,
2743 union spoolss_Field, option->types[i].count);
2744 if (!option->types[i].fields) {
2745 talloc_free(option);
2746 return NULL;
2748 for (k=0; k<option->types[i].count; k++) {
2749 option->types[i].fields[k] =
2750 r->types[i].fields[k];
2755 return option;
2758 /****************************************************************
2759 * _spoolss_RemoteFindFirstPrinterChangeNotifyEx
2761 * before replying OK: status=0 a rpc call is made to the workstation
2762 * asking ReplyOpenPrinter
2764 * in fact ReplyOpenPrinter is the changenotify equivalent on the spoolss pipe
2765 * called from api_spoolss_rffpcnex
2766 ****************************************************************/
2768 WERROR _spoolss_RemoteFindFirstPrinterChangeNotifyEx(pipes_struct *p,
2769 struct spoolss_RemoteFindFirstPrinterChangeNotifyEx *r)
2771 int snum = -1;
2772 struct spoolss_NotifyOption *option = r->in.notify_options;
2773 struct sockaddr_storage client_ss;
2775 /* store the notify value in the printer struct */
2777 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
2779 if (!Printer) {
2780 DEBUG(2,("_spoolss_RemoteFindFirstPrinterChangeNotifyEx: "
2781 "Invalid handle (%s:%u:%u).\n",
2782 OUR_HANDLE(r->in.handle)));
2783 return WERR_BADFID;
2786 Printer->notify.flags = r->in.flags;
2787 Printer->notify.options = r->in.options;
2788 Printer->notify.printerlocal = r->in.printer_local;
2790 TALLOC_FREE(Printer->notify.option);
2791 Printer->notify.option = dup_spoolss_NotifyOption(Printer, option);
2793 fstrcpy(Printer->notify.localmachine, r->in.local_machine);
2795 /* Connect to the client machine and send a ReplyOpenPrinter */
2797 if ( Printer->printer_type == SPLHND_SERVER)
2798 snum = -1;
2799 else if ( (Printer->printer_type == SPLHND_PRINTER) &&
2800 !get_printer_snum(p, r->in.handle, &snum, NULL) )
2801 return WERR_BADFID;
2803 if (!interpret_string_addr(&client_ss, p->client_address,
2804 AI_NUMERICHOST)) {
2805 return WERR_SERVER_UNAVAILABLE;
2808 if(!srv_spoolss_replyopenprinter(snum, Printer->notify.localmachine,
2809 Printer->notify.printerlocal, 1,
2810 &Printer->notify.client_hnd, &client_ss))
2811 return WERR_SERVER_UNAVAILABLE;
2813 Printer->notify.client_connected = true;
2815 return WERR_OK;
2818 /*******************************************************************
2819 * fill a notify_info_data with the servername
2820 ********************************************************************/
2822 void spoolss_notify_server_name(int snum,
2823 struct spoolss_Notify *data,
2824 print_queue_struct *queue,
2825 NT_PRINTER_INFO_LEVEL *printer,
2826 TALLOC_CTX *mem_ctx)
2828 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, printer->info_2->servername);
2831 /*******************************************************************
2832 * fill a notify_info_data with the printername (not including the servername).
2833 ********************************************************************/
2835 void spoolss_notify_printer_name(int snum,
2836 struct spoolss_Notify *data,
2837 print_queue_struct *queue,
2838 NT_PRINTER_INFO_LEVEL *printer,
2839 TALLOC_CTX *mem_ctx)
2841 /* the notify name should not contain the \\server\ part */
2842 char *p = strrchr(printer->info_2->printername, '\\');
2844 if (!p) {
2845 p = printer->info_2->printername;
2846 } else {
2847 p++;
2850 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, p);
2853 /*******************************************************************
2854 * fill a notify_info_data with the servicename
2855 ********************************************************************/
2857 void spoolss_notify_share_name(int snum,
2858 struct spoolss_Notify *data,
2859 print_queue_struct *queue,
2860 NT_PRINTER_INFO_LEVEL *printer,
2861 TALLOC_CTX *mem_ctx)
2863 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, lp_servicename(snum));
2866 /*******************************************************************
2867 * fill a notify_info_data with the port name
2868 ********************************************************************/
2870 void spoolss_notify_port_name(int snum,
2871 struct spoolss_Notify *data,
2872 print_queue_struct *queue,
2873 NT_PRINTER_INFO_LEVEL *printer,
2874 TALLOC_CTX *mem_ctx)
2876 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, printer->info_2->portname);
2879 /*******************************************************************
2880 * fill a notify_info_data with the printername
2881 * but it doesn't exist, have to see what to do
2882 ********************************************************************/
2884 void spoolss_notify_driver_name(int snum,
2885 struct spoolss_Notify *data,
2886 print_queue_struct *queue,
2887 NT_PRINTER_INFO_LEVEL *printer,
2888 TALLOC_CTX *mem_ctx)
2890 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, printer->info_2->drivername);
2893 /*******************************************************************
2894 * fill a notify_info_data with the comment
2895 ********************************************************************/
2897 void spoolss_notify_comment(int snum,
2898 struct spoolss_Notify *data,
2899 print_queue_struct *queue,
2900 NT_PRINTER_INFO_LEVEL *printer,
2901 TALLOC_CTX *mem_ctx)
2903 char *p;
2905 if (*printer->info_2->comment == '\0') {
2906 p = lp_comment(snum);
2907 } else {
2908 p = printer->info_2->comment;
2911 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, printer->info_2->comment);
2914 /*******************************************************************
2915 * fill a notify_info_data with the comment
2916 * location = "Room 1, floor 2, building 3"
2917 ********************************************************************/
2919 void spoolss_notify_location(int snum,
2920 struct spoolss_Notify *data,
2921 print_queue_struct *queue,
2922 NT_PRINTER_INFO_LEVEL *printer,
2923 TALLOC_CTX *mem_ctx)
2925 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, printer->info_2->location);
2928 /*******************************************************************
2929 * fill a notify_info_data with the device mode
2930 * jfm:xxxx don't to it for know but that's a real problem !!!
2931 ********************************************************************/
2933 static void spoolss_notify_devmode(int snum,
2934 struct spoolss_Notify *data,
2935 print_queue_struct *queue,
2936 NT_PRINTER_INFO_LEVEL *printer,
2937 TALLOC_CTX *mem_ctx)
2939 /* for a dummy implementation we have to zero the fields */
2940 SETUP_SPOOLSS_NOTIFY_DATA_DEVMODE(data, NULL);
2943 /*******************************************************************
2944 * fill a notify_info_data with the separator file name
2945 ********************************************************************/
2947 void spoolss_notify_sepfile(int snum,
2948 struct spoolss_Notify *data,
2949 print_queue_struct *queue,
2950 NT_PRINTER_INFO_LEVEL *printer,
2951 TALLOC_CTX *mem_ctx)
2953 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, printer->info_2->sepfile);
2956 /*******************************************************************
2957 * fill a notify_info_data with the print processor
2958 * jfm:xxxx return always winprint to indicate we don't do anything to it
2959 ********************************************************************/
2961 void spoolss_notify_print_processor(int snum,
2962 struct spoolss_Notify *data,
2963 print_queue_struct *queue,
2964 NT_PRINTER_INFO_LEVEL *printer,
2965 TALLOC_CTX *mem_ctx)
2967 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, printer->info_2->printprocessor);
2970 /*******************************************************************
2971 * fill a notify_info_data with the print processor options
2972 * jfm:xxxx send an empty string
2973 ********************************************************************/
2975 void spoolss_notify_parameters(int snum,
2976 struct spoolss_Notify *data,
2977 print_queue_struct *queue,
2978 NT_PRINTER_INFO_LEVEL *printer,
2979 TALLOC_CTX *mem_ctx)
2981 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, printer->info_2->parameters);
2984 /*******************************************************************
2985 * fill a notify_info_data with the data type
2986 * jfm:xxxx always send RAW as data type
2987 ********************************************************************/
2989 void spoolss_notify_datatype(int snum,
2990 struct spoolss_Notify *data,
2991 print_queue_struct *queue,
2992 NT_PRINTER_INFO_LEVEL *printer,
2993 TALLOC_CTX *mem_ctx)
2995 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, printer->info_2->datatype);
2998 /*******************************************************************
2999 * fill a notify_info_data with the security descriptor
3000 * jfm:xxxx send an null pointer to say no security desc
3001 * have to implement security before !
3002 ********************************************************************/
3004 static void spoolss_notify_security_desc(int snum,
3005 struct spoolss_Notify *data,
3006 print_queue_struct *queue,
3007 NT_PRINTER_INFO_LEVEL *printer,
3008 TALLOC_CTX *mem_ctx)
3010 SETUP_SPOOLSS_NOTIFY_DATA_SECDESC(data,
3011 printer->info_2->secdesc_buf->sd_size,
3012 printer->info_2->secdesc_buf->sd);
3015 /*******************************************************************
3016 * fill a notify_info_data with the attributes
3017 * jfm:xxxx a samba printer is always shared
3018 ********************************************************************/
3020 void spoolss_notify_attributes(int snum,
3021 struct spoolss_Notify *data,
3022 print_queue_struct *queue,
3023 NT_PRINTER_INFO_LEVEL *printer,
3024 TALLOC_CTX *mem_ctx)
3026 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, printer->info_2->attributes);
3029 /*******************************************************************
3030 * fill a notify_info_data with the priority
3031 ********************************************************************/
3033 static void spoolss_notify_priority(int snum,
3034 struct spoolss_Notify *data,
3035 print_queue_struct *queue,
3036 NT_PRINTER_INFO_LEVEL *printer,
3037 TALLOC_CTX *mem_ctx)
3039 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, printer->info_2->priority);
3042 /*******************************************************************
3043 * fill a notify_info_data with the default priority
3044 ********************************************************************/
3046 static void spoolss_notify_default_priority(int snum,
3047 struct spoolss_Notify *data,
3048 print_queue_struct *queue,
3049 NT_PRINTER_INFO_LEVEL *printer,
3050 TALLOC_CTX *mem_ctx)
3052 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, printer->info_2->default_priority);
3055 /*******************************************************************
3056 * fill a notify_info_data with the start time
3057 ********************************************************************/
3059 static void spoolss_notify_start_time(int snum,
3060 struct spoolss_Notify *data,
3061 print_queue_struct *queue,
3062 NT_PRINTER_INFO_LEVEL *printer,
3063 TALLOC_CTX *mem_ctx)
3065 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, printer->info_2->starttime);
3068 /*******************************************************************
3069 * fill a notify_info_data with the until time
3070 ********************************************************************/
3072 static void spoolss_notify_until_time(int snum,
3073 struct spoolss_Notify *data,
3074 print_queue_struct *queue,
3075 NT_PRINTER_INFO_LEVEL *printer,
3076 TALLOC_CTX *mem_ctx)
3078 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, printer->info_2->untiltime);
3081 /*******************************************************************
3082 * fill a notify_info_data with the status
3083 ********************************************************************/
3085 static void spoolss_notify_status(int snum,
3086 struct spoolss_Notify *data,
3087 print_queue_struct *queue,
3088 NT_PRINTER_INFO_LEVEL *printer,
3089 TALLOC_CTX *mem_ctx)
3091 print_status_struct status;
3093 print_queue_length(snum, &status);
3094 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, status.status);
3097 /*******************************************************************
3098 * fill a notify_info_data with the number of jobs queued
3099 ********************************************************************/
3101 void spoolss_notify_cjobs(int snum,
3102 struct spoolss_Notify *data,
3103 print_queue_struct *queue,
3104 NT_PRINTER_INFO_LEVEL *printer,
3105 TALLOC_CTX *mem_ctx)
3107 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, print_queue_length(snum, NULL));
3110 /*******************************************************************
3111 * fill a notify_info_data with the average ppm
3112 ********************************************************************/
3114 static void spoolss_notify_average_ppm(int snum,
3115 struct spoolss_Notify *data,
3116 print_queue_struct *queue,
3117 NT_PRINTER_INFO_LEVEL *printer,
3118 TALLOC_CTX *mem_ctx)
3120 /* always respond 8 pages per minutes */
3121 /* a little hard ! */
3122 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, printer->info_2->averageppm);
3125 /*******************************************************************
3126 * fill a notify_info_data with username
3127 ********************************************************************/
3129 static void spoolss_notify_username(int snum,
3130 struct spoolss_Notify *data,
3131 print_queue_struct *queue,
3132 NT_PRINTER_INFO_LEVEL *printer,
3133 TALLOC_CTX *mem_ctx)
3135 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, queue->fs_user);
3138 /*******************************************************************
3139 * fill a notify_info_data with job status
3140 ********************************************************************/
3142 static void spoolss_notify_job_status(int snum,
3143 struct spoolss_Notify *data,
3144 print_queue_struct *queue,
3145 NT_PRINTER_INFO_LEVEL *printer,
3146 TALLOC_CTX *mem_ctx)
3148 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, nt_printj_status(queue->status));
3151 /*******************************************************************
3152 * fill a notify_info_data with job name
3153 ********************************************************************/
3155 static void spoolss_notify_job_name(int snum,
3156 struct spoolss_Notify *data,
3157 print_queue_struct *queue,
3158 NT_PRINTER_INFO_LEVEL *printer,
3159 TALLOC_CTX *mem_ctx)
3161 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, queue->fs_file);
3164 /*******************************************************************
3165 * fill a notify_info_data with job status
3166 ********************************************************************/
3168 static void spoolss_notify_job_status_string(int snum,
3169 struct spoolss_Notify *data,
3170 print_queue_struct *queue,
3171 NT_PRINTER_INFO_LEVEL *printer,
3172 TALLOC_CTX *mem_ctx)
3175 * Now we're returning job status codes we just return a "" here. JRA.
3178 const char *p = "";
3180 #if 0 /* NO LONGER NEEDED - JRA. 02/22/2001 */
3181 p = "unknown";
3183 switch (queue->status) {
3184 case LPQ_QUEUED:
3185 p = "Queued";
3186 break;
3187 case LPQ_PAUSED:
3188 p = ""; /* NT provides the paused string */
3189 break;
3190 case LPQ_SPOOLING:
3191 p = "Spooling";
3192 break;
3193 case LPQ_PRINTING:
3194 p = "Printing";
3195 break;
3197 #endif /* NO LONGER NEEDED. */
3199 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, p);
3202 /*******************************************************************
3203 * fill a notify_info_data with job time
3204 ********************************************************************/
3206 static void spoolss_notify_job_time(int snum,
3207 struct spoolss_Notify *data,
3208 print_queue_struct *queue,
3209 NT_PRINTER_INFO_LEVEL *printer,
3210 TALLOC_CTX *mem_ctx)
3212 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, 0);
3215 /*******************************************************************
3216 * fill a notify_info_data with job size
3217 ********************************************************************/
3219 static void spoolss_notify_job_size(int snum,
3220 struct spoolss_Notify *data,
3221 print_queue_struct *queue,
3222 NT_PRINTER_INFO_LEVEL *printer,
3223 TALLOC_CTX *mem_ctx)
3225 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, queue->size);
3228 /*******************************************************************
3229 * fill a notify_info_data with page info
3230 ********************************************************************/
3231 static void spoolss_notify_total_pages(int snum,
3232 struct spoolss_Notify *data,
3233 print_queue_struct *queue,
3234 NT_PRINTER_INFO_LEVEL *printer,
3235 TALLOC_CTX *mem_ctx)
3237 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, queue->page_count);
3240 /*******************************************************************
3241 * fill a notify_info_data with pages printed info.
3242 ********************************************************************/
3243 static void spoolss_notify_pages_printed(int snum,
3244 struct spoolss_Notify *data,
3245 print_queue_struct *queue,
3246 NT_PRINTER_INFO_LEVEL *printer,
3247 TALLOC_CTX *mem_ctx)
3249 /* Add code when back-end tracks this */
3250 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, 0);
3253 /*******************************************************************
3254 Fill a notify_info_data with job position.
3255 ********************************************************************/
3257 static void spoolss_notify_job_position(int snum,
3258 struct spoolss_Notify *data,
3259 print_queue_struct *queue,
3260 NT_PRINTER_INFO_LEVEL *printer,
3261 TALLOC_CTX *mem_ctx)
3263 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, queue->job);
3266 /*******************************************************************
3267 Fill a notify_info_data with submitted time.
3268 ********************************************************************/
3270 static void spoolss_notify_submitted_time(int snum,
3271 struct spoolss_Notify *data,
3272 print_queue_struct *queue,
3273 NT_PRINTER_INFO_LEVEL *printer,
3274 TALLOC_CTX *mem_ctx)
3276 data->data.string.string = NULL;
3277 data->data.string.size = 0;
3279 init_systemtime_buffer(mem_ctx, gmtime(&queue->time),
3280 &data->data.string.string,
3281 &data->data.string.size);
3285 struct s_notify_info_data_table
3287 enum spoolss_NotifyType type;
3288 uint16_t field;
3289 const char *name;
3290 enum spoolss_NotifyTable variable_type;
3291 void (*fn) (int snum, struct spoolss_Notify *data,
3292 print_queue_struct *queue,
3293 NT_PRINTER_INFO_LEVEL *printer, TALLOC_CTX *mem_ctx);
3296 /* A table describing the various print notification constants and
3297 whether the notification data is a pointer to a variable sized
3298 buffer, a one value uint32_t or a two value uint32_t. */
3300 static const struct s_notify_info_data_table notify_info_data_table[] =
3302 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_SERVER_NAME, "PRINTER_NOTIFY_FIELD_SERVER_NAME", NOTIFY_TABLE_STRING, spoolss_notify_server_name },
3303 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PRINTER_NAME, "PRINTER_NOTIFY_FIELD_PRINTER_NAME", NOTIFY_TABLE_STRING, spoolss_notify_printer_name },
3304 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_SHARE_NAME, "PRINTER_NOTIFY_FIELD_SHARE_NAME", NOTIFY_TABLE_STRING, spoolss_notify_share_name },
3305 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PORT_NAME, "PRINTER_NOTIFY_FIELD_PORT_NAME", NOTIFY_TABLE_STRING, spoolss_notify_port_name },
3306 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_DRIVER_NAME, "PRINTER_NOTIFY_FIELD_DRIVER_NAME", NOTIFY_TABLE_STRING, spoolss_notify_driver_name },
3307 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_COMMENT, "PRINTER_NOTIFY_FIELD_COMMENT", NOTIFY_TABLE_STRING, spoolss_notify_comment },
3308 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_LOCATION, "PRINTER_NOTIFY_FIELD_LOCATION", NOTIFY_TABLE_STRING, spoolss_notify_location },
3309 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_DEVMODE, "PRINTER_NOTIFY_FIELD_DEVMODE", NOTIFY_TABLE_DEVMODE, spoolss_notify_devmode },
3310 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_SEPFILE, "PRINTER_NOTIFY_FIELD_SEPFILE", NOTIFY_TABLE_STRING, spoolss_notify_sepfile },
3311 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PRINT_PROCESSOR, "PRINTER_NOTIFY_FIELD_PRINT_PROCESSOR", NOTIFY_TABLE_STRING, spoolss_notify_print_processor },
3312 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PARAMETERS, "PRINTER_NOTIFY_FIELD_PARAMETERS", NOTIFY_TABLE_STRING, spoolss_notify_parameters },
3313 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_DATATYPE, "PRINTER_NOTIFY_FIELD_DATATYPE", NOTIFY_TABLE_STRING, spoolss_notify_datatype },
3314 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_SECURITY_DESCRIPTOR, "PRINTER_NOTIFY_FIELD_SECURITY_DESCRIPTOR", NOTIFY_TABLE_SECURITYDESCRIPTOR, spoolss_notify_security_desc },
3315 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_ATTRIBUTES, "PRINTER_NOTIFY_FIELD_ATTRIBUTES", NOTIFY_TABLE_DWORD, spoolss_notify_attributes },
3316 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PRIORITY, "PRINTER_NOTIFY_FIELD_PRIORITY", NOTIFY_TABLE_DWORD, spoolss_notify_priority },
3317 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_DEFAULT_PRIORITY, "PRINTER_NOTIFY_FIELD_DEFAULT_PRIORITY", NOTIFY_TABLE_DWORD, spoolss_notify_default_priority },
3318 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_START_TIME, "PRINTER_NOTIFY_FIELD_START_TIME", NOTIFY_TABLE_DWORD, spoolss_notify_start_time },
3319 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_UNTIL_TIME, "PRINTER_NOTIFY_FIELD_UNTIL_TIME", NOTIFY_TABLE_DWORD, spoolss_notify_until_time },
3320 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_STATUS, "PRINTER_NOTIFY_FIELD_STATUS", NOTIFY_TABLE_DWORD, spoolss_notify_status },
3321 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_STATUS_STRING, "PRINTER_NOTIFY_FIELD_STATUS_STRING", NOTIFY_TABLE_STRING, NULL },
3322 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_CJOBS, "PRINTER_NOTIFY_FIELD_CJOBS", NOTIFY_TABLE_DWORD, spoolss_notify_cjobs },
3323 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_AVERAGE_PPM, "PRINTER_NOTIFY_FIELD_AVERAGE_PPM", NOTIFY_TABLE_DWORD, spoolss_notify_average_ppm },
3324 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_TOTAL_PAGES, "PRINTER_NOTIFY_FIELD_TOTAL_PAGES", NOTIFY_TABLE_DWORD, NULL },
3325 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PAGES_PRINTED, "PRINTER_NOTIFY_FIELD_PAGES_PRINTED", NOTIFY_TABLE_DWORD, NULL },
3326 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_TOTAL_BYTES, "PRINTER_NOTIFY_FIELD_TOTAL_BYTES", NOTIFY_TABLE_DWORD, NULL },
3327 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_BYTES_PRINTED, "PRINTER_NOTIFY_FIELD_BYTES_PRINTED", NOTIFY_TABLE_DWORD, NULL },
3328 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_PRINTER_NAME, "JOB_NOTIFY_FIELD_PRINTER_NAME", NOTIFY_TABLE_STRING, spoolss_notify_printer_name },
3329 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_MACHINE_NAME, "JOB_NOTIFY_FIELD_MACHINE_NAME", NOTIFY_TABLE_STRING, spoolss_notify_server_name },
3330 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_PORT_NAME, "JOB_NOTIFY_FIELD_PORT_NAME", NOTIFY_TABLE_STRING, spoolss_notify_port_name },
3331 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_USER_NAME, "JOB_NOTIFY_FIELD_USER_NAME", NOTIFY_TABLE_STRING, spoolss_notify_username },
3332 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_NOTIFY_NAME, "JOB_NOTIFY_FIELD_NOTIFY_NAME", NOTIFY_TABLE_STRING, spoolss_notify_username },
3333 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_DATATYPE, "JOB_NOTIFY_FIELD_DATATYPE", NOTIFY_TABLE_STRING, spoolss_notify_datatype },
3334 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_PRINT_PROCESSOR, "JOB_NOTIFY_FIELD_PRINT_PROCESSOR", NOTIFY_TABLE_STRING, spoolss_notify_print_processor },
3335 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_PARAMETERS, "JOB_NOTIFY_FIELD_PARAMETERS", NOTIFY_TABLE_STRING, spoolss_notify_parameters },
3336 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_DRIVER_NAME, "JOB_NOTIFY_FIELD_DRIVER_NAME", NOTIFY_TABLE_STRING, spoolss_notify_driver_name },
3337 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_DEVMODE, "JOB_NOTIFY_FIELD_DEVMODE", NOTIFY_TABLE_DEVMODE, spoolss_notify_devmode },
3338 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_STATUS, "JOB_NOTIFY_FIELD_STATUS", NOTIFY_TABLE_DWORD, spoolss_notify_job_status },
3339 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_STATUS_STRING, "JOB_NOTIFY_FIELD_STATUS_STRING", NOTIFY_TABLE_STRING, spoolss_notify_job_status_string },
3340 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_SECURITY_DESCRIPTOR, "JOB_NOTIFY_FIELD_SECURITY_DESCRIPTOR", NOTIFY_TABLE_SECURITYDESCRIPTOR, NULL },
3341 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_DOCUMENT, "JOB_NOTIFY_FIELD_DOCUMENT", NOTIFY_TABLE_STRING, spoolss_notify_job_name },
3342 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_PRIORITY, "JOB_NOTIFY_FIELD_PRIORITY", NOTIFY_TABLE_DWORD, spoolss_notify_priority },
3343 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_POSITION, "JOB_NOTIFY_FIELD_POSITION", NOTIFY_TABLE_DWORD, spoolss_notify_job_position },
3344 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_SUBMITTED, "JOB_NOTIFY_FIELD_SUBMITTED", NOTIFY_TABLE_TIME, spoolss_notify_submitted_time },
3345 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_START_TIME, "JOB_NOTIFY_FIELD_START_TIME", NOTIFY_TABLE_DWORD, spoolss_notify_start_time },
3346 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_UNTIL_TIME, "JOB_NOTIFY_FIELD_UNTIL_TIME", NOTIFY_TABLE_DWORD, spoolss_notify_until_time },
3347 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_TIME, "JOB_NOTIFY_FIELD_TIME", NOTIFY_TABLE_DWORD, spoolss_notify_job_time },
3348 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_TOTAL_PAGES, "JOB_NOTIFY_FIELD_TOTAL_PAGES", NOTIFY_TABLE_DWORD, spoolss_notify_total_pages },
3349 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_PAGES_PRINTED, "JOB_NOTIFY_FIELD_PAGES_PRINTED", NOTIFY_TABLE_DWORD, spoolss_notify_pages_printed },
3350 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_TOTAL_BYTES, "JOB_NOTIFY_FIELD_TOTAL_BYTES", NOTIFY_TABLE_DWORD, spoolss_notify_job_size },
3353 /*******************************************************************
3354 Return the variable_type of info_data structure.
3355 ********************************************************************/
3357 static uint32_t variable_type_of_notify_info_data(enum spoolss_NotifyType type,
3358 uint16_t field)
3360 int i=0;
3362 for (i = 0; i < ARRAY_SIZE(notify_info_data_table); i++) {
3363 if ( (notify_info_data_table[i].type == type) &&
3364 (notify_info_data_table[i].field == field) ) {
3365 return notify_info_data_table[i].variable_type;
3369 DEBUG(5, ("invalid notify data type %d/%d\n", type, field));
3371 return 0;
3374 /****************************************************************************
3375 ****************************************************************************/
3377 static bool search_notify(enum spoolss_NotifyType type,
3378 uint16_t field,
3379 int *value)
3381 int i;
3383 for (i = 0; i < ARRAY_SIZE(notify_info_data_table); i++) {
3384 if (notify_info_data_table[i].type == type &&
3385 notify_info_data_table[i].field == field &&
3386 notify_info_data_table[i].fn != NULL) {
3387 *value = i;
3388 return true;
3392 return false;
3395 /****************************************************************************
3396 ****************************************************************************/
3398 void construct_info_data(struct spoolss_Notify *info_data,
3399 enum spoolss_NotifyType type,
3400 uint16_t field,
3401 int id)
3403 info_data->type = type;
3404 info_data->field.field = field;
3405 info_data->variable_type = variable_type_of_notify_info_data(type, field);
3406 info_data->job_id = id;
3409 /*******************************************************************
3411 * fill a notify_info struct with info asked
3413 ********************************************************************/
3415 static bool construct_notify_printer_info(Printer_entry *print_hnd,
3416 struct spoolss_NotifyInfo *info,
3417 int snum,
3418 const struct spoolss_NotifyOptionType *option_type,
3419 uint32_t id,
3420 TALLOC_CTX *mem_ctx)
3422 int field_num,j;
3423 enum spoolss_NotifyType type;
3424 uint16_t field;
3426 struct spoolss_Notify *current_data;
3427 NT_PRINTER_INFO_LEVEL *printer = NULL;
3428 print_queue_struct *queue=NULL;
3430 type = option_type->type;
3432 DEBUG(4,("construct_notify_printer_info: Notify type: [%s], number of notify info: [%d] on printer: [%s]\n",
3433 (type == PRINTER_NOTIFY_TYPE ? "PRINTER_NOTIFY_TYPE" : "JOB_NOTIFY_TYPE"),
3434 option_type->count, lp_servicename(snum)));
3436 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &printer, 2, lp_const_servicename(snum))))
3437 return false;
3439 for(field_num=0; field_num < option_type->count; field_num++) {
3440 field = option_type->fields[field_num].field;
3442 DEBUG(4,("construct_notify_printer_info: notify [%d]: type [%x], field [%x]\n", field_num, type, field));
3444 if (!search_notify(type, field, &j) )
3445 continue;
3447 info->notifies = TALLOC_REALLOC_ARRAY(info, info->notifies,
3448 struct spoolss_Notify,
3449 info->count + 1);
3450 if (info->notifies == NULL) {
3451 DEBUG(2,("construct_notify_printer_info: failed to enlarge buffer info->data!\n"));
3452 free_a_printer(&printer, 2);
3453 return false;
3456 current_data = &info->notifies[info->count];
3458 construct_info_data(current_data, type, field, id);
3460 DEBUG(10,("construct_notify_printer_info: calling [%s] snum=%d printername=[%s])\n",
3461 notify_info_data_table[j].name, snum, printer->info_2->printername ));
3463 notify_info_data_table[j].fn(snum, current_data, queue,
3464 printer, mem_ctx);
3466 info->count++;
3469 free_a_printer(&printer, 2);
3470 return true;
3473 /*******************************************************************
3475 * fill a notify_info struct with info asked
3477 ********************************************************************/
3479 static bool construct_notify_jobs_info(print_queue_struct *queue,
3480 struct spoolss_NotifyInfo *info,
3481 NT_PRINTER_INFO_LEVEL *printer,
3482 int snum,
3483 const struct spoolss_NotifyOptionType *option_type,
3484 uint32_t id,
3485 TALLOC_CTX *mem_ctx)
3487 int field_num,j;
3488 enum spoolss_NotifyType type;
3489 uint16_t field;
3490 struct spoolss_Notify *current_data;
3492 DEBUG(4,("construct_notify_jobs_info\n"));
3494 type = option_type->type;
3496 DEBUGADD(4,("Notify type: [%s], number of notify info: [%d]\n",
3497 (type == PRINTER_NOTIFY_TYPE ? "PRINTER_NOTIFY_TYPE" : "JOB_NOTIFY_TYPE"),
3498 option_type->count));
3500 for(field_num=0; field_num<option_type->count; field_num++) {
3501 field = option_type->fields[field_num].field;
3503 if (!search_notify(type, field, &j) )
3504 continue;
3506 info->notifies = TALLOC_REALLOC_ARRAY(info, info->notifies,
3507 struct spoolss_Notify,
3508 info->count + 1);
3509 if (info->notifies == NULL) {
3510 DEBUG(2,("construct_notify_jobs_info: failed to enlarg buffer info->data!\n"));
3511 return false;
3514 current_data=&(info->notifies[info->count]);
3516 construct_info_data(current_data, type, field, id);
3517 notify_info_data_table[j].fn(snum, current_data, queue,
3518 printer, mem_ctx);
3519 info->count++;
3522 return true;
3526 * JFM: The enumeration is not that simple, it's even non obvious.
3528 * let's take an example: I want to monitor the PRINTER SERVER for
3529 * the printer's name and the number of jobs currently queued.
3530 * So in the NOTIFY_OPTION, I have one NOTIFY_OPTION_TYPE structure.
3531 * Its type is PRINTER_NOTIFY_TYPE and it has 2 fields NAME and CJOBS.
3533 * I have 3 printers on the back of my server.
3535 * Now the response is a NOTIFY_INFO structure, with 6 NOTIFY_INFO_DATA
3536 * structures.
3537 * Number Data Id
3538 * 1 printer 1 name 1
3539 * 2 printer 1 cjob 1
3540 * 3 printer 2 name 2
3541 * 4 printer 2 cjob 2
3542 * 5 printer 3 name 3
3543 * 6 printer 3 name 3
3545 * that's the print server case, the printer case is even worse.
3548 /*******************************************************************
3550 * enumerate all printers on the printserver
3551 * fill a notify_info struct with info asked
3553 ********************************************************************/
3555 static WERROR printserver_notify_info(pipes_struct *p,
3556 struct policy_handle *hnd,
3557 struct spoolss_NotifyInfo *info,
3558 TALLOC_CTX *mem_ctx)
3560 int snum;
3561 Printer_entry *Printer = find_printer_index_by_hnd(p, hnd);
3562 int n_services=lp_numservices();
3563 int i;
3564 struct spoolss_NotifyOption *option;
3565 struct spoolss_NotifyOptionType option_type;
3567 DEBUG(4,("printserver_notify_info\n"));
3569 if (!Printer)
3570 return WERR_BADFID;
3572 option = Printer->notify.option;
3574 info->version = 2;
3575 info->notifies = NULL;
3576 info->count = 0;
3578 /* a bug in xp sp2 rc2 causes it to send a fnpcn request without
3579 sending a ffpcn() request first */
3581 if ( !option )
3582 return WERR_BADFID;
3584 for (i=0; i<option->count; i++) {
3585 option_type = option->types[i];
3587 if (option_type.type != PRINTER_NOTIFY_TYPE)
3588 continue;
3590 for (snum=0; snum<n_services; snum++)
3592 if ( lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) )
3593 construct_notify_printer_info ( Printer, info, snum, &option_type, snum, mem_ctx );
3597 #if 0
3599 * Debugging information, don't delete.
3602 DEBUG(1,("dumping the NOTIFY_INFO\n"));
3603 DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
3604 DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3606 for (i=0; i<info->count; i++) {
3607 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3608 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
3609 info->data[i].id, info->data[i].size, info->data[i].enc_type));
3611 #endif
3613 return WERR_OK;
3616 /*******************************************************************
3618 * fill a notify_info struct with info asked
3620 ********************************************************************/
3622 static WERROR printer_notify_info(pipes_struct *p, struct policy_handle *hnd,
3623 struct spoolss_NotifyInfo *info,
3624 TALLOC_CTX *mem_ctx)
3626 int snum;
3627 Printer_entry *Printer = find_printer_index_by_hnd(p, hnd);
3628 int i;
3629 uint32_t id;
3630 struct spoolss_NotifyOption *option;
3631 struct spoolss_NotifyOptionType option_type;
3632 int count,j;
3633 print_queue_struct *queue=NULL;
3634 print_status_struct status;
3636 DEBUG(4,("printer_notify_info\n"));
3638 if (!Printer)
3639 return WERR_BADFID;
3641 option = Printer->notify.option;
3642 id = 0x0;
3644 info->version = 2;
3645 info->notifies = NULL;
3646 info->count = 0;
3648 /* a bug in xp sp2 rc2 causes it to send a fnpcn request without
3649 sending a ffpcn() request first */
3651 if ( !option )
3652 return WERR_BADFID;
3654 get_printer_snum(p, hnd, &snum, NULL);
3656 for (i=0; i<option->count; i++) {
3657 option_type = option->types[i];
3659 switch (option_type.type) {
3660 case PRINTER_NOTIFY_TYPE:
3661 if(construct_notify_printer_info(Printer, info, snum,
3662 &option_type, id,
3663 mem_ctx))
3664 id--;
3665 break;
3667 case JOB_NOTIFY_TYPE: {
3668 NT_PRINTER_INFO_LEVEL *printer = NULL;
3670 count = print_queue_status(snum, &queue, &status);
3672 if (!W_ERROR_IS_OK(get_a_printer(Printer, &printer, 2, lp_const_servicename(snum))))
3673 goto done;
3675 for (j=0; j<count; j++) {
3676 construct_notify_jobs_info(&queue[j], info,
3677 printer, snum,
3678 &option_type,
3679 queue[j].job,
3680 mem_ctx);
3683 free_a_printer(&printer, 2);
3685 done:
3686 SAFE_FREE(queue);
3687 break;
3693 * Debugging information, don't delete.
3696 DEBUG(1,("dumping the NOTIFY_INFO\n"));
3697 DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
3698 DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3700 for (i=0; i<info->count; i++) {
3701 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3702 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
3703 info->data[i].id, info->data[i].size, info->data[i].enc_type));
3706 return WERR_OK;
3709 /****************************************************************
3710 _spoolss_RouterRefreshPrinterChangeNotify
3711 ****************************************************************/
3713 WERROR _spoolss_RouterRefreshPrinterChangeNotify(pipes_struct *p,
3714 struct spoolss_RouterRefreshPrinterChangeNotify *r)
3716 struct spoolss_NotifyInfo *info;
3718 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
3719 WERROR result = WERR_BADFID;
3721 /* we always have a spoolss_NotifyInfo struct */
3722 info = talloc_zero(p->mem_ctx, struct spoolss_NotifyInfo);
3723 if (!info) {
3724 result = WERR_NOMEM;
3725 goto done;
3728 *r->out.info = info;
3730 if (!Printer) {
3731 DEBUG(2,("_spoolss_RouterRefreshPrinterChangeNotify: "
3732 "Invalid handle (%s:%u:%u).\n",
3733 OUR_HANDLE(r->in.handle)));
3734 goto done;
3737 DEBUG(4,("Printer type %x\n",Printer->printer_type));
3740 * We are now using the change value, and
3741 * I should check for PRINTER_NOTIFY_OPTIONS_REFRESH but as
3742 * I don't have a global notification system, I'm sending back all the
3743 * informations even when _NOTHING_ has changed.
3746 /* We need to keep track of the change value to send back in
3747 RRPCN replies otherwise our updates are ignored. */
3749 Printer->notify.fnpcn = true;
3751 if (Printer->notify.client_connected) {
3752 DEBUG(10,("_spoolss_RouterRefreshPrinterChangeNotify: "
3753 "Saving change value in request [%x]\n",
3754 r->in.change_low));
3755 Printer->notify.change = r->in.change_low;
3758 /* just ignore the spoolss_NotifyOption */
3760 switch (Printer->printer_type) {
3761 case SPLHND_SERVER:
3762 result = printserver_notify_info(p, r->in.handle,
3763 info, p->mem_ctx);
3764 break;
3766 case SPLHND_PRINTER:
3767 result = printer_notify_info(p, r->in.handle,
3768 info, p->mem_ctx);
3769 break;
3772 Printer->notify.fnpcn = false;
3774 done:
3775 return result;
3778 /********************************************************************
3779 * construct_printer_info_0
3780 * fill a printer_info_0 struct
3781 ********************************************************************/
3783 static WERROR construct_printer_info0(TALLOC_CTX *mem_ctx,
3784 const NT_PRINTER_INFO_LEVEL *ntprinter,
3785 struct spoolss_PrinterInfo0 *r,
3786 int snum)
3788 int count;
3789 counter_printer_0 *session_counter;
3790 time_t setuptime;
3791 print_status_struct status;
3793 r->printername = talloc_strdup(mem_ctx, ntprinter->info_2->printername);
3794 W_ERROR_HAVE_NO_MEMORY(r->printername);
3796 r->servername = talloc_strdup(mem_ctx, ntprinter->info_2->servername);
3797 W_ERROR_HAVE_NO_MEMORY(r->servername);
3799 count = print_queue_length(snum, &status);
3801 /* check if we already have a counter for this printer */
3802 for (session_counter = counter_list; session_counter; session_counter = session_counter->next) {
3803 if (session_counter->snum == snum)
3804 break;
3807 /* it's the first time, add it to the list */
3808 if (session_counter == NULL) {
3809 session_counter = SMB_MALLOC_P(counter_printer_0);
3810 W_ERROR_HAVE_NO_MEMORY(session_counter);
3811 ZERO_STRUCTP(session_counter);
3812 session_counter->snum = snum;
3813 session_counter->counter = 0;
3814 DLIST_ADD(counter_list, session_counter);
3817 /* increment it */
3818 session_counter->counter++;
3820 r->cjobs = count;
3821 r->total_jobs = 0;
3822 r->total_bytes = 0;
3824 setuptime = (time_t)ntprinter->info_2->setuptime;
3826 init_systemtime(&r->time, gmtime(&setuptime));
3828 /* JFM:
3829 * the global_counter should be stored in a TDB as it's common to all the clients
3830 * and should be zeroed on samba startup
3832 r->global_counter = session_counter->counter;
3833 r->total_pages = 0;
3834 /* in 2.2 we reported ourselves as 0x0004 and 0x0565 */
3835 r->version = 0x0005; /* NT 5 */
3836 r->free_build = 0x0893; /* build 2195 */
3837 r->spooling = 0;
3838 r->max_spooling = 0;
3839 r->session_counter = session_counter->counter;
3840 r->num_error_out_of_paper = 0x0;
3841 r->num_error_not_ready = 0x0; /* number of print failure */
3842 r->job_error = 0x0;
3843 r->number_of_processors = 0x1;
3844 r->processor_type = PROCESSOR_INTEL_PENTIUM; /* 586 Pentium ? */
3845 r->high_part_total_bytes = 0x0;
3846 r->change_id = ntprinter->info_2->changeid; /* ChangeID in milliseconds*/
3847 r->last_error = WERR_OK;
3848 r->status = nt_printq_status(status.status);
3849 r->enumerate_network_printers = 0x0;
3850 r->c_setprinter = get_c_setprinter(); /* monotonically increasing sum of delta printer counts */
3851 r->processor_architecture = 0x0;
3852 r->processor_level = 0x6; /* 6 ???*/
3853 r->ref_ic = 0;
3854 r->reserved2 = 0;
3855 r->reserved3 = 0;
3857 return WERR_OK;
3860 /****************************************************************************
3861 Convert an NT_DEVICEMODE to a spoolss_DeviceMode structure. Both pointers
3862 should be valid upon entry
3863 ****************************************************************************/
3865 static WERROR convert_nt_devicemode(TALLOC_CTX *mem_ctx,
3866 struct spoolss_DeviceMode *r,
3867 const NT_DEVICEMODE *ntdevmode)
3869 if (!r || !ntdevmode) {
3870 return WERR_INVALID_PARAM;
3873 r->devicename = talloc_strdup(mem_ctx, ntdevmode->devicename);
3874 W_ERROR_HAVE_NO_MEMORY(r->devicename);
3876 r->specversion = ntdevmode->specversion;
3877 r->driverversion = ntdevmode->driverversion;
3878 r->size = ntdevmode->size;
3879 r->__driverextra_length = ntdevmode->driverextra;
3880 r->fields = ntdevmode->fields;
3882 r->orientation = ntdevmode->orientation;
3883 r->papersize = ntdevmode->papersize;
3884 r->paperlength = ntdevmode->paperlength;
3885 r->paperwidth = ntdevmode->paperwidth;
3886 r->scale = ntdevmode->scale;
3887 r->copies = ntdevmode->copies;
3888 r->defaultsource = ntdevmode->defaultsource;
3889 r->printquality = ntdevmode->printquality;
3890 r->color = ntdevmode->color;
3891 r->duplex = ntdevmode->duplex;
3892 r->yresolution = ntdevmode->yresolution;
3893 r->ttoption = ntdevmode->ttoption;
3894 r->collate = ntdevmode->collate;
3896 r->formname = talloc_strdup(mem_ctx, ntdevmode->formname);
3897 W_ERROR_HAVE_NO_MEMORY(r->formname);
3899 /* all 0 below are values that have not been set in the old parsing/copy
3900 * function, maybe they should... - gd */
3902 r->logpixels = 0;
3903 r->bitsperpel = 0;
3904 r->pelswidth = 0;
3905 r->pelsheight = 0;
3906 r->displayflags = 0;
3907 r->displayfrequency = 0;
3908 r->icmmethod = ntdevmode->icmmethod;
3909 r->icmintent = ntdevmode->icmintent;
3910 r->mediatype = ntdevmode->mediatype;
3911 r->dithertype = ntdevmode->dithertype;
3912 r->reserved1 = 0;
3913 r->reserved2 = 0;
3914 r->panningwidth = 0;
3915 r->panningheight = 0;
3917 if (ntdevmode->nt_dev_private != NULL) {
3918 r->driverextra_data = data_blob_talloc(mem_ctx,
3919 ntdevmode->nt_dev_private,
3920 ntdevmode->driverextra);
3921 W_ERROR_HAVE_NO_MEMORY(r->driverextra_data.data);
3924 return WERR_OK;
3928 /****************************************************************************
3929 Create a spoolss_DeviceMode struct. Returns talloced memory.
3930 ****************************************************************************/
3932 struct spoolss_DeviceMode *construct_dev_mode(TALLOC_CTX *mem_ctx,
3933 const char *servicename)
3935 WERROR result;
3936 NT_PRINTER_INFO_LEVEL *printer = NULL;
3937 struct spoolss_DeviceMode *devmode = NULL;
3939 DEBUG(7,("construct_dev_mode\n"));
3941 DEBUGADD(8,("getting printer characteristics\n"));
3943 if (!W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, servicename)))
3944 return NULL;
3946 if (!printer->info_2->devmode) {
3947 DEBUG(5, ("BONG! There was no device mode!\n"));
3948 goto done;
3951 devmode = TALLOC_ZERO_P(mem_ctx, struct spoolss_DeviceMode);
3952 if (!devmode) {
3953 DEBUG(2,("construct_dev_mode: talloc fail.\n"));
3954 goto done;
3957 DEBUGADD(8,("loading DEVICEMODE\n"));
3959 result = convert_nt_devicemode(mem_ctx, devmode, printer->info_2->devmode);
3960 if (!W_ERROR_IS_OK(result)) {
3961 TALLOC_FREE(devmode);
3964 done:
3965 free_a_printer(&printer,2);
3967 return devmode;
3970 /********************************************************************
3971 * construct_printer_info3
3972 * fill a spoolss_PrinterInfo3 struct
3973 ********************************************************************/
3975 static WERROR construct_printer_info3(TALLOC_CTX *mem_ctx,
3976 const NT_PRINTER_INFO_LEVEL *ntprinter,
3977 struct spoolss_PrinterInfo3 *r,
3978 int snum)
3980 /* These are the components of the SD we are returning. */
3982 if (ntprinter->info_2->secdesc_buf && ntprinter->info_2->secdesc_buf->sd_size != 0) {
3983 /* don't use talloc_steal() here unless you do a deep steal of all
3984 the SEC_DESC members */
3986 r->secdesc = dup_sec_desc(mem_ctx,
3987 ntprinter->info_2->secdesc_buf->sd);
3988 W_ERROR_HAVE_NO_MEMORY(r->secdesc);
3991 return WERR_OK;
3994 /********************************************************************
3995 * construct_printer_info4
3996 * fill a spoolss_PrinterInfo4 struct
3997 ********************************************************************/
3999 static WERROR construct_printer_info4(TALLOC_CTX *mem_ctx,
4000 const NT_PRINTER_INFO_LEVEL *ntprinter,
4001 struct spoolss_PrinterInfo4 *r,
4002 int snum)
4004 r->printername = talloc_strdup(mem_ctx, ntprinter->info_2->printername);
4005 W_ERROR_HAVE_NO_MEMORY(r->printername);
4006 r->servername = talloc_strdup(mem_ctx, ntprinter->info_2->servername);
4007 W_ERROR_HAVE_NO_MEMORY(r->servername);
4009 r->attributes = ntprinter->info_2->attributes;
4011 return WERR_OK;
4014 /********************************************************************
4015 * construct_printer_info5
4016 * fill a spoolss_PrinterInfo5 struct
4017 ********************************************************************/
4019 static WERROR construct_printer_info5(TALLOC_CTX *mem_ctx,
4020 const NT_PRINTER_INFO_LEVEL *ntprinter,
4021 struct spoolss_PrinterInfo5 *r,
4022 int snum)
4024 r->printername = talloc_strdup(mem_ctx, ntprinter->info_2->printername);
4025 W_ERROR_HAVE_NO_MEMORY(r->printername);
4026 r->portname = talloc_strdup(mem_ctx, ntprinter->info_2->portname);
4027 W_ERROR_HAVE_NO_MEMORY(r->portname);
4029 r->attributes = ntprinter->info_2->attributes;
4031 /* these two are not used by NT+ according to MSDN */
4033 r->device_not_selected_timeout = 0x0; /* have seen 0x3a98 */
4034 r->transmission_retry_timeout = 0x0; /* have seen 0xafc8 */
4036 return WERR_OK;
4039 /********************************************************************
4040 * construct_printer_info_6
4041 * fill a spoolss_PrinterInfo6 struct
4042 ********************************************************************/
4044 static WERROR construct_printer_info6(TALLOC_CTX *mem_ctx,
4045 const NT_PRINTER_INFO_LEVEL *ntprinter,
4046 struct spoolss_PrinterInfo6 *r,
4047 int snum)
4049 int count;
4050 print_status_struct status;
4052 count = print_queue_length(snum, &status);
4054 r->status = nt_printq_status(status.status);
4056 return WERR_OK;
4059 /********************************************************************
4060 * construct_printer_info7
4061 * fill a spoolss_PrinterInfo7 struct
4062 ********************************************************************/
4064 static WERROR construct_printer_info7(TALLOC_CTX *mem_ctx,
4065 Printer_entry *print_hnd,
4066 struct spoolss_PrinterInfo7 *r,
4067 int snum)
4069 struct GUID guid;
4071 if (is_printer_published(print_hnd, snum, &guid)) {
4072 r->guid = talloc_strdup_upper(mem_ctx, GUID_string2(mem_ctx, &guid));
4073 r->action = DSPRINT_PUBLISH;
4074 } else {
4075 r->guid = talloc_strdup(mem_ctx, "");
4076 r->action = DSPRINT_UNPUBLISH;
4078 W_ERROR_HAVE_NO_MEMORY(r->guid);
4080 return WERR_OK;
4083 /********************************************************************
4084 * construct_printer_info8
4085 * fill a spoolss_PrinterInfo8 struct
4086 ********************************************************************/
4088 static WERROR construct_printer_info8(TALLOC_CTX *mem_ctx,
4089 const NT_PRINTER_INFO_LEVEL *ntprinter,
4090 struct spoolss_DeviceModeInfo *r,
4091 int snum)
4093 struct spoolss_DeviceMode *devmode;
4094 WERROR result;
4096 if (!ntprinter->info_2->devmode) {
4097 r->devmode = NULL;
4098 return WERR_OK;
4101 devmode = TALLOC_ZERO_P(mem_ctx, struct spoolss_DeviceMode);
4102 W_ERROR_HAVE_NO_MEMORY(devmode);
4104 result = convert_nt_devicemode(mem_ctx, devmode, ntprinter->info_2->devmode);
4105 if (!W_ERROR_IS_OK(result)) {
4106 TALLOC_FREE(devmode);
4107 return result;
4110 r->devmode = devmode;
4112 return WERR_OK;
4116 /********************************************************************
4117 * construct_printer_info1
4118 * fill a spoolss_PrinterInfo1 struct
4119 ********************************************************************/
4121 static WERROR construct_printer_info1(TALLOC_CTX *mem_ctx,
4122 const NT_PRINTER_INFO_LEVEL *ntprinter,
4123 uint32_t flags,
4124 struct spoolss_PrinterInfo1 *r,
4125 int snum)
4127 r->flags = flags;
4129 r->description = talloc_asprintf(mem_ctx, "%s,%s,%s",
4130 ntprinter->info_2->printername,
4131 ntprinter->info_2->drivername,
4132 ntprinter->info_2->location);
4133 W_ERROR_HAVE_NO_MEMORY(r->description);
4135 if (*ntprinter->info_2->comment == '\0') {
4136 r->comment = talloc_strdup(mem_ctx, lp_comment(snum));
4137 } else {
4138 r->comment = talloc_strdup(mem_ctx, ntprinter->info_2->comment); /* saved comment */
4140 W_ERROR_HAVE_NO_MEMORY(r->comment);
4142 r->name = talloc_strdup(mem_ctx, ntprinter->info_2->printername);
4143 W_ERROR_HAVE_NO_MEMORY(r->name);
4145 return WERR_OK;
4148 /********************************************************************
4149 * construct_printer_info2
4150 * fill a spoolss_PrinterInfo2 struct
4151 ********************************************************************/
4153 static WERROR construct_printer_info2(TALLOC_CTX *mem_ctx,
4154 const NT_PRINTER_INFO_LEVEL *ntprinter,
4155 struct spoolss_PrinterInfo2 *r,
4156 int snum)
4158 int count;
4160 print_status_struct status;
4162 count = print_queue_length(snum, &status);
4164 r->servername = talloc_strdup(mem_ctx, ntprinter->info_2->servername);
4165 W_ERROR_HAVE_NO_MEMORY(r->servername);
4166 r->printername = talloc_strdup(mem_ctx, ntprinter->info_2->printername);
4167 W_ERROR_HAVE_NO_MEMORY(r->printername);
4168 r->sharename = talloc_strdup(mem_ctx, lp_servicename(snum));
4169 W_ERROR_HAVE_NO_MEMORY(r->sharename);
4170 r->portname = talloc_strdup(mem_ctx, ntprinter->info_2->portname);
4171 W_ERROR_HAVE_NO_MEMORY(r->portname);
4172 r->drivername = talloc_strdup(mem_ctx, ntprinter->info_2->drivername);
4173 W_ERROR_HAVE_NO_MEMORY(r->drivername);
4175 if (*ntprinter->info_2->comment == '\0') {
4176 r->comment = talloc_strdup(mem_ctx, lp_comment(snum));
4177 } else {
4178 r->comment = talloc_strdup(mem_ctx, ntprinter->info_2->comment);
4180 W_ERROR_HAVE_NO_MEMORY(r->comment);
4182 r->location = talloc_strdup(mem_ctx, ntprinter->info_2->location);
4183 W_ERROR_HAVE_NO_MEMORY(r->location);
4184 r->sepfile = talloc_strdup(mem_ctx, ntprinter->info_2->sepfile);
4185 W_ERROR_HAVE_NO_MEMORY(r->sepfile);
4186 r->printprocessor = talloc_strdup(mem_ctx, ntprinter->info_2->printprocessor);
4187 W_ERROR_HAVE_NO_MEMORY(r->printprocessor);
4188 r->datatype = talloc_strdup(mem_ctx, ntprinter->info_2->datatype);
4189 W_ERROR_HAVE_NO_MEMORY(r->datatype);
4190 r->parameters = talloc_strdup(mem_ctx, ntprinter->info_2->parameters);
4191 W_ERROR_HAVE_NO_MEMORY(r->parameters);
4193 r->attributes = ntprinter->info_2->attributes;
4195 r->priority = ntprinter->info_2->priority;
4196 r->defaultpriority = ntprinter->info_2->default_priority;
4197 r->starttime = ntprinter->info_2->starttime;
4198 r->untiltime = ntprinter->info_2->untiltime;
4199 r->status = nt_printq_status(status.status);
4200 r->cjobs = count;
4201 r->averageppm = ntprinter->info_2->averageppm;
4203 r->devmode = construct_dev_mode(mem_ctx, lp_const_servicename(snum));
4204 if (!r->devmode) {
4205 DEBUG(8,("Returning NULL Devicemode!\n"));
4208 r->secdesc = NULL;
4210 if (ntprinter->info_2->secdesc_buf && ntprinter->info_2->secdesc_buf->sd_size != 0) {
4211 /* don't use talloc_steal() here unless you do a deep steal of all
4212 the SEC_DESC members */
4214 r->secdesc = dup_sec_desc(mem_ctx, ntprinter->info_2->secdesc_buf->sd);
4217 return WERR_OK;
4220 /********************************************************************
4221 ********************************************************************/
4223 static bool snum_is_shared_printer(int snum)
4225 return (lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum));
4228 /********************************************************************
4229 Spoolss_enumprinters.
4230 ********************************************************************/
4232 static WERROR enum_all_printers_info_level(TALLOC_CTX *mem_ctx,
4233 uint32_t level,
4234 uint32_t flags,
4235 union spoolss_PrinterInfo **info_p,
4236 uint32_t *count_p)
4238 int snum;
4239 int n_services = lp_numservices();
4240 union spoolss_PrinterInfo *info = NULL;
4241 uint32_t count = 0;
4242 WERROR result = WERR_OK;
4244 *count_p = 0;
4245 *info_p = NULL;
4247 for (snum = 0; snum < n_services; snum++) {
4249 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4251 if (!snum_is_shared_printer(snum)) {
4252 continue;
4255 DEBUG(4,("Found a printer in smb.conf: %s[%x]\n",
4256 lp_servicename(snum), snum));
4258 info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
4259 union spoolss_PrinterInfo,
4260 count + 1);
4261 if (!info) {
4262 result = WERR_NOMEM;
4263 goto out;
4266 result = get_a_printer(NULL, &ntprinter, 2,
4267 lp_const_servicename(snum));
4268 if (!W_ERROR_IS_OK(result)) {
4269 goto out;
4272 switch (level) {
4273 case 0:
4274 result = construct_printer_info0(info, ntprinter,
4275 &info[count].info0, snum);
4276 break;
4277 case 1:
4278 result = construct_printer_info1(info, ntprinter, flags,
4279 &info[count].info1, snum);
4280 break;
4281 case 2:
4282 result = construct_printer_info2(info, ntprinter,
4283 &info[count].info2, snum);
4284 break;
4285 case 4:
4286 result = construct_printer_info4(info, ntprinter,
4287 &info[count].info4, snum);
4288 break;
4289 case 5:
4290 result = construct_printer_info5(info, ntprinter,
4291 &info[count].info5, snum);
4292 break;
4294 default:
4295 result = WERR_UNKNOWN_LEVEL;
4296 free_a_printer(&ntprinter, 2);
4297 goto out;
4300 free_a_printer(&ntprinter, 2);
4301 if (!W_ERROR_IS_OK(result)) {
4302 goto out;
4305 count++;
4308 *count_p = count;
4309 *info_p = info;
4311 out:
4312 if (!W_ERROR_IS_OK(result)) {
4313 TALLOC_FREE(info);
4314 return result;
4317 *info_p = info;
4319 return WERR_OK;
4322 /********************************************************************
4323 * handle enumeration of printers at level 0
4324 ********************************************************************/
4326 static WERROR enumprinters_level0(TALLOC_CTX *mem_ctx,
4327 uint32_t flags,
4328 const char *servername,
4329 union spoolss_PrinterInfo **info,
4330 uint32_t *count)
4332 DEBUG(4,("enum_all_printers_info_0\n"));
4334 return enum_all_printers_info_level(mem_ctx, 0, flags, info, count);
4338 /********************************************************************
4339 ********************************************************************/
4341 static WERROR enum_all_printers_info_1(TALLOC_CTX *mem_ctx,
4342 uint32_t flags,
4343 union spoolss_PrinterInfo **info,
4344 uint32_t *count)
4346 DEBUG(4,("enum_all_printers_info_1\n"));
4348 return enum_all_printers_info_level(mem_ctx, 1, flags, info, count);
4351 /********************************************************************
4352 enum_all_printers_info_1_local.
4353 *********************************************************************/
4355 static WERROR enum_all_printers_info_1_local(TALLOC_CTX *mem_ctx,
4356 union spoolss_PrinterInfo **info,
4357 uint32_t *count)
4359 DEBUG(4,("enum_all_printers_info_1_local\n"));
4361 return enum_all_printers_info_1(mem_ctx, PRINTER_ENUM_ICON8, info, count);
4364 /********************************************************************
4365 enum_all_printers_info_1_name.
4366 *********************************************************************/
4368 static WERROR enum_all_printers_info_1_name(TALLOC_CTX *mem_ctx,
4369 const char *name,
4370 union spoolss_PrinterInfo **info,
4371 uint32_t *count)
4373 const char *s = name;
4375 DEBUG(4,("enum_all_printers_info_1_name\n"));
4377 if ((name[0] == '\\') && (name[1] == '\\')) {
4378 s = name + 2;
4381 if (!is_myname_or_ipaddr(s)) {
4382 return WERR_INVALID_NAME;
4385 return enum_all_printers_info_1(mem_ctx, PRINTER_ENUM_ICON8, info, count);
4388 /********************************************************************
4389 enum_all_printers_info_1_network.
4390 *********************************************************************/
4392 static WERROR enum_all_printers_info_1_network(TALLOC_CTX *mem_ctx,
4393 const char *name,
4394 union spoolss_PrinterInfo **info,
4395 uint32_t *count)
4397 const char *s = name;
4399 DEBUG(4,("enum_all_printers_info_1_network\n"));
4401 /* If we respond to a enum_printers level 1 on our name with flags
4402 set to PRINTER_ENUM_REMOTE with a list of printers then these
4403 printers incorrectly appear in the APW browse list.
4404 Specifically the printers for the server appear at the workgroup
4405 level where all the other servers in the domain are
4406 listed. Windows responds to this call with a
4407 WERR_CAN_NOT_COMPLETE so we should do the same. */
4409 if (name[0] == '\\' && name[1] == '\\') {
4410 s = name + 2;
4413 if (is_myname_or_ipaddr(s)) {
4414 return WERR_CAN_NOT_COMPLETE;
4417 return enum_all_printers_info_1(mem_ctx, PRINTER_ENUM_NAME, info, count);
4420 /********************************************************************
4421 * api_spoolss_enumprinters
4423 * called from api_spoolss_enumprinters (see this to understand)
4424 ********************************************************************/
4426 static WERROR enum_all_printers_info_2(TALLOC_CTX *mem_ctx,
4427 union spoolss_PrinterInfo **info,
4428 uint32_t *count)
4430 DEBUG(4,("enum_all_printers_info_2\n"));
4432 return enum_all_printers_info_level(mem_ctx, 2, 0, info, count);
4435 /********************************************************************
4436 * handle enumeration of printers at level 1
4437 ********************************************************************/
4439 static WERROR enumprinters_level1(TALLOC_CTX *mem_ctx,
4440 uint32_t flags,
4441 const char *name,
4442 union spoolss_PrinterInfo **info,
4443 uint32_t *count)
4445 /* Not all the flags are equals */
4447 if (flags & PRINTER_ENUM_LOCAL) {
4448 return enum_all_printers_info_1_local(mem_ctx, info, count);
4451 if (flags & PRINTER_ENUM_NAME) {
4452 return enum_all_printers_info_1_name(mem_ctx, name, info, count);
4455 if (flags & PRINTER_ENUM_NETWORK) {
4456 return enum_all_printers_info_1_network(mem_ctx, name, info, count);
4459 return WERR_OK; /* NT4sp5 does that */
4462 /********************************************************************
4463 * handle enumeration of printers at level 2
4464 ********************************************************************/
4466 static WERROR enumprinters_level2(TALLOC_CTX *mem_ctx,
4467 uint32_t flags,
4468 const char *servername,
4469 union spoolss_PrinterInfo **info,
4470 uint32_t *count)
4472 if (flags & PRINTER_ENUM_LOCAL) {
4473 return enum_all_printers_info_2(mem_ctx, info, count);
4476 if (flags & PRINTER_ENUM_NAME) {
4477 if (!is_myname_or_ipaddr(canon_servername(servername))) {
4478 return WERR_INVALID_NAME;
4481 return enum_all_printers_info_2(mem_ctx, info, count);
4484 if (flags & PRINTER_ENUM_REMOTE) {
4485 return WERR_UNKNOWN_LEVEL;
4488 return WERR_OK;
4491 /********************************************************************
4492 * handle enumeration of printers at level 4
4493 ********************************************************************/
4495 static WERROR enumprinters_level4(TALLOC_CTX *mem_ctx,
4496 uint32_t flags,
4497 const char *servername,
4498 union spoolss_PrinterInfo **info,
4499 uint32_t *count)
4501 DEBUG(4,("enum_all_printers_info_4\n"));
4503 return enum_all_printers_info_level(mem_ctx, 4, flags, info, count);
4507 /********************************************************************
4508 * handle enumeration of printers at level 5
4509 ********************************************************************/
4511 static WERROR enumprinters_level5(TALLOC_CTX *mem_ctx,
4512 uint32_t flags,
4513 const char *servername,
4514 union spoolss_PrinterInfo **info,
4515 uint32_t *count)
4517 DEBUG(4,("enum_all_printers_info_5\n"));
4519 return enum_all_printers_info_level(mem_ctx, 5, flags, info, count);
4522 /****************************************************************
4523 _spoolss_EnumPrinters
4524 ****************************************************************/
4526 WERROR _spoolss_EnumPrinters(pipes_struct *p,
4527 struct spoolss_EnumPrinters *r)
4529 const char *name;
4530 WERROR result;
4532 /* that's an [in out] buffer */
4534 if (!r->in.buffer && (r->in.offered != 0)) {
4535 return WERR_INVALID_PARAM;
4538 DEBUG(4,("_spoolss_EnumPrinters\n"));
4540 *r->out.needed = 0;
4541 *r->out.count = 0;
4542 *r->out.info = NULL;
4545 * Level 1:
4546 * flags==PRINTER_ENUM_NAME
4547 * if name=="" then enumerates all printers
4548 * if name!="" then enumerate the printer
4549 * flags==PRINTER_ENUM_REMOTE
4550 * name is NULL, enumerate printers
4551 * Level 2: name!="" enumerates printers, name can't be NULL
4552 * Level 3: doesn't exist
4553 * Level 4: does a local registry lookup
4554 * Level 5: same as Level 2
4557 name = talloc_strdup_upper(p->mem_ctx, r->in.server);
4558 W_ERROR_HAVE_NO_MEMORY(name);
4560 switch (r->in.level) {
4561 case 0:
4562 result = enumprinters_level0(p->mem_ctx, r->in.flags, name,
4563 r->out.info, r->out.count);
4564 break;
4565 case 1:
4566 result = enumprinters_level1(p->mem_ctx, r->in.flags, name,
4567 r->out.info, r->out.count);
4568 break;
4569 case 2:
4570 result = enumprinters_level2(p->mem_ctx, r->in.flags, name,
4571 r->out.info, r->out.count);
4572 break;
4573 case 4:
4574 result = enumprinters_level4(p->mem_ctx, r->in.flags, name,
4575 r->out.info, r->out.count);
4576 break;
4577 case 5:
4578 result = enumprinters_level5(p->mem_ctx, r->in.flags, name,
4579 r->out.info, r->out.count);
4580 break;
4581 default:
4582 return WERR_UNKNOWN_LEVEL;
4585 if (!W_ERROR_IS_OK(result)) {
4586 return result;
4589 *r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
4590 spoolss_EnumPrinters, NULL,
4591 *r->out.info, r->in.level,
4592 *r->out.count);
4593 *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
4594 *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, 0);
4596 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
4599 /****************************************************************
4600 _spoolss_GetPrinter
4601 ****************************************************************/
4603 WERROR _spoolss_GetPrinter(pipes_struct *p,
4604 struct spoolss_GetPrinter *r)
4606 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
4607 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4608 WERROR result = WERR_OK;
4610 int snum;
4612 /* that's an [in out] buffer */
4614 if (!r->in.buffer && (r->in.offered != 0)) {
4615 return WERR_INVALID_PARAM;
4618 *r->out.needed = 0;
4620 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
4621 return WERR_BADFID;
4624 result = get_a_printer(Printer, &ntprinter, 2,
4625 lp_const_servicename(snum));
4626 if (!W_ERROR_IS_OK(result)) {
4627 return result;
4630 switch (r->in.level) {
4631 case 0:
4632 result = construct_printer_info0(p->mem_ctx, ntprinter,
4633 &r->out.info->info0, snum);
4634 break;
4635 case 1:
4636 result = construct_printer_info1(p->mem_ctx, ntprinter,
4637 PRINTER_ENUM_ICON8,
4638 &r->out.info->info1, snum);
4639 break;
4640 case 2:
4641 result = construct_printer_info2(p->mem_ctx, ntprinter,
4642 &r->out.info->info2, snum);
4643 break;
4644 case 3:
4645 result = construct_printer_info3(p->mem_ctx, ntprinter,
4646 &r->out.info->info3, snum);
4647 break;
4648 case 4:
4649 result = construct_printer_info4(p->mem_ctx, ntprinter,
4650 &r->out.info->info4, snum);
4651 break;
4652 case 5:
4653 result = construct_printer_info5(p->mem_ctx, ntprinter,
4654 &r->out.info->info5, snum);
4655 break;
4656 case 6:
4657 result = construct_printer_info6(p->mem_ctx, ntprinter,
4658 &r->out.info->info6, snum);
4659 break;
4660 case 7:
4661 result = construct_printer_info7(p->mem_ctx, Printer,
4662 &r->out.info->info7, snum);
4663 break;
4664 case 8:
4665 result = construct_printer_info8(p->mem_ctx, ntprinter,
4666 &r->out.info->info8, snum);
4667 break;
4668 default:
4669 result = WERR_UNKNOWN_LEVEL;
4670 break;
4673 free_a_printer(&ntprinter, 2);
4675 if (!W_ERROR_IS_OK(result)) {
4676 TALLOC_FREE(r->out.info);
4677 return result;
4680 *r->out.needed = SPOOLSS_BUFFER_UNION(spoolss_PrinterInfo, NULL,
4681 r->out.info, r->in.level);
4682 r->out.info = SPOOLSS_BUFFER_OK(r->out.info, NULL);
4684 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
4687 /********************************************************************
4688 ********************************************************************/
4690 static const char **string_array_from_driver_info(TALLOC_CTX *mem_ctx,
4691 fstring *fstring_array,
4692 const char *cservername)
4694 int i, num_strings = 0;
4695 const char **array = NULL;
4697 for (i=0; fstring_array && fstring_array[i][0] != '\0'; i++) {
4699 const char *str = talloc_asprintf(mem_ctx, "\\\\%s%s",
4700 cservername, fstring_array[i]);
4701 if (!str) {
4702 TALLOC_FREE(array);
4703 return NULL;
4707 if (!add_string_to_array(mem_ctx, str, &array, &num_strings)) {
4708 TALLOC_FREE(array);
4709 return NULL;
4713 if (i > 0) {
4714 ADD_TO_ARRAY(mem_ctx, const char *, NULL,
4715 &array, &num_strings);
4718 return array;
4721 /********************************************************************
4722 * fill a spoolss_DriverInfo1 struct
4723 ********************************************************************/
4725 static WERROR fill_printer_driver_info1(TALLOC_CTX *mem_ctx,
4726 struct spoolss_DriverInfo1 *r,
4727 const NT_PRINTER_DRIVER_INFO_LEVEL *driver,
4728 const char *servername,
4729 const char *architecture)
4731 r->driver_name = talloc_strdup(mem_ctx, driver->info_3->name);
4732 W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4734 return WERR_OK;
4737 /********************************************************************
4738 * fill a spoolss_DriverInfo2 struct
4739 ********************************************************************/
4741 static WERROR fill_printer_driver_info2(TALLOC_CTX *mem_ctx,
4742 struct spoolss_DriverInfo2 *r,
4743 const NT_PRINTER_DRIVER_INFO_LEVEL *driver,
4744 const char *servername)
4747 const char *cservername = canon_servername(servername);
4749 r->version = driver->info_3->cversion;
4751 r->driver_name = talloc_strdup(mem_ctx, driver->info_3->name);
4752 W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4753 r->architecture = talloc_strdup(mem_ctx, driver->info_3->environment);
4754 W_ERROR_HAVE_NO_MEMORY(r->architecture);
4756 if (strlen(driver->info_3->driverpath)) {
4757 r->driver_path = talloc_asprintf(mem_ctx, "\\\\%s%s",
4758 cservername, driver->info_3->driverpath);
4759 } else {
4760 r->driver_path = talloc_strdup(mem_ctx, "");
4762 W_ERROR_HAVE_NO_MEMORY(r->driver_path);
4764 if (strlen(driver->info_3->datafile)) {
4765 r->data_file = talloc_asprintf(mem_ctx, "\\\\%s%s",
4766 cservername, driver->info_3->datafile);
4767 } else {
4768 r->data_file = talloc_strdup(mem_ctx, "");
4770 W_ERROR_HAVE_NO_MEMORY(r->data_file);
4772 if (strlen(driver->info_3->configfile)) {
4773 r->config_file = talloc_asprintf(mem_ctx, "\\\\%s%s",
4774 cservername, driver->info_3->configfile);
4775 } else {
4776 r->config_file = talloc_strdup(mem_ctx, "");
4778 W_ERROR_HAVE_NO_MEMORY(r->config_file);
4780 return WERR_OK;
4783 /********************************************************************
4784 * fill a spoolss_DriverInfo3 struct
4785 ********************************************************************/
4787 static WERROR fill_printer_driver_info3(TALLOC_CTX *mem_ctx,
4788 struct spoolss_DriverInfo3 *r,
4789 const NT_PRINTER_DRIVER_INFO_LEVEL *driver,
4790 const char *servername)
4792 const char *cservername = canon_servername(servername);
4794 r->version = driver->info_3->cversion;
4796 r->driver_name = talloc_strdup(mem_ctx, driver->info_3->name);
4797 W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4798 r->architecture = talloc_strdup(mem_ctx, driver->info_3->environment);
4799 W_ERROR_HAVE_NO_MEMORY(r->architecture);
4801 if (strlen(driver->info_3->driverpath)) {
4802 r->driver_path = talloc_asprintf(mem_ctx, "\\\\%s%s",
4803 cservername, driver->info_3->driverpath);
4804 } else {
4805 r->driver_path = talloc_strdup(mem_ctx, "");
4807 W_ERROR_HAVE_NO_MEMORY(r->driver_path);
4809 if (strlen(driver->info_3->datafile)) {
4810 r->data_file = talloc_asprintf(mem_ctx, "\\\\%s%s",
4811 cservername, driver->info_3->datafile);
4812 } else {
4813 r->data_file = talloc_strdup(mem_ctx, "");
4815 W_ERROR_HAVE_NO_MEMORY(r->data_file);
4817 if (strlen(driver->info_3->configfile)) {
4818 r->config_file = talloc_asprintf(mem_ctx, "\\\\%s%s",
4819 cservername, driver->info_3->configfile);
4820 } else {
4821 r->config_file = talloc_strdup(mem_ctx, "");
4823 W_ERROR_HAVE_NO_MEMORY(r->config_file);
4825 if (strlen(driver->info_3->helpfile)) {
4826 r->help_file = talloc_asprintf(mem_ctx, "\\\\%s%s",
4827 cservername, driver->info_3->helpfile);
4828 } else {
4829 r->help_file = talloc_strdup(mem_ctx, "");
4831 W_ERROR_HAVE_NO_MEMORY(r->help_file);
4833 r->monitor_name = talloc_strdup(mem_ctx, driver->info_3->monitorname);
4834 W_ERROR_HAVE_NO_MEMORY(r->monitor_name);
4835 r->default_datatype = talloc_strdup(mem_ctx, driver->info_3->defaultdatatype);
4836 W_ERROR_HAVE_NO_MEMORY(r->default_datatype);
4838 r->dependent_files = string_array_from_driver_info(mem_ctx,
4839 driver->info_3->dependentfiles,
4840 cservername);
4841 return WERR_OK;
4844 /********************************************************************
4845 * fill a spoolss_DriverInfo4 struct
4846 ********************************************************************/
4848 static WERROR fill_printer_driver_info4(TALLOC_CTX *mem_ctx,
4849 struct spoolss_DriverInfo4 *r,
4850 const NT_PRINTER_DRIVER_INFO_LEVEL *driver,
4851 const char *servername)
4853 const char *cservername = canon_servername(servername);
4855 r->version = driver->info_3->cversion;
4857 r->driver_name = talloc_strdup(mem_ctx, driver->info_3->name);
4858 W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4859 r->architecture = talloc_strdup(mem_ctx, driver->info_3->environment);
4860 W_ERROR_HAVE_NO_MEMORY(r->architecture);
4862 if (strlen(driver->info_3->driverpath)) {
4863 r->driver_path = talloc_asprintf(mem_ctx, "\\\\%s%s",
4864 cservername, driver->info_3->driverpath);
4865 } else {
4866 r->driver_path = talloc_strdup(mem_ctx, "");
4868 W_ERROR_HAVE_NO_MEMORY(r->driver_path);
4870 if (strlen(driver->info_3->datafile)) {
4871 r->data_file = talloc_asprintf(mem_ctx, "\\\\%s%s",
4872 cservername, driver->info_3->datafile);
4873 } else {
4874 r->data_file = talloc_strdup(mem_ctx, "");
4876 W_ERROR_HAVE_NO_MEMORY(r->data_file);
4878 if (strlen(driver->info_3->configfile)) {
4879 r->config_file = talloc_asprintf(mem_ctx, "\\\\%s%s",
4880 cservername, driver->info_3->configfile);
4881 } else {
4882 r->config_file = talloc_strdup(mem_ctx, "");
4884 W_ERROR_HAVE_NO_MEMORY(r->config_file);
4886 if (strlen(driver->info_3->helpfile)) {
4887 r->help_file = talloc_asprintf(mem_ctx, "\\\\%s%s",
4888 cservername, driver->info_3->helpfile);
4889 } else {
4890 r->help_file = talloc_strdup(mem_ctx, "");
4892 W_ERROR_HAVE_NO_MEMORY(r->help_file);
4894 r->dependent_files = string_array_from_driver_info(mem_ctx,
4895 driver->info_3->dependentfiles,
4896 cservername);
4899 r->monitor_name = talloc_strdup(mem_ctx, driver->info_3->monitorname);
4900 W_ERROR_HAVE_NO_MEMORY(r->monitor_name);
4901 r->default_datatype = talloc_strdup(mem_ctx, driver->info_3->defaultdatatype);
4902 W_ERROR_HAVE_NO_MEMORY(r->default_datatype);
4904 r->previous_names = string_array_from_driver_info(mem_ctx,
4905 NULL,
4906 cservername);
4908 return WERR_OK;
4911 /********************************************************************
4912 * fill a spoolss_DriverInfo5 struct
4913 ********************************************************************/
4915 static WERROR fill_printer_driver_info5(TALLOC_CTX *mem_ctx,
4916 struct spoolss_DriverInfo5 *r,
4917 const NT_PRINTER_DRIVER_INFO_LEVEL *driver,
4918 const char *servername)
4920 const char *cservername = canon_servername(servername);
4922 r->version = driver->info_3->cversion;
4924 r->driver_name = talloc_strdup(mem_ctx, driver->info_3->name);
4925 W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4926 r->architecture = talloc_strdup(mem_ctx, driver->info_3->environment);
4927 W_ERROR_HAVE_NO_MEMORY(r->architecture);
4929 if (strlen(driver->info_3->driverpath)) {
4930 r->driver_path = talloc_asprintf(mem_ctx, "\\\\%s%s",
4931 cservername, driver->info_3->driverpath);
4932 } else {
4933 r->driver_path = talloc_strdup(mem_ctx, "");
4935 W_ERROR_HAVE_NO_MEMORY(r->driver_path);
4937 if (strlen(driver->info_3->datafile)) {
4938 r->data_file = talloc_asprintf(mem_ctx, "\\\\%s%s",
4939 cservername, driver->info_3->datafile);
4940 } else {
4941 r->data_file = talloc_strdup(mem_ctx, "");
4943 W_ERROR_HAVE_NO_MEMORY(r->data_file);
4945 if (strlen(driver->info_3->configfile)) {
4946 r->config_file = talloc_asprintf(mem_ctx, "\\\\%s%s",
4947 cservername, driver->info_3->configfile);
4948 } else {
4949 r->config_file = talloc_strdup(mem_ctx, "");
4951 W_ERROR_HAVE_NO_MEMORY(r->config_file);
4953 r->driver_attributes = 0;
4954 r->config_version = 0;
4955 r->driver_version = 0;
4957 return WERR_OK;
4959 /********************************************************************
4960 * fill a spoolss_DriverInfo6 struct
4961 ********************************************************************/
4963 static WERROR fill_printer_driver_info6(TALLOC_CTX *mem_ctx,
4964 struct spoolss_DriverInfo6 *r,
4965 const NT_PRINTER_DRIVER_INFO_LEVEL *driver,
4966 const char *servername)
4968 const char *cservername = canon_servername(servername);
4970 r->version = driver->info_3->cversion;
4972 r->driver_name = talloc_strdup(mem_ctx, driver->info_3->name);
4973 W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4974 r->architecture = talloc_strdup(mem_ctx, driver->info_3->environment);
4975 W_ERROR_HAVE_NO_MEMORY(r->architecture);
4977 if (strlen(driver->info_3->driverpath)) {
4978 r->driver_path = talloc_asprintf(mem_ctx, "\\\\%s%s",
4979 cservername, driver->info_3->driverpath);
4980 } else {
4981 r->driver_path = talloc_strdup(mem_ctx, "");
4983 W_ERROR_HAVE_NO_MEMORY(r->driver_path);
4985 if (strlen(driver->info_3->datafile)) {
4986 r->data_file = talloc_asprintf(mem_ctx, "\\\\%s%s",
4987 cservername, driver->info_3->datafile);
4988 } else {
4989 r->data_file = talloc_strdup(mem_ctx, "");
4991 W_ERROR_HAVE_NO_MEMORY(r->data_file);
4993 if (strlen(driver->info_3->configfile)) {
4994 r->config_file = talloc_asprintf(mem_ctx, "\\\\%s%s",
4995 cservername, driver->info_3->configfile);
4996 } else {
4997 r->config_file = talloc_strdup(mem_ctx, "");
4999 W_ERROR_HAVE_NO_MEMORY(r->config_file);
5001 if (strlen(driver->info_3->helpfile)) {
5002 r->help_file = talloc_asprintf(mem_ctx, "\\\\%s%s",
5003 cservername, driver->info_3->helpfile);
5004 } else {
5005 r->help_file = talloc_strdup(mem_ctx, "");
5007 W_ERROR_HAVE_NO_MEMORY(r->help_file);
5009 r->monitor_name = talloc_strdup(mem_ctx, driver->info_3->monitorname);
5010 W_ERROR_HAVE_NO_MEMORY(r->monitor_name);
5011 r->default_datatype = talloc_strdup(mem_ctx, driver->info_3->defaultdatatype);
5012 W_ERROR_HAVE_NO_MEMORY(r->default_datatype);
5014 r->dependent_files = string_array_from_driver_info(mem_ctx,
5015 driver->info_3->dependentfiles,
5016 cservername);
5017 r->previous_names = string_array_from_driver_info(mem_ctx,
5018 NULL,
5019 cservername);
5021 r->driver_date = 0;
5022 r->driver_version = 0;
5024 r->manufacturer_name = talloc_strdup(mem_ctx, "");
5025 W_ERROR_HAVE_NO_MEMORY(r->manufacturer_name);
5026 r->manufacturer_url = talloc_strdup(mem_ctx, "");
5027 W_ERROR_HAVE_NO_MEMORY(r->manufacturer_url);
5028 r->hardware_id = talloc_strdup(mem_ctx, "");
5029 W_ERROR_HAVE_NO_MEMORY(r->hardware_id);
5030 r->provider = talloc_strdup(mem_ctx, "");
5031 W_ERROR_HAVE_NO_MEMORY(r->provider);
5033 return WERR_OK;
5036 /********************************************************************
5037 ********************************************************************/
5039 static WERROR fill_spoolss_DriverFileInfo(TALLOC_CTX *mem_ctx,
5040 struct spoolss_DriverFileInfo *r,
5041 const char *cservername,
5042 const char *file_name,
5043 enum spoolss_DriverFileType file_type,
5044 uint32_t file_version)
5046 r->file_name = talloc_asprintf(mem_ctx, "\\\\%s%s",
5047 cservername, file_name);
5048 W_ERROR_HAVE_NO_MEMORY(r->file_name);
5049 r->file_type = file_type;
5050 r->file_version = file_version;
5052 return WERR_OK;
5055 /********************************************************************
5056 ********************************************************************/
5058 static WERROR spoolss_DriverFileInfo_from_driver(TALLOC_CTX *mem_ctx,
5059 const NT_PRINTER_DRIVER_INFO_LEVEL *driver,
5060 const char *cservername,
5061 struct spoolss_DriverFileInfo **info_p,
5062 uint32_t *count_p)
5064 struct spoolss_DriverFileInfo *info = NULL;
5065 uint32_t count = 0;
5066 WERROR result;
5067 uint32_t i;
5069 *info_p = NULL;
5070 *count_p = 0;
5072 if (strlen(driver->info_3->driverpath)) {
5073 info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
5074 struct spoolss_DriverFileInfo,
5075 count + 1);
5076 W_ERROR_HAVE_NO_MEMORY(info);
5077 result = fill_spoolss_DriverFileInfo(info,
5078 &info[count],
5079 cservername,
5080 driver->info_3->driverpath,
5081 SPOOLSS_DRIVER_FILE_TYPE_RENDERING,
5083 W_ERROR_NOT_OK_RETURN(result);
5084 count++;
5087 if (strlen(driver->info_3->configfile)) {
5088 info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
5089 struct spoolss_DriverFileInfo,
5090 count + 1);
5091 W_ERROR_HAVE_NO_MEMORY(info);
5092 result = fill_spoolss_DriverFileInfo(info,
5093 &info[count],
5094 cservername,
5095 driver->info_3->configfile,
5096 SPOOLSS_DRIVER_FILE_TYPE_CONFIGURATION,
5098 W_ERROR_NOT_OK_RETURN(result);
5099 count++;
5102 if (strlen(driver->info_3->datafile)) {
5103 info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
5104 struct spoolss_DriverFileInfo,
5105 count + 1);
5106 W_ERROR_HAVE_NO_MEMORY(info);
5107 result = fill_spoolss_DriverFileInfo(info,
5108 &info[count],
5109 cservername,
5110 driver->info_3->datafile,
5111 SPOOLSS_DRIVER_FILE_TYPE_DATA,
5113 W_ERROR_NOT_OK_RETURN(result);
5114 count++;
5117 if (strlen(driver->info_3->helpfile)) {
5118 info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
5119 struct spoolss_DriverFileInfo,
5120 count + 1);
5121 W_ERROR_HAVE_NO_MEMORY(info);
5122 result = fill_spoolss_DriverFileInfo(info,
5123 &info[count],
5124 cservername,
5125 driver->info_3->helpfile,
5126 SPOOLSS_DRIVER_FILE_TYPE_HELP,
5128 W_ERROR_NOT_OK_RETURN(result);
5129 count++;
5132 for (i=0; driver->info_3->dependentfiles[i][0] != '\0'; i++) {
5133 info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
5134 struct spoolss_DriverFileInfo,
5135 count + 1);
5136 W_ERROR_HAVE_NO_MEMORY(info);
5137 result = fill_spoolss_DriverFileInfo(info,
5138 &info[count],
5139 cservername,
5140 driver->info_3->dependentfiles[i],
5141 SPOOLSS_DRIVER_FILE_TYPE_OTHER,
5143 W_ERROR_NOT_OK_RETURN(result);
5144 count++;
5147 *info_p = info;
5148 *count_p = count;
5150 return WERR_OK;
5153 /********************************************************************
5154 * fill a spoolss_DriverInfo101 sttruct
5155 ********************************************************************/
5157 static WERROR fill_printer_driver_info101(TALLOC_CTX *mem_ctx,
5158 struct spoolss_DriverInfo101 *r,
5159 const NT_PRINTER_DRIVER_INFO_LEVEL *driver,
5160 const char *servername)
5162 const char *cservername = canon_servername(servername);
5163 WERROR result;
5165 r->version = driver->info_3->cversion;
5167 r->driver_name = talloc_strdup(mem_ctx, driver->info_3->name);
5168 W_ERROR_HAVE_NO_MEMORY(r->driver_name);
5169 r->architecture = talloc_strdup(mem_ctx, driver->info_3->environment);
5170 W_ERROR_HAVE_NO_MEMORY(r->architecture);
5172 result = spoolss_DriverFileInfo_from_driver(mem_ctx, driver,
5173 cservername,
5174 &r->file_info,
5175 &r->file_count);
5176 if (!W_ERROR_IS_OK(result)) {
5177 return result;
5180 r->monitor_name = talloc_strdup(mem_ctx, driver->info_3->monitorname);
5181 W_ERROR_HAVE_NO_MEMORY(r->monitor_name);
5183 r->default_datatype = talloc_strdup(mem_ctx, driver->info_3->defaultdatatype);
5184 W_ERROR_HAVE_NO_MEMORY(r->default_datatype);
5186 r->previous_names = string_array_from_driver_info(mem_ctx,
5187 NULL,
5188 cservername);
5189 r->driver_date = 0;
5190 r->driver_version = 0;
5192 r->manufacturer_name = talloc_strdup(mem_ctx, "");
5193 W_ERROR_HAVE_NO_MEMORY(r->manufacturer_name);
5194 r->manufacturer_url = talloc_strdup(mem_ctx, "");
5195 W_ERROR_HAVE_NO_MEMORY(r->manufacturer_url);
5196 r->hardware_id = talloc_strdup(mem_ctx, "");
5197 W_ERROR_HAVE_NO_MEMORY(r->hardware_id);
5198 r->provider = talloc_strdup(mem_ctx, "");
5199 W_ERROR_HAVE_NO_MEMORY(r->provider);
5201 return WERR_OK;
5204 /********************************************************************
5205 * construct_printer_driver_info_1
5206 ********************************************************************/
5208 static WERROR construct_printer_driver_info_1(TALLOC_CTX *mem_ctx,
5209 struct spoolss_DriverInfo1 *r,
5210 int snum,
5211 const char *servername,
5212 const char *architecture,
5213 uint32_t version)
5215 NT_PRINTER_INFO_LEVEL *printer = NULL;
5216 NT_PRINTER_DRIVER_INFO_LEVEL driver;
5217 WERROR result;
5219 ZERO_STRUCT(driver);
5221 if (!W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, lp_const_servicename(snum))))
5222 return WERR_INVALID_PRINTER_NAME;
5224 if (!W_ERROR_IS_OK(get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version))) {
5225 free_a_printer(&printer, 2);
5226 return WERR_UNKNOWN_PRINTER_DRIVER;
5229 result = fill_printer_driver_info1(mem_ctx, r, &driver, servername, architecture);
5231 free_a_printer(&printer,2);
5233 return result;
5236 /********************************************************************
5237 * construct_printer_driver_info_2
5238 * fill a printer_info_2 struct
5239 ********************************************************************/
5241 static WERROR construct_printer_driver_info_2(TALLOC_CTX *mem_ctx,
5242 struct spoolss_DriverInfo2 *r,
5243 int snum,
5244 const char *servername,
5245 const char *architecture,
5246 uint32_t version)
5248 NT_PRINTER_INFO_LEVEL *printer = NULL;
5249 NT_PRINTER_DRIVER_INFO_LEVEL driver;
5250 WERROR result;
5252 ZERO_STRUCT(printer);
5253 ZERO_STRUCT(driver);
5255 if (!W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, lp_const_servicename(snum))))
5256 return WERR_INVALID_PRINTER_NAME;
5258 if (!W_ERROR_IS_OK(get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version))) {
5259 free_a_printer(&printer, 2);
5260 return WERR_UNKNOWN_PRINTER_DRIVER;
5263 result = fill_printer_driver_info2(mem_ctx, r, &driver, servername);
5265 free_a_printer(&printer,2);
5267 return result;
5270 /********************************************************************
5271 * construct_printer_info_3
5272 * fill a printer_info_3 struct
5273 ********************************************************************/
5275 static WERROR construct_printer_driver_info_3(TALLOC_CTX *mem_ctx,
5276 struct spoolss_DriverInfo3 *r,
5277 int snum,
5278 const char *servername,
5279 const char *architecture,
5280 uint32_t version)
5282 NT_PRINTER_INFO_LEVEL *printer = NULL;
5283 NT_PRINTER_DRIVER_INFO_LEVEL driver;
5284 WERROR status;
5285 ZERO_STRUCT(driver);
5287 status=get_a_printer(NULL, &printer, 2, lp_const_servicename(snum) );
5288 DEBUG(8,("construct_printer_driver_info_3: status: %s\n", win_errstr(status)));
5289 if (!W_ERROR_IS_OK(status))
5290 return WERR_INVALID_PRINTER_NAME;
5292 status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
5293 DEBUG(8,("construct_printer_driver_info_3: status: %s\n", win_errstr(status)));
5295 #if 0 /* JERRY */
5298 * I put this code in during testing. Helpful when commenting out the
5299 * support for DRIVER_INFO_6 in regards to win2k. Not needed in general
5300 * as win2k always queries the driver using an infor level of 6.
5301 * I've left it in (but ifdef'd out) because I'll probably
5302 * use it in experimentation again in the future. --jerry 22/01/2002
5305 if (!W_ERROR_IS_OK(status)) {
5307 * Is this a W2k client ?
5309 if (version == 3) {
5310 /* Yes - try again with a WinNT driver. */
5311 version = 2;
5312 status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
5313 DEBUG(8,("construct_printer_driver_info_3: status: %s\n", win_errstr(status)));
5315 #endif
5317 if (!W_ERROR_IS_OK(status)) {
5318 free_a_printer(&printer,2);
5319 return WERR_UNKNOWN_PRINTER_DRIVER;
5322 #if 0 /* JERRY */
5324 #endif
5327 status = fill_printer_driver_info3(mem_ctx, r, &driver, servername);
5329 free_a_printer(&printer,2);
5331 return status;
5334 /********************************************************************
5335 * construct_printer_info_6
5336 * fill a printer_info_6 struct
5337 ********************************************************************/
5339 static WERROR construct_printer_driver_info_6(TALLOC_CTX *mem_ctx,
5340 struct spoolss_DriverInfo6 *r,
5341 int snum,
5342 const char *servername,
5343 const char *architecture,
5344 uint32_t version)
5346 NT_PRINTER_INFO_LEVEL *printer = NULL;
5347 NT_PRINTER_DRIVER_INFO_LEVEL driver;
5348 WERROR status;
5350 ZERO_STRUCT(driver);
5352 status=get_a_printer(NULL, &printer, 2, lp_const_servicename(snum) );
5354 DEBUG(8,("construct_printer_driver_info_6: status: %s\n", win_errstr(status)));
5356 if (!W_ERROR_IS_OK(status))
5357 return WERR_INVALID_PRINTER_NAME;
5359 status = get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
5361 DEBUG(8,("construct_printer_driver_info_6: status: %s\n", win_errstr(status)));
5363 if (!W_ERROR_IS_OK(status))
5366 * Is this a W2k client ?
5369 if (version < 3) {
5370 free_a_printer(&printer,2);
5371 return WERR_UNKNOWN_PRINTER_DRIVER;
5374 /* Yes - try again with a WinNT driver. */
5375 version = 2;
5376 status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
5377 DEBUG(8,("construct_printer_driver_info_6: status: %s\n", win_errstr(status)));
5378 if (!W_ERROR_IS_OK(status)) {
5379 free_a_printer(&printer,2);
5380 return WERR_UNKNOWN_PRINTER_DRIVER;
5384 status = fill_printer_driver_info6(mem_ctx, r, &driver, servername);
5386 free_a_printer(&printer,2);
5387 free_a_printer_driver(driver, 3);
5389 return status;
5392 /********************************************************************
5393 * construct_printer_info_101
5394 * fill a printer_info_101 struct
5395 ********************************************************************/
5397 static WERROR construct_printer_driver_info_101(TALLOC_CTX *mem_ctx,
5398 struct spoolss_DriverInfo101 *r,
5399 int snum,
5400 const char *servername,
5401 const char *architecture,
5402 uint32_t version)
5404 NT_PRINTER_INFO_LEVEL *printer = NULL;
5405 NT_PRINTER_DRIVER_INFO_LEVEL driver;
5406 WERROR result;
5408 ZERO_STRUCT(driver);
5410 result = get_a_printer(NULL, &printer, 2, lp_const_servicename(snum));
5412 DEBUG(8,("construct_printer_driver_info_101: status: %s\n",
5413 win_errstr(result)));
5415 if (!W_ERROR_IS_OK(result)) {
5416 return WERR_INVALID_PRINTER_NAME;
5419 result = get_a_printer_driver(&driver, 3, printer->info_2->drivername,
5420 architecture, version);
5422 DEBUG(8,("construct_printer_driver_info_101: status: %s\n",
5423 win_errstr(result)));
5425 if (!W_ERROR_IS_OK(result)) {
5427 * Is this a W2k client ?
5430 if (version < 3) {
5431 free_a_printer(&printer, 2);
5432 return WERR_UNKNOWN_PRINTER_DRIVER;
5435 /* Yes - try again with a WinNT driver. */
5436 version = 2;
5437 result = get_a_printer_driver(&driver, 3, printer->info_2->drivername,
5438 architecture, version);
5439 DEBUG(8,("construct_printer_driver_info_6: status: %s\n",
5440 win_errstr(result)));
5441 if (!W_ERROR_IS_OK(result)) {
5442 free_a_printer(&printer, 2);
5443 return WERR_UNKNOWN_PRINTER_DRIVER;
5447 result = fill_printer_driver_info101(mem_ctx, r, &driver, servername);
5449 free_a_printer(&printer, 2);
5450 free_a_printer_driver(driver, 3);
5452 return result;
5455 /****************************************************************
5456 _spoolss_GetPrinterDriver2
5457 ****************************************************************/
5459 WERROR _spoolss_GetPrinterDriver2(pipes_struct *p,
5460 struct spoolss_GetPrinterDriver2 *r)
5462 Printer_entry *printer;
5463 WERROR result;
5465 const char *servername;
5466 int snum;
5468 /* that's an [in out] buffer */
5470 if (!r->in.buffer && (r->in.offered != 0)) {
5471 return WERR_INVALID_PARAM;
5474 DEBUG(4,("_spoolss_GetPrinterDriver2\n"));
5476 if (!(printer = find_printer_index_by_hnd(p, r->in.handle))) {
5477 DEBUG(0,("_spoolss_GetPrinterDriver2: invalid printer handle!\n"));
5478 return WERR_INVALID_PRINTER_NAME;
5481 *r->out.needed = 0;
5482 *r->out.server_major_version = 0;
5483 *r->out.server_minor_version = 0;
5485 servername = get_server_name(printer);
5487 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
5488 return WERR_BADFID;
5491 switch (r->in.level) {
5492 case 1:
5493 result = construct_printer_driver_info_1(p->mem_ctx,
5494 &r->out.info->info1,
5495 snum,
5496 servername,
5497 r->in.architecture,
5498 r->in.client_major_version);
5499 break;
5500 case 2:
5501 result = construct_printer_driver_info_2(p->mem_ctx,
5502 &r->out.info->info2,
5503 snum,
5504 servername,
5505 r->in.architecture,
5506 r->in.client_major_version);
5507 break;
5508 case 3:
5509 result = construct_printer_driver_info_3(p->mem_ctx,
5510 &r->out.info->info3,
5511 snum,
5512 servername,
5513 r->in.architecture,
5514 r->in.client_major_version);
5515 break;
5516 case 6:
5517 result = construct_printer_driver_info_6(p->mem_ctx,
5518 &r->out.info->info6,
5519 snum,
5520 servername,
5521 r->in.architecture,
5522 r->in.client_major_version);
5523 break;
5524 case 101:
5525 result = construct_printer_driver_info_101(p->mem_ctx,
5526 &r->out.info->info101,
5527 snum,
5528 servername,
5529 r->in.architecture,
5530 r->in.client_major_version);
5531 break;
5532 default:
5533 result = WERR_UNKNOWN_LEVEL;
5534 break;
5537 if (!W_ERROR_IS_OK(result)) {
5538 TALLOC_FREE(r->out.info);
5539 return result;
5542 *r->out.needed = SPOOLSS_BUFFER_UNION(spoolss_DriverInfo, NULL,
5543 r->out.info, r->in.level);
5544 r->out.info = SPOOLSS_BUFFER_OK(r->out.info, NULL);
5546 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
5550 /****************************************************************
5551 _spoolss_StartPagePrinter
5552 ****************************************************************/
5554 WERROR _spoolss_StartPagePrinter(pipes_struct *p,
5555 struct spoolss_StartPagePrinter *r)
5557 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
5559 if (!Printer) {
5560 DEBUG(3,("_spoolss_StartPagePrinter: "
5561 "Error in startpageprinter printer handle\n"));
5562 return WERR_BADFID;
5565 Printer->page_started = true;
5566 return WERR_OK;
5569 /****************************************************************
5570 _spoolss_EndPagePrinter
5571 ****************************************************************/
5573 WERROR _spoolss_EndPagePrinter(pipes_struct *p,
5574 struct spoolss_EndPagePrinter *r)
5576 int snum;
5578 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
5580 if (!Printer) {
5581 DEBUG(2,("_spoolss_EndPagePrinter: Invalid handle (%s:%u:%u).\n",
5582 OUR_HANDLE(r->in.handle)));
5583 return WERR_BADFID;
5586 if (!get_printer_snum(p, r->in.handle, &snum, NULL))
5587 return WERR_BADFID;
5589 Printer->page_started = false;
5590 print_job_endpage(snum, Printer->jobid);
5592 return WERR_OK;
5595 /****************************************************************
5596 _spoolss_StartDocPrinter
5597 ****************************************************************/
5599 WERROR _spoolss_StartDocPrinter(pipes_struct *p,
5600 struct spoolss_StartDocPrinter *r)
5602 struct spoolss_DocumentInfo1 *info_1;
5603 int snum;
5604 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
5606 if (!Printer) {
5607 DEBUG(2,("_spoolss_StartDocPrinter: "
5608 "Invalid handle (%s:%u:%u)\n",
5609 OUR_HANDLE(r->in.handle)));
5610 return WERR_BADFID;
5613 if (r->in.level != 1) {
5614 return WERR_UNKNOWN_LEVEL;
5617 info_1 = r->in.info.info1;
5620 * a nice thing with NT is it doesn't listen to what you tell it.
5621 * when asked to send _only_ RAW datas, it tries to send datas
5622 * in EMF format.
5624 * So I add checks like in NT Server ...
5627 if (info_1->datatype) {
5628 if (strcmp(info_1->datatype, "RAW") != 0) {
5629 *r->out.job_id = 0;
5630 return WERR_INVALID_DATATYPE;
5634 /* get the share number of the printer */
5635 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
5636 return WERR_BADFID;
5639 Printer->jobid = print_job_start(p->server_info, snum,
5640 info_1->document_name,
5641 Printer->nt_devmode);
5643 /* An error occured in print_job_start() so return an appropriate
5644 NT error code. */
5646 if (Printer->jobid == -1) {
5647 return map_werror_from_unix(errno);
5650 Printer->document_started = true;
5651 *r->out.job_id = Printer->jobid;
5653 return WERR_OK;
5656 /****************************************************************
5657 _spoolss_EndDocPrinter
5658 ****************************************************************/
5660 WERROR _spoolss_EndDocPrinter(pipes_struct *p,
5661 struct spoolss_EndDocPrinter *r)
5663 return _spoolss_enddocprinter_internal(p, r->in.handle);
5666 /****************************************************************
5667 _spoolss_WritePrinter
5668 ****************************************************************/
5670 WERROR _spoolss_WritePrinter(pipes_struct *p,
5671 struct spoolss_WritePrinter *r)
5673 uint32_t buffer_written;
5674 int snum;
5675 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
5677 if (!Printer) {
5678 DEBUG(2,("_spoolss_WritePrinter: Invalid handle (%s:%u:%u)\n",
5679 OUR_HANDLE(r->in.handle)));
5680 *r->out.num_written = r->in._data_size;
5681 return WERR_BADFID;
5684 if (!get_printer_snum(p, r->in.handle, &snum, NULL))
5685 return WERR_BADFID;
5687 buffer_written = (uint32_t)print_job_write(snum, Printer->jobid,
5688 (const char *)r->in.data.data,
5689 (SMB_OFF_T)-1,
5690 (size_t)r->in._data_size);
5691 if (buffer_written == (uint32_t)-1) {
5692 *r->out.num_written = 0;
5693 if (errno == ENOSPC)
5694 return WERR_NO_SPOOL_SPACE;
5695 else
5696 return WERR_ACCESS_DENIED;
5699 *r->out.num_written = r->in._data_size;
5701 return WERR_OK;
5704 /********************************************************************
5705 * api_spoolss_getprinter
5706 * called from the spoolss dispatcher
5708 ********************************************************************/
5710 static WERROR control_printer(struct policy_handle *handle, uint32_t command,
5711 pipes_struct *p)
5713 int snum;
5714 WERROR errcode = WERR_BADFUNC;
5715 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5717 if (!Printer) {
5718 DEBUG(2,("control_printer: Invalid handle (%s:%u:%u)\n",
5719 OUR_HANDLE(handle)));
5720 return WERR_BADFID;
5723 if (!get_printer_snum(p, handle, &snum, NULL))
5724 return WERR_BADFID;
5726 switch (command) {
5727 case SPOOLSS_PRINTER_CONTROL_PAUSE:
5728 errcode = print_queue_pause(p->server_info, snum);
5729 break;
5730 case SPOOLSS_PRINTER_CONTROL_RESUME:
5731 case SPOOLSS_PRINTER_CONTROL_UNPAUSE:
5732 errcode = print_queue_resume(p->server_info, snum);
5733 break;
5734 case SPOOLSS_PRINTER_CONTROL_PURGE:
5735 errcode = print_queue_purge(p->server_info, snum);
5736 break;
5737 default:
5738 return WERR_UNKNOWN_LEVEL;
5741 return errcode;
5745 /****************************************************************
5746 _spoolss_AbortPrinter
5747 * From MSDN: "Deletes printer's spool file if printer is configured
5748 * for spooling"
5749 ****************************************************************/
5751 WERROR _spoolss_AbortPrinter(pipes_struct *p,
5752 struct spoolss_AbortPrinter *r)
5754 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
5755 int snum;
5756 WERROR errcode = WERR_OK;
5758 if (!Printer) {
5759 DEBUG(2,("_spoolss_AbortPrinter: Invalid handle (%s:%u:%u)\n",
5760 OUR_HANDLE(r->in.handle)));
5761 return WERR_BADFID;
5764 if (!get_printer_snum(p, r->in.handle, &snum, NULL))
5765 return WERR_BADFID;
5767 print_job_delete(p->server_info, snum, Printer->jobid, &errcode );
5769 return errcode;
5772 /********************************************************************
5773 * called by spoolss_api_setprinter
5774 * when updating a printer description
5775 ********************************************************************/
5777 static WERROR update_printer_sec(struct policy_handle *handle,
5778 pipes_struct *p, SEC_DESC_BUF *secdesc_ctr)
5780 SEC_DESC_BUF *new_secdesc_ctr = NULL, *old_secdesc_ctr = NULL;
5781 WERROR result;
5782 int snum;
5784 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5786 if (!Printer || !get_printer_snum(p, handle, &snum, NULL)) {
5787 DEBUG(2,("update_printer_sec: Invalid handle (%s:%u:%u)\n",
5788 OUR_HANDLE(handle)));
5790 result = WERR_BADFID;
5791 goto done;
5794 if (!secdesc_ctr) {
5795 DEBUG(10,("update_printer_sec: secdesc_ctr is NULL !\n"));
5796 result = WERR_INVALID_PARAM;
5797 goto done;
5800 /* Check the user has permissions to change the security
5801 descriptor. By experimentation with two NT machines, the user
5802 requires Full Access to the printer to change security
5803 information. */
5805 if ( Printer->access_granted != PRINTER_ACCESS_ADMINISTER ) {
5806 DEBUG(4,("update_printer_sec: updated denied by printer permissions\n"));
5807 result = WERR_ACCESS_DENIED;
5808 goto done;
5811 /* NT seems to like setting the security descriptor even though
5812 nothing may have actually changed. */
5814 if ( !nt_printing_getsec(p->mem_ctx, Printer->sharename, &old_secdesc_ctr)) {
5815 DEBUG(2,("update_printer_sec: nt_printing_getsec() failed\n"));
5816 result = WERR_BADFID;
5817 goto done;
5820 if (DEBUGLEVEL >= 10) {
5821 SEC_ACL *the_acl;
5822 int i;
5824 the_acl = old_secdesc_ctr->sd->dacl;
5825 DEBUG(10, ("old_secdesc_ctr for %s has %d aces:\n",
5826 PRINTERNAME(snum), the_acl->num_aces));
5828 for (i = 0; i < the_acl->num_aces; i++) {
5829 DEBUG(10, ("%s 0x%08x\n", sid_string_dbg(
5830 &the_acl->aces[i].trustee),
5831 the_acl->aces[i].access_mask));
5834 the_acl = secdesc_ctr->sd->dacl;
5836 if (the_acl) {
5837 DEBUG(10, ("secdesc_ctr for %s has %d aces:\n",
5838 PRINTERNAME(snum), the_acl->num_aces));
5840 for (i = 0; i < the_acl->num_aces; i++) {
5841 DEBUG(10, ("%s 0x%08x\n", sid_string_dbg(
5842 &the_acl->aces[i].trustee),
5843 the_acl->aces[i].access_mask));
5845 } else {
5846 DEBUG(10, ("dacl for secdesc_ctr is NULL\n"));
5850 new_secdesc_ctr = sec_desc_merge(p->mem_ctx, secdesc_ctr, old_secdesc_ctr);
5851 if (!new_secdesc_ctr) {
5852 result = WERR_NOMEM;
5853 goto done;
5856 if (sec_desc_equal(new_secdesc_ctr->sd, old_secdesc_ctr->sd)) {
5857 result = WERR_OK;
5858 goto done;
5861 result = nt_printing_setsec(Printer->sharename, new_secdesc_ctr);
5863 done:
5865 return result;
5868 /********************************************************************
5869 Canonicalize printer info from a client
5871 ATTN: It does not matter what we set the servername to hear
5872 since we do the necessary work in get_a_printer() to set it to
5873 the correct value based on what the client sent in the
5874 _spoolss_open_printer_ex().
5875 ********************************************************************/
5877 static bool check_printer_ok(NT_PRINTER_INFO_LEVEL_2 *info, int snum)
5879 fstring printername;
5880 const char *p;
5882 DEBUG(5,("check_printer_ok: servername=%s printername=%s sharename=%s "
5883 "portname=%s drivername=%s comment=%s location=%s\n",
5884 info->servername, info->printername, info->sharename,
5885 info->portname, info->drivername, info->comment, info->location));
5887 /* we force some elements to "correct" values */
5888 slprintf(info->servername, sizeof(info->servername)-1, "\\\\%s", global_myname());
5889 fstrcpy(info->sharename, lp_servicename(snum));
5891 /* check to see if we allow printername != sharename */
5893 if ( lp_force_printername(snum) ) {
5894 slprintf(info->printername, sizeof(info->printername)-1, "\\\\%s\\%s",
5895 global_myname(), info->sharename );
5896 } else {
5898 /* make sure printername is in \\server\printername format */
5900 fstrcpy( printername, info->printername );
5901 p = printername;
5902 if ( printername[0] == '\\' && printername[1] == '\\' ) {
5903 if ( (p = strchr_m( &printername[2], '\\' )) != NULL )
5904 p++;
5907 slprintf(info->printername, sizeof(info->printername)-1, "\\\\%s\\%s",
5908 global_myname(), p );
5911 info->attributes |= PRINTER_ATTRIBUTE_SAMBA;
5912 info->attributes &= ~PRINTER_ATTRIBUTE_NOT_SAMBA;
5916 return true;
5919 /****************************************************************************
5920 ****************************************************************************/
5922 WERROR add_port_hook(TALLOC_CTX *ctx, NT_USER_TOKEN *token, const char *portname, const char *uri )
5924 char *cmd = lp_addport_cmd();
5925 char *command = NULL;
5926 int ret;
5927 SE_PRIV se_printop = SE_PRINT_OPERATOR;
5928 bool is_print_op = false;
5930 if ( !*cmd ) {
5931 return WERR_ACCESS_DENIED;
5934 command = talloc_asprintf(ctx,
5935 "%s \"%s\" \"%s\"", cmd, portname, uri );
5936 if (!command) {
5937 return WERR_NOMEM;
5940 if ( token )
5941 is_print_op = user_has_privileges( token, &se_printop );
5943 DEBUG(10,("Running [%s]\n", command));
5945 /********* BEGIN SePrintOperatorPrivilege **********/
5947 if ( is_print_op )
5948 become_root();
5950 ret = smbrun(command, NULL);
5952 if ( is_print_op )
5953 unbecome_root();
5955 /********* END SePrintOperatorPrivilege **********/
5957 DEBUGADD(10,("returned [%d]\n", ret));
5959 TALLOC_FREE(command);
5961 if ( ret != 0 ) {
5962 return WERR_ACCESS_DENIED;
5965 return WERR_OK;
5968 /****************************************************************************
5969 ****************************************************************************/
5971 bool add_printer_hook(TALLOC_CTX *ctx, NT_USER_TOKEN *token, NT_PRINTER_INFO_LEVEL *printer)
5973 char *cmd = lp_addprinter_cmd();
5974 char **qlines;
5975 char *command = NULL;
5976 int numlines;
5977 int ret;
5978 int fd;
5979 SE_PRIV se_printop = SE_PRINT_OPERATOR;
5980 bool is_print_op = false;
5981 char *remote_machine = talloc_strdup(ctx, "%m");
5983 if (!remote_machine) {
5984 return false;
5986 remote_machine = talloc_sub_basic(ctx,
5987 current_user_info.smb_name,
5988 current_user_info.domain,
5989 remote_machine);
5990 if (!remote_machine) {
5991 return false;
5994 command = talloc_asprintf(ctx,
5995 "%s \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\"",
5996 cmd, printer->info_2->printername, printer->info_2->sharename,
5997 printer->info_2->portname, printer->info_2->drivername,
5998 printer->info_2->location, printer->info_2->comment, remote_machine);
5999 if (!command) {
6000 return false;
6003 if ( token )
6004 is_print_op = user_has_privileges( token, &se_printop );
6006 DEBUG(10,("Running [%s]\n", command));
6008 /********* BEGIN SePrintOperatorPrivilege **********/
6010 if ( is_print_op )
6011 become_root();
6013 if ( (ret = smbrun(command, &fd)) == 0 ) {
6014 /* Tell everyone we updated smb.conf. */
6015 message_send_all(smbd_messaging_context(),
6016 MSG_SMB_CONF_UPDATED, NULL, 0, NULL);
6019 if ( is_print_op )
6020 unbecome_root();
6022 /********* END SePrintOperatorPrivilege **********/
6024 DEBUGADD(10,("returned [%d]\n", ret));
6026 TALLOC_FREE(command);
6027 TALLOC_FREE(remote_machine);
6029 if ( ret != 0 ) {
6030 if (fd != -1)
6031 close(fd);
6032 return false;
6035 /* reload our services immediately */
6036 become_root();
6037 reload_services(false);
6038 unbecome_root();
6040 numlines = 0;
6041 /* Get lines and convert them back to dos-codepage */
6042 qlines = fd_lines_load(fd, &numlines, 0, NULL);
6043 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
6044 close(fd);
6046 /* Set the portname to what the script says the portname should be. */
6047 /* but don't require anything to be return from the script exit a good error code */
6049 if (numlines) {
6050 /* Set the portname to what the script says the portname should be. */
6051 strncpy(printer->info_2->portname, qlines[0], sizeof(printer->info_2->portname));
6052 DEBUGADD(6,("Line[0] = [%s]\n", qlines[0]));
6055 TALLOC_FREE(qlines);
6056 return true;
6060 /********************************************************************
6061 * Called by spoolss_api_setprinter
6062 * when updating a printer description.
6063 ********************************************************************/
6065 static WERROR update_printer(pipes_struct *p, struct policy_handle *handle,
6066 struct spoolss_SetPrinterInfoCtr *info_ctr,
6067 struct spoolss_DeviceMode *devmode)
6069 int snum;
6070 NT_PRINTER_INFO_LEVEL *printer = NULL, *old_printer = NULL;
6071 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
6072 WERROR result;
6073 UNISTR2 buffer;
6074 fstring asc_buffer;
6076 DEBUG(8,("update_printer\n"));
6078 result = WERR_OK;
6080 if (!Printer) {
6081 result = WERR_BADFID;
6082 goto done;
6085 if (!get_printer_snum(p, handle, &snum, NULL)) {
6086 result = WERR_BADFID;
6087 goto done;
6090 if (!W_ERROR_IS_OK(get_a_printer(Printer, &printer, 2, lp_const_servicename(snum))) ||
6091 (!W_ERROR_IS_OK(get_a_printer(Printer, &old_printer, 2, lp_const_servicename(snum))))) {
6092 result = WERR_BADFID;
6093 goto done;
6096 DEBUGADD(8,("Converting info_2 struct\n"));
6099 * convert_printer_info converts the incoming
6100 * info from the client and overwrites the info
6101 * just read from the tdb in the pointer 'printer'.
6104 if (!convert_printer_info(info_ctr, printer)) {
6105 result = WERR_NOMEM;
6106 goto done;
6109 if (devmode) {
6110 /* we have a valid devmode
6111 convert it and link it*/
6113 DEBUGADD(8,("update_printer: Converting the devicemode struct\n"));
6114 if (!convert_devicemode(printer->info_2->printername, devmode,
6115 &printer->info_2->devmode)) {
6116 result = WERR_NOMEM;
6117 goto done;
6121 /* Do sanity check on the requested changes for Samba */
6123 if (!check_printer_ok(printer->info_2, snum)) {
6124 result = WERR_INVALID_PARAM;
6125 goto done;
6128 /* FIXME!!! If the driver has changed we really should verify that
6129 it is installed before doing much else --jerry */
6131 /* Check calling user has permission to update printer description */
6133 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
6134 DEBUG(3, ("update_printer: printer property change denied by handle\n"));
6135 result = WERR_ACCESS_DENIED;
6136 goto done;
6139 /* Call addprinter hook */
6140 /* Check changes to see if this is really needed */
6142 if ( *lp_addprinter_cmd()
6143 && (!strequal(printer->info_2->drivername, old_printer->info_2->drivername)
6144 || !strequal(printer->info_2->comment, old_printer->info_2->comment)
6145 || !strequal(printer->info_2->portname, old_printer->info_2->portname)
6146 || !strequal(printer->info_2->location, old_printer->info_2->location)) )
6148 /* add_printer_hook() will call reload_services() */
6150 if ( !add_printer_hook(p->mem_ctx, p->server_info->ptok,
6151 printer) ) {
6152 result = WERR_ACCESS_DENIED;
6153 goto done;
6158 * When a *new* driver is bound to a printer, the drivername is used to
6159 * lookup previously saved driver initialization info, which is then
6160 * bound to the printer, simulating what happens in the Windows arch.
6162 if (!strequal(printer->info_2->drivername, old_printer->info_2->drivername))
6164 if (!set_driver_init(printer, 2))
6166 DEBUG(5,("update_printer: Error restoring driver initialization data for driver [%s]!\n",
6167 printer->info_2->drivername));
6170 DEBUG(10,("update_printer: changing driver [%s]! Sending event!\n",
6171 printer->info_2->drivername));
6173 notify_printer_driver(snum, printer->info_2->drivername);
6177 * flag which changes actually occured. This is a small subset of
6178 * all the possible changes. We also have to update things in the
6179 * DsSpooler key.
6182 if (!strequal(printer->info_2->comment, old_printer->info_2->comment)) {
6183 init_unistr2( &buffer, printer->info_2->comment, UNI_STR_TERMINATE);
6184 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "description",
6185 REG_SZ, (uint8_t *)buffer.buffer, buffer.uni_str_len*2 );
6187 notify_printer_comment(snum, printer->info_2->comment);
6190 if (!strequal(printer->info_2->sharename, old_printer->info_2->sharename)) {
6191 init_unistr2( &buffer, printer->info_2->sharename, UNI_STR_TERMINATE);
6192 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "shareName",
6193 REG_SZ, (uint8_t *)buffer.buffer, buffer.uni_str_len*2 );
6195 notify_printer_sharename(snum, printer->info_2->sharename);
6198 if (!strequal(printer->info_2->printername, old_printer->info_2->printername)) {
6199 char *pname;
6201 if ( (pname = strchr_m( printer->info_2->printername+2, '\\' )) != NULL )
6202 pname++;
6203 else
6204 pname = printer->info_2->printername;
6207 init_unistr2( &buffer, pname, UNI_STR_TERMINATE);
6208 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "printerName",
6209 REG_SZ, (uint8_t *)buffer.buffer, buffer.uni_str_len*2 );
6211 notify_printer_printername( snum, pname );
6214 if (!strequal(printer->info_2->portname, old_printer->info_2->portname)) {
6215 init_unistr2( &buffer, printer->info_2->portname, UNI_STR_TERMINATE);
6216 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "portName",
6217 REG_SZ, (uint8_t *)buffer.buffer, buffer.uni_str_len*2 );
6219 notify_printer_port(snum, printer->info_2->portname);
6222 if (!strequal(printer->info_2->location, old_printer->info_2->location)) {
6223 init_unistr2( &buffer, printer->info_2->location, UNI_STR_TERMINATE);
6224 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "location",
6225 REG_SZ, (uint8_t *)buffer.buffer, buffer.uni_str_len*2 );
6227 notify_printer_location(snum, printer->info_2->location);
6230 /* here we need to update some more DsSpooler keys */
6231 /* uNCName, serverName, shortServerName */
6233 init_unistr2( &buffer, global_myname(), UNI_STR_TERMINATE);
6234 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "serverName",
6235 REG_SZ, (uint8_t *)buffer.buffer, buffer.uni_str_len*2 );
6236 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "shortServerName",
6237 REG_SZ, (uint8_t *)buffer.buffer, buffer.uni_str_len*2 );
6239 slprintf( asc_buffer, sizeof(asc_buffer)-1, "\\\\%s\\%s",
6240 global_myname(), printer->info_2->sharename );
6241 init_unistr2( &buffer, asc_buffer, UNI_STR_TERMINATE);
6242 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "uNCName",
6243 REG_SZ, (uint8_t *)buffer.buffer, buffer.uni_str_len*2 );
6245 /* Update printer info */
6246 result = mod_a_printer(printer, 2);
6248 done:
6249 free_a_printer(&printer, 2);
6250 free_a_printer(&old_printer, 2);
6253 return result;
6256 /****************************************************************************
6257 ****************************************************************************/
6258 static WERROR publish_or_unpublish_printer(pipes_struct *p,
6259 struct policy_handle *handle,
6260 struct spoolss_SetPrinterInfo7 *info7)
6262 #ifdef HAVE_ADS
6263 int snum;
6264 Printer_entry *Printer;
6266 if ( lp_security() != SEC_ADS ) {
6267 return WERR_UNKNOWN_LEVEL;
6270 Printer = find_printer_index_by_hnd(p, handle);
6272 DEBUG(5,("publish_or_unpublish_printer, action = %d\n",info7->action));
6274 if (!Printer)
6275 return WERR_BADFID;
6277 if (!get_printer_snum(p, handle, &snum, NULL))
6278 return WERR_BADFID;
6280 nt_printer_publish(Printer, snum, info7->action);
6282 return WERR_OK;
6283 #else
6284 return WERR_UNKNOWN_LEVEL;
6285 #endif
6288 /****************************************************************
6289 _spoolss_SetPrinter
6290 ****************************************************************/
6292 WERROR _spoolss_SetPrinter(pipes_struct *p,
6293 struct spoolss_SetPrinter *r)
6295 WERROR result;
6297 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
6299 if (!Printer) {
6300 DEBUG(2,("_spoolss_SetPrinter: Invalid handle (%s:%u:%u)\n",
6301 OUR_HANDLE(r->in.handle)));
6302 return WERR_BADFID;
6305 /* check the level */
6306 switch (r->in.info_ctr->level) {
6307 case 0:
6308 return control_printer(r->in.handle, r->in.command, p);
6309 case 2:
6310 result = update_printer(p, r->in.handle,
6311 r->in.info_ctr,
6312 r->in.devmode_ctr->devmode);
6313 if (!W_ERROR_IS_OK(result))
6314 return result;
6315 if (r->in.secdesc_ctr->sd)
6316 result = update_printer_sec(r->in.handle, p,
6317 r->in.secdesc_ctr);
6318 return result;
6319 case 3:
6320 return update_printer_sec(r->in.handle, p,
6321 r->in.secdesc_ctr);
6322 case 7:
6323 return publish_or_unpublish_printer(p, r->in.handle,
6324 r->in.info_ctr->info.info7);
6325 default:
6326 return WERR_UNKNOWN_LEVEL;
6330 /****************************************************************
6331 _spoolss_FindClosePrinterNotify
6332 ****************************************************************/
6334 WERROR _spoolss_FindClosePrinterNotify(pipes_struct *p,
6335 struct spoolss_FindClosePrinterNotify *r)
6337 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
6339 if (!Printer) {
6340 DEBUG(2,("_spoolss_FindClosePrinterNotify: "
6341 "Invalid handle (%s:%u:%u)\n", OUR_HANDLE(r->in.handle)));
6342 return WERR_BADFID;
6345 if (Printer->notify.client_connected == true) {
6346 int snum = -1;
6348 if ( Printer->printer_type == SPLHND_SERVER)
6349 snum = -1;
6350 else if ( (Printer->printer_type == SPLHND_PRINTER) &&
6351 !get_printer_snum(p, r->in.handle, &snum, NULL) )
6352 return WERR_BADFID;
6354 srv_spoolss_replycloseprinter(snum, &Printer->notify.client_hnd);
6357 Printer->notify.flags=0;
6358 Printer->notify.options=0;
6359 Printer->notify.localmachine[0]='\0';
6360 Printer->notify.printerlocal=0;
6361 TALLOC_FREE(Printer->notify.option);
6362 Printer->notify.client_connected = false;
6364 return WERR_OK;
6367 /****************************************************************
6368 _spoolss_AddJob
6369 ****************************************************************/
6371 WERROR _spoolss_AddJob(pipes_struct *p,
6372 struct spoolss_AddJob *r)
6374 if (!r->in.buffer && (r->in.offered != 0)) {
6375 return WERR_INVALID_PARAM;
6378 /* this is what a NT server returns for AddJob. AddJob must fail on
6379 * non-local printers */
6381 if (r->in.level != 1) {
6382 return WERR_UNKNOWN_LEVEL;
6385 return WERR_INVALID_PARAM;
6388 /****************************************************************************
6389 fill_job_info1
6390 ****************************************************************************/
6392 static WERROR fill_job_info1(TALLOC_CTX *mem_ctx,
6393 struct spoolss_JobInfo1 *r,
6394 const print_queue_struct *queue,
6395 int position, int snum,
6396 const NT_PRINTER_INFO_LEVEL *ntprinter)
6398 struct tm *t;
6400 t = gmtime(&queue->time);
6402 r->job_id = queue->job;
6404 r->printer_name = talloc_strdup(mem_ctx, lp_servicename(snum));
6405 W_ERROR_HAVE_NO_MEMORY(r->printer_name);
6406 r->server_name = talloc_strdup(mem_ctx, ntprinter->info_2->servername);
6407 W_ERROR_HAVE_NO_MEMORY(r->server_name);
6408 r->user_name = talloc_strdup(mem_ctx, queue->fs_user);
6409 W_ERROR_HAVE_NO_MEMORY(r->user_name);
6410 r->document_name = talloc_strdup(mem_ctx, queue->fs_file);
6411 W_ERROR_HAVE_NO_MEMORY(r->document_name);
6412 r->data_type = talloc_strdup(mem_ctx, "RAW");
6413 W_ERROR_HAVE_NO_MEMORY(r->data_type);
6414 r->text_status = talloc_strdup(mem_ctx, "");
6415 W_ERROR_HAVE_NO_MEMORY(r->text_status);
6417 r->status = nt_printj_status(queue->status);
6418 r->priority = queue->priority;
6419 r->position = position;
6420 r->total_pages = queue->page_count;
6421 r->pages_printed = 0; /* ??? */
6423 init_systemtime(&r->submitted, t);
6425 return WERR_OK;
6428 /****************************************************************************
6429 fill_job_info2
6430 ****************************************************************************/
6432 static WERROR fill_job_info2(TALLOC_CTX *mem_ctx,
6433 struct spoolss_JobInfo2 *r,
6434 const print_queue_struct *queue,
6435 int position, int snum,
6436 const NT_PRINTER_INFO_LEVEL *ntprinter,
6437 struct spoolss_DeviceMode *devmode)
6439 struct tm *t;
6441 t = gmtime(&queue->time);
6443 r->job_id = queue->job;
6445 r->printer_name = talloc_strdup(mem_ctx, lp_servicename(snum));
6446 W_ERROR_HAVE_NO_MEMORY(r->printer_name);
6447 r->server_name = talloc_strdup(mem_ctx, ntprinter->info_2->servername);
6448 W_ERROR_HAVE_NO_MEMORY(r->server_name);
6449 r->user_name = talloc_strdup(mem_ctx, queue->fs_user);
6450 W_ERROR_HAVE_NO_MEMORY(r->user_name);
6451 r->document_name = talloc_strdup(mem_ctx, queue->fs_file);
6452 W_ERROR_HAVE_NO_MEMORY(r->document_name);
6453 r->notify_name = talloc_strdup(mem_ctx, queue->fs_user);
6454 W_ERROR_HAVE_NO_MEMORY(r->notify_name);
6455 r->data_type = talloc_strdup(mem_ctx, "RAW");
6456 W_ERROR_HAVE_NO_MEMORY(r->data_type);
6457 r->print_processor = talloc_strdup(mem_ctx, "winprint");
6458 W_ERROR_HAVE_NO_MEMORY(r->print_processor);
6459 r->parameters = talloc_strdup(mem_ctx, "");
6460 W_ERROR_HAVE_NO_MEMORY(r->parameters);
6461 r->driver_name = talloc_strdup(mem_ctx, ntprinter->info_2->drivername);
6462 W_ERROR_HAVE_NO_MEMORY(r->driver_name);
6464 r->devmode = devmode;
6466 r->text_status = talloc_strdup(mem_ctx, "");
6467 W_ERROR_HAVE_NO_MEMORY(r->text_status);
6469 r->secdesc = NULL;
6471 r->status = nt_printj_status(queue->status);
6472 r->priority = queue->priority;
6473 r->position = position;
6474 r->start_time = 0;
6475 r->until_time = 0;
6476 r->total_pages = queue->page_count;
6477 r->size = queue->size;
6478 init_systemtime(&r->submitted, t);
6479 r->time = 0;
6480 r->pages_printed = 0; /* ??? */
6482 return WERR_OK;
6485 /****************************************************************************
6486 Enumjobs at level 1.
6487 ****************************************************************************/
6489 static WERROR enumjobs_level1(TALLOC_CTX *mem_ctx,
6490 const print_queue_struct *queue,
6491 uint32_t num_queues, int snum,
6492 const NT_PRINTER_INFO_LEVEL *ntprinter,
6493 union spoolss_JobInfo **info_p,
6494 uint32_t *count)
6496 union spoolss_JobInfo *info;
6497 int i;
6498 WERROR result = WERR_OK;
6500 info = TALLOC_ARRAY(mem_ctx, union spoolss_JobInfo, num_queues);
6501 W_ERROR_HAVE_NO_MEMORY(info);
6503 *count = num_queues;
6505 for (i=0; i<*count; i++) {
6506 result = fill_job_info1(info,
6507 &info[i].info1,
6508 &queue[i],
6510 snum,
6511 ntprinter);
6512 if (!W_ERROR_IS_OK(result)) {
6513 goto out;
6517 out:
6518 if (!W_ERROR_IS_OK(result)) {
6519 TALLOC_FREE(info);
6520 *count = 0;
6521 return result;
6524 *info_p = info;
6526 return WERR_OK;
6529 /****************************************************************************
6530 Enumjobs at level 2.
6531 ****************************************************************************/
6533 static WERROR enumjobs_level2(TALLOC_CTX *mem_ctx,
6534 const print_queue_struct *queue,
6535 uint32_t num_queues, int snum,
6536 const NT_PRINTER_INFO_LEVEL *ntprinter,
6537 union spoolss_JobInfo **info_p,
6538 uint32_t *count)
6540 union spoolss_JobInfo *info;
6541 int i;
6542 WERROR result = WERR_OK;
6544 info = TALLOC_ARRAY(mem_ctx, union spoolss_JobInfo, num_queues);
6545 W_ERROR_HAVE_NO_MEMORY(info);
6547 *count = num_queues;
6549 for (i=0; i<*count; i++) {
6551 struct spoolss_DeviceMode *devmode;
6553 devmode = construct_dev_mode(info, lp_const_servicename(snum));
6554 if (!devmode) {
6555 result = WERR_NOMEM;
6556 goto out;
6559 result = fill_job_info2(info,
6560 &info[i].info2,
6561 &queue[i],
6563 snum,
6564 ntprinter,
6565 devmode);
6566 if (!W_ERROR_IS_OK(result)) {
6567 goto out;
6571 out:
6572 if (!W_ERROR_IS_OK(result)) {
6573 TALLOC_FREE(info);
6574 *count = 0;
6575 return result;
6578 *info_p = info;
6580 return WERR_OK;
6583 /****************************************************************
6584 _spoolss_EnumJobs
6585 ****************************************************************/
6587 WERROR _spoolss_EnumJobs(pipes_struct *p,
6588 struct spoolss_EnumJobs *r)
6590 WERROR result;
6591 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
6592 int snum;
6593 print_status_struct prt_status;
6594 print_queue_struct *queue = NULL;
6595 uint32_t count;
6597 /* that's an [in out] buffer */
6599 if (!r->in.buffer && (r->in.offered != 0)) {
6600 return WERR_INVALID_PARAM;
6603 DEBUG(4,("_spoolss_EnumJobs\n"));
6605 *r->out.needed = 0;
6606 *r->out.count = 0;
6607 *r->out.info = NULL;
6609 /* lookup the printer snum and tdb entry */
6611 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
6612 return WERR_BADFID;
6615 result = get_a_printer(NULL, &ntprinter, 2, lp_servicename(snum));
6616 if (!W_ERROR_IS_OK(result)) {
6617 return result;
6620 count = print_queue_status(snum, &queue, &prt_status);
6621 DEBUGADD(4,("count:[%d], status:[%d], [%s]\n",
6622 count, prt_status.status, prt_status.message));
6624 if (count == 0) {
6625 SAFE_FREE(queue);
6626 free_a_printer(&ntprinter, 2);
6627 return WERR_OK;
6630 switch (r->in.level) {
6631 case 1:
6632 result = enumjobs_level1(p->mem_ctx, queue, count, snum,
6633 ntprinter, r->out.info, r->out.count);
6634 break;
6635 case 2:
6636 result = enumjobs_level2(p->mem_ctx, queue, count, snum,
6637 ntprinter, r->out.info, r->out.count);
6638 break;
6639 default:
6640 result = WERR_UNKNOWN_LEVEL;
6641 break;
6644 SAFE_FREE(queue);
6645 free_a_printer(&ntprinter, 2);
6647 if (!W_ERROR_IS_OK(result)) {
6648 return result;
6651 *r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
6652 spoolss_EnumJobs, NULL,
6653 *r->out.info, r->in.level,
6654 *r->out.count);
6655 *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
6656 *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, 0);
6658 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
6661 /****************************************************************
6662 _spoolss_ScheduleJob
6663 ****************************************************************/
6665 WERROR _spoolss_ScheduleJob(pipes_struct *p,
6666 struct spoolss_ScheduleJob *r)
6668 return WERR_OK;
6671 /****************************************************************
6672 _spoolss_SetJob
6673 ****************************************************************/
6675 WERROR _spoolss_SetJob(pipes_struct *p,
6676 struct spoolss_SetJob *r)
6678 int snum;
6679 WERROR errcode = WERR_BADFUNC;
6681 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
6682 return WERR_BADFID;
6685 if (!print_job_exists(lp_const_servicename(snum), r->in.job_id)) {
6686 return WERR_INVALID_PRINTER_NAME;
6689 switch (r->in.command) {
6690 case SPOOLSS_JOB_CONTROL_CANCEL:
6691 case SPOOLSS_JOB_CONTROL_DELETE:
6692 if (print_job_delete(p->server_info, snum, r->in.job_id, &errcode)) {
6693 errcode = WERR_OK;
6695 break;
6696 case SPOOLSS_JOB_CONTROL_PAUSE:
6697 if (print_job_pause(p->server_info, snum, r->in.job_id, &errcode)) {
6698 errcode = WERR_OK;
6700 break;
6701 case SPOOLSS_JOB_CONTROL_RESTART:
6702 case SPOOLSS_JOB_CONTROL_RESUME:
6703 if (print_job_resume(p->server_info, snum, r->in.job_id, &errcode)) {
6704 errcode = WERR_OK;
6706 break;
6707 default:
6708 return WERR_UNKNOWN_LEVEL;
6711 return errcode;
6714 /****************************************************************************
6715 Enumerates all printer drivers by level.
6716 ****************************************************************************/
6718 static WERROR enumprinterdrivers_level(TALLOC_CTX *mem_ctx,
6719 const char *servername,
6720 const char *architecture,
6721 uint32_t level,
6722 union spoolss_DriverInfo **info_p,
6723 uint32_t *count_p)
6725 int i;
6726 int ndrivers;
6727 uint32_t version;
6728 fstring *list = NULL;
6729 NT_PRINTER_DRIVER_INFO_LEVEL driver;
6730 union spoolss_DriverInfo *info = NULL;
6731 uint32_t count = 0;
6732 WERROR result = WERR_OK;
6734 *count_p = 0;
6735 *info_p = NULL;
6737 for (version=0; version<DRIVER_MAX_VERSION; version++) {
6738 list = NULL;
6739 ndrivers = get_ntdrivers(&list, architecture, version);
6740 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n",
6741 ndrivers, architecture, version));
6743 if (ndrivers == -1) {
6744 result = WERR_NOMEM;
6745 goto out;
6748 if (ndrivers != 0) {
6749 info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
6750 union spoolss_DriverInfo,
6751 count + ndrivers);
6752 if (!info) {
6753 DEBUG(0,("enumprinterdrivers_level1: "
6754 "failed to enlarge driver info buffer!\n"));
6755 result = WERR_NOMEM;
6756 goto out;
6760 for (i=0; i<ndrivers; i++) {
6761 DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
6762 ZERO_STRUCT(driver);
6763 result = get_a_printer_driver(&driver, 3, list[i],
6764 architecture, version);
6765 if (!W_ERROR_IS_OK(result)) {
6766 goto out;
6769 switch (level) {
6770 case 1:
6771 result = fill_printer_driver_info1(info, &info[count+i].info1,
6772 &driver, servername,
6773 architecture);
6774 break;
6775 case 2:
6776 result = fill_printer_driver_info2(info, &info[count+i].info2,
6777 &driver, servername);
6778 break;
6779 case 3:
6780 result = fill_printer_driver_info3(info, &info[count+i].info3,
6781 &driver, servername);
6782 break;
6783 case 4:
6784 result = fill_printer_driver_info4(info, &info[count+i].info4,
6785 &driver, servername);
6786 break;
6787 case 5:
6788 result = fill_printer_driver_info5(info, &info[count+i].info5,
6789 &driver, servername);
6790 break;
6791 case 6:
6792 result = fill_printer_driver_info6(info, &info[count+i].info6,
6793 &driver, servername);
6794 break;
6795 default:
6796 result = WERR_UNKNOWN_LEVEL;
6797 break;
6800 if (!W_ERROR_IS_OK(result)) {
6801 free_a_printer_driver(driver, 3);
6802 goto out;
6804 free_a_printer_driver(driver, 3);
6807 count += ndrivers;
6808 SAFE_FREE(list);
6811 out:
6812 SAFE_FREE(list);
6814 if (!W_ERROR_IS_OK(result)) {
6815 TALLOC_FREE(info);
6816 return result;
6819 *info_p = info;
6820 *count_p = count;
6822 return WERR_OK;
6825 /****************************************************************************
6826 Enumerates all printer drivers at level 1.
6827 ****************************************************************************/
6829 static WERROR enumprinterdrivers_level1(TALLOC_CTX *mem_ctx,
6830 const char *servername,
6831 const char *architecture,
6832 union spoolss_DriverInfo **info_p,
6833 uint32_t *count)
6835 return enumprinterdrivers_level(mem_ctx, servername, architecture, 1,
6836 info_p, count);
6839 /****************************************************************************
6840 Enumerates all printer drivers at level 2.
6841 ****************************************************************************/
6843 static WERROR enumprinterdrivers_level2(TALLOC_CTX *mem_ctx,
6844 const char *servername,
6845 const char *architecture,
6846 union spoolss_DriverInfo **info_p,
6847 uint32_t *count)
6849 return enumprinterdrivers_level(mem_ctx, servername, architecture, 2,
6850 info_p, count);
6853 /****************************************************************************
6854 Enumerates all printer drivers at level 3.
6855 ****************************************************************************/
6857 static WERROR enumprinterdrivers_level3(TALLOC_CTX *mem_ctx,
6858 const char *servername,
6859 const char *architecture,
6860 union spoolss_DriverInfo **info_p,
6861 uint32_t *count)
6863 return enumprinterdrivers_level(mem_ctx, servername, architecture, 3,
6864 info_p, count);
6867 /****************************************************************************
6868 Enumerates all printer drivers at level 4.
6869 ****************************************************************************/
6871 static WERROR enumprinterdrivers_level4(TALLOC_CTX *mem_ctx,
6872 const char *servername,
6873 const char *architecture,
6874 union spoolss_DriverInfo **info_p,
6875 uint32_t *count)
6877 return enumprinterdrivers_level(mem_ctx, servername, architecture, 4,
6878 info_p, count);
6881 /****************************************************************************
6882 Enumerates all printer drivers at level 5.
6883 ****************************************************************************/
6885 static WERROR enumprinterdrivers_level5(TALLOC_CTX *mem_ctx,
6886 const char *servername,
6887 const char *architecture,
6888 union spoolss_DriverInfo **info_p,
6889 uint32_t *count)
6891 return enumprinterdrivers_level(mem_ctx, servername, architecture, 5,
6892 info_p, count);
6895 /****************************************************************************
6896 Enumerates all printer drivers at level 6.
6897 ****************************************************************************/
6899 static WERROR enumprinterdrivers_level6(TALLOC_CTX *mem_ctx,
6900 const char *servername,
6901 const char *architecture,
6902 union spoolss_DriverInfo **info_p,
6903 uint32_t *count)
6905 return enumprinterdrivers_level(mem_ctx, servername, architecture, 6,
6906 info_p, count);
6910 /****************************************************************
6911 _spoolss_EnumPrinterDrivers
6912 ****************************************************************/
6914 WERROR _spoolss_EnumPrinterDrivers(pipes_struct *p,
6915 struct spoolss_EnumPrinterDrivers *r)
6917 const char *cservername;
6918 WERROR result;
6920 /* that's an [in out] buffer */
6922 if (!r->in.buffer && (r->in.offered != 0)) {
6923 return WERR_INVALID_PARAM;
6926 DEBUG(4,("_spoolss_EnumPrinterDrivers\n"));
6928 *r->out.needed = 0;
6929 *r->out.count = 0;
6930 *r->out.info = NULL;
6932 cservername = canon_servername(r->in.server);
6934 if (!is_myname_or_ipaddr(cservername)) {
6935 return WERR_UNKNOWN_PRINTER_DRIVER;
6938 switch (r->in.level) {
6939 case 1:
6940 result = enumprinterdrivers_level1(p->mem_ctx, cservername,
6941 r->in.environment,
6942 r->out.info, r->out.count);
6943 break;
6944 case 2:
6945 result = enumprinterdrivers_level2(p->mem_ctx, cservername,
6946 r->in.environment,
6947 r->out.info, r->out.count);
6948 break;
6949 case 3:
6950 result = enumprinterdrivers_level3(p->mem_ctx, cservername,
6951 r->in.environment,
6952 r->out.info, r->out.count);
6953 break;
6954 case 4:
6955 result = enumprinterdrivers_level4(p->mem_ctx, cservername,
6956 r->in.environment,
6957 r->out.info, r->out.count);
6958 break;
6959 case 5:
6960 result = enumprinterdrivers_level5(p->mem_ctx, cservername,
6961 r->in.environment,
6962 r->out.info, r->out.count);
6963 break;
6964 case 6:
6965 result = enumprinterdrivers_level6(p->mem_ctx, cservername,
6966 r->in.environment,
6967 r->out.info, r->out.count);
6968 break;
6969 default:
6970 return WERR_UNKNOWN_LEVEL;
6973 if (!W_ERROR_IS_OK(result)) {
6974 return result;
6977 *r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
6978 spoolss_EnumPrinterDrivers, NULL,
6979 *r->out.info, r->in.level,
6980 *r->out.count);
6981 *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
6982 *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, 0);
6984 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
6987 /****************************************************************************
6988 ****************************************************************************/
6990 static WERROR fill_form_info_1(TALLOC_CTX *mem_ctx,
6991 struct spoolss_FormInfo1 *r,
6992 const nt_forms_struct *form)
6994 r->form_name = talloc_strdup(mem_ctx, form->name);
6995 W_ERROR_HAVE_NO_MEMORY(r->form_name);
6997 r->flags = form->flag;
6998 r->size.width = form->width;
6999 r->size.height = form->length;
7000 r->area.left = form->left;
7001 r->area.top = form->top;
7002 r->area.right = form->right;
7003 r->area.bottom = form->bottom;
7005 return WERR_OK;
7008 /****************************************************************
7009 spoolss_enumforms_level1
7010 ****************************************************************/
7012 static WERROR spoolss_enumforms_level1(TALLOC_CTX *mem_ctx,
7013 const nt_forms_struct *builtin_forms,
7014 uint32_t num_builtin_forms,
7015 const nt_forms_struct *user_forms,
7016 uint32_t num_user_forms,
7017 union spoolss_FormInfo **info_p,
7018 uint32_t *count)
7020 union spoolss_FormInfo *info;
7021 WERROR result = WERR_OK;
7022 int i;
7024 *count = num_builtin_forms + num_user_forms;
7026 info = TALLOC_ARRAY(mem_ctx, union spoolss_FormInfo, *count);
7027 W_ERROR_HAVE_NO_MEMORY(info);
7029 /* construct the list of form structures */
7030 for (i=0; i<num_builtin_forms; i++) {
7031 DEBUGADD(6,("Filling builtin form number [%d]\n",i));
7032 result = fill_form_info_1(info, &info[i].info1,
7033 &builtin_forms[i]);
7034 if (!W_ERROR_IS_OK(result)) {
7035 goto out;
7039 for (i=0; i<num_user_forms; i++) {
7040 DEBUGADD(6,("Filling user form number [%d]\n",i));
7041 result = fill_form_info_1(info, &info[i+num_builtin_forms].info1,
7042 &user_forms[i]);
7043 if (!W_ERROR_IS_OK(result)) {
7044 goto out;
7048 out:
7049 if (!W_ERROR_IS_OK(result)) {
7050 TALLOC_FREE(info);
7051 *count = 0;
7052 return result;
7055 *info_p = info;
7057 return WERR_OK;
7060 /****************************************************************
7061 _spoolss_EnumForms
7062 ****************************************************************/
7064 WERROR _spoolss_EnumForms(pipes_struct *p,
7065 struct spoolss_EnumForms *r)
7067 WERROR result;
7068 nt_forms_struct *user_forms = NULL;
7069 nt_forms_struct *builtin_forms = NULL;
7070 uint32_t num_user_forms;
7071 uint32_t num_builtin_forms;
7073 *r->out.count = 0;
7074 *r->out.needed = 0;
7075 *r->out.info = NULL;
7077 /* that's an [in out] buffer */
7079 if (!r->in.buffer && (r->in.offered != 0) ) {
7080 return WERR_INVALID_PARAM;
7083 DEBUG(4,("_spoolss_EnumForms\n"));
7084 DEBUGADD(5,("Offered buffer size [%d]\n", r->in.offered));
7085 DEBUGADD(5,("Info level [%d]\n", r->in.level));
7087 num_builtin_forms = get_builtin_ntforms(&builtin_forms);
7088 DEBUGADD(5,("Number of builtin forms [%d]\n", num_builtin_forms));
7089 num_user_forms = get_ntforms(&user_forms);
7090 DEBUGADD(5,("Number of user forms [%d]\n", num_user_forms));
7092 if (num_user_forms + num_builtin_forms == 0) {
7093 SAFE_FREE(builtin_forms);
7094 SAFE_FREE(user_forms);
7095 return WERR_NO_MORE_ITEMS;
7098 switch (r->in.level) {
7099 case 1:
7100 result = spoolss_enumforms_level1(p->mem_ctx,
7101 builtin_forms,
7102 num_builtin_forms,
7103 user_forms,
7104 num_user_forms,
7105 r->out.info,
7106 r->out.count);
7107 break;
7108 default:
7109 result = WERR_UNKNOWN_LEVEL;
7110 break;
7113 SAFE_FREE(user_forms);
7114 SAFE_FREE(builtin_forms);
7116 if (!W_ERROR_IS_OK(result)) {
7117 return result;
7120 *r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
7121 spoolss_EnumForms, NULL,
7122 *r->out.info, r->in.level,
7123 *r->out.count);
7124 *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
7125 *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, 0);
7127 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
7130 /****************************************************************
7131 ****************************************************************/
7133 static WERROR find_form_byname(const char *name,
7134 nt_forms_struct *form)
7136 nt_forms_struct *list = NULL;
7137 int num_forms = 0, i = 0;
7139 if (get_a_builtin_ntform_by_string(name, form)) {
7140 return WERR_OK;
7143 num_forms = get_ntforms(&list);
7144 DEBUGADD(5,("Number of forms [%d]\n", num_forms));
7146 if (num_forms == 0) {
7147 return WERR_BADFID;
7150 /* Check if the requested name is in the list of form structures */
7151 for (i = 0; i < num_forms; i++) {
7153 DEBUG(4,("checking form %s (want %s)\n", list[i].name, name));
7155 if (strequal(name, list[i].name)) {
7156 DEBUGADD(6,("Found form %s number [%d]\n", name, i));
7157 *form = list[i];
7158 SAFE_FREE(list);
7159 return WERR_OK;
7163 SAFE_FREE(list);
7165 return WERR_BADFID;
7168 /****************************************************************
7169 _spoolss_GetForm
7170 ****************************************************************/
7172 WERROR _spoolss_GetForm(pipes_struct *p,
7173 struct spoolss_GetForm *r)
7175 WERROR result;
7176 nt_forms_struct form;
7178 /* that's an [in out] buffer */
7180 if (!r->in.buffer && (r->in.offered != 0)) {
7181 return WERR_INVALID_PARAM;
7184 DEBUG(4,("_spoolss_GetForm\n"));
7185 DEBUGADD(5,("Offered buffer size [%d]\n", r->in.offered));
7186 DEBUGADD(5,("Info level [%d]\n", r->in.level));
7188 result = find_form_byname(r->in.form_name, &form);
7189 if (!W_ERROR_IS_OK(result)) {
7190 TALLOC_FREE(r->out.info);
7191 return result;
7194 switch (r->in.level) {
7195 case 1:
7196 result = fill_form_info_1(p->mem_ctx,
7197 &r->out.info->info1,
7198 &form);
7199 break;
7201 default:
7202 result = WERR_UNKNOWN_LEVEL;
7203 break;
7206 if (!W_ERROR_IS_OK(result)) {
7207 TALLOC_FREE(r->out.info);
7208 return result;
7211 *r->out.needed = SPOOLSS_BUFFER_UNION(spoolss_FormInfo, NULL,
7212 r->out.info, r->in.level);
7213 r->out.info = SPOOLSS_BUFFER_OK(r->out.info, NULL);
7215 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
7218 /****************************************************************************
7219 ****************************************************************************/
7221 static WERROR fill_port_1(TALLOC_CTX *mem_ctx,
7222 struct spoolss_PortInfo1 *r,
7223 const char *name)
7225 r->port_name = talloc_strdup(mem_ctx, name);
7226 W_ERROR_HAVE_NO_MEMORY(r->port_name);
7228 return WERR_OK;
7231 /****************************************************************************
7232 TODO: This probably needs distinguish between TCP/IP and Local ports
7233 somehow.
7234 ****************************************************************************/
7236 static WERROR fill_port_2(TALLOC_CTX *mem_ctx,
7237 struct spoolss_PortInfo2 *r,
7238 const char *name)
7240 r->port_name = talloc_strdup(mem_ctx, name);
7241 W_ERROR_HAVE_NO_MEMORY(r->port_name);
7243 r->monitor_name = talloc_strdup(mem_ctx, "Local Monitor");
7244 W_ERROR_HAVE_NO_MEMORY(r->monitor_name);
7246 r->description = talloc_strdup(mem_ctx, SPL_LOCAL_PORT);
7247 W_ERROR_HAVE_NO_MEMORY(r->description);
7249 r->port_type = SPOOLSS_PORT_TYPE_WRITE;
7250 r->reserved = 0;
7252 return WERR_OK;
7256 /****************************************************************************
7257 wrapper around the enumer ports command
7258 ****************************************************************************/
7260 WERROR enumports_hook(TALLOC_CTX *ctx, int *count, char ***lines )
7262 char *cmd = lp_enumports_cmd();
7263 char **qlines = NULL;
7264 char *command = NULL;
7265 int numlines;
7266 int ret;
7267 int fd;
7269 *count = 0;
7270 *lines = NULL;
7272 /* if no hook then just fill in the default port */
7274 if ( !*cmd ) {
7275 if (!(qlines = TALLOC_ARRAY( NULL, char*, 2 ))) {
7276 return WERR_NOMEM;
7278 if (!(qlines[0] = talloc_strdup(qlines, SAMBA_PRINTER_PORT_NAME ))) {
7279 TALLOC_FREE(qlines);
7280 return WERR_NOMEM;
7282 qlines[1] = NULL;
7283 numlines = 1;
7285 else {
7286 /* we have a valid enumport command */
7288 command = talloc_asprintf(ctx, "%s \"%d\"", cmd, 1);
7289 if (!command) {
7290 return WERR_NOMEM;
7293 DEBUG(10,("Running [%s]\n", command));
7294 ret = smbrun(command, &fd);
7295 DEBUG(10,("Returned [%d]\n", ret));
7296 TALLOC_FREE(command);
7297 if (ret != 0) {
7298 if (fd != -1) {
7299 close(fd);
7301 return WERR_ACCESS_DENIED;
7304 numlines = 0;
7305 qlines = fd_lines_load(fd, &numlines, 0, NULL);
7306 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
7307 close(fd);
7310 *count = numlines;
7311 *lines = qlines;
7313 return WERR_OK;
7316 /****************************************************************************
7317 enumports level 1.
7318 ****************************************************************************/
7320 static WERROR enumports_level_1(TALLOC_CTX *mem_ctx,
7321 union spoolss_PortInfo **info_p,
7322 uint32_t *count)
7324 union spoolss_PortInfo *info = NULL;
7325 int i=0;
7326 WERROR result = WERR_OK;
7327 char **qlines = NULL;
7328 int numlines = 0;
7330 result = enumports_hook(talloc_tos(), &numlines, &qlines );
7331 if (!W_ERROR_IS_OK(result)) {
7332 goto out;
7335 if (numlines) {
7336 info = TALLOC_ARRAY(mem_ctx, union spoolss_PortInfo, numlines);
7337 if (!info) {
7338 DEBUG(10,("Returning WERR_NOMEM\n"));
7339 result = WERR_NOMEM;
7340 goto out;
7343 for (i=0; i<numlines; i++) {
7344 DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
7345 result = fill_port_1(info, &info[i].info1, qlines[i]);
7346 if (!W_ERROR_IS_OK(result)) {
7347 goto out;
7351 TALLOC_FREE(qlines);
7353 out:
7354 if (!W_ERROR_IS_OK(result)) {
7355 TALLOC_FREE(info);
7356 TALLOC_FREE(qlines);
7357 *count = 0;
7358 *info_p = NULL;
7359 return result;
7362 *info_p = info;
7363 *count = numlines;
7365 return WERR_OK;
7368 /****************************************************************************
7369 enumports level 2.
7370 ****************************************************************************/
7372 static WERROR enumports_level_2(TALLOC_CTX *mem_ctx,
7373 union spoolss_PortInfo **info_p,
7374 uint32_t *count)
7376 union spoolss_PortInfo *info = NULL;
7377 int i=0;
7378 WERROR result = WERR_OK;
7379 char **qlines = NULL;
7380 int numlines = 0;
7382 result = enumports_hook(talloc_tos(), &numlines, &qlines );
7383 if (!W_ERROR_IS_OK(result)) {
7384 goto out;
7387 if (numlines) {
7388 info = TALLOC_ARRAY(mem_ctx, union spoolss_PortInfo, numlines);
7389 if (!info) {
7390 DEBUG(10,("Returning WERR_NOMEM\n"));
7391 result = WERR_NOMEM;
7392 goto out;
7395 for (i=0; i<numlines; i++) {
7396 DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
7397 result = fill_port_2(info, &info[i].info2, qlines[i]);
7398 if (!W_ERROR_IS_OK(result)) {
7399 goto out;
7403 TALLOC_FREE(qlines);
7405 out:
7406 if (!W_ERROR_IS_OK(result)) {
7407 TALLOC_FREE(info);
7408 TALLOC_FREE(qlines);
7409 *count = 0;
7410 *info_p = NULL;
7411 return result;
7414 *info_p = info;
7415 *count = numlines;
7417 return WERR_OK;
7420 /****************************************************************
7421 _spoolss_EnumPorts
7422 ****************************************************************/
7424 WERROR _spoolss_EnumPorts(pipes_struct *p,
7425 struct spoolss_EnumPorts *r)
7427 WERROR result;
7429 /* that's an [in out] buffer */
7431 if (!r->in.buffer && (r->in.offered != 0)) {
7432 return WERR_INVALID_PARAM;
7435 DEBUG(4,("_spoolss_EnumPorts\n"));
7437 *r->out.count = 0;
7438 *r->out.needed = 0;
7439 *r->out.info = NULL;
7441 switch (r->in.level) {
7442 case 1:
7443 result = enumports_level_1(p->mem_ctx, r->out.info,
7444 r->out.count);
7445 break;
7446 case 2:
7447 result = enumports_level_2(p->mem_ctx, r->out.info,
7448 r->out.count);
7449 break;
7450 default:
7451 return WERR_UNKNOWN_LEVEL;
7454 if (!W_ERROR_IS_OK(result)) {
7455 return result;
7458 *r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
7459 spoolss_EnumPorts, NULL,
7460 *r->out.info, r->in.level,
7461 *r->out.count);
7462 *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
7463 *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, 0);
7465 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
7468 /****************************************************************************
7469 ****************************************************************************/
7471 static WERROR spoolss_addprinterex_level_2(pipes_struct *p,
7472 const char *server,
7473 struct spoolss_SetPrinterInfoCtr *info_ctr,
7474 struct spoolss_DeviceMode *devmode,
7475 struct security_descriptor *sec_desc,
7476 struct spoolss_UserLevelCtr *user_ctr,
7477 struct policy_handle *handle)
7479 NT_PRINTER_INFO_LEVEL *printer = NULL;
7480 fstring name;
7481 int snum;
7482 WERROR err = WERR_OK;
7484 if ( !(printer = TALLOC_ZERO_P(NULL, NT_PRINTER_INFO_LEVEL)) ) {
7485 DEBUG(0,("spoolss_addprinterex_level_2: malloc fail.\n"));
7486 return WERR_NOMEM;
7489 /* convert from UNICODE to ASCII - this allocates the info_2 struct inside *printer.*/
7490 if (!convert_printer_info(info_ctr, printer)) {
7491 free_a_printer(&printer, 2);
7492 return WERR_NOMEM;
7495 /* check to see if the printer already exists */
7497 if ((snum = print_queue_snum(printer->info_2->sharename)) != -1) {
7498 DEBUG(5, ("spoolss_addprinterex_level_2: Attempted to add a printer named [%s] when one already existed!\n",
7499 printer->info_2->sharename));
7500 free_a_printer(&printer, 2);
7501 return WERR_PRINTER_ALREADY_EXISTS;
7504 /* FIXME!!! smbd should check to see if the driver is installed before
7505 trying to add a printer like this --jerry */
7507 if (*lp_addprinter_cmd() ) {
7508 if ( !add_printer_hook(p->mem_ctx, p->server_info->ptok,
7509 printer) ) {
7510 free_a_printer(&printer,2);
7511 return WERR_ACCESS_DENIED;
7513 } else {
7514 DEBUG(0,("spoolss_addprinterex_level_2: add printer for printer %s called and no"
7515 "smb.conf parameter \"addprinter command\" is defined. This"
7516 "parameter must exist for this call to succeed\n",
7517 printer->info_2->sharename ));
7520 /* use our primary netbios name since get_a_printer() will convert
7521 it to what the client expects on a case by case basis */
7523 slprintf(name, sizeof(name)-1, "\\\\%s\\%s", global_myname(),
7524 printer->info_2->sharename);
7527 if ((snum = print_queue_snum(printer->info_2->sharename)) == -1) {
7528 free_a_printer(&printer,2);
7529 return WERR_ACCESS_DENIED;
7532 /* you must be a printer admin to add a new printer */
7533 if (!print_access_check(p->server_info, snum, PRINTER_ACCESS_ADMINISTER)) {
7534 free_a_printer(&printer,2);
7535 return WERR_ACCESS_DENIED;
7539 * Do sanity check on the requested changes for Samba.
7542 if (!check_printer_ok(printer->info_2, snum)) {
7543 free_a_printer(&printer,2);
7544 return WERR_INVALID_PARAM;
7548 * When a printer is created, the drivername bound to the printer is used
7549 * to lookup previously saved driver initialization info, which is then
7550 * bound to the new printer, simulating what happens in the Windows arch.
7553 if (!devmode)
7555 set_driver_init(printer, 2);
7557 else
7559 /* A valid devmode was included, convert and link it
7561 DEBUGADD(10, ("spoolss_addprinterex_level_2: devmode included, converting\n"));
7563 if (!convert_devicemode(printer->info_2->printername, devmode,
7564 &printer->info_2->devmode)) {
7565 return WERR_NOMEM;
7569 /* write the ASCII on disk */
7570 err = mod_a_printer(printer, 2);
7571 if (!W_ERROR_IS_OK(err)) {
7572 free_a_printer(&printer,2);
7573 return err;
7576 if (!open_printer_hnd(p, handle, name, PRINTER_ACCESS_ADMINISTER)) {
7577 /* Handle open failed - remove addition. */
7578 del_a_printer(printer->info_2->sharename);
7579 free_a_printer(&printer,2);
7580 ZERO_STRUCTP(handle);
7581 return WERR_ACCESS_DENIED;
7584 update_c_setprinter(false);
7585 free_a_printer(&printer,2);
7587 return WERR_OK;
7590 /****************************************************************
7591 _spoolss_AddPrinterEx
7592 ****************************************************************/
7594 WERROR _spoolss_AddPrinterEx(pipes_struct *p,
7595 struct spoolss_AddPrinterEx *r)
7597 switch (r->in.info_ctr->level) {
7598 case 1:
7599 /* we don't handle yet */
7600 /* but I know what to do ... */
7601 return WERR_UNKNOWN_LEVEL;
7602 case 2:
7603 return spoolss_addprinterex_level_2(p, r->in.server,
7604 r->in.info_ctr,
7605 r->in.devmode_ctr->devmode,
7606 r->in.secdesc_ctr->sd,
7607 r->in.userlevel_ctr,
7608 r->out.handle);
7609 default:
7610 return WERR_UNKNOWN_LEVEL;
7614 /****************************************************************
7615 _spoolss_AddPrinterDriver
7616 ****************************************************************/
7618 WERROR _spoolss_AddPrinterDriver(pipes_struct *p,
7619 struct spoolss_AddPrinterDriver *r)
7621 uint32_t level = r->in.info_ctr->level;
7622 struct spoolss_AddDriverInfoCtr *info = r->in.info_ctr;
7623 WERROR err = WERR_OK;
7624 NT_PRINTER_DRIVER_INFO_LEVEL driver;
7625 const char *driver_name = NULL;
7626 uint32_t version;
7627 const char *fn;
7629 switch (p->hdr_req.opnum) {
7630 case NDR_SPOOLSS_ADDPRINTERDRIVER:
7631 fn = "_spoolss_AddPrinterDriver";
7632 break;
7633 case NDR_SPOOLSS_ADDPRINTERDRIVEREX:
7634 fn = "_spoolss_AddPrinterDriverEx";
7635 break;
7636 default:
7637 return WERR_INVALID_PARAM;
7641 /* FIXME */
7642 if (level != 3 && level != 6) {
7643 /* Clever hack from Martin Zielinski <mz@seh.de>
7644 * to allow downgrade from level 8 (Vista).
7646 DEBUG(0,("%s: level %d not yet implemented\n", fn, level));
7647 return WERR_UNKNOWN_LEVEL;
7650 ZERO_STRUCT(driver);
7652 if (!convert_printer_driver_info(info, &driver, level)) {
7653 err = WERR_NOMEM;
7654 goto done;
7657 DEBUG(5,("Cleaning driver's information\n"));
7658 err = clean_up_driver_struct(p, driver, level);
7659 if (!W_ERROR_IS_OK(err))
7660 goto done;
7662 DEBUG(5,("Moving driver to final destination\n"));
7663 if( !W_ERROR_IS_OK(err = move_driver_to_download_area(p, driver, level,
7664 &err)) ) {
7665 goto done;
7668 if (add_a_printer_driver(driver, level)!=0) {
7669 err = WERR_ACCESS_DENIED;
7670 goto done;
7673 switch(level) {
7674 case 3:
7675 driver_name = driver.info_3->name ? driver.info_3->name : "";
7676 break;
7677 case 6:
7678 driver_name = driver.info_6->name ? driver.info_6->name : "";
7679 break;
7683 * I think this is where he DrvUpgradePrinter() hook would be
7684 * be called in a driver's interface DLL on a Windows NT 4.0/2k
7685 * server. Right now, we just need to send ourselves a message
7686 * to update each printer bound to this driver. --jerry
7689 if (!srv_spoolss_drv_upgrade_printer(driver_name)) {
7690 DEBUG(0,("%s: Failed to send message about upgrading driver [%s]!\n",
7691 fn, driver_name));
7695 * Based on the version (e.g. driver destination dir: 0=9x,2=Nt/2k,3=2k/Xp),
7696 * decide if the driver init data should be deleted. The rules are:
7697 * 1) never delete init data if it is a 9x driver, they don't use it anyway
7698 * 2) delete init data only if there is no 2k/Xp driver
7699 * 3) always delete init data
7700 * The generalized rule is always use init data from the highest order driver.
7701 * It is necessary to follow the driver install by an initialization step to
7702 * finish off this process.
7704 if (level == 3)
7705 version = driver.info_3->cversion;
7706 else if (level == 6)
7707 version = driver.info_6->version;
7708 else
7709 version = -1;
7710 switch (version) {
7712 * 9x printer driver - never delete init data
7714 case 0:
7715 DEBUG(10,("%s: init data not deleted for 9x driver [%s]\n",
7716 fn, driver_name));
7717 break;
7720 * Nt or 2k (compatiblity mode) printer driver - only delete init data if
7721 * there is no 2k/Xp driver init data for this driver name.
7723 case 2:
7725 NT_PRINTER_DRIVER_INFO_LEVEL driver1;
7727 if (!W_ERROR_IS_OK(get_a_printer_driver(&driver1, 3, driver_name, "Windows NT x86", 3))) {
7729 * No 2k/Xp driver found, delete init data (if any) for the new Nt driver.
7731 if (!del_driver_init(driver_name))
7732 DEBUG(6,("%s: del_driver_init(%s) Nt failed!\n",
7733 fn, driver_name));
7734 } else {
7736 * a 2k/Xp driver was found, don't delete init data because Nt driver will use it.
7738 free_a_printer_driver(driver1,3);
7739 DEBUG(10,("%s: init data not deleted for Nt driver [%s]\n",
7740 fn, driver_name));
7743 break;
7746 * 2k or Xp printer driver - always delete init data
7748 case 3:
7749 if (!del_driver_init(driver_name))
7750 DEBUG(6,("%s: del_driver_init(%s) 2k/Xp failed!\n",
7751 fn, driver_name));
7752 break;
7754 default:
7755 DEBUG(0,("%s: invalid level=%d\n", fn, level));
7756 break;
7760 done:
7761 free_a_printer_driver(driver, level);
7762 return err;
7765 /****************************************************************
7766 _spoolss_AddPrinterDriverEx
7767 ****************************************************************/
7769 WERROR _spoolss_AddPrinterDriverEx(pipes_struct *p,
7770 struct spoolss_AddPrinterDriverEx *r)
7772 struct spoolss_AddPrinterDriver a;
7775 * we only support the semantics of AddPrinterDriver()
7776 * i.e. only copy files that are newer than existing ones
7779 if (r->in.flags != APD_COPY_NEW_FILES) {
7780 return WERR_ACCESS_DENIED;
7783 a.in.servername = r->in.servername;
7784 a.in.info_ctr = r->in.info_ctr;
7786 return _spoolss_AddPrinterDriver(p, &a);
7789 /****************************************************************************
7790 ****************************************************************************/
7792 struct _spoolss_paths {
7793 int type;
7794 const char *share;
7795 const char *dir;
7798 enum { SPOOLSS_DRIVER_PATH, SPOOLSS_PRTPROCS_PATH };
7800 static const struct _spoolss_paths spoolss_paths[]= {
7801 { SPOOLSS_DRIVER_PATH, "print$", "DRIVERS" },
7802 { SPOOLSS_PRTPROCS_PATH, "prnproc$", "PRTPROCS" }
7805 static WERROR compose_spoolss_server_path(TALLOC_CTX *mem_ctx,
7806 const char *servername,
7807 const char *environment,
7808 int component,
7809 char **path)
7811 const char *pservername = NULL;
7812 const char *long_archi = SPOOLSS_ARCHITECTURE_NT_X86;
7813 const char *short_archi;
7815 *path = NULL;
7817 /* environment may be empty */
7818 if (environment && strlen(environment)) {
7819 long_archi = environment;
7822 /* servername may be empty */
7823 if (servername && strlen(servername)) {
7824 pservername = canon_servername(servername);
7826 if (!is_myname_or_ipaddr(pservername)) {
7827 return WERR_INVALID_PARAM;
7831 if (!(short_archi = get_short_archi(long_archi))) {
7832 return WERR_INVALID_ENVIRONMENT;
7835 switch (component) {
7836 case SPOOLSS_PRTPROCS_PATH:
7837 case SPOOLSS_DRIVER_PATH:
7838 if (pservername) {
7839 *path = talloc_asprintf(mem_ctx,
7840 "\\\\%s\\%s\\%s",
7841 pservername,
7842 spoolss_paths[component].share,
7843 short_archi);
7844 } else {
7845 *path = talloc_asprintf(mem_ctx, "%s\\%s\\%s",
7846 SPOOLSS_DEFAULT_SERVER_PATH,
7847 spoolss_paths[component].dir,
7848 short_archi);
7850 break;
7851 default:
7852 return WERR_INVALID_PARAM;
7855 if (!*path) {
7856 return WERR_NOMEM;
7859 return WERR_OK;
7862 /****************************************************************************
7863 ****************************************************************************/
7865 static WERROR getprinterdriverdir_level_1(TALLOC_CTX *mem_ctx,
7866 const char *servername,
7867 const char *environment,
7868 struct spoolss_DriverDirectoryInfo1 *r)
7870 WERROR werr;
7871 char *path = NULL;
7873 werr = compose_spoolss_server_path(mem_ctx,
7874 servername,
7875 environment,
7876 SPOOLSS_DRIVER_PATH,
7877 &path);
7878 if (!W_ERROR_IS_OK(werr)) {
7879 return werr;
7882 DEBUG(4,("printer driver directory: [%s]\n", path));
7884 r->directory_name = path;
7886 return WERR_OK;
7889 /****************************************************************
7890 _spoolss_GetPrinterDriverDirectory
7891 ****************************************************************/
7893 WERROR _spoolss_GetPrinterDriverDirectory(pipes_struct *p,
7894 struct spoolss_GetPrinterDriverDirectory *r)
7896 WERROR werror;
7898 /* that's an [in out] buffer */
7900 if (!r->in.buffer && (r->in.offered != 0)) {
7901 return WERR_INVALID_PARAM;
7904 DEBUG(5,("_spoolss_GetPrinterDriverDirectory: level %d\n",
7905 r->in.level));
7907 *r->out.needed = 0;
7909 /* r->in.level is ignored */
7911 werror = getprinterdriverdir_level_1(p->mem_ctx,
7912 r->in.server,
7913 r->in.environment,
7914 &r->out.info->info1);
7915 if (!W_ERROR_IS_OK(werror)) {
7916 TALLOC_FREE(r->out.info);
7917 return werror;
7920 *r->out.needed = SPOOLSS_BUFFER_UNION(spoolss_DriverDirectoryInfo, NULL,
7921 r->out.info, r->in.level);
7922 r->out.info = SPOOLSS_BUFFER_OK(r->out.info, NULL);
7924 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
7927 /****************************************************************
7928 _spoolss_EnumPrinterData
7929 ****************************************************************/
7931 WERROR _spoolss_EnumPrinterData(pipes_struct *p,
7932 struct spoolss_EnumPrinterData *r)
7934 NT_PRINTER_INFO_LEVEL *printer = NULL;
7935 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
7936 int snum;
7937 WERROR result;
7938 REGISTRY_VALUE *val = NULL;
7939 NT_PRINTER_DATA *p_data;
7940 int i, key_index, num_values;
7941 int name_length;
7943 *r->out.value_needed = 0;
7944 *r->out.type = REG_NONE;
7945 *r->out.data_needed = 0;
7947 DEBUG(5,("_spoolss_EnumPrinterData\n"));
7949 if (!Printer) {
7950 DEBUG(2,("_spoolss_EnumPrinterData: Invalid handle (%s:%u:%u).\n",
7951 OUR_HANDLE(r->in.handle)));
7952 return WERR_BADFID;
7955 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
7956 return WERR_BADFID;
7959 result = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
7960 if (!W_ERROR_IS_OK(result)) {
7961 return result;
7964 p_data = printer->info_2->data;
7965 key_index = lookup_printerkey( p_data, SPOOL_PRINTERDATA_KEY );
7967 result = WERR_OK;
7970 * The NT machine wants to know the biggest size of value and data
7972 * cf: MSDN EnumPrinterData remark section
7975 if (!r->in.value_offered && !r->in.data_offered && (key_index != -1)) {
7977 uint32_t biggest_valuesize = 0;
7978 uint32_t biggest_datasize = 0;
7980 DEBUGADD(6,("Activating NT mega-hack to find sizes\n"));
7982 num_values = regval_ctr_numvals( p_data->keys[key_index].values );
7984 for ( i=0; i<num_values; i++ )
7986 val = regval_ctr_specific_value( p_data->keys[key_index].values, i );
7988 name_length = strlen(val->valuename);
7989 if ( strlen(val->valuename) > biggest_valuesize )
7990 biggest_valuesize = name_length;
7992 if ( val->size > biggest_datasize )
7993 biggest_datasize = val->size;
7995 DEBUG(6,("current values: [%d], [%d]\n", biggest_valuesize,
7996 biggest_datasize));
7999 /* the value is an UNICODE string but real_value_size is the length
8000 in bytes including the trailing 0 */
8002 *r->out.value_needed = 2 * (1 + biggest_valuesize);
8003 *r->out.data_needed = biggest_datasize;
8005 DEBUG(6,("final values: [%d], [%d]\n",
8006 *r->out.value_needed, *r->out.data_needed));
8008 goto done;
8012 * the value len is wrong in NT sp3
8013 * that's the number of bytes not the number of unicode chars
8016 if (key_index != -1) {
8017 val = regval_ctr_specific_value(p_data->keys[key_index].values,
8018 r->in.enum_index);
8021 if (!val) {
8023 /* out_value should default to "" or else NT4 has
8024 problems unmarshalling the response */
8026 if (r->in.value_offered) {
8027 *r->out.value_needed = 1;
8028 r->out.value_name = talloc_strdup(r, "");
8029 if (!r->out.value_name) {
8030 result = WERR_NOMEM;
8031 goto done;
8033 } else {
8034 r->out.value_name = NULL;
8035 *r->out.value_needed = 0;
8038 /* the data is counted in bytes */
8040 *r->out.data_needed = r->in.data_offered;
8042 result = WERR_NO_MORE_ITEMS;
8043 } else {
8045 * the value is:
8046 * - counted in bytes in the request
8047 * - counted in UNICODE chars in the max reply
8048 * - counted in bytes in the real size
8050 * take a pause *before* coding not *during* coding
8053 /* name */
8054 if (r->in.value_offered) {
8055 r->out.value_name = talloc_strdup(r, regval_name(val));
8056 if (!r->out.value_name) {
8057 result = WERR_NOMEM;
8058 goto done;
8060 *r->out.value_needed = strlen_m(regval_name(val));
8061 } else {
8062 r->out.value_name = NULL;
8063 *r->out.value_needed = 0;
8066 /* type */
8068 *r->out.type = regval_type(val);
8070 /* data - counted in bytes */
8072 if (r->out.data && regval_size(val)) {
8073 memcpy(r->out.data, regval_data_p(val), regval_size(val));
8076 *r->out.data_needed = regval_size(val);
8079 done:
8080 free_a_printer(&printer, 2);
8081 return result;
8084 /****************************************************************
8085 _spoolss_SetPrinterData
8086 ****************************************************************/
8088 WERROR _spoolss_SetPrinterData(pipes_struct *p,
8089 struct spoolss_SetPrinterData *r)
8091 NT_PRINTER_INFO_LEVEL *printer = NULL;
8092 int snum=0;
8093 WERROR result = WERR_OK;
8094 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
8095 DATA_BLOB blob;
8097 DEBUG(5,("_spoolss_SetPrinterData\n"));
8099 if (!Printer) {
8100 DEBUG(2,("_spoolss_SetPrinterData: Invalid handle (%s:%u:%u).\n",
8101 OUR_HANDLE(r->in.handle)));
8102 return WERR_BADFID;
8105 if (Printer->printer_type == SPLHND_SERVER) {
8106 DEBUG(10,("_spoolss_SetPrinterData: "
8107 "Not implemented for server handles yet\n"));
8108 return WERR_INVALID_PARAM;
8111 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
8112 return WERR_BADFID;
8116 * Access check : NT returns "access denied" if you make a
8117 * SetPrinterData call without the necessary privildge.
8118 * we were originally returning OK if nothing changed
8119 * which made Win2k issue **a lot** of SetPrinterData
8120 * when connecting to a printer --jerry
8123 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
8124 DEBUG(3,("_spoolss_SetPrinterData: "
8125 "change denied by handle access permissions\n"));
8126 result = WERR_ACCESS_DENIED;
8127 goto done;
8130 result = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8131 if (!W_ERROR_IS_OK(result)) {
8132 return result;
8135 result = push_spoolss_PrinterData(p->mem_ctx, &blob,
8136 r->in.type, &r->in.data);
8137 if (!W_ERROR_IS_OK(result)) {
8138 goto done;
8142 * When client side code sets a magic printer data key, detect it and save
8143 * the current printer data and the magic key's data (its the DEVMODE) for
8144 * future printer/driver initializations.
8146 if ((r->in.type == REG_BINARY) && strequal(r->in.value_name, PHANTOM_DEVMODE_KEY)) {
8147 /* Set devmode and printer initialization info */
8148 result = save_driver_init(printer, 2, blob.data, blob.length);
8150 srv_spoolss_reset_printerdata(printer->info_2->drivername);
8152 goto done;
8155 result = set_printer_dataex(printer, SPOOL_PRINTERDATA_KEY,
8156 r->in.value_name, r->in.type,
8157 blob.data, blob.length);
8158 if (W_ERROR_IS_OK(result)) {
8159 result = mod_a_printer(printer, 2);
8162 done:
8163 free_a_printer(&printer, 2);
8165 return result;
8168 /****************************************************************
8169 _spoolss_ResetPrinter
8170 ****************************************************************/
8172 WERROR _spoolss_ResetPrinter(pipes_struct *p,
8173 struct spoolss_ResetPrinter *r)
8175 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
8176 int snum;
8178 DEBUG(5,("_spoolss_ResetPrinter\n"));
8181 * All we do is to check to see if the handle and queue is valid.
8182 * This call really doesn't mean anything to us because we only
8183 * support RAW printing. --jerry
8186 if (!Printer) {
8187 DEBUG(2,("_spoolss_ResetPrinter: Invalid handle (%s:%u:%u).\n",
8188 OUR_HANDLE(r->in.handle)));
8189 return WERR_BADFID;
8192 if (!get_printer_snum(p, r->in.handle, &snum, NULL))
8193 return WERR_BADFID;
8196 /* blindly return success */
8197 return WERR_OK;
8200 /****************************************************************
8201 _spoolss_DeletePrinterData
8202 ****************************************************************/
8204 WERROR _spoolss_DeletePrinterData(pipes_struct *p,
8205 struct spoolss_DeletePrinterData *r)
8207 NT_PRINTER_INFO_LEVEL *printer = NULL;
8208 int snum=0;
8209 WERROR status = WERR_OK;
8210 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
8212 DEBUG(5,("_spoolss_DeletePrinterData\n"));
8214 if (!Printer) {
8215 DEBUG(2,("_spoolss_DeletePrinterData: Invalid handle (%s:%u:%u).\n",
8216 OUR_HANDLE(r->in.handle)));
8217 return WERR_BADFID;
8220 if (!get_printer_snum(p, r->in.handle, &snum, NULL))
8221 return WERR_BADFID;
8223 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
8224 DEBUG(3, ("_spoolss_DeletePrinterData: "
8225 "printer properties change denied by handle\n"));
8226 return WERR_ACCESS_DENIED;
8229 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8230 if (!W_ERROR_IS_OK(status))
8231 return status;
8233 if (!r->in.value_name) {
8234 free_a_printer(&printer, 2);
8235 return WERR_NOMEM;
8238 status = delete_printer_dataex( printer, SPOOL_PRINTERDATA_KEY,
8239 r->in.value_name );
8241 if ( W_ERROR_IS_OK(status) )
8242 mod_a_printer( printer, 2 );
8244 free_a_printer(&printer, 2);
8246 return status;
8249 /****************************************************************
8250 _spoolss_AddForm
8251 ****************************************************************/
8253 WERROR _spoolss_AddForm(pipes_struct *p,
8254 struct spoolss_AddForm *r)
8256 struct spoolss_AddFormInfo1 *form = r->in.info.info1;
8257 nt_forms_struct tmpForm;
8258 int snum = -1;
8259 WERROR status = WERR_OK;
8260 NT_PRINTER_INFO_LEVEL *printer = NULL;
8261 SE_PRIV se_printop = SE_PRINT_OPERATOR;
8263 int count=0;
8264 nt_forms_struct *list=NULL;
8265 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
8267 DEBUG(5,("_spoolss_AddForm\n"));
8269 if (!Printer) {
8270 DEBUG(2,("_spoolss_AddForm: Invalid handle (%s:%u:%u).\n",
8271 OUR_HANDLE(r->in.handle)));
8272 return WERR_BADFID;
8276 /* forms can be added on printer of on the print server handle */
8278 if ( Printer->printer_type == SPLHND_PRINTER )
8280 if (!get_printer_snum(p, r->in.handle, &snum, NULL))
8281 return WERR_BADFID;
8283 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8284 if (!W_ERROR_IS_OK(status))
8285 goto done;
8288 /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
8289 and not a printer admin, then fail */
8291 if ((p->server_info->utok.uid != sec_initial_uid()) &&
8292 !user_has_privileges(p->server_info->ptok, &se_printop) &&
8293 !token_contains_name_in_list(uidtoname(p->server_info->utok.uid),
8294 NULL, NULL,
8295 p->server_info->ptok,
8296 lp_printer_admin(snum))) {
8297 DEBUG(2,("_spoolss_Addform: denied by insufficient permissions.\n"));
8298 return WERR_ACCESS_DENIED;
8301 /* can't add if builtin */
8303 if (get_a_builtin_ntform_by_string(form->form_name, &tmpForm)) {
8304 status = WERR_FILE_EXISTS;
8305 goto done;
8308 count = get_ntforms(&list);
8310 if(!add_a_form(&list, form, &count)) {
8311 status = WERR_NOMEM;
8312 goto done;
8315 become_root();
8316 write_ntforms(&list, count);
8317 unbecome_root();
8320 * ChangeID must always be set if this is a printer
8323 if ( Printer->printer_type == SPLHND_PRINTER )
8324 status = mod_a_printer(printer, 2);
8326 done:
8327 if ( printer )
8328 free_a_printer(&printer, 2);
8329 SAFE_FREE(list);
8331 return status;
8334 /****************************************************************
8335 _spoolss_DeleteForm
8336 ****************************************************************/
8338 WERROR _spoolss_DeleteForm(pipes_struct *p,
8339 struct spoolss_DeleteForm *r)
8341 const char *form_name = r->in.form_name;
8342 nt_forms_struct tmpForm;
8343 int count=0;
8344 nt_forms_struct *list=NULL;
8345 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
8346 int snum = -1;
8347 WERROR status = WERR_OK;
8348 NT_PRINTER_INFO_LEVEL *printer = NULL;
8349 SE_PRIV se_printop = SE_PRINT_OPERATOR;
8350 bool ret = false;
8352 DEBUG(5,("_spoolss_DeleteForm\n"));
8354 if (!Printer) {
8355 DEBUG(2,("_spoolss_DeleteForm: Invalid handle (%s:%u:%u).\n",
8356 OUR_HANDLE(r->in.handle)));
8357 return WERR_BADFID;
8360 /* forms can be deleted on printer of on the print server handle */
8362 if ( Printer->printer_type == SPLHND_PRINTER )
8364 if (!get_printer_snum(p, r->in.handle, &snum, NULL))
8365 return WERR_BADFID;
8367 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8368 if (!W_ERROR_IS_OK(status))
8369 goto done;
8372 if ((p->server_info->utok.uid != sec_initial_uid()) &&
8373 !user_has_privileges(p->server_info->ptok, &se_printop) &&
8374 !token_contains_name_in_list(uidtoname(p->server_info->utok.uid),
8375 NULL, NULL,
8376 p->server_info->ptok,
8377 lp_printer_admin(snum))) {
8378 DEBUG(2,("_spoolss_DeleteForm: denied by insufficient permissions.\n"));
8379 return WERR_ACCESS_DENIED;
8383 /* can't delete if builtin */
8385 if (get_a_builtin_ntform_by_string(form_name,&tmpForm)) {
8386 status = WERR_INVALID_PARAM;
8387 goto done;
8390 count = get_ntforms(&list);
8392 become_root();
8393 ret = delete_a_form(&list, form_name, &count, &status);
8394 unbecome_root();
8395 if (ret == false) {
8396 goto done;
8400 * ChangeID must always be set if this is a printer
8403 if ( Printer->printer_type == SPLHND_PRINTER )
8404 status = mod_a_printer(printer, 2);
8406 done:
8407 if ( printer )
8408 free_a_printer(&printer, 2);
8409 SAFE_FREE(list);
8411 return status;
8414 /****************************************************************
8415 _spoolss_SetForm
8416 ****************************************************************/
8418 WERROR _spoolss_SetForm(pipes_struct *p,
8419 struct spoolss_SetForm *r)
8421 struct spoolss_AddFormInfo1 *form = r->in.info.info1;
8422 nt_forms_struct tmpForm;
8423 int snum = -1;
8424 WERROR status = WERR_OK;
8425 NT_PRINTER_INFO_LEVEL *printer = NULL;
8426 SE_PRIV se_printop = SE_PRINT_OPERATOR;
8428 int count=0;
8429 nt_forms_struct *list=NULL;
8430 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
8432 DEBUG(5,("_spoolss_SetForm\n"));
8434 if (!Printer) {
8435 DEBUG(2,("_spoolss_SetForm: Invalid handle (%s:%u:%u).\n",
8436 OUR_HANDLE(r->in.handle)));
8437 return WERR_BADFID;
8440 /* forms can be modified on printer of on the print server handle */
8442 if ( Printer->printer_type == SPLHND_PRINTER )
8444 if (!get_printer_snum(p, r->in.handle, &snum, NULL))
8445 return WERR_BADFID;
8447 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8448 if (!W_ERROR_IS_OK(status))
8449 goto done;
8452 /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
8453 and not a printer admin, then fail */
8455 if ((p->server_info->utok.uid != sec_initial_uid()) &&
8456 !user_has_privileges(p->server_info->ptok, &se_printop) &&
8457 !token_contains_name_in_list(uidtoname(p->server_info->utok.uid),
8458 NULL, NULL,
8459 p->server_info->ptok,
8460 lp_printer_admin(snum))) {
8461 DEBUG(2,("_spoolss_Setform: denied by insufficient permissions.\n"));
8462 return WERR_ACCESS_DENIED;
8465 /* can't set if builtin */
8466 if (get_a_builtin_ntform_by_string(form->form_name, &tmpForm)) {
8467 status = WERR_INVALID_PARAM;
8468 goto done;
8471 count = get_ntforms(&list);
8472 update_a_form(&list, form, count);
8473 become_root();
8474 write_ntforms(&list, count);
8475 unbecome_root();
8478 * ChangeID must always be set if this is a printer
8481 if ( Printer->printer_type == SPLHND_PRINTER )
8482 status = mod_a_printer(printer, 2);
8485 done:
8486 if ( printer )
8487 free_a_printer(&printer, 2);
8488 SAFE_FREE(list);
8490 return status;
8493 /****************************************************************************
8494 fill_print_processor1
8495 ****************************************************************************/
8497 static WERROR fill_print_processor1(TALLOC_CTX *mem_ctx,
8498 struct spoolss_PrintProcessorInfo1 *r,
8499 const char *print_processor_name)
8501 r->print_processor_name = talloc_strdup(mem_ctx, print_processor_name);
8502 W_ERROR_HAVE_NO_MEMORY(r->print_processor_name);
8504 return WERR_OK;
8507 /****************************************************************************
8508 enumprintprocessors level 1.
8509 ****************************************************************************/
8511 static WERROR enumprintprocessors_level_1(TALLOC_CTX *mem_ctx,
8512 union spoolss_PrintProcessorInfo **info_p,
8513 uint32_t *count)
8515 union spoolss_PrintProcessorInfo *info;
8516 WERROR result;
8518 info = TALLOC_ARRAY(mem_ctx, union spoolss_PrintProcessorInfo, 1);
8519 W_ERROR_HAVE_NO_MEMORY(info);
8521 *count = 1;
8523 result = fill_print_processor1(info, &info[0].info1, "winprint");
8524 if (!W_ERROR_IS_OK(result)) {
8525 goto out;
8528 out:
8529 if (!W_ERROR_IS_OK(result)) {
8530 TALLOC_FREE(info);
8531 *count = 0;
8532 return result;
8535 *info_p = info;
8537 return WERR_OK;
8540 /****************************************************************
8541 _spoolss_EnumPrintProcessors
8542 ****************************************************************/
8544 WERROR _spoolss_EnumPrintProcessors(pipes_struct *p,
8545 struct spoolss_EnumPrintProcessors *r)
8547 WERROR result;
8549 /* that's an [in out] buffer */
8551 if (!r->in.buffer && (r->in.offered != 0)) {
8552 return WERR_INVALID_PARAM;
8555 DEBUG(5,("_spoolss_EnumPrintProcessors\n"));
8558 * Enumerate the print processors ...
8560 * Just reply with "winprint", to keep NT happy
8561 * and I can use my nice printer checker.
8564 *r->out.count = 0;
8565 *r->out.needed = 0;
8566 *r->out.info = NULL;
8568 switch (r->in.level) {
8569 case 1:
8570 result = enumprintprocessors_level_1(p->mem_ctx, r->out.info,
8571 r->out.count);
8572 break;
8573 default:
8574 return WERR_UNKNOWN_LEVEL;
8577 if (!W_ERROR_IS_OK(result)) {
8578 return result;
8581 *r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
8582 spoolss_EnumPrintProcessors, NULL,
8583 *r->out.info, r->in.level,
8584 *r->out.count);
8585 *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
8586 *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, 0);
8588 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
8591 /****************************************************************************
8592 fill_printprocdatatype1
8593 ****************************************************************************/
8595 static WERROR fill_printprocdatatype1(TALLOC_CTX *mem_ctx,
8596 struct spoolss_PrintProcDataTypesInfo1 *r,
8597 const char *name_array)
8599 r->name_array = talloc_strdup(mem_ctx, name_array);
8600 W_ERROR_HAVE_NO_MEMORY(r->name_array);
8602 return WERR_OK;
8605 /****************************************************************************
8606 enumprintprocdatatypes level 1.
8607 ****************************************************************************/
8609 static WERROR enumprintprocdatatypes_level_1(TALLOC_CTX *mem_ctx,
8610 union spoolss_PrintProcDataTypesInfo **info_p,
8611 uint32_t *count)
8613 WERROR result;
8614 union spoolss_PrintProcDataTypesInfo *info;
8616 info = TALLOC_ARRAY(mem_ctx, union spoolss_PrintProcDataTypesInfo, 1);
8617 W_ERROR_HAVE_NO_MEMORY(info);
8619 *count = 1;
8621 result = fill_printprocdatatype1(info, &info[0].info1, "RAW");
8622 if (!W_ERROR_IS_OK(result)) {
8623 goto out;
8626 out:
8627 if (!W_ERROR_IS_OK(result)) {
8628 TALLOC_FREE(info);
8629 *count = 0;
8630 return result;
8633 *info_p = info;
8635 return WERR_OK;
8638 /****************************************************************
8639 _spoolss_EnumPrintProcDataTypes
8640 ****************************************************************/
8642 WERROR _spoolss_EnumPrintProcDataTypes(pipes_struct *p,
8643 struct spoolss_EnumPrintProcDataTypes *r)
8645 WERROR result;
8647 /* that's an [in out] buffer */
8649 if (!r->in.buffer && (r->in.offered != 0)) {
8650 return WERR_INVALID_PARAM;
8653 DEBUG(5,("_spoolss_EnumPrintProcDataTypes\n"));
8655 *r->out.count = 0;
8656 *r->out.needed = 0;
8657 *r->out.info = NULL;
8659 switch (r->in.level) {
8660 case 1:
8661 result = enumprintprocdatatypes_level_1(p->mem_ctx, r->out.info,
8662 r->out.count);
8663 break;
8664 default:
8665 return WERR_UNKNOWN_LEVEL;
8668 *r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
8669 spoolss_EnumPrintProcDataTypes, NULL,
8670 *r->out.info, r->in.level,
8671 *r->out.count);
8672 *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
8673 *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, 0);
8675 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
8678 /****************************************************************************
8679 fill_monitor_1
8680 ****************************************************************************/
8682 static WERROR fill_monitor_1(TALLOC_CTX *mem_ctx,
8683 struct spoolss_MonitorInfo1 *r,
8684 const char *monitor_name)
8686 r->monitor_name = talloc_strdup(mem_ctx, monitor_name);
8687 W_ERROR_HAVE_NO_MEMORY(r->monitor_name);
8689 return WERR_OK;
8692 /****************************************************************************
8693 fill_monitor_2
8694 ****************************************************************************/
8696 static WERROR fill_monitor_2(TALLOC_CTX *mem_ctx,
8697 struct spoolss_MonitorInfo2 *r,
8698 const char *monitor_name,
8699 const char *environment,
8700 const char *dll_name)
8702 r->monitor_name = talloc_strdup(mem_ctx, monitor_name);
8703 W_ERROR_HAVE_NO_MEMORY(r->monitor_name);
8704 r->environment = talloc_strdup(mem_ctx, environment);
8705 W_ERROR_HAVE_NO_MEMORY(r->environment);
8706 r->dll_name = talloc_strdup(mem_ctx, dll_name);
8707 W_ERROR_HAVE_NO_MEMORY(r->dll_name);
8709 return WERR_OK;
8712 /****************************************************************************
8713 enumprintmonitors level 1.
8714 ****************************************************************************/
8716 static WERROR enumprintmonitors_level_1(TALLOC_CTX *mem_ctx,
8717 union spoolss_MonitorInfo **info_p,
8718 uint32_t *count)
8720 union spoolss_MonitorInfo *info;
8721 WERROR result = WERR_OK;
8723 info = TALLOC_ARRAY(mem_ctx, union spoolss_MonitorInfo, 2);
8724 W_ERROR_HAVE_NO_MEMORY(info);
8726 *count = 2;
8728 result = fill_monitor_1(info, &info[0].info1,
8729 SPL_LOCAL_PORT);
8730 if (!W_ERROR_IS_OK(result)) {
8731 goto out;
8734 result = fill_monitor_1(info, &info[1].info1,
8735 SPL_TCPIP_PORT);
8736 if (!W_ERROR_IS_OK(result)) {
8737 goto out;
8740 out:
8741 if (!W_ERROR_IS_OK(result)) {
8742 TALLOC_FREE(info);
8743 *count = 0;
8744 return result;
8747 *info_p = info;
8749 return WERR_OK;
8752 /****************************************************************************
8753 enumprintmonitors level 2.
8754 ****************************************************************************/
8756 static WERROR enumprintmonitors_level_2(TALLOC_CTX *mem_ctx,
8757 union spoolss_MonitorInfo **info_p,
8758 uint32_t *count)
8760 union spoolss_MonitorInfo *info;
8761 WERROR result = WERR_OK;
8763 info = TALLOC_ARRAY(mem_ctx, union spoolss_MonitorInfo, 2);
8764 W_ERROR_HAVE_NO_MEMORY(info);
8766 *count = 2;
8768 result = fill_monitor_2(info, &info[0].info2,
8769 SPL_LOCAL_PORT,
8770 "Windows NT X86", /* FIXME */
8771 "localmon.dll");
8772 if (!W_ERROR_IS_OK(result)) {
8773 goto out;
8776 result = fill_monitor_2(info, &info[1].info2,
8777 SPL_TCPIP_PORT,
8778 "Windows NT X86", /* FIXME */
8779 "tcpmon.dll");
8780 if (!W_ERROR_IS_OK(result)) {
8781 goto out;
8784 out:
8785 if (!W_ERROR_IS_OK(result)) {
8786 TALLOC_FREE(info);
8787 *count = 0;
8788 return result;
8791 *info_p = info;
8793 return WERR_OK;
8796 /****************************************************************
8797 _spoolss_EnumMonitors
8798 ****************************************************************/
8800 WERROR _spoolss_EnumMonitors(pipes_struct *p,
8801 struct spoolss_EnumMonitors *r)
8803 WERROR result;
8805 /* that's an [in out] buffer */
8807 if (!r->in.buffer && (r->in.offered != 0)) {
8808 return WERR_INVALID_PARAM;
8811 DEBUG(5,("_spoolss_EnumMonitors\n"));
8814 * Enumerate the print monitors ...
8816 * Just reply with "Local Port", to keep NT happy
8817 * and I can use my nice printer checker.
8820 *r->out.count = 0;
8821 *r->out.needed = 0;
8822 *r->out.info = NULL;
8824 switch (r->in.level) {
8825 case 1:
8826 result = enumprintmonitors_level_1(p->mem_ctx, r->out.info,
8827 r->out.count);
8828 break;
8829 case 2:
8830 result = enumprintmonitors_level_2(p->mem_ctx, r->out.info,
8831 r->out.count);
8832 break;
8833 default:
8834 return WERR_UNKNOWN_LEVEL;
8837 if (!W_ERROR_IS_OK(result)) {
8838 return result;
8841 *r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
8842 spoolss_EnumMonitors, NULL,
8843 *r->out.info, r->in.level,
8844 *r->out.count);
8845 *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
8846 *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, 0);
8848 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
8851 /****************************************************************************
8852 ****************************************************************************/
8854 static WERROR getjob_level_1(TALLOC_CTX *mem_ctx,
8855 const print_queue_struct *queue,
8856 int count, int snum,
8857 const NT_PRINTER_INFO_LEVEL *ntprinter,
8858 uint32_t jobid,
8859 struct spoolss_JobInfo1 *r)
8861 int i = 0;
8862 bool found = false;
8864 for (i=0; i<count && found == false; i++) {
8865 if (queue[i].job == (int)jobid) {
8866 found = true;
8870 if (found == false) {
8871 /* NT treats not found as bad param... yet another bad choice */
8872 return WERR_INVALID_PARAM;
8875 return fill_job_info1(mem_ctx,
8877 &queue[i-1],
8879 snum,
8880 ntprinter);
8883 /****************************************************************************
8884 ****************************************************************************/
8886 static WERROR getjob_level_2(TALLOC_CTX *mem_ctx,
8887 const print_queue_struct *queue,
8888 int count, int snum,
8889 const NT_PRINTER_INFO_LEVEL *ntprinter,
8890 uint32_t jobid,
8891 struct spoolss_JobInfo2 *r)
8893 int i = 0;
8894 bool found = false;
8895 struct spoolss_DeviceMode *devmode;
8896 NT_DEVICEMODE *nt_devmode;
8897 WERROR result;
8899 for (i=0; i<count && found == false; i++) {
8900 if (queue[i].job == (int)jobid) {
8901 found = true;
8905 if (found == false) {
8906 /* NT treats not found as bad param... yet another bad
8907 choice */
8908 return WERR_INVALID_PARAM;
8912 * if the print job does not have a DEVMODE associated with it,
8913 * just use the one for the printer. A NULL devicemode is not
8914 * a failure condition
8917 nt_devmode = print_job_devmode(lp_const_servicename(snum), jobid);
8918 if (nt_devmode) {
8919 devmode = TALLOC_ZERO_P(mem_ctx, struct spoolss_DeviceMode);
8920 W_ERROR_HAVE_NO_MEMORY(devmode);
8921 result = convert_nt_devicemode(devmode, devmode, nt_devmode);
8922 if (!W_ERROR_IS_OK(result)) {
8923 return result;
8925 } else {
8926 devmode = construct_dev_mode(mem_ctx, lp_const_servicename(snum));
8927 W_ERROR_HAVE_NO_MEMORY(devmode);
8930 return fill_job_info2(mem_ctx,
8932 &queue[i-1],
8934 snum,
8935 ntprinter,
8936 devmode);
8939 /****************************************************************
8940 _spoolss_GetJob
8941 ****************************************************************/
8943 WERROR _spoolss_GetJob(pipes_struct *p,
8944 struct spoolss_GetJob *r)
8946 WERROR result = WERR_OK;
8947 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
8948 int snum;
8949 int count;
8950 print_queue_struct *queue = NULL;
8951 print_status_struct prt_status;
8953 /* that's an [in out] buffer */
8955 if (!r->in.buffer && (r->in.offered != 0)) {
8956 return WERR_INVALID_PARAM;
8959 DEBUG(5,("_spoolss_GetJob\n"));
8961 *r->out.needed = 0;
8963 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
8964 return WERR_BADFID;
8967 result = get_a_printer(NULL, &ntprinter, 2, lp_servicename(snum));
8968 if (!W_ERROR_IS_OK(result)) {
8969 return result;
8972 count = print_queue_status(snum, &queue, &prt_status);
8974 DEBUGADD(4,("count:[%d], prt_status:[%d], [%s]\n",
8975 count, prt_status.status, prt_status.message));
8977 switch (r->in.level) {
8978 case 1:
8979 result = getjob_level_1(p->mem_ctx,
8980 queue, count, snum, ntprinter,
8981 r->in.job_id, &r->out.info->info1);
8982 break;
8983 case 2:
8984 result = getjob_level_2(p->mem_ctx,
8985 queue, count, snum, ntprinter,
8986 r->in.job_id, &r->out.info->info2);
8987 break;
8988 default:
8989 result = WERR_UNKNOWN_LEVEL;
8990 break;
8993 SAFE_FREE(queue);
8994 free_a_printer(&ntprinter, 2);
8996 if (!W_ERROR_IS_OK(result)) {
8997 TALLOC_FREE(r->out.info);
8998 return result;
9001 *r->out.needed = SPOOLSS_BUFFER_UNION(spoolss_JobInfo, NULL,
9002 r->out.info, r->in.level);
9003 r->out.info = SPOOLSS_BUFFER_OK(r->out.info, NULL);
9005 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
9008 /****************************************************************
9009 _spoolss_GetPrinterDataEx
9011 From MSDN documentation of GetPrinterDataEx: pass request
9012 to GetPrinterData if key is "PrinterDriverData".
9013 ****************************************************************/
9015 WERROR _spoolss_GetPrinterDataEx(pipes_struct *p,
9016 struct spoolss_GetPrinterDataEx *r)
9019 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
9020 REGISTRY_VALUE *val = NULL;
9021 NT_PRINTER_INFO_LEVEL *printer = NULL;
9022 int snum = 0;
9023 WERROR result = WERR_OK;
9025 DEBUG(4,("_spoolss_GetPrinterDataEx\n"));
9027 DEBUG(10, ("_spoolss_GetPrinterDataEx: key => [%s], value => [%s]\n",
9028 r->in.key_name, r->in.value_name));
9030 /* in case of problem, return some default values */
9032 *r->out.needed = 0;
9033 *r->out.type = REG_NONE;
9035 if (!Printer) {
9036 DEBUG(2,("_spoolss_GetPrinterDataEx: Invalid handle (%s:%u:%u).\n",
9037 OUR_HANDLE(r->in.handle)));
9038 result = WERR_BADFID;
9039 goto done;
9042 /* Is the handle to a printer or to the server? */
9044 if (Printer->printer_type == SPLHND_SERVER) {
9045 DEBUG(10,("_spoolss_GetPrinterDataEx: "
9046 "Not implemented for server handles yet\n"));
9047 result = WERR_INVALID_PARAM;
9048 goto done;
9051 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9052 return WERR_BADFID;
9055 result = get_a_printer(Printer, &printer, 2, lp_servicename(snum));
9056 if (!W_ERROR_IS_OK(result)) {
9057 goto done;
9060 /* check to see if the keyname is valid */
9061 if (!strlen(r->in.key_name)) {
9062 result = WERR_INVALID_PARAM;
9063 goto done;
9066 if (lookup_printerkey(printer->info_2->data, r->in.key_name) == -1) {
9067 DEBUG(4,("_spoolss_GetPrinterDataEx: "
9068 "Invalid keyname [%s]\n", r->in.key_name ));
9069 result = WERR_BADFILE;
9070 goto done;
9073 /* When given a new keyname, we should just create it */
9075 val = get_printer_data(printer->info_2,
9076 r->in.key_name, r->in.value_name);
9077 if (!val) {
9078 result = WERR_BADFILE;
9079 goto done;
9082 *r->out.needed = regval_size(val);
9084 if (*r->out.needed > r->in.offered) {
9085 result = WERR_MORE_DATA;
9086 goto done;
9089 *r->out.type = regval_type(val);
9091 memcpy(r->out.buffer, regval_data_p(val), regval_size(val));
9093 done:
9094 if (printer) {
9095 free_a_printer(&printer, 2);
9098 return result;
9101 /****************************************************************
9102 _spoolss_SetPrinterDataEx
9103 ****************************************************************/
9105 WERROR _spoolss_SetPrinterDataEx(pipes_struct *p,
9106 struct spoolss_SetPrinterDataEx *r)
9108 NT_PRINTER_INFO_LEVEL *printer = NULL;
9109 int snum = 0;
9110 WERROR result = WERR_OK;
9111 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
9112 char *oid_string;
9114 DEBUG(4,("_spoolss_SetPrinterDataEx\n"));
9116 /* From MSDN documentation of SetPrinterDataEx: pass request to
9117 SetPrinterData if key is "PrinterDriverData" */
9119 if (!Printer) {
9120 DEBUG(2,("_spoolss_SetPrinterDataEx: Invalid handle (%s:%u:%u).\n",
9121 OUR_HANDLE(r->in.handle)));
9122 return WERR_BADFID;
9125 if (Printer->printer_type == SPLHND_SERVER) {
9126 DEBUG(10,("_spoolss_SetPrinterDataEx: "
9127 "Not implemented for server handles yet\n"));
9128 return WERR_INVALID_PARAM;
9131 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9132 return WERR_BADFID;
9136 * Access check : NT returns "access denied" if you make a
9137 * SetPrinterData call without the necessary privildge.
9138 * we were originally returning OK if nothing changed
9139 * which made Win2k issue **a lot** of SetPrinterData
9140 * when connecting to a printer --jerry
9143 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
9144 DEBUG(3, ("_spoolss_SetPrinterDataEx: "
9145 "change denied by handle access permissions\n"));
9146 return WERR_ACCESS_DENIED;
9149 result = get_a_printer(Printer, &printer, 2, lp_servicename(snum));
9150 if (!W_ERROR_IS_OK(result)) {
9151 return result;
9154 /* check for OID in valuename */
9156 oid_string = strchr(r->in.value_name, ',');
9157 if (oid_string) {
9158 *oid_string = '\0';
9159 oid_string++;
9162 /* save the registry data */
9164 result = set_printer_dataex(printer, r->in.key_name, r->in.value_name,
9165 r->in.type, r->in.buffer, r->in.offered);
9167 if (W_ERROR_IS_OK(result)) {
9168 /* save the OID if one was specified */
9169 if (oid_string) {
9170 char *str = talloc_asprintf(p->mem_ctx, "%s\\%s",
9171 r->in.key_name, SPOOL_OID_KEY);
9172 if (!str) {
9173 result = WERR_NOMEM;
9174 goto done;
9178 * I'm not checking the status here on purpose. Don't know
9179 * if this is right, but I'm returning the status from the
9180 * previous set_printer_dataex() call. I have no idea if
9181 * this is right. --jerry
9184 set_printer_dataex(printer, str, r->in.value_name,
9185 REG_SZ, (uint8_t *)oid_string,
9186 strlen(oid_string)+1);
9189 result = mod_a_printer(printer, 2);
9192 done:
9193 free_a_printer(&printer, 2);
9195 return result;
9198 /****************************************************************
9199 _spoolss_DeletePrinterDataEx
9200 ****************************************************************/
9202 WERROR _spoolss_DeletePrinterDataEx(pipes_struct *p,
9203 struct spoolss_DeletePrinterDataEx *r)
9205 NT_PRINTER_INFO_LEVEL *printer = NULL;
9206 int snum=0;
9207 WERROR status = WERR_OK;
9208 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
9210 DEBUG(5,("_spoolss_DeletePrinterDataEx\n"));
9212 if (!Printer) {
9213 DEBUG(2,("_spoolss_DeletePrinterDataEx: "
9214 "Invalid handle (%s:%u:%u).\n",
9215 OUR_HANDLE(r->in.handle)));
9216 return WERR_BADFID;
9219 if (!get_printer_snum(p, r->in.handle, &snum, NULL))
9220 return WERR_BADFID;
9222 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
9223 DEBUG(3, ("_spoolss_DeletePrinterDataEx: "
9224 "printer properties change denied by handle\n"));
9225 return WERR_ACCESS_DENIED;
9228 if (!r->in.value_name || !r->in.key_name) {
9229 return WERR_NOMEM;
9232 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
9233 if (!W_ERROR_IS_OK(status))
9234 return status;
9236 status = delete_printer_dataex( printer, r->in.key_name, r->in.value_name );
9238 if ( W_ERROR_IS_OK(status) )
9239 mod_a_printer( printer, 2 );
9241 free_a_printer(&printer, 2);
9243 return status;
9246 /****************************************************************
9247 _spoolss_EnumPrinterKey
9248 ****************************************************************/
9250 WERROR _spoolss_EnumPrinterKey(pipes_struct *p,
9251 struct spoolss_EnumPrinterKey *r)
9253 fstring *keynames = NULL;
9254 int num_keys;
9255 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
9256 NT_PRINTER_DATA *data;
9257 NT_PRINTER_INFO_LEVEL *printer = NULL;
9258 int snum = 0;
9259 WERROR result = WERR_BADFILE;
9260 int i;
9261 const char **array = NULL;
9262 DATA_BLOB blob;
9264 DEBUG(4,("_spoolss_EnumPrinterKey\n"));
9266 if (!Printer) {
9267 DEBUG(2,("_spoolss_EnumPrinterKey: Invalid handle (%s:%u:%u).\n",
9268 OUR_HANDLE(r->in.handle)));
9269 return WERR_BADFID;
9272 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9273 return WERR_BADFID;
9276 result = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
9277 if (!W_ERROR_IS_OK(result)) {
9278 return result;
9281 /* get the list of subkey names */
9283 data = printer->info_2->data;
9285 num_keys = get_printer_subkeys(data, r->in.key_name, &keynames);
9286 if (num_keys == -1) {
9287 result = WERR_BADFILE;
9288 goto done;
9291 array = talloc_zero_array(r->out.key_buffer, const char *, num_keys + 1);
9292 if (!array) {
9293 result = WERR_NOMEM;
9294 goto done;
9297 for (i=0; i < num_keys; i++) {
9299 DEBUG(10,("_spoolss_EnumPrinterKey: adding keyname: %s\n",
9300 keynames[i]));
9302 array[i] = talloc_strdup(array, keynames[i]);
9303 if (!array[i]) {
9304 result = WERR_NOMEM;
9305 goto done;
9309 if (!push_reg_multi_sz(p->mem_ctx, &blob, array)) {
9310 result = WERR_NOMEM;
9311 goto done;
9314 *r->out.needed = blob.length;
9316 if (r->in.offered < *r->out.needed) {
9317 result = WERR_MORE_DATA;
9318 } else {
9319 result = WERR_OK;
9320 r->out.key_buffer->string = array;
9323 done:
9324 if (!W_ERROR_IS_OK(result)) {
9325 TALLOC_FREE(array);
9326 if (!W_ERROR_EQUAL(result, WERR_MORE_DATA)) {
9327 *r->out.needed = 0;
9331 free_a_printer(&printer, 2);
9332 SAFE_FREE(keynames);
9334 return result;
9337 /****************************************************************
9338 _spoolss_DeletePrinterKey
9339 ****************************************************************/
9341 WERROR _spoolss_DeletePrinterKey(pipes_struct *p,
9342 struct spoolss_DeletePrinterKey *r)
9344 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
9345 NT_PRINTER_INFO_LEVEL *printer = NULL;
9346 int snum=0;
9347 WERROR status;
9349 DEBUG(5,("_spoolss_DeletePrinterKey\n"));
9351 if (!Printer) {
9352 DEBUG(2,("_spoolss_DeletePrinterKey: Invalid handle (%s:%u:%u).\n",
9353 OUR_HANDLE(r->in.handle)));
9354 return WERR_BADFID;
9357 /* if keyname == NULL, return error */
9359 if ( !r->in.key_name )
9360 return WERR_INVALID_PARAM;
9362 if (!get_printer_snum(p, r->in.handle, &snum, NULL))
9363 return WERR_BADFID;
9365 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
9366 DEBUG(3, ("_spoolss_DeletePrinterKey: "
9367 "printer properties change denied by handle\n"));
9368 return WERR_ACCESS_DENIED;
9371 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
9372 if (!W_ERROR_IS_OK(status))
9373 return status;
9375 /* delete the key and all subneys */
9377 status = delete_all_printer_data( printer->info_2, r->in.key_name );
9379 if ( W_ERROR_IS_OK(status) )
9380 status = mod_a_printer(printer, 2);
9382 free_a_printer( &printer, 2 );
9384 return status;
9387 /****************************************************************
9388 ****************************************************************/
9390 static WERROR registry_value_to_printer_enum_value(TALLOC_CTX *mem_ctx,
9391 REGISTRY_VALUE *v,
9392 struct spoolss_PrinterEnumValues *r)
9394 WERROR result;
9396 r->data = TALLOC_ZERO_P(mem_ctx, union spoolss_PrinterData);
9397 W_ERROR_HAVE_NO_MEMORY(r->data);
9399 r->value_name = talloc_strdup(mem_ctx, regval_name(v));
9400 W_ERROR_HAVE_NO_MEMORY(r->value_name);
9402 r->type = regval_type(v);
9403 r->data_length = regval_size(v);
9405 if (r->data_length) {
9406 DATA_BLOB blob = data_blob_const(regval_data_p(v),
9407 regval_size(v));
9408 result = pull_spoolss_PrinterData(mem_ctx, &blob,
9409 r->data,
9410 r->type);
9411 if (!W_ERROR_IS_OK(result)) {
9412 return result;
9416 return WERR_OK;
9419 /****************************************************************
9420 _spoolss_EnumPrinterDataEx
9421 ****************************************************************/
9423 WERROR _spoolss_EnumPrinterDataEx(pipes_struct *p,
9424 struct spoolss_EnumPrinterDataEx *r)
9426 uint32_t count = 0;
9427 NT_PRINTER_INFO_LEVEL *printer = NULL;
9428 struct spoolss_PrinterEnumValues *info = NULL;
9429 NT_PRINTER_DATA *p_data;
9430 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
9431 int snum;
9432 WERROR result;
9433 int key_index;
9434 int i;
9436 DEBUG(4,("_spoolss_EnumPrinterDataEx\n"));
9438 *r->out.count = 0;
9439 *r->out.needed = 0;
9440 *r->out.info = NULL;
9442 if (!Printer) {
9443 DEBUG(2,("_spoolss_EnumPrinterDataEx: Invalid handle (%s:%u:%u1<).\n",
9444 OUR_HANDLE(r->in.handle)));
9445 return WERR_BADFID;
9449 * first check for a keyname of NULL or "". Win2k seems to send
9450 * this a lot and we should send back WERR_INVALID_PARAM
9451 * no need to spend time looking up the printer in this case.
9452 * --jerry
9455 if (!strlen(r->in.key_name)) {
9456 result = WERR_INVALID_PARAM;
9457 goto done;
9460 /* get the printer off of disk */
9462 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9463 return WERR_BADFID;
9466 ZERO_STRUCT(printer);
9467 result = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
9468 if (!W_ERROR_IS_OK(result)) {
9469 return result;
9472 /* now look for a match on the key name */
9474 p_data = printer->info_2->data;
9476 key_index = lookup_printerkey(p_data, r->in.key_name);
9477 if (key_index == -1) {
9478 DEBUG(10,("_spoolss_EnumPrinterDataEx: Unknown keyname [%s]\n",
9479 r->in.key_name));
9480 result = WERR_INVALID_PARAM;
9481 goto done;
9484 /* allocate the memory for the array of pointers -- if necessary */
9486 count = regval_ctr_numvals(p_data->keys[key_index].values);
9487 if (!count) {
9488 result = WERR_OK; /* ??? */
9489 goto done;
9492 info = TALLOC_ZERO_ARRAY(p->mem_ctx,
9493 struct spoolss_PrinterEnumValues,
9494 count);
9495 if (!info) {
9496 DEBUG(0,("_spoolss_EnumPrinterDataEx: talloc() failed\n"));
9497 result = WERR_NOMEM;
9498 goto done;
9502 * loop through all params and build the array to pass
9503 * back to the client
9506 for (i=0; i < count; i++) {
9508 REGISTRY_VALUE *val;
9510 /* lookup the registry value */
9512 val = regval_ctr_specific_value(p_data->keys[key_index].values, i);
9514 DEBUG(10,("retrieved value number [%d] [%s]\n", i, regval_name(val)));
9516 /* copy the data */
9518 result = registry_value_to_printer_enum_value(info, val, &info[i]);
9519 if (!W_ERROR_IS_OK(result)) {
9520 goto done;
9524 #if 0 /* FIXME - gd */
9525 /* housekeeping information in the reply */
9527 /* Fix from Martin Zielinski <mz@seh.de> - ensure
9528 * the hand marshalled container size is a multiple
9529 * of 4 bytes for RPC alignment.
9532 if (needed % 4) {
9533 needed += 4-(needed % 4);
9535 #endif
9536 *r->out.count = count;
9537 *r->out.info = info;
9539 done:
9541 if (printer) {
9542 free_a_printer(&printer, 2);
9545 if (!W_ERROR_IS_OK(result)) {
9546 return result;
9549 *r->out.needed = SPOOLSS_BUFFER_ARRAY(p->mem_ctx,
9550 spoolss_EnumPrinterDataEx, NULL,
9551 *r->out.info,
9552 *r->out.count);
9553 *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
9554 *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, *r->out.count);
9556 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_MORE_DATA);
9559 /****************************************************************************
9560 ****************************************************************************/
9562 static WERROR getprintprocessordirectory_level_1(TALLOC_CTX *mem_ctx,
9563 const char *servername,
9564 const char *environment,
9565 struct spoolss_PrintProcessorDirectoryInfo1 *r)
9567 WERROR werr;
9568 char *path = NULL;
9570 werr = compose_spoolss_server_path(mem_ctx,
9571 servername,
9572 environment,
9573 SPOOLSS_PRTPROCS_PATH,
9574 &path);
9575 if (!W_ERROR_IS_OK(werr)) {
9576 return werr;
9579 DEBUG(4,("print processor directory: [%s]\n", path));
9581 r->directory_name = path;
9583 return WERR_OK;
9586 /****************************************************************
9587 _spoolss_GetPrintProcessorDirectory
9588 ****************************************************************/
9590 WERROR _spoolss_GetPrintProcessorDirectory(pipes_struct *p,
9591 struct spoolss_GetPrintProcessorDirectory *r)
9593 WERROR result;
9595 /* that's an [in out] buffer */
9597 if (!r->in.buffer && (r->in.offered != 0)) {
9598 return WERR_INVALID_PARAM;
9601 DEBUG(5,("_spoolss_GetPrintProcessorDirectory: level %d\n",
9602 r->in.level));
9604 *r->out.needed = 0;
9606 /* r->in.level is ignored */
9608 /* We always should reply with a local print processor directory so that
9609 * users are not forced to have a [prnproc$] share on the Samba spoolss
9610 * server - Guenther */
9612 result = getprintprocessordirectory_level_1(p->mem_ctx,
9613 NULL, /* r->in.server */
9614 r->in.environment,
9615 &r->out.info->info1);
9616 if (!W_ERROR_IS_OK(result)) {
9617 TALLOC_FREE(r->out.info);
9618 return result;
9621 *r->out.needed = SPOOLSS_BUFFER_UNION(spoolss_PrintProcessorDirectoryInfo, NULL,
9622 r->out.info, r->in.level);
9623 r->out.info = SPOOLSS_BUFFER_OK(r->out.info, NULL);
9625 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
9628 /*******************************************************************
9629 ********************************************************************/
9631 static bool push_monitorui_buf(TALLOC_CTX *mem_ctx, DATA_BLOB *buf,
9632 const char *dllname)
9634 enum ndr_err_code ndr_err;
9635 struct spoolss_MonitorUi ui;
9637 ui.dll_name = dllname;
9639 ndr_err = ndr_push_struct_blob(buf, mem_ctx, NULL, &ui,
9640 (ndr_push_flags_fn_t)ndr_push_spoolss_MonitorUi);
9641 if (NDR_ERR_CODE_IS_SUCCESS(ndr_err) && (DEBUGLEVEL >= 10)) {
9642 NDR_PRINT_DEBUG(spoolss_MonitorUi, &ui);
9644 return NDR_ERR_CODE_IS_SUCCESS(ndr_err);
9647 /*******************************************************************
9648 Streams the monitor UI DLL name in UNICODE
9649 *******************************************************************/
9651 static WERROR xcvtcp_monitorui(TALLOC_CTX *mem_ctx,
9652 NT_USER_TOKEN *token, DATA_BLOB *in,
9653 DATA_BLOB *out, uint32_t *needed)
9655 const char *dllname = "tcpmonui.dll";
9657 *needed = (strlen(dllname)+1) * 2;
9659 if (out->length < *needed) {
9660 return WERR_INSUFFICIENT_BUFFER;
9663 if (!push_monitorui_buf(mem_ctx, out, dllname)) {
9664 return WERR_NOMEM;
9667 return WERR_OK;
9670 /*******************************************************************
9671 ********************************************************************/
9673 static bool pull_port_data_1(TALLOC_CTX *mem_ctx,
9674 struct spoolss_PortData1 *port1,
9675 const DATA_BLOB *buf)
9677 enum ndr_err_code ndr_err;
9678 ndr_err = ndr_pull_struct_blob(buf, mem_ctx, NULL, port1,
9679 (ndr_pull_flags_fn_t)ndr_pull_spoolss_PortData1);
9680 if (NDR_ERR_CODE_IS_SUCCESS(ndr_err) && (DEBUGLEVEL >= 10)) {
9681 NDR_PRINT_DEBUG(spoolss_PortData1, port1);
9683 return NDR_ERR_CODE_IS_SUCCESS(ndr_err);
9686 /*******************************************************************
9687 ********************************************************************/
9689 static bool pull_port_data_2(TALLOC_CTX *mem_ctx,
9690 struct spoolss_PortData2 *port2,
9691 const DATA_BLOB *buf)
9693 enum ndr_err_code ndr_err;
9694 ndr_err = ndr_pull_struct_blob(buf, mem_ctx, NULL, port2,
9695 (ndr_pull_flags_fn_t)ndr_pull_spoolss_PortData2);
9696 if (NDR_ERR_CODE_IS_SUCCESS(ndr_err) && (DEBUGLEVEL >= 10)) {
9697 NDR_PRINT_DEBUG(spoolss_PortData2, port2);
9699 return NDR_ERR_CODE_IS_SUCCESS(ndr_err);
9702 /*******************************************************************
9703 Create a new TCP/IP port
9704 *******************************************************************/
9706 static WERROR xcvtcp_addport(TALLOC_CTX *mem_ctx,
9707 NT_USER_TOKEN *token, DATA_BLOB *in,
9708 DATA_BLOB *out, uint32_t *needed)
9710 struct spoolss_PortData1 port1;
9711 struct spoolss_PortData2 port2;
9712 char *device_uri = NULL;
9713 uint32_t version;
9715 const char *portname;
9716 const char *hostaddress;
9717 const char *queue;
9718 uint32_t port_number;
9719 uint32_t protocol;
9721 /* peek for spoolss_PortData version */
9723 if (!in || (in->length < (128 + 4))) {
9724 return WERR_GENERAL_FAILURE;
9727 version = IVAL(in->data, 128);
9729 switch (version) {
9730 case 1:
9731 ZERO_STRUCT(port1);
9733 if (!pull_port_data_1(mem_ctx, &port1, in)) {
9734 return WERR_NOMEM;
9737 portname = port1.portname;
9738 hostaddress = port1.hostaddress;
9739 queue = port1.queue;
9740 protocol = port1.protocol;
9741 port_number = port1.port_number;
9743 break;
9744 case 2:
9745 ZERO_STRUCT(port2);
9747 if (!pull_port_data_2(mem_ctx, &port2, in)) {
9748 return WERR_NOMEM;
9751 portname = port2.portname;
9752 hostaddress = port2.hostaddress;
9753 queue = port2.queue;
9754 protocol = port2.protocol;
9755 port_number = port2.port_number;
9757 break;
9758 default:
9759 DEBUG(1,("xcvtcp_addport: "
9760 "unknown version of port_data: %d\n", version));
9761 return WERR_UNKNOWN_PORT;
9764 /* create the device URI and call the add_port_hook() */
9766 switch (protocol) {
9767 case PROTOCOL_RAWTCP_TYPE:
9768 device_uri = talloc_asprintf(mem_ctx,
9769 "socket://%s:%d/", hostaddress,
9770 port_number);
9771 break;
9773 case PROTOCOL_LPR_TYPE:
9774 device_uri = talloc_asprintf(mem_ctx,
9775 "lpr://%s/%s", hostaddress, queue );
9776 break;
9778 default:
9779 return WERR_UNKNOWN_PORT;
9782 if (!device_uri) {
9783 return WERR_NOMEM;
9786 return add_port_hook(mem_ctx, token, portname, device_uri);
9789 /*******************************************************************
9790 *******************************************************************/
9792 struct xcv_api_table xcvtcp_cmds[] = {
9793 { "MonitorUI", xcvtcp_monitorui },
9794 { "AddPort", xcvtcp_addport},
9795 { NULL, NULL }
9798 static WERROR process_xcvtcp_command(TALLOC_CTX *mem_ctx,
9799 NT_USER_TOKEN *token, const char *command,
9800 DATA_BLOB *inbuf,
9801 DATA_BLOB *outbuf,
9802 uint32_t *needed )
9804 int i;
9806 DEBUG(10,("process_xcvtcp_command: Received command \"%s\"\n", command));
9808 for ( i=0; xcvtcp_cmds[i].name; i++ ) {
9809 if ( strcmp( command, xcvtcp_cmds[i].name ) == 0 )
9810 return xcvtcp_cmds[i].fn(mem_ctx, token, inbuf, outbuf, needed);
9813 return WERR_BADFUNC;
9816 /*******************************************************************
9817 *******************************************************************/
9818 #if 0 /* don't support management using the "Local Port" monitor */
9820 static WERROR xcvlocal_monitorui(TALLOC_CTX *mem_ctx,
9821 NT_USER_TOKEN *token, DATA_BLOB *in,
9822 DATA_BLOB *out, uint32_t *needed)
9824 const char *dllname = "localui.dll";
9826 *needed = (strlen(dllname)+1) * 2;
9828 if (out->length < *needed) {
9829 return WERR_INSUFFICIENT_BUFFER;
9832 if (!push_monitorui_buf(mem_ctx, out, dllname)) {
9833 return WERR_NOMEM;
9836 return WERR_OK;
9839 /*******************************************************************
9840 *******************************************************************/
9842 struct xcv_api_table xcvlocal_cmds[] = {
9843 { "MonitorUI", xcvlocal_monitorui },
9844 { NULL, NULL }
9846 #else
9847 struct xcv_api_table xcvlocal_cmds[] = {
9848 { NULL, NULL }
9850 #endif
9854 /*******************************************************************
9855 *******************************************************************/
9857 static WERROR process_xcvlocal_command(TALLOC_CTX *mem_ctx,
9858 NT_USER_TOKEN *token, const char *command,
9859 DATA_BLOB *inbuf, DATA_BLOB *outbuf,
9860 uint32_t *needed)
9862 int i;
9864 DEBUG(10,("process_xcvlocal_command: Received command \"%s\"\n", command));
9866 for ( i=0; xcvlocal_cmds[i].name; i++ ) {
9867 if ( strcmp( command, xcvlocal_cmds[i].name ) == 0 )
9868 return xcvlocal_cmds[i].fn(mem_ctx, token, inbuf, outbuf, needed);
9870 return WERR_BADFUNC;
9873 /****************************************************************
9874 _spoolss_XcvData
9875 ****************************************************************/
9877 WERROR _spoolss_XcvData(pipes_struct *p,
9878 struct spoolss_XcvData *r)
9880 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
9881 DATA_BLOB out_data = data_blob_null;
9882 WERROR werror;
9884 if (!Printer) {
9885 DEBUG(2,("_spoolss_XcvData: Invalid handle (%s:%u:%u).\n",
9886 OUR_HANDLE(r->in.handle)));
9887 return WERR_BADFID;
9890 /* Has to be a handle to the TCP/IP port monitor */
9892 if ( !(Printer->printer_type & (SPLHND_PORTMON_LOCAL|SPLHND_PORTMON_TCP)) ) {
9893 DEBUG(2,("_spoolss_XcvData: Call only valid for Port Monitors\n"));
9894 return WERR_BADFID;
9897 /* requires administrative access to the server */
9899 if ( !(Printer->access_granted & SERVER_ACCESS_ADMINISTER) ) {
9900 DEBUG(2,("_spoolss_XcvData: denied by handle permissions.\n"));
9901 return WERR_ACCESS_DENIED;
9904 /* Allocate the outgoing buffer */
9906 if (r->in.out_data_size) {
9907 out_data = data_blob_talloc_zero(p->mem_ctx, r->in.out_data_size);
9908 if (out_data.data == NULL) {
9909 return WERR_NOMEM;
9913 switch ( Printer->printer_type ) {
9914 case SPLHND_PORTMON_TCP:
9915 werror = process_xcvtcp_command(p->mem_ctx,
9916 p->server_info->ptok,
9917 r->in.function_name,
9918 &r->in.in_data, &out_data,
9919 r->out.needed);
9920 break;
9921 case SPLHND_PORTMON_LOCAL:
9922 werror = process_xcvlocal_command(p->mem_ctx,
9923 p->server_info->ptok,
9924 r->in.function_name,
9925 &r->in.in_data, &out_data,
9926 r->out.needed);
9927 break;
9928 default:
9929 werror = WERR_INVALID_PRINT_MONITOR;
9932 if (!W_ERROR_IS_OK(werror)) {
9933 return werror;
9936 *r->out.status_code = 0;
9938 memcpy(r->out.out_data, out_data.data, out_data.length);
9940 return WERR_OK;
9943 /****************************************************************
9944 _spoolss_AddPrintProcessor
9945 ****************************************************************/
9947 WERROR _spoolss_AddPrintProcessor(pipes_struct *p,
9948 struct spoolss_AddPrintProcessor *r)
9950 /* for now, just indicate success and ignore the add. We'll
9951 automatically set the winprint processor for printer
9952 entries later. Used to debug the LexMark Optra S 1855 PCL
9953 driver --jerry */
9955 return WERR_OK;
9958 /****************************************************************
9959 _spoolss_AddPort
9960 ****************************************************************/
9962 WERROR _spoolss_AddPort(pipes_struct *p,
9963 struct spoolss_AddPort *r)
9965 /* do what w2k3 does */
9967 return WERR_NOT_SUPPORTED;
9970 /****************************************************************
9971 _spoolss_AddPrinter
9972 ****************************************************************/
9974 WERROR _spoolss_AddPrinter(pipes_struct *p,
9975 struct spoolss_AddPrinter *r)
9977 p->rng_fault_state = true;
9978 return WERR_NOT_SUPPORTED;
9981 /****************************************************************
9982 _spoolss_GetPrinterDriver
9983 ****************************************************************/
9985 WERROR _spoolss_GetPrinterDriver(pipes_struct *p,
9986 struct spoolss_GetPrinterDriver *r)
9988 p->rng_fault_state = true;
9989 return WERR_NOT_SUPPORTED;
9992 /****************************************************************
9993 _spoolss_ReadPrinter
9994 ****************************************************************/
9996 WERROR _spoolss_ReadPrinter(pipes_struct *p,
9997 struct spoolss_ReadPrinter *r)
9999 p->rng_fault_state = true;
10000 return WERR_NOT_SUPPORTED;
10003 /****************************************************************
10004 _spoolss_WaitForPrinterChange
10005 ****************************************************************/
10007 WERROR _spoolss_WaitForPrinterChange(pipes_struct *p,
10008 struct spoolss_WaitForPrinterChange *r)
10010 p->rng_fault_state = true;
10011 return WERR_NOT_SUPPORTED;
10014 /****************************************************************
10015 _spoolss_ConfigurePort
10016 ****************************************************************/
10018 WERROR _spoolss_ConfigurePort(pipes_struct *p,
10019 struct spoolss_ConfigurePort *r)
10021 p->rng_fault_state = true;
10022 return WERR_NOT_SUPPORTED;
10025 /****************************************************************
10026 _spoolss_DeletePort
10027 ****************************************************************/
10029 WERROR _spoolss_DeletePort(pipes_struct *p,
10030 struct spoolss_DeletePort *r)
10032 p->rng_fault_state = true;
10033 return WERR_NOT_SUPPORTED;
10036 /****************************************************************
10037 _spoolss_CreatePrinterIC
10038 ****************************************************************/
10040 WERROR _spoolss_CreatePrinterIC(pipes_struct *p,
10041 struct spoolss_CreatePrinterIC *r)
10043 p->rng_fault_state = true;
10044 return WERR_NOT_SUPPORTED;
10047 /****************************************************************
10048 _spoolss_PlayGDIScriptOnPrinterIC
10049 ****************************************************************/
10051 WERROR _spoolss_PlayGDIScriptOnPrinterIC(pipes_struct *p,
10052 struct spoolss_PlayGDIScriptOnPrinterIC *r)
10054 p->rng_fault_state = true;
10055 return WERR_NOT_SUPPORTED;
10058 /****************************************************************
10059 _spoolss_DeletePrinterIC
10060 ****************************************************************/
10062 WERROR _spoolss_DeletePrinterIC(pipes_struct *p,
10063 struct spoolss_DeletePrinterIC *r)
10065 p->rng_fault_state = true;
10066 return WERR_NOT_SUPPORTED;
10069 /****************************************************************
10070 _spoolss_AddPrinterConnection
10071 ****************************************************************/
10073 WERROR _spoolss_AddPrinterConnection(pipes_struct *p,
10074 struct spoolss_AddPrinterConnection *r)
10076 p->rng_fault_state = true;
10077 return WERR_NOT_SUPPORTED;
10080 /****************************************************************
10081 _spoolss_DeletePrinterConnection
10082 ****************************************************************/
10084 WERROR _spoolss_DeletePrinterConnection(pipes_struct *p,
10085 struct spoolss_DeletePrinterConnection *r)
10087 p->rng_fault_state = true;
10088 return WERR_NOT_SUPPORTED;
10091 /****************************************************************
10092 _spoolss_PrinterMessageBox
10093 ****************************************************************/
10095 WERROR _spoolss_PrinterMessageBox(pipes_struct *p,
10096 struct spoolss_PrinterMessageBox *r)
10098 p->rng_fault_state = true;
10099 return WERR_NOT_SUPPORTED;
10102 /****************************************************************
10103 _spoolss_AddMonitor
10104 ****************************************************************/
10106 WERROR _spoolss_AddMonitor(pipes_struct *p,
10107 struct spoolss_AddMonitor *r)
10109 p->rng_fault_state = true;
10110 return WERR_NOT_SUPPORTED;
10113 /****************************************************************
10114 _spoolss_DeleteMonitor
10115 ****************************************************************/
10117 WERROR _spoolss_DeleteMonitor(pipes_struct *p,
10118 struct spoolss_DeleteMonitor *r)
10120 p->rng_fault_state = true;
10121 return WERR_NOT_SUPPORTED;
10124 /****************************************************************
10125 _spoolss_DeletePrintProcessor
10126 ****************************************************************/
10128 WERROR _spoolss_DeletePrintProcessor(pipes_struct *p,
10129 struct spoolss_DeletePrintProcessor *r)
10131 p->rng_fault_state = true;
10132 return WERR_NOT_SUPPORTED;
10135 /****************************************************************
10136 _spoolss_AddPrintProvidor
10137 ****************************************************************/
10139 WERROR _spoolss_AddPrintProvidor(pipes_struct *p,
10140 struct spoolss_AddPrintProvidor *r)
10142 p->rng_fault_state = true;
10143 return WERR_NOT_SUPPORTED;
10146 /****************************************************************
10147 _spoolss_DeletePrintProvidor
10148 ****************************************************************/
10150 WERROR _spoolss_DeletePrintProvidor(pipes_struct *p,
10151 struct spoolss_DeletePrintProvidor *r)
10153 p->rng_fault_state = true;
10154 return WERR_NOT_SUPPORTED;
10157 /****************************************************************
10158 _spoolss_FindFirstPrinterChangeNotification
10159 ****************************************************************/
10161 WERROR _spoolss_FindFirstPrinterChangeNotification(pipes_struct *p,
10162 struct spoolss_FindFirstPrinterChangeNotification *r)
10164 p->rng_fault_state = true;
10165 return WERR_NOT_SUPPORTED;
10168 /****************************************************************
10169 _spoolss_FindNextPrinterChangeNotification
10170 ****************************************************************/
10172 WERROR _spoolss_FindNextPrinterChangeNotification(pipes_struct *p,
10173 struct spoolss_FindNextPrinterChangeNotification *r)
10175 p->rng_fault_state = true;
10176 return WERR_NOT_SUPPORTED;
10179 /****************************************************************
10180 _spoolss_RouterFindFirstPrinterChangeNotificationOld
10181 ****************************************************************/
10183 WERROR _spoolss_RouterFindFirstPrinterChangeNotificationOld(pipes_struct *p,
10184 struct spoolss_RouterFindFirstPrinterChangeNotificationOld *r)
10186 p->rng_fault_state = true;
10187 return WERR_NOT_SUPPORTED;
10190 /****************************************************************
10191 _spoolss_ReplyOpenPrinter
10192 ****************************************************************/
10194 WERROR _spoolss_ReplyOpenPrinter(pipes_struct *p,
10195 struct spoolss_ReplyOpenPrinter *r)
10197 p->rng_fault_state = true;
10198 return WERR_NOT_SUPPORTED;
10201 /****************************************************************
10202 _spoolss_RouterReplyPrinter
10203 ****************************************************************/
10205 WERROR _spoolss_RouterReplyPrinter(pipes_struct *p,
10206 struct spoolss_RouterReplyPrinter *r)
10208 p->rng_fault_state = true;
10209 return WERR_NOT_SUPPORTED;
10212 /****************************************************************
10213 _spoolss_ReplyClosePrinter
10214 ****************************************************************/
10216 WERROR _spoolss_ReplyClosePrinter(pipes_struct *p,
10217 struct spoolss_ReplyClosePrinter *r)
10219 p->rng_fault_state = true;
10220 return WERR_NOT_SUPPORTED;
10223 /****************************************************************
10224 _spoolss_AddPortEx
10225 ****************************************************************/
10227 WERROR _spoolss_AddPortEx(pipes_struct *p,
10228 struct spoolss_AddPortEx *r)
10230 p->rng_fault_state = true;
10231 return WERR_NOT_SUPPORTED;
10234 /****************************************************************
10235 _spoolss_RouterFindFirstPrinterChangeNotification
10236 ****************************************************************/
10238 WERROR _spoolss_RouterFindFirstPrinterChangeNotification(pipes_struct *p,
10239 struct spoolss_RouterFindFirstPrinterChangeNotification *r)
10241 p->rng_fault_state = true;
10242 return WERR_NOT_SUPPORTED;
10245 /****************************************************************
10246 _spoolss_SpoolerInit
10247 ****************************************************************/
10249 WERROR _spoolss_SpoolerInit(pipes_struct *p,
10250 struct spoolss_SpoolerInit *r)
10252 p->rng_fault_state = true;
10253 return WERR_NOT_SUPPORTED;
10256 /****************************************************************
10257 _spoolss_ResetPrinterEx
10258 ****************************************************************/
10260 WERROR _spoolss_ResetPrinterEx(pipes_struct *p,
10261 struct spoolss_ResetPrinterEx *r)
10263 p->rng_fault_state = true;
10264 return WERR_NOT_SUPPORTED;
10267 /****************************************************************
10268 _spoolss_RouterReplyPrinterEx
10269 ****************************************************************/
10271 WERROR _spoolss_RouterReplyPrinterEx(pipes_struct *p,
10272 struct spoolss_RouterReplyPrinterEx *r)
10274 p->rng_fault_state = true;
10275 return WERR_NOT_SUPPORTED;
10278 /****************************************************************
10279 _spoolss_44
10280 ****************************************************************/
10282 WERROR _spoolss_44(pipes_struct *p,
10283 struct spoolss_44 *r)
10285 p->rng_fault_state = true;
10286 return WERR_NOT_SUPPORTED;
10289 /****************************************************************
10290 _spoolss_47
10291 ****************************************************************/
10293 WERROR _spoolss_47(pipes_struct *p,
10294 struct spoolss_47 *r)
10296 p->rng_fault_state = true;
10297 return WERR_NOT_SUPPORTED;
10300 /****************************************************************
10301 _spoolss_4a
10302 ****************************************************************/
10304 WERROR _spoolss_4a(pipes_struct *p,
10305 struct spoolss_4a *r)
10307 p->rng_fault_state = true;
10308 return WERR_NOT_SUPPORTED;
10311 /****************************************************************
10312 _spoolss_4b
10313 ****************************************************************/
10315 WERROR _spoolss_4b(pipes_struct *p,
10316 struct spoolss_4b *r)
10318 p->rng_fault_state = true;
10319 return WERR_NOT_SUPPORTED;
10322 /****************************************************************
10323 _spoolss_4c
10324 ****************************************************************/
10326 WERROR _spoolss_4c(pipes_struct *p,
10327 struct spoolss_4c *r)
10329 p->rng_fault_state = true;
10330 return WERR_NOT_SUPPORTED;
10333 /****************************************************************
10334 _spoolss_53
10335 ****************************************************************/
10337 WERROR _spoolss_53(pipes_struct *p,
10338 struct spoolss_53 *r)
10340 p->rng_fault_state = true;
10341 return WERR_NOT_SUPPORTED;
10344 /****************************************************************
10345 _spoolss_55
10346 ****************************************************************/
10348 WERROR _spoolss_55(pipes_struct *p,
10349 struct spoolss_55 *r)
10351 p->rng_fault_state = true;
10352 return WERR_NOT_SUPPORTED;
10355 /****************************************************************
10356 _spoolss_56
10357 ****************************************************************/
10359 WERROR _spoolss_56(pipes_struct *p,
10360 struct spoolss_56 *r)
10362 p->rng_fault_state = true;
10363 return WERR_NOT_SUPPORTED;
10366 /****************************************************************
10367 _spoolss_57
10368 ****************************************************************/
10370 WERROR _spoolss_57(pipes_struct *p,
10371 struct spoolss_57 *r)
10373 p->rng_fault_state = true;
10374 return WERR_NOT_SUPPORTED;
10377 /****************************************************************
10378 _spoolss_5a
10379 ****************************************************************/
10381 WERROR _spoolss_5a(pipes_struct *p,
10382 struct spoolss_5a *r)
10384 p->rng_fault_state = true;
10385 return WERR_NOT_SUPPORTED;
10388 /****************************************************************
10389 _spoolss_5b
10390 ****************************************************************/
10392 WERROR _spoolss_5b(pipes_struct *p,
10393 struct spoolss_5b *r)
10395 p->rng_fault_state = true;
10396 return WERR_NOT_SUPPORTED;
10399 /****************************************************************
10400 _spoolss_5c
10401 ****************************************************************/
10403 WERROR _spoolss_5c(pipes_struct *p,
10404 struct spoolss_5c *r)
10406 p->rng_fault_state = true;
10407 return WERR_NOT_SUPPORTED;
10410 /****************************************************************
10411 _spoolss_5d
10412 ****************************************************************/
10414 WERROR _spoolss_5d(pipes_struct *p,
10415 struct spoolss_5d *r)
10417 p->rng_fault_state = true;
10418 return WERR_NOT_SUPPORTED;
10421 /****************************************************************
10422 _spoolss_5e
10423 ****************************************************************/
10425 WERROR _spoolss_5e(pipes_struct *p,
10426 struct spoolss_5e *r)
10428 p->rng_fault_state = true;
10429 return WERR_NOT_SUPPORTED;
10432 /****************************************************************
10433 _spoolss_5f
10434 ****************************************************************/
10436 WERROR _spoolss_5f(pipes_struct *p,
10437 struct spoolss_5f *r)
10439 p->rng_fault_state = true;
10440 return WERR_NOT_SUPPORTED;