s3: Add an async smbsock_connect
[Samba.git] / source3 / rpc_server / srv_spoolss_nt.c
blob4b75d7c7b96574c365448b1338b6cb99cbd704ab
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 fstrcpy(nt_devmode->devicename, devmode->devicename);
1485 fstrcpy(nt_devmode->formname, devmode->formname);
1487 nt_devmode->devicename[31] = '\0';
1488 nt_devmode->formname[31] = '\0';
1490 nt_devmode->specversion = devmode->specversion;
1491 nt_devmode->driverversion = devmode->driverversion;
1492 nt_devmode->size = devmode->size;
1493 nt_devmode->fields = devmode->fields;
1494 nt_devmode->orientation = devmode->orientation;
1495 nt_devmode->papersize = devmode->papersize;
1496 nt_devmode->paperlength = devmode->paperlength;
1497 nt_devmode->paperwidth = devmode->paperwidth;
1498 nt_devmode->scale = devmode->scale;
1499 nt_devmode->copies = devmode->copies;
1500 nt_devmode->defaultsource = devmode->defaultsource;
1501 nt_devmode->printquality = devmode->printquality;
1502 nt_devmode->color = devmode->color;
1503 nt_devmode->duplex = devmode->duplex;
1504 nt_devmode->yresolution = devmode->yresolution;
1505 nt_devmode->ttoption = devmode->ttoption;
1506 nt_devmode->collate = devmode->collate;
1508 nt_devmode->logpixels = devmode->logpixels;
1509 nt_devmode->bitsperpel = devmode->bitsperpel;
1510 nt_devmode->pelswidth = devmode->pelswidth;
1511 nt_devmode->pelsheight = devmode->pelsheight;
1512 nt_devmode->displayflags = devmode->displayflags;
1513 nt_devmode->displayfrequency = devmode->displayfrequency;
1514 nt_devmode->icmmethod = devmode->icmmethod;
1515 nt_devmode->icmintent = devmode->icmintent;
1516 nt_devmode->mediatype = devmode->mediatype;
1517 nt_devmode->dithertype = devmode->dithertype;
1518 nt_devmode->reserved1 = devmode->reserved1;
1519 nt_devmode->reserved2 = devmode->reserved2;
1520 nt_devmode->panningwidth = devmode->panningwidth;
1521 nt_devmode->panningheight = devmode->panningheight;
1524 * Only change private and driverextra if the incoming devmode
1525 * has a new one. JRA.
1528 if ((devmode->__driverextra_length != 0) && (devmode->driverextra_data.data != NULL)) {
1529 SAFE_FREE(nt_devmode->nt_dev_private);
1530 nt_devmode->driverextra = devmode->__driverextra_length;
1531 if((nt_devmode->nt_dev_private = SMB_MALLOC_ARRAY(uint8_t, nt_devmode->driverextra)) == NULL)
1532 return false;
1533 memcpy(nt_devmode->nt_dev_private, devmode->driverextra_data.data, nt_devmode->driverextra);
1536 *pp_nt_devmode = nt_devmode;
1538 return true;
1541 /****************************************************************
1542 _spoolss_OpenPrinterEx
1543 ****************************************************************/
1545 WERROR _spoolss_OpenPrinterEx(pipes_struct *p,
1546 struct spoolss_OpenPrinterEx *r)
1548 int snum;
1549 Printer_entry *Printer=NULL;
1551 if (!r->in.printername) {
1552 return WERR_INVALID_PARAM;
1555 /* some sanity check because you can open a printer or a print server */
1556 /* aka: \\server\printer or \\server */
1558 DEBUGADD(3,("checking name: %s\n", r->in.printername));
1560 if (!open_printer_hnd(p, r->out.handle, r->in.printername, 0)) {
1561 ZERO_STRUCTP(r->out.handle);
1562 return WERR_INVALID_PARAM;
1565 Printer = find_printer_index_by_hnd(p, r->out.handle);
1566 if ( !Printer ) {
1567 DEBUG(0,("_spoolss_OpenPrinterEx: logic error. Can't find printer "
1568 "handle we created for printer %s\n", r->in.printername));
1569 close_printer_handle(p, r->out.handle);
1570 ZERO_STRUCTP(r->out.handle);
1571 return WERR_INVALID_PARAM;
1575 * First case: the user is opening the print server:
1577 * Disallow MS AddPrinterWizard if parameter disables it. A Win2k
1578 * client 1st tries an OpenPrinterEx with access==0, MUST be allowed.
1580 * Then both Win2k and WinNT clients try an OpenPrinterEx with
1581 * SERVER_ALL_ACCESS, which we allow only if the user is root (uid=0)
1582 * or if the user is listed in the smb.conf printer admin parameter.
1584 * Then they try OpenPrinterEx with SERVER_READ which we allow. This lets the
1585 * client view printer folder, but does not show the MSAPW.
1587 * Note: this test needs code to check access rights here too. Jeremy
1588 * could you look at this?
1590 * Second case: the user is opening a printer:
1591 * NT doesn't let us connect to a printer if the connecting user
1592 * doesn't have print permission.
1594 * Third case: user is opening a Port Monitor
1595 * access checks same as opening a handle to the print server.
1598 switch (Printer->printer_type )
1600 case SPLHND_SERVER:
1601 case SPLHND_PORTMON_TCP:
1602 case SPLHND_PORTMON_LOCAL:
1603 /* Printserver handles use global struct... */
1605 snum = -1;
1607 /* Map standard access rights to object specific access rights */
1609 se_map_standard(&r->in.access_mask,
1610 &printserver_std_mapping);
1612 /* Deny any object specific bits that don't apply to print
1613 servers (i.e printer and job specific bits) */
1615 r->in.access_mask &= SPECIFIC_RIGHTS_MASK;
1617 if (r->in.access_mask &
1618 ~(SERVER_ACCESS_ADMINISTER | SERVER_ACCESS_ENUMERATE)) {
1619 DEBUG(3, ("access DENIED for non-printserver bits\n"));
1620 close_printer_handle(p, r->out.handle);
1621 ZERO_STRUCTP(r->out.handle);
1622 return WERR_ACCESS_DENIED;
1625 /* Allow admin access */
1627 if ( r->in.access_mask & SERVER_ACCESS_ADMINISTER )
1629 SE_PRIV se_printop = SE_PRINT_OPERATOR;
1631 if (!lp_ms_add_printer_wizard()) {
1632 close_printer_handle(p, r->out.handle);
1633 ZERO_STRUCTP(r->out.handle);
1634 return WERR_ACCESS_DENIED;
1637 /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
1638 and not a printer admin, then fail */
1640 if ((p->server_info->utok.uid != sec_initial_uid()) &&
1641 !user_has_privileges(p->server_info->ptok,
1642 &se_printop ) &&
1643 !token_contains_name_in_list(
1644 uidtoname(p->server_info->utok.uid),
1645 pdb_get_domain(p->server_info->sam_account),
1646 NULL,
1647 p->server_info->ptok,
1648 lp_printer_admin(snum))) {
1649 close_printer_handle(p, r->out.handle);
1650 ZERO_STRUCTP(r->out.handle);
1651 return WERR_ACCESS_DENIED;
1654 r->in.access_mask = SERVER_ACCESS_ADMINISTER;
1656 else
1658 r->in.access_mask = SERVER_ACCESS_ENUMERATE;
1661 DEBUG(4,("Setting print server access = %s\n", (r->in.access_mask == SERVER_ACCESS_ADMINISTER)
1662 ? "SERVER_ACCESS_ADMINISTER" : "SERVER_ACCESS_ENUMERATE" ));
1664 /* We fall through to return WERR_OK */
1665 break;
1667 case SPLHND_PRINTER:
1668 /* NT doesn't let us connect to a printer if the connecting user
1669 doesn't have print permission. */
1671 if (!get_printer_snum(p, r->out.handle, &snum, NULL)) {
1672 close_printer_handle(p, r->out.handle);
1673 ZERO_STRUCTP(r->out.handle);
1674 return WERR_BADFID;
1677 if (r->in.access_mask == SEC_FLAG_MAXIMUM_ALLOWED) {
1678 r->in.access_mask = PRINTER_ACCESS_ADMINISTER;
1681 se_map_standard(&r->in.access_mask, &printer_std_mapping);
1683 /* map an empty access mask to the minimum access mask */
1684 if (r->in.access_mask == 0x0)
1685 r->in.access_mask = PRINTER_ACCESS_USE;
1688 * If we are not serving the printer driver for this printer,
1689 * map PRINTER_ACCESS_ADMINISTER to PRINTER_ACCESS_USE. This
1690 * will keep NT clients happy --jerry
1693 if (lp_use_client_driver(snum)
1694 && (r->in.access_mask & PRINTER_ACCESS_ADMINISTER))
1696 r->in.access_mask = PRINTER_ACCESS_USE;
1699 /* check smb.conf parameters and the the sec_desc */
1701 if ( !check_access(get_client_fd(), lp_hostsallow(snum), lp_hostsdeny(snum)) ) {
1702 DEBUG(3, ("access DENIED (hosts allow/deny) for printer open\n"));
1703 ZERO_STRUCTP(r->out.handle);
1704 return WERR_ACCESS_DENIED;
1707 if (!user_ok_token(uidtoname(p->server_info->utok.uid), NULL,
1708 p->server_info->ptok, snum) ||
1709 !print_access_check(p->server_info, snum,
1710 r->in.access_mask)) {
1711 DEBUG(3, ("access DENIED for printer open\n"));
1712 close_printer_handle(p, r->out.handle);
1713 ZERO_STRUCTP(r->out.handle);
1714 return WERR_ACCESS_DENIED;
1717 if ((r->in.access_mask & SPECIFIC_RIGHTS_MASK)& ~(PRINTER_ACCESS_ADMINISTER|PRINTER_ACCESS_USE)) {
1718 DEBUG(3, ("access DENIED for printer open - unknown bits\n"));
1719 close_printer_handle(p, r->out.handle);
1720 ZERO_STRUCTP(r->out.handle);
1721 return WERR_ACCESS_DENIED;
1724 if (r->in.access_mask & PRINTER_ACCESS_ADMINISTER)
1725 r->in.access_mask = PRINTER_ACCESS_ADMINISTER;
1726 else
1727 r->in.access_mask = PRINTER_ACCESS_USE;
1729 DEBUG(4,("Setting printer access = %s\n", (r->in.access_mask == PRINTER_ACCESS_ADMINISTER)
1730 ? "PRINTER_ACCESS_ADMINISTER" : "PRINTER_ACCESS_USE" ));
1732 break;
1734 default:
1735 /* sanity check to prevent programmer error */
1736 ZERO_STRUCTP(r->out.handle);
1737 return WERR_BADFID;
1740 Printer->access_granted = r->in.access_mask;
1743 * If the client sent a devmode in the OpenPrinter() call, then
1744 * save it here in case we get a job submission on this handle
1747 if ((Printer->printer_type != SPLHND_SERVER) &&
1748 r->in.devmode_ctr.devmode) {
1749 convert_devicemode(Printer->sharename,
1750 r->in.devmode_ctr.devmode,
1751 &Printer->nt_devmode);
1754 #if 0 /* JERRY -- I'm doubtful this is really effective */
1755 /* HACK ALERT!!! Sleep for 1/3 of a second to try trigger a LAN/WAN
1756 optimization in Windows 2000 clients --jerry */
1758 if ( (r->in.access_mask == PRINTER_ACCESS_ADMINISTER)
1759 && (RA_WIN2K == get_remote_arch()) )
1761 DEBUG(10,("_spoolss_OpenPrinterEx: Enabling LAN/WAN hack for Win2k clients.\n"));
1762 sys_usleep( 500000 );
1764 #endif
1766 return WERR_OK;
1769 /****************************************************************************
1770 ****************************************************************************/
1772 static bool printer_info2_to_nt_printer_info2(struct spoolss_SetPrinterInfo2 *r,
1773 NT_PRINTER_INFO_LEVEL_2 *d)
1775 DEBUG(7,("printer_info2_to_nt_printer_info2\n"));
1777 if (!r || !d) {
1778 return false;
1781 d->attributes = r->attributes;
1782 d->priority = r->priority;
1783 d->default_priority = r->defaultpriority;
1784 d->starttime = r->starttime;
1785 d->untiltime = r->untiltime;
1786 d->status = r->status;
1787 d->cjobs = r->cjobs;
1789 fstrcpy(d->servername, r->servername);
1790 fstrcpy(d->printername, r->printername);
1791 fstrcpy(d->sharename, r->sharename);
1792 fstrcpy(d->portname, r->portname);
1793 fstrcpy(d->drivername, r->drivername);
1794 slprintf(d->comment, sizeof(d->comment)-1, "%s", r->comment);
1795 fstrcpy(d->location, r->location);
1796 fstrcpy(d->sepfile, r->sepfile);
1797 fstrcpy(d->printprocessor, r->printprocessor);
1798 fstrcpy(d->datatype, r->datatype);
1799 fstrcpy(d->parameters, r->parameters);
1801 return true;
1804 /****************************************************************************
1805 ****************************************************************************/
1807 static bool convert_printer_info(struct spoolss_SetPrinterInfoCtr *info_ctr,
1808 NT_PRINTER_INFO_LEVEL *printer)
1810 bool ret;
1812 switch (info_ctr->level) {
1813 case 2:
1814 /* allocate memory if needed. Messy because
1815 convert_printer_info is used to update an existing
1816 printer or build a new one */
1818 if (!printer->info_2) {
1819 printer->info_2 = TALLOC_ZERO_P(printer, NT_PRINTER_INFO_LEVEL_2);
1820 if (!printer->info_2) {
1821 DEBUG(0,("convert_printer_info: "
1822 "talloc() failed!\n"));
1823 return false;
1827 ret = printer_info2_to_nt_printer_info2(info_ctr->info.info2,
1828 printer->info_2);
1829 printer->info_2->setuptime = time(NULL);
1830 return ret;
1833 return false;
1836 /*******************************************************************
1837 ********************************************************************/
1839 static bool string_array_to_fstring_array(const char **sarray, fstring **farray)
1841 int i;
1843 if (!sarray) {
1844 *farray = NULL;
1845 return true;
1848 *farray = SMB_MALLOC_ARRAY(fstring, 1);
1849 if (!*farray) {
1850 return false;
1853 for (i=0; sarray[i] != NULL; i++) {
1854 *farray = SMB_REALLOC_ARRAY(*farray, fstring, i+2);
1855 if (!*farray) {
1856 return false;
1858 fstrcpy((*farray)[i], sarray[i]);
1861 fstrcpy((*farray)[i], "");
1863 return true;
1866 /*******************************************************************
1867 ********************************************************************/
1869 static bool driver_info3_to_nt_driver_info3(struct spoolss_AddDriverInfo3 *r,
1870 NT_PRINTER_DRIVER_INFO_LEVEL_3 **p)
1872 NT_PRINTER_DRIVER_INFO_LEVEL_3 *d;
1874 DEBUG(7,("driver_info3_to_nt_driver_info3: Converting from UNICODE to ASCII\n"));
1876 if (*p == NULL) {
1877 *p = SMB_MALLOC_P(NT_PRINTER_DRIVER_INFO_LEVEL_3);
1878 if (*p == NULL) {
1879 return false;
1881 ZERO_STRUCTP(*p);
1884 d = *p;
1886 d->cversion = r->version;
1888 fstrcpy(d->name, r->driver_name);
1889 fstrcpy(d->environment, r->architecture);
1890 fstrcpy(d->driverpath, r->driver_path);
1891 fstrcpy(d->datafile, r->data_file);
1892 fstrcpy(d->configfile, r->config_file);
1893 fstrcpy(d->helpfile, r->help_file);
1894 fstrcpy(d->monitorname, r->monitor_name);
1895 fstrcpy(d->defaultdatatype, r->default_datatype);
1897 DEBUGADD(8,( "version: %d\n", d->cversion));
1898 DEBUGADD(8,( "name: %s\n", d->name));
1899 DEBUGADD(8,( "environment: %s\n", d->environment));
1900 DEBUGADD(8,( "driverpath: %s\n", d->driverpath));
1901 DEBUGADD(8,( "datafile: %s\n", d->datafile));
1902 DEBUGADD(8,( "configfile: %s\n", d->configfile));
1903 DEBUGADD(8,( "helpfile: %s\n", d->helpfile));
1904 DEBUGADD(8,( "monitorname: %s\n", d->monitorname));
1905 DEBUGADD(8,( "defaultdatatype: %s\n", d->defaultdatatype));
1907 if (r->dependent_files) {
1908 if (!string_array_to_fstring_array(r->dependent_files->string,
1909 &d->dependentfiles)) {
1910 SAFE_FREE(*p);
1911 return false;
1915 return true;
1918 /*******************************************************************
1919 ********************************************************************/
1921 static bool driver_info6_to_nt_driver_info6(struct spoolss_AddDriverInfo6 *r,
1922 NT_PRINTER_DRIVER_INFO_LEVEL_6 **p)
1924 NT_PRINTER_DRIVER_INFO_LEVEL_6 *d;
1926 DEBUG(7,("driver_info6_to_nt_driver_info6: Converting from UNICODE to ASCII\n"));
1928 if (*p == NULL) {
1929 *p = SMB_MALLOC_P(NT_PRINTER_DRIVER_INFO_LEVEL_6);
1930 if (*p == NULL) {
1931 return false;
1933 ZERO_STRUCTP(*p);
1936 d = *p;
1938 d->version = r->version;
1940 fstrcpy(d->name, r->driver_name);
1941 fstrcpy(d->environment, r->architecture);
1942 fstrcpy(d->driverpath, r->driver_path);
1943 fstrcpy(d->datafile, r->data_file);
1944 fstrcpy(d->configfile, r->config_file);
1945 fstrcpy(d->helpfile, r->help_file);
1946 fstrcpy(d->monitorname, r->monitor_name);
1947 fstrcpy(d->defaultdatatype, r->default_datatype);
1949 DEBUGADD(8,( "version: %d\n", d->version));
1950 DEBUGADD(8,( "name: %s\n", d->name));
1951 DEBUGADD(8,( "environment: %s\n", d->environment));
1952 DEBUGADD(8,( "driverpath: %s\n", d->driverpath));
1953 DEBUGADD(8,( "datafile: %s\n", d->datafile));
1954 DEBUGADD(8,( "configfile: %s\n", d->configfile));
1955 DEBUGADD(8,( "helpfile: %s\n", d->helpfile));
1956 DEBUGADD(8,( "monitorname: %s\n", d->monitorname));
1957 DEBUGADD(8,( "defaultdatatype: %s\n", d->defaultdatatype));
1959 if (r->dependent_files) {
1960 if (!string_array_to_fstring_array(r->dependent_files->string,
1961 &d->dependentfiles)) {
1962 goto error;
1966 if (r->previous_names) {
1967 if (!string_array_to_fstring_array(r->previous_names->string,
1968 &d->previousnames)) {
1969 goto error;
1973 return true;
1975 error:
1976 SAFE_FREE(*p);
1977 return false;
1980 /********************************************************************
1981 ********************************************************************/
1983 static bool convert_printer_driver_info(const struct spoolss_AddDriverInfoCtr *r,
1984 NT_PRINTER_DRIVER_INFO_LEVEL *printer,
1985 uint32_t level)
1987 switch (level) {
1988 case 3:
1989 printer->info_3 = NULL;
1990 if (!driver_info3_to_nt_driver_info3(r->info.info3, &printer->info_3)) {
1991 return false;
1993 break;
1994 case 6:
1995 printer->info_6 = NULL;
1996 if (!driver_info6_to_nt_driver_info6(r->info.info6, &printer->info_6)) {
1997 return false;
1999 break;
2000 default:
2001 return false;
2004 return true;
2007 /********************************************************************
2008 * _spoolss_enddocprinter_internal.
2009 ********************************************************************/
2011 static WERROR _spoolss_enddocprinter_internal(pipes_struct *p,
2012 struct policy_handle *handle)
2014 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
2015 int snum;
2017 if (!Printer) {
2018 DEBUG(2,("_spoolss_enddocprinter_internal: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
2019 return WERR_BADFID;
2022 if (!get_printer_snum(p, handle, &snum, NULL))
2023 return WERR_BADFID;
2025 Printer->document_started = false;
2026 print_job_end(snum, Printer->jobid,NORMAL_CLOSE);
2027 /* error codes unhandled so far ... */
2029 return WERR_OK;
2032 /****************************************************************
2033 _spoolss_ClosePrinter
2034 ****************************************************************/
2036 WERROR _spoolss_ClosePrinter(pipes_struct *p,
2037 struct spoolss_ClosePrinter *r)
2039 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
2041 if (Printer && Printer->document_started)
2042 _spoolss_enddocprinter_internal(p, r->in.handle); /* print job was not closed */
2044 if (!close_printer_handle(p, r->in.handle))
2045 return WERR_BADFID;
2047 /* clear the returned printer handle. Observed behavior
2048 from Win2k server. Don't think this really matters.
2049 Previous code just copied the value of the closed
2050 handle. --jerry */
2052 ZERO_STRUCTP(r->out.handle);
2054 return WERR_OK;
2057 /****************************************************************
2058 _spoolss_DeletePrinter
2059 ****************************************************************/
2061 WERROR _spoolss_DeletePrinter(pipes_struct *p,
2062 struct spoolss_DeletePrinter *r)
2064 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
2065 WERROR result;
2067 if (Printer && Printer->document_started)
2068 _spoolss_enddocprinter_internal(p, r->in.handle); /* print job was not closed */
2070 result = delete_printer_handle(p, r->in.handle);
2072 update_c_setprinter(false);
2074 return result;
2077 /*******************************************************************
2078 * static function to lookup the version id corresponding to an
2079 * long architecture string
2080 ******************************************************************/
2082 static int get_version_id(const char *arch)
2084 int i;
2085 struct print_architecture_table_node archi_table[]= {
2087 {"Windows 4.0", "WIN40", 0 },
2088 {"Windows NT x86", "W32X86", 2 },
2089 {"Windows NT R4000", "W32MIPS", 2 },
2090 {"Windows NT Alpha_AXP", "W32ALPHA", 2 },
2091 {"Windows NT PowerPC", "W32PPC", 2 },
2092 {"Windows IA64", "IA64", 3 },
2093 {"Windows x64", "x64", 3 },
2094 {NULL, "", -1 }
2097 for (i=0; archi_table[i].long_archi != NULL; i++)
2099 if (strcmp(arch, archi_table[i].long_archi) == 0)
2100 return (archi_table[i].version);
2103 return -1;
2106 /****************************************************************
2107 _spoolss_DeletePrinterDriver
2108 ****************************************************************/
2110 WERROR _spoolss_DeletePrinterDriver(pipes_struct *p,
2111 struct spoolss_DeletePrinterDriver *r)
2113 NT_PRINTER_DRIVER_INFO_LEVEL info;
2114 NT_PRINTER_DRIVER_INFO_LEVEL info_win2k;
2115 int version;
2116 WERROR status;
2117 WERROR status_win2k = WERR_ACCESS_DENIED;
2118 SE_PRIV se_printop = SE_PRINT_OPERATOR;
2120 /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
2121 and not a printer admin, then fail */
2123 if ( (p->server_info->utok.uid != sec_initial_uid())
2124 && !user_has_privileges(p->server_info->ptok, &se_printop )
2125 && !token_contains_name_in_list(
2126 uidtoname(p->server_info->utok.uid),
2127 pdb_get_domain(p->server_info->sam_account),
2128 NULL,
2129 p->server_info->ptok,
2130 lp_printer_admin(-1)) )
2132 return WERR_ACCESS_DENIED;
2135 /* check that we have a valid driver name first */
2137 if ((version = get_version_id(r->in.architecture)) == -1)
2138 return WERR_INVALID_ENVIRONMENT;
2140 ZERO_STRUCT(info);
2141 ZERO_STRUCT(info_win2k);
2143 if (!W_ERROR_IS_OK(get_a_printer_driver(&info, 3, r->in.driver,
2144 r->in.architecture,
2145 version)))
2147 /* try for Win2k driver if "Windows NT x86" */
2149 if ( version == 2 ) {
2150 version = 3;
2151 if (!W_ERROR_IS_OK(get_a_printer_driver(&info, 3,
2152 r->in.driver,
2153 r->in.architecture,
2154 version))) {
2155 status = WERR_UNKNOWN_PRINTER_DRIVER;
2156 goto done;
2159 /* otherwise it was a failure */
2160 else {
2161 status = WERR_UNKNOWN_PRINTER_DRIVER;
2162 goto done;
2167 if (printer_driver_in_use(info.info_3)) {
2168 status = WERR_PRINTER_DRIVER_IN_USE;
2169 goto done;
2172 if ( version == 2 )
2174 if (W_ERROR_IS_OK(get_a_printer_driver(&info_win2k, 3,
2175 r->in.driver,
2176 r->in.architecture, 3)))
2178 /* if we get to here, we now have 2 driver info structures to remove */
2179 /* remove the Win2k driver first*/
2181 status_win2k = delete_printer_driver(
2182 p, info_win2k.info_3, 3, false);
2183 free_a_printer_driver( info_win2k, 3 );
2185 /* this should not have failed---if it did, report to client */
2186 if ( !W_ERROR_IS_OK(status_win2k) )
2188 status = status_win2k;
2189 goto done;
2194 status = delete_printer_driver(p, info.info_3, version, false);
2196 /* if at least one of the deletes succeeded return OK */
2198 if ( W_ERROR_IS_OK(status) || W_ERROR_IS_OK(status_win2k) )
2199 status = WERR_OK;
2201 done:
2202 free_a_printer_driver( info, 3 );
2204 return status;
2207 /****************************************************************
2208 _spoolss_DeletePrinterDriverEx
2209 ****************************************************************/
2211 WERROR _spoolss_DeletePrinterDriverEx(pipes_struct *p,
2212 struct spoolss_DeletePrinterDriverEx *r)
2214 NT_PRINTER_DRIVER_INFO_LEVEL info;
2215 NT_PRINTER_DRIVER_INFO_LEVEL info_win2k;
2216 int version;
2217 bool delete_files;
2218 WERROR status;
2219 WERROR status_win2k = WERR_ACCESS_DENIED;
2220 SE_PRIV se_printop = SE_PRINT_OPERATOR;
2222 /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
2223 and not a printer admin, then fail */
2225 if ( (p->server_info->utok.uid != sec_initial_uid())
2226 && !user_has_privileges(p->server_info->ptok, &se_printop )
2227 && !token_contains_name_in_list(
2228 uidtoname(p->server_info->utok.uid),
2229 pdb_get_domain(p->server_info->sam_account),
2230 NULL,
2231 p->server_info->ptok, lp_printer_admin(-1)) )
2233 return WERR_ACCESS_DENIED;
2236 /* check that we have a valid driver name first */
2237 if ((version = get_version_id(r->in.architecture)) == -1) {
2238 /* this is what NT returns */
2239 return WERR_INVALID_ENVIRONMENT;
2242 if (r->in.delete_flags & DPD_DELETE_SPECIFIC_VERSION)
2243 version = r->in.version;
2245 ZERO_STRUCT(info);
2246 ZERO_STRUCT(info_win2k);
2248 status = get_a_printer_driver(&info, 3, r->in.driver,
2249 r->in.architecture, version);
2251 if ( !W_ERROR_IS_OK(status) )
2254 * if the client asked for a specific version,
2255 * or this is something other than Windows NT x86,
2256 * then we've failed
2259 if ( (r->in.delete_flags & DPD_DELETE_SPECIFIC_VERSION) || (version !=2) )
2260 goto done;
2262 /* try for Win2k driver if "Windows NT x86" */
2264 version = 3;
2265 if (!W_ERROR_IS_OK(get_a_printer_driver(&info, 3, r->in.driver,
2266 r->in.architecture,
2267 version))) {
2268 status = WERR_UNKNOWN_PRINTER_DRIVER;
2269 goto done;
2273 if ( printer_driver_in_use(info.info_3) ) {
2274 status = WERR_PRINTER_DRIVER_IN_USE;
2275 goto done;
2279 * we have a couple of cases to consider.
2280 * (1) Are any files in use? If so and DPD_DELTE_ALL_FILE is set,
2281 * then the delete should fail if **any** files overlap with
2282 * other drivers
2283 * (2) If DPD_DELTE_UNUSED_FILES is sert, then delete all
2284 * non-overlapping files
2285 * (3) If neither DPD_DELTE_ALL_FILE nor DPD_DELTE_ALL_FILES
2286 * is set, the do not delete any files
2287 * Refer to MSDN docs on DeletePrinterDriverEx() for details.
2290 delete_files = r->in.delete_flags & (DPD_DELETE_ALL_FILES|DPD_DELETE_UNUSED_FILES);
2292 /* fail if any files are in use and DPD_DELETE_ALL_FILES is set */
2294 if ( delete_files && printer_driver_files_in_use(info.info_3) & (r->in.delete_flags & DPD_DELETE_ALL_FILES) ) {
2295 /* no idea of the correct error here */
2296 status = WERR_ACCESS_DENIED;
2297 goto done;
2301 /* also check for W32X86/3 if necessary; maybe we already have? */
2303 if ( (version == 2) && ((r->in.delete_flags & DPD_DELETE_SPECIFIC_VERSION) != DPD_DELETE_SPECIFIC_VERSION) ) {
2304 if (W_ERROR_IS_OK(get_a_printer_driver(&info_win2k, 3,
2305 r->in.driver,
2306 r->in.architecture, 3)))
2309 if ( delete_files && printer_driver_files_in_use(info_win2k.info_3) & (r->in.delete_flags & DPD_DELETE_ALL_FILES) ) {
2310 /* no idea of the correct error here */
2311 free_a_printer_driver( info_win2k, 3 );
2312 status = WERR_ACCESS_DENIED;
2313 goto done;
2316 /* if we get to here, we now have 2 driver info structures to remove */
2317 /* remove the Win2k driver first*/
2319 status_win2k = delete_printer_driver(
2320 p, info_win2k.info_3, 3, delete_files);
2321 free_a_printer_driver( info_win2k, 3 );
2323 /* this should not have failed---if it did, report to client */
2325 if ( !W_ERROR_IS_OK(status_win2k) )
2326 goto done;
2330 status = delete_printer_driver(p, info.info_3, version, delete_files);
2332 if ( W_ERROR_IS_OK(status) || W_ERROR_IS_OK(status_win2k) )
2333 status = WERR_OK;
2334 done:
2335 free_a_printer_driver( info, 3 );
2337 return status;
2341 /****************************************************************************
2342 Internal routine for removing printerdata
2343 ***************************************************************************/
2345 static WERROR delete_printer_dataex( NT_PRINTER_INFO_LEVEL *printer, const char *key, const char *value )
2347 return delete_printer_data( printer->info_2, key, value );
2350 /****************************************************************************
2351 Internal routine for storing printerdata
2352 ***************************************************************************/
2354 WERROR set_printer_dataex(NT_PRINTER_INFO_LEVEL *printer,
2355 const char *key, const char *value,
2356 uint32_t type, uint8_t *data, int real_len)
2358 /* the registry objects enforce uniqueness based on value name */
2360 return add_printer_data( printer->info_2, key, value, type, data, real_len );
2363 /********************************************************************
2364 GetPrinterData on a printer server Handle.
2365 ********************************************************************/
2367 static WERROR getprinterdata_printer_server(TALLOC_CTX *mem_ctx,
2368 const char *value,
2369 enum winreg_Type *type,
2370 union spoolss_PrinterData *data)
2372 DEBUG(8,("getprinterdata_printer_server:%s\n", value));
2374 if (!StrCaseCmp(value, "W3SvcInstalled")) {
2375 *type = REG_DWORD;
2376 data->value = 0x00;
2377 return WERR_OK;
2380 if (!StrCaseCmp(value, "BeepEnabled")) {
2381 *type = REG_DWORD;
2382 data->value = 0x00;
2383 return WERR_OK;
2386 if (!StrCaseCmp(value, "EventLog")) {
2387 *type = REG_DWORD;
2388 /* formally was 0x1b */
2389 data->value = 0x00;
2390 return WERR_OK;
2393 if (!StrCaseCmp(value, "NetPopup")) {
2394 *type = REG_DWORD;
2395 data->value = 0x00;
2396 return WERR_OK;
2399 if (!StrCaseCmp(value, "MajorVersion")) {
2400 *type = REG_DWORD;
2402 /* Windows NT 4.0 seems to not allow uploading of drivers
2403 to a server that reports 0x3 as the MajorVersion.
2404 need to investigate more how Win2k gets around this .
2405 -- jerry */
2407 if (RA_WINNT == get_remote_arch()) {
2408 data->value = 0x02;
2409 } else {
2410 data->value = 0x03;
2413 return WERR_OK;
2416 if (!StrCaseCmp(value, "MinorVersion")) {
2417 *type = REG_DWORD;
2418 data->value = 0x00;
2419 return WERR_OK;
2422 /* REG_BINARY
2423 * uint32_t size = 0x114
2424 * uint32_t major = 5
2425 * uint32_t minor = [0|1]
2426 * uint32_t build = [2195|2600]
2427 * extra unicode string = e.g. "Service Pack 3"
2429 if (!StrCaseCmp(value, "OSVersion")) {
2430 DATA_BLOB blob;
2431 enum ndr_err_code ndr_err;
2432 struct spoolss_OSVersion os;
2434 os.major = 5; /* Windows 2000 == 5.0 */
2435 os.minor = 0;
2436 os.build = 2195; /* build */
2437 os.extra_string = ""; /* leave extra string empty */
2439 ndr_err = ndr_push_struct_blob(&blob, mem_ctx, NULL, &os,
2440 (ndr_push_flags_fn_t)ndr_push_spoolss_OSVersion);
2441 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
2442 return WERR_GENERAL_FAILURE;
2445 *type = REG_BINARY;
2446 data->binary = blob;
2448 return WERR_OK;
2452 if (!StrCaseCmp(value, "DefaultSpoolDirectory")) {
2453 *type = REG_SZ;
2455 data->string = talloc_strdup(mem_ctx, "C:\\PRINTERS");
2456 W_ERROR_HAVE_NO_MEMORY(data->string);
2458 return WERR_OK;
2461 if (!StrCaseCmp(value, "Architecture")) {
2462 *type = REG_SZ;
2464 data->string = talloc_strdup(mem_ctx, "Windows NT x86");
2465 W_ERROR_HAVE_NO_MEMORY(data->string);
2467 return WERR_OK;
2470 if (!StrCaseCmp(value, "DsPresent")) {
2471 *type = REG_DWORD;
2473 /* only show the publish check box if we are a
2474 member of a AD domain */
2476 if (lp_security() == SEC_ADS) {
2477 data->value = 0x01;
2478 } else {
2479 data->value = 0x00;
2481 return WERR_OK;
2484 if (!StrCaseCmp(value, "DNSMachineName")) {
2485 const char *hostname = get_mydnsfullname();
2487 if (!hostname) {
2488 return WERR_BADFILE;
2491 *type = REG_SZ;
2492 data->string = talloc_strdup(mem_ctx, hostname);
2493 W_ERROR_HAVE_NO_MEMORY(data->string);
2495 return WERR_OK;
2498 *type = REG_NONE;
2500 return WERR_INVALID_PARAM;
2503 /****************************************************************
2504 _spoolss_GetPrinterData
2505 ****************************************************************/
2507 WERROR _spoolss_GetPrinterData(pipes_struct *p,
2508 struct spoolss_GetPrinterData *r)
2510 struct spoolss_GetPrinterDataEx r2;
2512 r2.in.handle = r->in.handle;
2513 r2.in.key_name = "PrinterDriverData";
2514 r2.in.value_name = r->in.value_name;
2515 r2.in.offered = r->in.offered;
2516 r2.out.type = r->out.type;
2517 r2.out.data = r->out.data;
2518 r2.out.needed = r->out.needed;
2520 return _spoolss_GetPrinterDataEx(p, &r2);
2523 /*********************************************************
2524 Connect to the client machine.
2525 **********************************************************/
2527 static bool spoolss_connect_to_client(struct rpc_pipe_client **pp_pipe,
2528 struct sockaddr_storage *client_ss, const char *remote_machine)
2530 NTSTATUS ret;
2531 struct cli_state *the_cli;
2532 struct sockaddr_storage rm_addr;
2534 if ( is_zero_addr((struct sockaddr *)client_ss) ) {
2535 if ( !resolve_name( remote_machine, &rm_addr, 0x20) ) {
2536 DEBUG(2,("spoolss_connect_to_client: Can't resolve address for %s\n", remote_machine));
2537 return false;
2540 if (ismyaddr((struct sockaddr *)&rm_addr)) {
2541 DEBUG(0,("spoolss_connect_to_client: Machine %s is one of our addresses. Cannot add to ourselves.\n", remote_machine));
2542 return false;
2544 } else {
2545 char addr[INET6_ADDRSTRLEN];
2546 rm_addr = *client_ss;
2547 print_sockaddr(addr, sizeof(addr), &rm_addr);
2548 DEBUG(5,("spoolss_connect_to_client: Using address %s (no name resolution necessary)\n",
2549 addr));
2552 /* setup the connection */
2554 ret = cli_full_connection( &the_cli, global_myname(), remote_machine,
2555 &rm_addr, 0, "IPC$", "IPC",
2556 "", /* username */
2557 "", /* domain */
2558 "", /* password */
2559 0, lp_client_signing(), NULL );
2561 if ( !NT_STATUS_IS_OK( ret ) ) {
2562 DEBUG(2,("spoolss_connect_to_client: connection to [%s] failed!\n",
2563 remote_machine ));
2564 return false;
2567 if ( the_cli->protocol != PROTOCOL_NT1 ) {
2568 DEBUG(0,("spoolss_connect_to_client: machine %s didn't negotiate NT protocol.\n", remote_machine));
2569 cli_shutdown(the_cli);
2570 return false;
2574 * Ok - we have an anonymous connection to the IPC$ share.
2575 * Now start the NT Domain stuff :-).
2578 ret = cli_rpc_pipe_open_noauth(the_cli, &ndr_table_spoolss.syntax_id, pp_pipe);
2579 if (!NT_STATUS_IS_OK(ret)) {
2580 DEBUG(2,("spoolss_connect_to_client: unable to open the spoolss pipe on machine %s. Error was : %s.\n",
2581 remote_machine, nt_errstr(ret)));
2582 cli_shutdown(the_cli);
2583 return false;
2586 return true;
2589 /***************************************************************************
2590 Connect to the client.
2591 ****************************************************************************/
2593 static bool srv_spoolss_replyopenprinter(int snum, const char *printer,
2594 uint32_t localprinter, uint32_t type,
2595 struct policy_handle *handle,
2596 struct sockaddr_storage *client_ss)
2598 WERROR result;
2599 NTSTATUS status;
2602 * If it's the first connection, contact the client
2603 * and connect to the IPC$ share anonymously
2605 if (smb_connections==0) {
2606 fstring unix_printer;
2608 fstrcpy(unix_printer, printer+2); /* the +2 is to strip the leading 2 backslashs */
2610 if ( !spoolss_connect_to_client( &notify_cli_pipe, client_ss, unix_printer ))
2611 return false;
2613 messaging_register(smbd_messaging_context(), NULL,
2614 MSG_PRINTER_NOTIFY2,
2615 receive_notify2_message_list);
2616 /* Tell the connections db we're now interested in printer
2617 * notify messages. */
2618 register_message_flags(true, FLAG_MSG_PRINT_NOTIFY);
2622 * Tell the specific printing tdb we want messages for this printer
2623 * by registering our PID.
2626 if (!print_notify_register_pid(snum))
2627 DEBUG(0,("print_notify_register_pid: Failed to register our pid for printer %s\n", printer ));
2629 smb_connections++;
2631 status = rpccli_spoolss_ReplyOpenPrinter(notify_cli_pipe, talloc_tos(),
2632 printer,
2633 localprinter,
2634 type,
2636 NULL,
2637 handle,
2638 &result);
2639 if (!NT_STATUS_IS_OK(status) || !W_ERROR_IS_OK(result))
2640 DEBUG(5,("srv_spoolss_reply_open_printer: Client RPC returned [%s]\n",
2641 win_errstr(result)));
2643 return (W_ERROR_IS_OK(result));
2646 /****************************************************************
2647 ****************************************************************/
2649 static struct spoolss_NotifyOption *dup_spoolss_NotifyOption(TALLOC_CTX *mem_ctx,
2650 const struct spoolss_NotifyOption *r)
2652 struct spoolss_NotifyOption *option;
2653 uint32_t i,k;
2655 if (!r) {
2656 return NULL;
2659 option = talloc_zero(mem_ctx, struct spoolss_NotifyOption);
2660 if (!option) {
2661 return NULL;
2664 *option = *r;
2666 if (!option->count) {
2667 return option;
2670 option->types = talloc_zero_array(option,
2671 struct spoolss_NotifyOptionType, option->count);
2672 if (!option->types) {
2673 talloc_free(option);
2674 return NULL;
2677 for (i=0; i < option->count; i++) {
2678 option->types[i] = r->types[i];
2680 if (option->types[i].count) {
2681 option->types[i].fields = talloc_zero_array(option,
2682 union spoolss_Field, option->types[i].count);
2683 if (!option->types[i].fields) {
2684 talloc_free(option);
2685 return NULL;
2687 for (k=0; k<option->types[i].count; k++) {
2688 option->types[i].fields[k] =
2689 r->types[i].fields[k];
2694 return option;
2697 /****************************************************************
2698 * _spoolss_RemoteFindFirstPrinterChangeNotifyEx
2700 * before replying OK: status=0 a rpc call is made to the workstation
2701 * asking ReplyOpenPrinter
2703 * in fact ReplyOpenPrinter is the changenotify equivalent on the spoolss pipe
2704 * called from api_spoolss_rffpcnex
2705 ****************************************************************/
2707 WERROR _spoolss_RemoteFindFirstPrinterChangeNotifyEx(pipes_struct *p,
2708 struct spoolss_RemoteFindFirstPrinterChangeNotifyEx *r)
2710 int snum = -1;
2711 struct spoolss_NotifyOption *option = r->in.notify_options;
2712 struct sockaddr_storage client_ss;
2714 /* store the notify value in the printer struct */
2716 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
2718 if (!Printer) {
2719 DEBUG(2,("_spoolss_RemoteFindFirstPrinterChangeNotifyEx: "
2720 "Invalid handle (%s:%u:%u).\n",
2721 OUR_HANDLE(r->in.handle)));
2722 return WERR_BADFID;
2725 Printer->notify.flags = r->in.flags;
2726 Printer->notify.options = r->in.options;
2727 Printer->notify.printerlocal = r->in.printer_local;
2729 TALLOC_FREE(Printer->notify.option);
2730 Printer->notify.option = dup_spoolss_NotifyOption(Printer, option);
2732 fstrcpy(Printer->notify.localmachine, r->in.local_machine);
2734 /* Connect to the client machine and send a ReplyOpenPrinter */
2736 if ( Printer->printer_type == SPLHND_SERVER)
2737 snum = -1;
2738 else if ( (Printer->printer_type == SPLHND_PRINTER) &&
2739 !get_printer_snum(p, r->in.handle, &snum, NULL) )
2740 return WERR_BADFID;
2742 if (!interpret_string_addr(&client_ss, p->client_address,
2743 AI_NUMERICHOST)) {
2744 return WERR_SERVER_UNAVAILABLE;
2747 if(!srv_spoolss_replyopenprinter(snum, Printer->notify.localmachine,
2748 Printer->notify.printerlocal, 1,
2749 &Printer->notify.client_hnd, &client_ss))
2750 return WERR_SERVER_UNAVAILABLE;
2752 Printer->notify.client_connected = true;
2754 return WERR_OK;
2757 /*******************************************************************
2758 * fill a notify_info_data with the servername
2759 ********************************************************************/
2761 void spoolss_notify_server_name(int snum,
2762 struct spoolss_Notify *data,
2763 print_queue_struct *queue,
2764 NT_PRINTER_INFO_LEVEL *printer,
2765 TALLOC_CTX *mem_ctx)
2767 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, printer->info_2->servername);
2770 /*******************************************************************
2771 * fill a notify_info_data with the printername (not including the servername).
2772 ********************************************************************/
2774 void spoolss_notify_printer_name(int snum,
2775 struct spoolss_Notify *data,
2776 print_queue_struct *queue,
2777 NT_PRINTER_INFO_LEVEL *printer,
2778 TALLOC_CTX *mem_ctx)
2780 /* the notify name should not contain the \\server\ part */
2781 char *p = strrchr(printer->info_2->printername, '\\');
2783 if (!p) {
2784 p = printer->info_2->printername;
2785 } else {
2786 p++;
2789 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, p);
2792 /*******************************************************************
2793 * fill a notify_info_data with the servicename
2794 ********************************************************************/
2796 void spoolss_notify_share_name(int snum,
2797 struct spoolss_Notify *data,
2798 print_queue_struct *queue,
2799 NT_PRINTER_INFO_LEVEL *printer,
2800 TALLOC_CTX *mem_ctx)
2802 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, lp_servicename(snum));
2805 /*******************************************************************
2806 * fill a notify_info_data with the port name
2807 ********************************************************************/
2809 void spoolss_notify_port_name(int snum,
2810 struct spoolss_Notify *data,
2811 print_queue_struct *queue,
2812 NT_PRINTER_INFO_LEVEL *printer,
2813 TALLOC_CTX *mem_ctx)
2815 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, printer->info_2->portname);
2818 /*******************************************************************
2819 * fill a notify_info_data with the printername
2820 * but it doesn't exist, have to see what to do
2821 ********************************************************************/
2823 void spoolss_notify_driver_name(int snum,
2824 struct spoolss_Notify *data,
2825 print_queue_struct *queue,
2826 NT_PRINTER_INFO_LEVEL *printer,
2827 TALLOC_CTX *mem_ctx)
2829 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, printer->info_2->drivername);
2832 /*******************************************************************
2833 * fill a notify_info_data with the comment
2834 ********************************************************************/
2836 void spoolss_notify_comment(int snum,
2837 struct spoolss_Notify *data,
2838 print_queue_struct *queue,
2839 NT_PRINTER_INFO_LEVEL *printer,
2840 TALLOC_CTX *mem_ctx)
2842 char *p;
2844 if (*printer->info_2->comment == '\0') {
2845 p = lp_comment(snum);
2846 } else {
2847 p = printer->info_2->comment;
2850 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, printer->info_2->comment);
2853 /*******************************************************************
2854 * fill a notify_info_data with the comment
2855 * location = "Room 1, floor 2, building 3"
2856 ********************************************************************/
2858 void spoolss_notify_location(int snum,
2859 struct spoolss_Notify *data,
2860 print_queue_struct *queue,
2861 NT_PRINTER_INFO_LEVEL *printer,
2862 TALLOC_CTX *mem_ctx)
2864 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, printer->info_2->location);
2867 /*******************************************************************
2868 * fill a notify_info_data with the device mode
2869 * jfm:xxxx don't to it for know but that's a real problem !!!
2870 ********************************************************************/
2872 static void spoolss_notify_devmode(int snum,
2873 struct spoolss_Notify *data,
2874 print_queue_struct *queue,
2875 NT_PRINTER_INFO_LEVEL *printer,
2876 TALLOC_CTX *mem_ctx)
2878 /* for a dummy implementation we have to zero the fields */
2879 SETUP_SPOOLSS_NOTIFY_DATA_DEVMODE(data, NULL);
2882 /*******************************************************************
2883 * fill a notify_info_data with the separator file name
2884 ********************************************************************/
2886 void spoolss_notify_sepfile(int snum,
2887 struct spoolss_Notify *data,
2888 print_queue_struct *queue,
2889 NT_PRINTER_INFO_LEVEL *printer,
2890 TALLOC_CTX *mem_ctx)
2892 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, printer->info_2->sepfile);
2895 /*******************************************************************
2896 * fill a notify_info_data with the print processor
2897 * jfm:xxxx return always winprint to indicate we don't do anything to it
2898 ********************************************************************/
2900 void spoolss_notify_print_processor(int snum,
2901 struct spoolss_Notify *data,
2902 print_queue_struct *queue,
2903 NT_PRINTER_INFO_LEVEL *printer,
2904 TALLOC_CTX *mem_ctx)
2906 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, printer->info_2->printprocessor);
2909 /*******************************************************************
2910 * fill a notify_info_data with the print processor options
2911 * jfm:xxxx send an empty string
2912 ********************************************************************/
2914 void spoolss_notify_parameters(int snum,
2915 struct spoolss_Notify *data,
2916 print_queue_struct *queue,
2917 NT_PRINTER_INFO_LEVEL *printer,
2918 TALLOC_CTX *mem_ctx)
2920 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, printer->info_2->parameters);
2923 /*******************************************************************
2924 * fill a notify_info_data with the data type
2925 * jfm:xxxx always send RAW as data type
2926 ********************************************************************/
2928 void spoolss_notify_datatype(int snum,
2929 struct spoolss_Notify *data,
2930 print_queue_struct *queue,
2931 NT_PRINTER_INFO_LEVEL *printer,
2932 TALLOC_CTX *mem_ctx)
2934 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, printer->info_2->datatype);
2937 /*******************************************************************
2938 * fill a notify_info_data with the security descriptor
2939 * jfm:xxxx send an null pointer to say no security desc
2940 * have to implement security before !
2941 ********************************************************************/
2943 static void spoolss_notify_security_desc(int snum,
2944 struct spoolss_Notify *data,
2945 print_queue_struct *queue,
2946 NT_PRINTER_INFO_LEVEL *printer,
2947 TALLOC_CTX *mem_ctx)
2949 SETUP_SPOOLSS_NOTIFY_DATA_SECDESC(data,
2950 printer->info_2->secdesc_buf->sd_size,
2951 printer->info_2->secdesc_buf->sd);
2954 /*******************************************************************
2955 * fill a notify_info_data with the attributes
2956 * jfm:xxxx a samba printer is always shared
2957 ********************************************************************/
2959 void spoolss_notify_attributes(int snum,
2960 struct spoolss_Notify *data,
2961 print_queue_struct *queue,
2962 NT_PRINTER_INFO_LEVEL *printer,
2963 TALLOC_CTX *mem_ctx)
2965 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, printer->info_2->attributes);
2968 /*******************************************************************
2969 * fill a notify_info_data with the priority
2970 ********************************************************************/
2972 static void spoolss_notify_priority(int snum,
2973 struct spoolss_Notify *data,
2974 print_queue_struct *queue,
2975 NT_PRINTER_INFO_LEVEL *printer,
2976 TALLOC_CTX *mem_ctx)
2978 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, printer->info_2->priority);
2981 /*******************************************************************
2982 * fill a notify_info_data with the default priority
2983 ********************************************************************/
2985 static void spoolss_notify_default_priority(int snum,
2986 struct spoolss_Notify *data,
2987 print_queue_struct *queue,
2988 NT_PRINTER_INFO_LEVEL *printer,
2989 TALLOC_CTX *mem_ctx)
2991 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, printer->info_2->default_priority);
2994 /*******************************************************************
2995 * fill a notify_info_data with the start time
2996 ********************************************************************/
2998 static void spoolss_notify_start_time(int snum,
2999 struct spoolss_Notify *data,
3000 print_queue_struct *queue,
3001 NT_PRINTER_INFO_LEVEL *printer,
3002 TALLOC_CTX *mem_ctx)
3004 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, printer->info_2->starttime);
3007 /*******************************************************************
3008 * fill a notify_info_data with the until time
3009 ********************************************************************/
3011 static void spoolss_notify_until_time(int snum,
3012 struct spoolss_Notify *data,
3013 print_queue_struct *queue,
3014 NT_PRINTER_INFO_LEVEL *printer,
3015 TALLOC_CTX *mem_ctx)
3017 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, printer->info_2->untiltime);
3020 /*******************************************************************
3021 * fill a notify_info_data with the status
3022 ********************************************************************/
3024 static void spoolss_notify_status(int snum,
3025 struct spoolss_Notify *data,
3026 print_queue_struct *queue,
3027 NT_PRINTER_INFO_LEVEL *printer,
3028 TALLOC_CTX *mem_ctx)
3030 print_status_struct status;
3032 print_queue_length(snum, &status);
3033 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, status.status);
3036 /*******************************************************************
3037 * fill a notify_info_data with the number of jobs queued
3038 ********************************************************************/
3040 void spoolss_notify_cjobs(int snum,
3041 struct spoolss_Notify *data,
3042 print_queue_struct *queue,
3043 NT_PRINTER_INFO_LEVEL *printer,
3044 TALLOC_CTX *mem_ctx)
3046 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, print_queue_length(snum, NULL));
3049 /*******************************************************************
3050 * fill a notify_info_data with the average ppm
3051 ********************************************************************/
3053 static void spoolss_notify_average_ppm(int snum,
3054 struct spoolss_Notify *data,
3055 print_queue_struct *queue,
3056 NT_PRINTER_INFO_LEVEL *printer,
3057 TALLOC_CTX *mem_ctx)
3059 /* always respond 8 pages per minutes */
3060 /* a little hard ! */
3061 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, printer->info_2->averageppm);
3064 /*******************************************************************
3065 * fill a notify_info_data with username
3066 ********************************************************************/
3068 static void spoolss_notify_username(int snum,
3069 struct spoolss_Notify *data,
3070 print_queue_struct *queue,
3071 NT_PRINTER_INFO_LEVEL *printer,
3072 TALLOC_CTX *mem_ctx)
3074 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, queue->fs_user);
3077 /*******************************************************************
3078 * fill a notify_info_data with job status
3079 ********************************************************************/
3081 static void spoolss_notify_job_status(int snum,
3082 struct spoolss_Notify *data,
3083 print_queue_struct *queue,
3084 NT_PRINTER_INFO_LEVEL *printer,
3085 TALLOC_CTX *mem_ctx)
3087 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, nt_printj_status(queue->status));
3090 /*******************************************************************
3091 * fill a notify_info_data with job name
3092 ********************************************************************/
3094 static void spoolss_notify_job_name(int snum,
3095 struct spoolss_Notify *data,
3096 print_queue_struct *queue,
3097 NT_PRINTER_INFO_LEVEL *printer,
3098 TALLOC_CTX *mem_ctx)
3100 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, queue->fs_file);
3103 /*******************************************************************
3104 * fill a notify_info_data with job status
3105 ********************************************************************/
3107 static void spoolss_notify_job_status_string(int snum,
3108 struct spoolss_Notify *data,
3109 print_queue_struct *queue,
3110 NT_PRINTER_INFO_LEVEL *printer,
3111 TALLOC_CTX *mem_ctx)
3114 * Now we're returning job status codes we just return a "" here. JRA.
3117 const char *p = "";
3119 #if 0 /* NO LONGER NEEDED - JRA. 02/22/2001 */
3120 p = "unknown";
3122 switch (queue->status) {
3123 case LPQ_QUEUED:
3124 p = "Queued";
3125 break;
3126 case LPQ_PAUSED:
3127 p = ""; /* NT provides the paused string */
3128 break;
3129 case LPQ_SPOOLING:
3130 p = "Spooling";
3131 break;
3132 case LPQ_PRINTING:
3133 p = "Printing";
3134 break;
3136 #endif /* NO LONGER NEEDED. */
3138 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, p);
3141 /*******************************************************************
3142 * fill a notify_info_data with job time
3143 ********************************************************************/
3145 static void spoolss_notify_job_time(int snum,
3146 struct spoolss_Notify *data,
3147 print_queue_struct *queue,
3148 NT_PRINTER_INFO_LEVEL *printer,
3149 TALLOC_CTX *mem_ctx)
3151 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, 0);
3154 /*******************************************************************
3155 * fill a notify_info_data with job size
3156 ********************************************************************/
3158 static void spoolss_notify_job_size(int snum,
3159 struct spoolss_Notify *data,
3160 print_queue_struct *queue,
3161 NT_PRINTER_INFO_LEVEL *printer,
3162 TALLOC_CTX *mem_ctx)
3164 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, queue->size);
3167 /*******************************************************************
3168 * fill a notify_info_data with page info
3169 ********************************************************************/
3170 static void spoolss_notify_total_pages(int snum,
3171 struct spoolss_Notify *data,
3172 print_queue_struct *queue,
3173 NT_PRINTER_INFO_LEVEL *printer,
3174 TALLOC_CTX *mem_ctx)
3176 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, queue->page_count);
3179 /*******************************************************************
3180 * fill a notify_info_data with pages printed info.
3181 ********************************************************************/
3182 static void spoolss_notify_pages_printed(int snum,
3183 struct spoolss_Notify *data,
3184 print_queue_struct *queue,
3185 NT_PRINTER_INFO_LEVEL *printer,
3186 TALLOC_CTX *mem_ctx)
3188 /* Add code when back-end tracks this */
3189 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, 0);
3192 /*******************************************************************
3193 Fill a notify_info_data with job position.
3194 ********************************************************************/
3196 static void spoolss_notify_job_position(int snum,
3197 struct spoolss_Notify *data,
3198 print_queue_struct *queue,
3199 NT_PRINTER_INFO_LEVEL *printer,
3200 TALLOC_CTX *mem_ctx)
3202 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, queue->job);
3205 /*******************************************************************
3206 Fill a notify_info_data with submitted time.
3207 ********************************************************************/
3209 static void spoolss_notify_submitted_time(int snum,
3210 struct spoolss_Notify *data,
3211 print_queue_struct *queue,
3212 NT_PRINTER_INFO_LEVEL *printer,
3213 TALLOC_CTX *mem_ctx)
3215 data->data.string.string = NULL;
3216 data->data.string.size = 0;
3218 init_systemtime_buffer(mem_ctx, gmtime(&queue->time),
3219 &data->data.string.string,
3220 &data->data.string.size);
3224 struct s_notify_info_data_table
3226 enum spoolss_NotifyType type;
3227 uint16_t field;
3228 const char *name;
3229 enum spoolss_NotifyTable variable_type;
3230 void (*fn) (int snum, struct spoolss_Notify *data,
3231 print_queue_struct *queue,
3232 NT_PRINTER_INFO_LEVEL *printer, TALLOC_CTX *mem_ctx);
3235 /* A table describing the various print notification constants and
3236 whether the notification data is a pointer to a variable sized
3237 buffer, a one value uint32_t or a two value uint32_t. */
3239 static const struct s_notify_info_data_table notify_info_data_table[] =
3241 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_SERVER_NAME, "PRINTER_NOTIFY_FIELD_SERVER_NAME", NOTIFY_TABLE_STRING, spoolss_notify_server_name },
3242 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PRINTER_NAME, "PRINTER_NOTIFY_FIELD_PRINTER_NAME", NOTIFY_TABLE_STRING, spoolss_notify_printer_name },
3243 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_SHARE_NAME, "PRINTER_NOTIFY_FIELD_SHARE_NAME", NOTIFY_TABLE_STRING, spoolss_notify_share_name },
3244 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PORT_NAME, "PRINTER_NOTIFY_FIELD_PORT_NAME", NOTIFY_TABLE_STRING, spoolss_notify_port_name },
3245 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_DRIVER_NAME, "PRINTER_NOTIFY_FIELD_DRIVER_NAME", NOTIFY_TABLE_STRING, spoolss_notify_driver_name },
3246 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_COMMENT, "PRINTER_NOTIFY_FIELD_COMMENT", NOTIFY_TABLE_STRING, spoolss_notify_comment },
3247 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_LOCATION, "PRINTER_NOTIFY_FIELD_LOCATION", NOTIFY_TABLE_STRING, spoolss_notify_location },
3248 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_DEVMODE, "PRINTER_NOTIFY_FIELD_DEVMODE", NOTIFY_TABLE_DEVMODE, spoolss_notify_devmode },
3249 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_SEPFILE, "PRINTER_NOTIFY_FIELD_SEPFILE", NOTIFY_TABLE_STRING, spoolss_notify_sepfile },
3250 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PRINT_PROCESSOR, "PRINTER_NOTIFY_FIELD_PRINT_PROCESSOR", NOTIFY_TABLE_STRING, spoolss_notify_print_processor },
3251 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PARAMETERS, "PRINTER_NOTIFY_FIELD_PARAMETERS", NOTIFY_TABLE_STRING, spoolss_notify_parameters },
3252 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_DATATYPE, "PRINTER_NOTIFY_FIELD_DATATYPE", NOTIFY_TABLE_STRING, spoolss_notify_datatype },
3253 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_SECURITY_DESCRIPTOR, "PRINTER_NOTIFY_FIELD_SECURITY_DESCRIPTOR", NOTIFY_TABLE_SECURITYDESCRIPTOR, spoolss_notify_security_desc },
3254 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_ATTRIBUTES, "PRINTER_NOTIFY_FIELD_ATTRIBUTES", NOTIFY_TABLE_DWORD, spoolss_notify_attributes },
3255 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PRIORITY, "PRINTER_NOTIFY_FIELD_PRIORITY", NOTIFY_TABLE_DWORD, spoolss_notify_priority },
3256 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_DEFAULT_PRIORITY, "PRINTER_NOTIFY_FIELD_DEFAULT_PRIORITY", NOTIFY_TABLE_DWORD, spoolss_notify_default_priority },
3257 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_START_TIME, "PRINTER_NOTIFY_FIELD_START_TIME", NOTIFY_TABLE_DWORD, spoolss_notify_start_time },
3258 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_UNTIL_TIME, "PRINTER_NOTIFY_FIELD_UNTIL_TIME", NOTIFY_TABLE_DWORD, spoolss_notify_until_time },
3259 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_STATUS, "PRINTER_NOTIFY_FIELD_STATUS", NOTIFY_TABLE_DWORD, spoolss_notify_status },
3260 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_STATUS_STRING, "PRINTER_NOTIFY_FIELD_STATUS_STRING", NOTIFY_TABLE_STRING, NULL },
3261 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_CJOBS, "PRINTER_NOTIFY_FIELD_CJOBS", NOTIFY_TABLE_DWORD, spoolss_notify_cjobs },
3262 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_AVERAGE_PPM, "PRINTER_NOTIFY_FIELD_AVERAGE_PPM", NOTIFY_TABLE_DWORD, spoolss_notify_average_ppm },
3263 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_TOTAL_PAGES, "PRINTER_NOTIFY_FIELD_TOTAL_PAGES", NOTIFY_TABLE_DWORD, NULL },
3264 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PAGES_PRINTED, "PRINTER_NOTIFY_FIELD_PAGES_PRINTED", NOTIFY_TABLE_DWORD, NULL },
3265 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_TOTAL_BYTES, "PRINTER_NOTIFY_FIELD_TOTAL_BYTES", NOTIFY_TABLE_DWORD, NULL },
3266 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_BYTES_PRINTED, "PRINTER_NOTIFY_FIELD_BYTES_PRINTED", NOTIFY_TABLE_DWORD, NULL },
3267 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_PRINTER_NAME, "JOB_NOTIFY_FIELD_PRINTER_NAME", NOTIFY_TABLE_STRING, spoolss_notify_printer_name },
3268 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_MACHINE_NAME, "JOB_NOTIFY_FIELD_MACHINE_NAME", NOTIFY_TABLE_STRING, spoolss_notify_server_name },
3269 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_PORT_NAME, "JOB_NOTIFY_FIELD_PORT_NAME", NOTIFY_TABLE_STRING, spoolss_notify_port_name },
3270 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_USER_NAME, "JOB_NOTIFY_FIELD_USER_NAME", NOTIFY_TABLE_STRING, spoolss_notify_username },
3271 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_NOTIFY_NAME, "JOB_NOTIFY_FIELD_NOTIFY_NAME", NOTIFY_TABLE_STRING, spoolss_notify_username },
3272 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_DATATYPE, "JOB_NOTIFY_FIELD_DATATYPE", NOTIFY_TABLE_STRING, spoolss_notify_datatype },
3273 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_PRINT_PROCESSOR, "JOB_NOTIFY_FIELD_PRINT_PROCESSOR", NOTIFY_TABLE_STRING, spoolss_notify_print_processor },
3274 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_PARAMETERS, "JOB_NOTIFY_FIELD_PARAMETERS", NOTIFY_TABLE_STRING, spoolss_notify_parameters },
3275 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_DRIVER_NAME, "JOB_NOTIFY_FIELD_DRIVER_NAME", NOTIFY_TABLE_STRING, spoolss_notify_driver_name },
3276 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_DEVMODE, "JOB_NOTIFY_FIELD_DEVMODE", NOTIFY_TABLE_DEVMODE, spoolss_notify_devmode },
3277 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_STATUS, "JOB_NOTIFY_FIELD_STATUS", NOTIFY_TABLE_DWORD, spoolss_notify_job_status },
3278 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_STATUS_STRING, "JOB_NOTIFY_FIELD_STATUS_STRING", NOTIFY_TABLE_STRING, spoolss_notify_job_status_string },
3279 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_SECURITY_DESCRIPTOR, "JOB_NOTIFY_FIELD_SECURITY_DESCRIPTOR", NOTIFY_TABLE_SECURITYDESCRIPTOR, NULL },
3280 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_DOCUMENT, "JOB_NOTIFY_FIELD_DOCUMENT", NOTIFY_TABLE_STRING, spoolss_notify_job_name },
3281 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_PRIORITY, "JOB_NOTIFY_FIELD_PRIORITY", NOTIFY_TABLE_DWORD, spoolss_notify_priority },
3282 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_POSITION, "JOB_NOTIFY_FIELD_POSITION", NOTIFY_TABLE_DWORD, spoolss_notify_job_position },
3283 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_SUBMITTED, "JOB_NOTIFY_FIELD_SUBMITTED", NOTIFY_TABLE_TIME, spoolss_notify_submitted_time },
3284 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_START_TIME, "JOB_NOTIFY_FIELD_START_TIME", NOTIFY_TABLE_DWORD, spoolss_notify_start_time },
3285 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_UNTIL_TIME, "JOB_NOTIFY_FIELD_UNTIL_TIME", NOTIFY_TABLE_DWORD, spoolss_notify_until_time },
3286 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_TIME, "JOB_NOTIFY_FIELD_TIME", NOTIFY_TABLE_DWORD, spoolss_notify_job_time },
3287 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_TOTAL_PAGES, "JOB_NOTIFY_FIELD_TOTAL_PAGES", NOTIFY_TABLE_DWORD, spoolss_notify_total_pages },
3288 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_PAGES_PRINTED, "JOB_NOTIFY_FIELD_PAGES_PRINTED", NOTIFY_TABLE_DWORD, spoolss_notify_pages_printed },
3289 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_TOTAL_BYTES, "JOB_NOTIFY_FIELD_TOTAL_BYTES", NOTIFY_TABLE_DWORD, spoolss_notify_job_size },
3292 /*******************************************************************
3293 Return the variable_type of info_data structure.
3294 ********************************************************************/
3296 static uint32_t variable_type_of_notify_info_data(enum spoolss_NotifyType type,
3297 uint16_t field)
3299 int i=0;
3301 for (i = 0; i < ARRAY_SIZE(notify_info_data_table); i++) {
3302 if ( (notify_info_data_table[i].type == type) &&
3303 (notify_info_data_table[i].field == field) ) {
3304 return notify_info_data_table[i].variable_type;
3308 DEBUG(5, ("invalid notify data type %d/%d\n", type, field));
3310 return 0;
3313 /****************************************************************************
3314 ****************************************************************************/
3316 static bool search_notify(enum spoolss_NotifyType type,
3317 uint16_t field,
3318 int *value)
3320 int i;
3322 for (i = 0; i < ARRAY_SIZE(notify_info_data_table); i++) {
3323 if (notify_info_data_table[i].type == type &&
3324 notify_info_data_table[i].field == field &&
3325 notify_info_data_table[i].fn != NULL) {
3326 *value = i;
3327 return true;
3331 return false;
3334 /****************************************************************************
3335 ****************************************************************************/
3337 void construct_info_data(struct spoolss_Notify *info_data,
3338 enum spoolss_NotifyType type,
3339 uint16_t field,
3340 int id)
3342 info_data->type = type;
3343 info_data->field.field = field;
3344 info_data->variable_type = variable_type_of_notify_info_data(type, field);
3345 info_data->job_id = id;
3348 /*******************************************************************
3350 * fill a notify_info struct with info asked
3352 ********************************************************************/
3354 static bool construct_notify_printer_info(Printer_entry *print_hnd,
3355 struct spoolss_NotifyInfo *info,
3356 int snum,
3357 const struct spoolss_NotifyOptionType *option_type,
3358 uint32_t id,
3359 TALLOC_CTX *mem_ctx)
3361 int field_num,j;
3362 enum spoolss_NotifyType type;
3363 uint16_t field;
3365 struct spoolss_Notify *current_data;
3366 NT_PRINTER_INFO_LEVEL *printer = NULL;
3367 print_queue_struct *queue=NULL;
3369 type = option_type->type;
3371 DEBUG(4,("construct_notify_printer_info: Notify type: [%s], number of notify info: [%d] on printer: [%s]\n",
3372 (type == PRINTER_NOTIFY_TYPE ? "PRINTER_NOTIFY_TYPE" : "JOB_NOTIFY_TYPE"),
3373 option_type->count, lp_servicename(snum)));
3375 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &printer, 2, lp_const_servicename(snum))))
3376 return false;
3378 for(field_num=0; field_num < option_type->count; field_num++) {
3379 field = option_type->fields[field_num].field;
3381 DEBUG(4,("construct_notify_printer_info: notify [%d]: type [%x], field [%x]\n", field_num, type, field));
3383 if (!search_notify(type, field, &j) )
3384 continue;
3386 info->notifies = TALLOC_REALLOC_ARRAY(info, info->notifies,
3387 struct spoolss_Notify,
3388 info->count + 1);
3389 if (info->notifies == NULL) {
3390 DEBUG(2,("construct_notify_printer_info: failed to enlarge buffer info->data!\n"));
3391 free_a_printer(&printer, 2);
3392 return false;
3395 current_data = &info->notifies[info->count];
3397 construct_info_data(current_data, type, field, id);
3399 DEBUG(10,("construct_notify_printer_info: calling [%s] snum=%d printername=[%s])\n",
3400 notify_info_data_table[j].name, snum, printer->info_2->printername ));
3402 notify_info_data_table[j].fn(snum, current_data, queue,
3403 printer, mem_ctx);
3405 info->count++;
3408 free_a_printer(&printer, 2);
3409 return true;
3412 /*******************************************************************
3414 * fill a notify_info struct with info asked
3416 ********************************************************************/
3418 static bool construct_notify_jobs_info(print_queue_struct *queue,
3419 struct spoolss_NotifyInfo *info,
3420 NT_PRINTER_INFO_LEVEL *printer,
3421 int snum,
3422 const struct spoolss_NotifyOptionType *option_type,
3423 uint32_t id,
3424 TALLOC_CTX *mem_ctx)
3426 int field_num,j;
3427 enum spoolss_NotifyType type;
3428 uint16_t field;
3429 struct spoolss_Notify *current_data;
3431 DEBUG(4,("construct_notify_jobs_info\n"));
3433 type = option_type->type;
3435 DEBUGADD(4,("Notify type: [%s], number of notify info: [%d]\n",
3436 (type == PRINTER_NOTIFY_TYPE ? "PRINTER_NOTIFY_TYPE" : "JOB_NOTIFY_TYPE"),
3437 option_type->count));
3439 for(field_num=0; field_num<option_type->count; field_num++) {
3440 field = option_type->fields[field_num].field;
3442 if (!search_notify(type, field, &j) )
3443 continue;
3445 info->notifies = TALLOC_REALLOC_ARRAY(info, info->notifies,
3446 struct spoolss_Notify,
3447 info->count + 1);
3448 if (info->notifies == NULL) {
3449 DEBUG(2,("construct_notify_jobs_info: failed to enlarg buffer info->data!\n"));
3450 return false;
3453 current_data=&(info->notifies[info->count]);
3455 construct_info_data(current_data, type, field, id);
3456 notify_info_data_table[j].fn(snum, current_data, queue,
3457 printer, mem_ctx);
3458 info->count++;
3461 return true;
3465 * JFM: The enumeration is not that simple, it's even non obvious.
3467 * let's take an example: I want to monitor the PRINTER SERVER for
3468 * the printer's name and the number of jobs currently queued.
3469 * So in the NOTIFY_OPTION, I have one NOTIFY_OPTION_TYPE structure.
3470 * Its type is PRINTER_NOTIFY_TYPE and it has 2 fields NAME and CJOBS.
3472 * I have 3 printers on the back of my server.
3474 * Now the response is a NOTIFY_INFO structure, with 6 NOTIFY_INFO_DATA
3475 * structures.
3476 * Number Data Id
3477 * 1 printer 1 name 1
3478 * 2 printer 1 cjob 1
3479 * 3 printer 2 name 2
3480 * 4 printer 2 cjob 2
3481 * 5 printer 3 name 3
3482 * 6 printer 3 name 3
3484 * that's the print server case, the printer case is even worse.
3487 /*******************************************************************
3489 * enumerate all printers on the printserver
3490 * fill a notify_info struct with info asked
3492 ********************************************************************/
3494 static WERROR printserver_notify_info(pipes_struct *p,
3495 struct policy_handle *hnd,
3496 struct spoolss_NotifyInfo *info,
3497 TALLOC_CTX *mem_ctx)
3499 int snum;
3500 Printer_entry *Printer = find_printer_index_by_hnd(p, hnd);
3501 int n_services=lp_numservices();
3502 int i;
3503 struct spoolss_NotifyOption *option;
3504 struct spoolss_NotifyOptionType option_type;
3506 DEBUG(4,("printserver_notify_info\n"));
3508 if (!Printer)
3509 return WERR_BADFID;
3511 option = Printer->notify.option;
3513 info->version = 2;
3514 info->notifies = NULL;
3515 info->count = 0;
3517 /* a bug in xp sp2 rc2 causes it to send a fnpcn request without
3518 sending a ffpcn() request first */
3520 if ( !option )
3521 return WERR_BADFID;
3523 for (i=0; i<option->count; i++) {
3524 option_type = option->types[i];
3526 if (option_type.type != PRINTER_NOTIFY_TYPE)
3527 continue;
3529 for (snum=0; snum<n_services; snum++)
3531 if ( lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) )
3532 construct_notify_printer_info ( Printer, info, snum, &option_type, snum, mem_ctx );
3536 #if 0
3538 * Debugging information, don't delete.
3541 DEBUG(1,("dumping the NOTIFY_INFO\n"));
3542 DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
3543 DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3545 for (i=0; i<info->count; i++) {
3546 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3547 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
3548 info->data[i].id, info->data[i].size, info->data[i].enc_type));
3550 #endif
3552 return WERR_OK;
3555 /*******************************************************************
3557 * fill a notify_info struct with info asked
3559 ********************************************************************/
3561 static WERROR printer_notify_info(pipes_struct *p, struct policy_handle *hnd,
3562 struct spoolss_NotifyInfo *info,
3563 TALLOC_CTX *mem_ctx)
3565 int snum;
3566 Printer_entry *Printer = find_printer_index_by_hnd(p, hnd);
3567 int i;
3568 uint32_t id;
3569 struct spoolss_NotifyOption *option;
3570 struct spoolss_NotifyOptionType option_type;
3571 int count,j;
3572 print_queue_struct *queue=NULL;
3573 print_status_struct status;
3575 DEBUG(4,("printer_notify_info\n"));
3577 if (!Printer)
3578 return WERR_BADFID;
3580 option = Printer->notify.option;
3581 id = 0x0;
3583 info->version = 2;
3584 info->notifies = NULL;
3585 info->count = 0;
3587 /* a bug in xp sp2 rc2 causes it to send a fnpcn request without
3588 sending a ffpcn() request first */
3590 if ( !option )
3591 return WERR_BADFID;
3593 get_printer_snum(p, hnd, &snum, NULL);
3595 for (i=0; i<option->count; i++) {
3596 option_type = option->types[i];
3598 switch (option_type.type) {
3599 case PRINTER_NOTIFY_TYPE:
3600 if(construct_notify_printer_info(Printer, info, snum,
3601 &option_type, id,
3602 mem_ctx))
3603 id--;
3604 break;
3606 case JOB_NOTIFY_TYPE: {
3607 NT_PRINTER_INFO_LEVEL *printer = NULL;
3609 count = print_queue_status(snum, &queue, &status);
3611 if (!W_ERROR_IS_OK(get_a_printer(Printer, &printer, 2, lp_const_servicename(snum))))
3612 goto done;
3614 for (j=0; j<count; j++) {
3615 construct_notify_jobs_info(&queue[j], info,
3616 printer, snum,
3617 &option_type,
3618 queue[j].job,
3619 mem_ctx);
3622 free_a_printer(&printer, 2);
3624 done:
3625 SAFE_FREE(queue);
3626 break;
3632 * Debugging information, don't delete.
3635 DEBUG(1,("dumping the NOTIFY_INFO\n"));
3636 DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
3637 DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3639 for (i=0; i<info->count; i++) {
3640 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3641 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
3642 info->data[i].id, info->data[i].size, info->data[i].enc_type));
3645 return WERR_OK;
3648 /****************************************************************
3649 _spoolss_RouterRefreshPrinterChangeNotify
3650 ****************************************************************/
3652 WERROR _spoolss_RouterRefreshPrinterChangeNotify(pipes_struct *p,
3653 struct spoolss_RouterRefreshPrinterChangeNotify *r)
3655 struct spoolss_NotifyInfo *info;
3657 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
3658 WERROR result = WERR_BADFID;
3660 /* we always have a spoolss_NotifyInfo struct */
3661 info = talloc_zero(p->mem_ctx, struct spoolss_NotifyInfo);
3662 if (!info) {
3663 result = WERR_NOMEM;
3664 goto done;
3667 *r->out.info = info;
3669 if (!Printer) {
3670 DEBUG(2,("_spoolss_RouterRefreshPrinterChangeNotify: "
3671 "Invalid handle (%s:%u:%u).\n",
3672 OUR_HANDLE(r->in.handle)));
3673 goto done;
3676 DEBUG(4,("Printer type %x\n",Printer->printer_type));
3679 * We are now using the change value, and
3680 * I should check for PRINTER_NOTIFY_OPTIONS_REFRESH but as
3681 * I don't have a global notification system, I'm sending back all the
3682 * informations even when _NOTHING_ has changed.
3685 /* We need to keep track of the change value to send back in
3686 RRPCN replies otherwise our updates are ignored. */
3688 Printer->notify.fnpcn = true;
3690 if (Printer->notify.client_connected) {
3691 DEBUG(10,("_spoolss_RouterRefreshPrinterChangeNotify: "
3692 "Saving change value in request [%x]\n",
3693 r->in.change_low));
3694 Printer->notify.change = r->in.change_low;
3697 /* just ignore the spoolss_NotifyOption */
3699 switch (Printer->printer_type) {
3700 case SPLHND_SERVER:
3701 result = printserver_notify_info(p, r->in.handle,
3702 info, p->mem_ctx);
3703 break;
3705 case SPLHND_PRINTER:
3706 result = printer_notify_info(p, r->in.handle,
3707 info, p->mem_ctx);
3708 break;
3711 Printer->notify.fnpcn = false;
3713 done:
3714 return result;
3717 /********************************************************************
3718 * construct_printer_info_0
3719 * fill a printer_info_0 struct
3720 ********************************************************************/
3722 static WERROR construct_printer_info0(TALLOC_CTX *mem_ctx,
3723 const NT_PRINTER_INFO_LEVEL *ntprinter,
3724 struct spoolss_PrinterInfo0 *r,
3725 int snum)
3727 int count;
3728 counter_printer_0 *session_counter;
3729 time_t setuptime;
3730 print_status_struct status;
3732 r->printername = talloc_strdup(mem_ctx, ntprinter->info_2->printername);
3733 W_ERROR_HAVE_NO_MEMORY(r->printername);
3735 r->servername = talloc_strdup(mem_ctx, ntprinter->info_2->servername);
3736 W_ERROR_HAVE_NO_MEMORY(r->servername);
3738 count = print_queue_length(snum, &status);
3740 /* check if we already have a counter for this printer */
3741 for (session_counter = counter_list; session_counter; session_counter = session_counter->next) {
3742 if (session_counter->snum == snum)
3743 break;
3746 /* it's the first time, add it to the list */
3747 if (session_counter == NULL) {
3748 session_counter = SMB_MALLOC_P(counter_printer_0);
3749 W_ERROR_HAVE_NO_MEMORY(session_counter);
3750 ZERO_STRUCTP(session_counter);
3751 session_counter->snum = snum;
3752 session_counter->counter = 0;
3753 DLIST_ADD(counter_list, session_counter);
3756 /* increment it */
3757 session_counter->counter++;
3759 r->cjobs = count;
3760 r->total_jobs = 0;
3761 r->total_bytes = 0;
3763 setuptime = (time_t)ntprinter->info_2->setuptime;
3765 init_systemtime(&r->time, gmtime(&setuptime));
3767 /* JFM:
3768 * the global_counter should be stored in a TDB as it's common to all the clients
3769 * and should be zeroed on samba startup
3771 r->global_counter = session_counter->counter;
3772 r->total_pages = 0;
3773 /* in 2.2 we reported ourselves as 0x0004 and 0x0565 */
3774 r->version = 0x0005; /* NT 5 */
3775 r->free_build = 0x0893; /* build 2195 */
3776 r->spooling = 0;
3777 r->max_spooling = 0;
3778 r->session_counter = session_counter->counter;
3779 r->num_error_out_of_paper = 0x0;
3780 r->num_error_not_ready = 0x0; /* number of print failure */
3781 r->job_error = 0x0;
3782 r->number_of_processors = 0x1;
3783 r->processor_type = PROCESSOR_INTEL_PENTIUM; /* 586 Pentium ? */
3784 r->high_part_total_bytes = 0x0;
3785 r->change_id = ntprinter->info_2->changeid; /* ChangeID in milliseconds*/
3786 r->last_error = WERR_OK;
3787 r->status = nt_printq_status(status.status);
3788 r->enumerate_network_printers = 0x0;
3789 r->c_setprinter = get_c_setprinter(); /* monotonically increasing sum of delta printer counts */
3790 r->processor_architecture = 0x0;
3791 r->processor_level = 0x6; /* 6 ???*/
3792 r->ref_ic = 0;
3793 r->reserved2 = 0;
3794 r->reserved3 = 0;
3796 return WERR_OK;
3799 /****************************************************************************
3800 Convert an NT_DEVICEMODE to a spoolss_DeviceMode structure. Both pointers
3801 should be valid upon entry
3802 ****************************************************************************/
3804 static WERROR convert_nt_devicemode(TALLOC_CTX *mem_ctx,
3805 struct spoolss_DeviceMode *r,
3806 const NT_DEVICEMODE *ntdevmode)
3808 if (!r || !ntdevmode) {
3809 return WERR_INVALID_PARAM;
3812 r->devicename = talloc_strdup(mem_ctx, ntdevmode->devicename);
3813 W_ERROR_HAVE_NO_MEMORY(r->devicename);
3815 r->specversion = ntdevmode->specversion;
3816 r->driverversion = ntdevmode->driverversion;
3817 r->size = ntdevmode->size;
3818 r->__driverextra_length = ntdevmode->driverextra;
3819 r->fields = ntdevmode->fields;
3821 r->orientation = ntdevmode->orientation;
3822 r->papersize = ntdevmode->papersize;
3823 r->paperlength = ntdevmode->paperlength;
3824 r->paperwidth = ntdevmode->paperwidth;
3825 r->scale = ntdevmode->scale;
3826 r->copies = ntdevmode->copies;
3827 r->defaultsource = ntdevmode->defaultsource;
3828 r->printquality = ntdevmode->printquality;
3829 r->color = ntdevmode->color;
3830 r->duplex = ntdevmode->duplex;
3831 r->yresolution = ntdevmode->yresolution;
3832 r->ttoption = ntdevmode->ttoption;
3833 r->collate = ntdevmode->collate;
3835 r->formname = talloc_strdup(mem_ctx, ntdevmode->formname);
3836 W_ERROR_HAVE_NO_MEMORY(r->formname);
3838 /* all 0 below are values that have not been set in the old parsing/copy
3839 * function, maybe they should... - gd */
3841 r->logpixels = 0;
3842 r->bitsperpel = 0;
3843 r->pelswidth = 0;
3844 r->pelsheight = 0;
3845 r->displayflags = 0;
3846 r->displayfrequency = 0;
3847 r->icmmethod = ntdevmode->icmmethod;
3848 r->icmintent = ntdevmode->icmintent;
3849 r->mediatype = ntdevmode->mediatype;
3850 r->dithertype = ntdevmode->dithertype;
3851 r->reserved1 = 0;
3852 r->reserved2 = 0;
3853 r->panningwidth = 0;
3854 r->panningheight = 0;
3856 if (ntdevmode->nt_dev_private != NULL) {
3857 r->driverextra_data = data_blob_talloc(mem_ctx,
3858 ntdevmode->nt_dev_private,
3859 ntdevmode->driverextra);
3860 W_ERROR_HAVE_NO_MEMORY(r->driverextra_data.data);
3863 return WERR_OK;
3867 /****************************************************************************
3868 Create a spoolss_DeviceMode struct. Returns talloced memory.
3869 ****************************************************************************/
3871 struct spoolss_DeviceMode *construct_dev_mode(TALLOC_CTX *mem_ctx,
3872 const char *servicename)
3874 WERROR result;
3875 NT_PRINTER_INFO_LEVEL *printer = NULL;
3876 struct spoolss_DeviceMode *devmode = NULL;
3878 DEBUG(7,("construct_dev_mode\n"));
3880 DEBUGADD(8,("getting printer characteristics\n"));
3882 if (!W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, servicename)))
3883 return NULL;
3885 if (!printer->info_2->devmode) {
3886 DEBUG(5, ("BONG! There was no device mode!\n"));
3887 goto done;
3890 devmode = TALLOC_ZERO_P(mem_ctx, struct spoolss_DeviceMode);
3891 if (!devmode) {
3892 DEBUG(2,("construct_dev_mode: talloc fail.\n"));
3893 goto done;
3896 DEBUGADD(8,("loading DEVICEMODE\n"));
3898 result = convert_nt_devicemode(mem_ctx, devmode, printer->info_2->devmode);
3899 if (!W_ERROR_IS_OK(result)) {
3900 TALLOC_FREE(devmode);
3903 done:
3904 free_a_printer(&printer,2);
3906 return devmode;
3909 /********************************************************************
3910 * construct_printer_info3
3911 * fill a spoolss_PrinterInfo3 struct
3912 ********************************************************************/
3914 static WERROR construct_printer_info3(TALLOC_CTX *mem_ctx,
3915 const NT_PRINTER_INFO_LEVEL *ntprinter,
3916 struct spoolss_PrinterInfo3 *r,
3917 int snum)
3919 /* These are the components of the SD we are returning. */
3921 if (ntprinter->info_2->secdesc_buf && ntprinter->info_2->secdesc_buf->sd_size != 0) {
3922 /* don't use talloc_steal() here unless you do a deep steal of all
3923 the SEC_DESC members */
3925 r->secdesc = dup_sec_desc(mem_ctx,
3926 ntprinter->info_2->secdesc_buf->sd);
3927 W_ERROR_HAVE_NO_MEMORY(r->secdesc);
3930 return WERR_OK;
3933 /********************************************************************
3934 * construct_printer_info4
3935 * fill a spoolss_PrinterInfo4 struct
3936 ********************************************************************/
3938 static WERROR construct_printer_info4(TALLOC_CTX *mem_ctx,
3939 const NT_PRINTER_INFO_LEVEL *ntprinter,
3940 struct spoolss_PrinterInfo4 *r,
3941 int snum)
3943 r->printername = talloc_strdup(mem_ctx, ntprinter->info_2->printername);
3944 W_ERROR_HAVE_NO_MEMORY(r->printername);
3945 r->servername = talloc_strdup(mem_ctx, ntprinter->info_2->servername);
3946 W_ERROR_HAVE_NO_MEMORY(r->servername);
3948 r->attributes = ntprinter->info_2->attributes;
3950 return WERR_OK;
3953 /********************************************************************
3954 * construct_printer_info5
3955 * fill a spoolss_PrinterInfo5 struct
3956 ********************************************************************/
3958 static WERROR construct_printer_info5(TALLOC_CTX *mem_ctx,
3959 const NT_PRINTER_INFO_LEVEL *ntprinter,
3960 struct spoolss_PrinterInfo5 *r,
3961 int snum)
3963 r->printername = talloc_strdup(mem_ctx, ntprinter->info_2->printername);
3964 W_ERROR_HAVE_NO_MEMORY(r->printername);
3965 r->portname = talloc_strdup(mem_ctx, ntprinter->info_2->portname);
3966 W_ERROR_HAVE_NO_MEMORY(r->portname);
3968 r->attributes = ntprinter->info_2->attributes;
3970 /* these two are not used by NT+ according to MSDN */
3972 r->device_not_selected_timeout = 0x0; /* have seen 0x3a98 */
3973 r->transmission_retry_timeout = 0x0; /* have seen 0xafc8 */
3975 return WERR_OK;
3978 /********************************************************************
3979 * construct_printer_info_6
3980 * fill a spoolss_PrinterInfo6 struct
3981 ********************************************************************/
3983 static WERROR construct_printer_info6(TALLOC_CTX *mem_ctx,
3984 const NT_PRINTER_INFO_LEVEL *ntprinter,
3985 struct spoolss_PrinterInfo6 *r,
3986 int snum)
3988 int count;
3989 print_status_struct status;
3991 count = print_queue_length(snum, &status);
3993 r->status = nt_printq_status(status.status);
3995 return WERR_OK;
3998 /********************************************************************
3999 * construct_printer_info7
4000 * fill a spoolss_PrinterInfo7 struct
4001 ********************************************************************/
4003 static WERROR construct_printer_info7(TALLOC_CTX *mem_ctx,
4004 Printer_entry *print_hnd,
4005 struct spoolss_PrinterInfo7 *r,
4006 int snum)
4008 struct GUID guid;
4010 if (is_printer_published(print_hnd, snum, &guid)) {
4011 r->guid = talloc_strdup_upper(mem_ctx, GUID_string2(mem_ctx, &guid));
4012 r->action = DSPRINT_PUBLISH;
4013 } else {
4014 r->guid = talloc_strdup(mem_ctx, "");
4015 r->action = DSPRINT_UNPUBLISH;
4017 W_ERROR_HAVE_NO_MEMORY(r->guid);
4019 return WERR_OK;
4022 /********************************************************************
4023 * construct_printer_info8
4024 * fill a spoolss_PrinterInfo8 struct
4025 ********************************************************************/
4027 static WERROR construct_printer_info8(TALLOC_CTX *mem_ctx,
4028 const NT_PRINTER_INFO_LEVEL *ntprinter,
4029 struct spoolss_DeviceModeInfo *r,
4030 int snum)
4032 struct spoolss_DeviceMode *devmode;
4033 WERROR result;
4035 if (!ntprinter->info_2->devmode) {
4036 r->devmode = NULL;
4037 return WERR_OK;
4040 devmode = TALLOC_ZERO_P(mem_ctx, struct spoolss_DeviceMode);
4041 W_ERROR_HAVE_NO_MEMORY(devmode);
4043 result = convert_nt_devicemode(mem_ctx, devmode, ntprinter->info_2->devmode);
4044 if (!W_ERROR_IS_OK(result)) {
4045 TALLOC_FREE(devmode);
4046 return result;
4049 r->devmode = devmode;
4051 return WERR_OK;
4055 /********************************************************************
4056 * construct_printer_info1
4057 * fill a spoolss_PrinterInfo1 struct
4058 ********************************************************************/
4060 static WERROR construct_printer_info1(TALLOC_CTX *mem_ctx,
4061 const NT_PRINTER_INFO_LEVEL *ntprinter,
4062 uint32_t flags,
4063 struct spoolss_PrinterInfo1 *r,
4064 int snum)
4066 r->flags = flags;
4068 r->description = talloc_asprintf(mem_ctx, "%s,%s,%s",
4069 ntprinter->info_2->printername,
4070 ntprinter->info_2->drivername,
4071 ntprinter->info_2->location);
4072 W_ERROR_HAVE_NO_MEMORY(r->description);
4074 if (*ntprinter->info_2->comment == '\0') {
4075 r->comment = talloc_strdup(mem_ctx, lp_comment(snum));
4076 } else {
4077 r->comment = talloc_strdup(mem_ctx, ntprinter->info_2->comment); /* saved comment */
4079 W_ERROR_HAVE_NO_MEMORY(r->comment);
4081 r->name = talloc_strdup(mem_ctx, ntprinter->info_2->printername);
4082 W_ERROR_HAVE_NO_MEMORY(r->name);
4084 return WERR_OK;
4087 /********************************************************************
4088 * construct_printer_info2
4089 * fill a spoolss_PrinterInfo2 struct
4090 ********************************************************************/
4092 static WERROR construct_printer_info2(TALLOC_CTX *mem_ctx,
4093 const NT_PRINTER_INFO_LEVEL *ntprinter,
4094 struct spoolss_PrinterInfo2 *r,
4095 int snum)
4097 int count;
4099 print_status_struct status;
4101 count = print_queue_length(snum, &status);
4103 r->servername = talloc_strdup(mem_ctx, ntprinter->info_2->servername);
4104 W_ERROR_HAVE_NO_MEMORY(r->servername);
4105 r->printername = talloc_strdup(mem_ctx, ntprinter->info_2->printername);
4106 W_ERROR_HAVE_NO_MEMORY(r->printername);
4107 r->sharename = talloc_strdup(mem_ctx, lp_servicename(snum));
4108 W_ERROR_HAVE_NO_MEMORY(r->sharename);
4109 r->portname = talloc_strdup(mem_ctx, ntprinter->info_2->portname);
4110 W_ERROR_HAVE_NO_MEMORY(r->portname);
4111 r->drivername = talloc_strdup(mem_ctx, ntprinter->info_2->drivername);
4112 W_ERROR_HAVE_NO_MEMORY(r->drivername);
4114 if (*ntprinter->info_2->comment == '\0') {
4115 r->comment = talloc_strdup(mem_ctx, lp_comment(snum));
4116 } else {
4117 r->comment = talloc_strdup(mem_ctx, ntprinter->info_2->comment);
4119 W_ERROR_HAVE_NO_MEMORY(r->comment);
4121 r->location = talloc_strdup(mem_ctx, ntprinter->info_2->location);
4122 W_ERROR_HAVE_NO_MEMORY(r->location);
4123 r->sepfile = talloc_strdup(mem_ctx, ntprinter->info_2->sepfile);
4124 W_ERROR_HAVE_NO_MEMORY(r->sepfile);
4125 r->printprocessor = talloc_strdup(mem_ctx, ntprinter->info_2->printprocessor);
4126 W_ERROR_HAVE_NO_MEMORY(r->printprocessor);
4127 r->datatype = talloc_strdup(mem_ctx, ntprinter->info_2->datatype);
4128 W_ERROR_HAVE_NO_MEMORY(r->datatype);
4129 r->parameters = talloc_strdup(mem_ctx, ntprinter->info_2->parameters);
4130 W_ERROR_HAVE_NO_MEMORY(r->parameters);
4132 r->attributes = ntprinter->info_2->attributes;
4134 r->priority = ntprinter->info_2->priority;
4135 r->defaultpriority = ntprinter->info_2->default_priority;
4136 r->starttime = ntprinter->info_2->starttime;
4137 r->untiltime = ntprinter->info_2->untiltime;
4138 r->status = nt_printq_status(status.status);
4139 r->cjobs = count;
4140 r->averageppm = ntprinter->info_2->averageppm;
4142 r->devmode = construct_dev_mode(mem_ctx, lp_const_servicename(snum));
4143 if (!r->devmode) {
4144 DEBUG(8,("Returning NULL Devicemode!\n"));
4147 r->secdesc = NULL;
4149 if (ntprinter->info_2->secdesc_buf && ntprinter->info_2->secdesc_buf->sd_size != 0) {
4150 /* don't use talloc_steal() here unless you do a deep steal of all
4151 the SEC_DESC members */
4153 r->secdesc = dup_sec_desc(mem_ctx, ntprinter->info_2->secdesc_buf->sd);
4156 return WERR_OK;
4159 /********************************************************************
4160 ********************************************************************/
4162 static bool snum_is_shared_printer(int snum)
4164 return (lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum));
4167 /********************************************************************
4168 Spoolss_enumprinters.
4169 ********************************************************************/
4171 static WERROR enum_all_printers_info_level(TALLOC_CTX *mem_ctx,
4172 uint32_t level,
4173 uint32_t flags,
4174 union spoolss_PrinterInfo **info_p,
4175 uint32_t *count_p)
4177 int snum;
4178 int n_services = lp_numservices();
4179 union spoolss_PrinterInfo *info = NULL;
4180 uint32_t count = 0;
4181 WERROR result = WERR_OK;
4183 *count_p = 0;
4184 *info_p = NULL;
4186 for (snum = 0; snum < n_services; snum++) {
4188 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4190 if (!snum_is_shared_printer(snum)) {
4191 continue;
4194 DEBUG(4,("Found a printer in smb.conf: %s[%x]\n",
4195 lp_servicename(snum), snum));
4197 info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
4198 union spoolss_PrinterInfo,
4199 count + 1);
4200 if (!info) {
4201 result = WERR_NOMEM;
4202 goto out;
4205 result = get_a_printer(NULL, &ntprinter, 2,
4206 lp_const_servicename(snum));
4207 if (!W_ERROR_IS_OK(result)) {
4208 goto out;
4211 switch (level) {
4212 case 0:
4213 result = construct_printer_info0(info, ntprinter,
4214 &info[count].info0, snum);
4215 break;
4216 case 1:
4217 result = construct_printer_info1(info, ntprinter, flags,
4218 &info[count].info1, snum);
4219 break;
4220 case 2:
4221 result = construct_printer_info2(info, ntprinter,
4222 &info[count].info2, snum);
4223 break;
4224 case 4:
4225 result = construct_printer_info4(info, ntprinter,
4226 &info[count].info4, snum);
4227 break;
4228 case 5:
4229 result = construct_printer_info5(info, ntprinter,
4230 &info[count].info5, snum);
4231 break;
4233 default:
4234 result = WERR_UNKNOWN_LEVEL;
4235 free_a_printer(&ntprinter, 2);
4236 goto out;
4239 free_a_printer(&ntprinter, 2);
4240 if (!W_ERROR_IS_OK(result)) {
4241 goto out;
4244 count++;
4247 *count_p = count;
4248 *info_p = info;
4250 out:
4251 if (!W_ERROR_IS_OK(result)) {
4252 TALLOC_FREE(info);
4253 return result;
4256 *info_p = info;
4258 return WERR_OK;
4261 /********************************************************************
4262 * handle enumeration of printers at level 0
4263 ********************************************************************/
4265 static WERROR enumprinters_level0(TALLOC_CTX *mem_ctx,
4266 uint32_t flags,
4267 const char *servername,
4268 union spoolss_PrinterInfo **info,
4269 uint32_t *count)
4271 DEBUG(4,("enum_all_printers_info_0\n"));
4273 return enum_all_printers_info_level(mem_ctx, 0, flags, info, count);
4277 /********************************************************************
4278 ********************************************************************/
4280 static WERROR enum_all_printers_info_1(TALLOC_CTX *mem_ctx,
4281 uint32_t flags,
4282 union spoolss_PrinterInfo **info,
4283 uint32_t *count)
4285 DEBUG(4,("enum_all_printers_info_1\n"));
4287 return enum_all_printers_info_level(mem_ctx, 1, flags, info, count);
4290 /********************************************************************
4291 enum_all_printers_info_1_local.
4292 *********************************************************************/
4294 static WERROR enum_all_printers_info_1_local(TALLOC_CTX *mem_ctx,
4295 union spoolss_PrinterInfo **info,
4296 uint32_t *count)
4298 DEBUG(4,("enum_all_printers_info_1_local\n"));
4300 return enum_all_printers_info_1(mem_ctx, PRINTER_ENUM_ICON8, info, count);
4303 /********************************************************************
4304 enum_all_printers_info_1_name.
4305 *********************************************************************/
4307 static WERROR enum_all_printers_info_1_name(TALLOC_CTX *mem_ctx,
4308 const char *name,
4309 union spoolss_PrinterInfo **info,
4310 uint32_t *count)
4312 const char *s = name;
4314 DEBUG(4,("enum_all_printers_info_1_name\n"));
4316 if ((name[0] == '\\') && (name[1] == '\\')) {
4317 s = name + 2;
4320 if (!is_myname_or_ipaddr(s)) {
4321 return WERR_INVALID_NAME;
4324 return enum_all_printers_info_1(mem_ctx, PRINTER_ENUM_ICON8, info, count);
4327 /********************************************************************
4328 enum_all_printers_info_1_network.
4329 *********************************************************************/
4331 static WERROR enum_all_printers_info_1_network(TALLOC_CTX *mem_ctx,
4332 const char *name,
4333 union spoolss_PrinterInfo **info,
4334 uint32_t *count)
4336 const char *s = name;
4338 DEBUG(4,("enum_all_printers_info_1_network\n"));
4340 /* If we respond to a enum_printers level 1 on our name with flags
4341 set to PRINTER_ENUM_REMOTE with a list of printers then these
4342 printers incorrectly appear in the APW browse list.
4343 Specifically the printers for the server appear at the workgroup
4344 level where all the other servers in the domain are
4345 listed. Windows responds to this call with a
4346 WERR_CAN_NOT_COMPLETE so we should do the same. */
4348 if (name[0] == '\\' && name[1] == '\\') {
4349 s = name + 2;
4352 if (is_myname_or_ipaddr(s)) {
4353 return WERR_CAN_NOT_COMPLETE;
4356 return enum_all_printers_info_1(mem_ctx, PRINTER_ENUM_NAME, info, count);
4359 /********************************************************************
4360 * api_spoolss_enumprinters
4362 * called from api_spoolss_enumprinters (see this to understand)
4363 ********************************************************************/
4365 static WERROR enum_all_printers_info_2(TALLOC_CTX *mem_ctx,
4366 union spoolss_PrinterInfo **info,
4367 uint32_t *count)
4369 DEBUG(4,("enum_all_printers_info_2\n"));
4371 return enum_all_printers_info_level(mem_ctx, 2, 0, info, count);
4374 /********************************************************************
4375 * handle enumeration of printers at level 1
4376 ********************************************************************/
4378 static WERROR enumprinters_level1(TALLOC_CTX *mem_ctx,
4379 uint32_t flags,
4380 const char *name,
4381 union spoolss_PrinterInfo **info,
4382 uint32_t *count)
4384 /* Not all the flags are equals */
4386 if (flags & PRINTER_ENUM_LOCAL) {
4387 return enum_all_printers_info_1_local(mem_ctx, info, count);
4390 if (flags & PRINTER_ENUM_NAME) {
4391 return enum_all_printers_info_1_name(mem_ctx, name, info, count);
4394 if (flags & PRINTER_ENUM_NETWORK) {
4395 return enum_all_printers_info_1_network(mem_ctx, name, info, count);
4398 return WERR_OK; /* NT4sp5 does that */
4401 /********************************************************************
4402 * handle enumeration of printers at level 2
4403 ********************************************************************/
4405 static WERROR enumprinters_level2(TALLOC_CTX *mem_ctx,
4406 uint32_t flags,
4407 const char *servername,
4408 union spoolss_PrinterInfo **info,
4409 uint32_t *count)
4411 if (flags & PRINTER_ENUM_LOCAL) {
4412 return enum_all_printers_info_2(mem_ctx, info, count);
4415 if (flags & PRINTER_ENUM_NAME) {
4416 if (!is_myname_or_ipaddr(canon_servername(servername))) {
4417 return WERR_INVALID_NAME;
4420 return enum_all_printers_info_2(mem_ctx, info, count);
4423 if (flags & PRINTER_ENUM_REMOTE) {
4424 return WERR_UNKNOWN_LEVEL;
4427 return WERR_OK;
4430 /********************************************************************
4431 * handle enumeration of printers at level 4
4432 ********************************************************************/
4434 static WERROR enumprinters_level4(TALLOC_CTX *mem_ctx,
4435 uint32_t flags,
4436 const char *servername,
4437 union spoolss_PrinterInfo **info,
4438 uint32_t *count)
4440 DEBUG(4,("enum_all_printers_info_4\n"));
4442 return enum_all_printers_info_level(mem_ctx, 4, flags, info, count);
4446 /********************************************************************
4447 * handle enumeration of printers at level 5
4448 ********************************************************************/
4450 static WERROR enumprinters_level5(TALLOC_CTX *mem_ctx,
4451 uint32_t flags,
4452 const char *servername,
4453 union spoolss_PrinterInfo **info,
4454 uint32_t *count)
4456 DEBUG(4,("enum_all_printers_info_5\n"));
4458 return enum_all_printers_info_level(mem_ctx, 5, flags, info, count);
4461 /****************************************************************
4462 _spoolss_EnumPrinters
4463 ****************************************************************/
4465 WERROR _spoolss_EnumPrinters(pipes_struct *p,
4466 struct spoolss_EnumPrinters *r)
4468 const char *name = NULL;
4469 WERROR result;
4471 /* that's an [in out] buffer */
4473 if (!r->in.buffer && (r->in.offered != 0)) {
4474 return WERR_INVALID_PARAM;
4477 DEBUG(4,("_spoolss_EnumPrinters\n"));
4479 *r->out.needed = 0;
4480 *r->out.count = 0;
4481 *r->out.info = NULL;
4484 * Level 1:
4485 * flags==PRINTER_ENUM_NAME
4486 * if name=="" then enumerates all printers
4487 * if name!="" then enumerate the printer
4488 * flags==PRINTER_ENUM_REMOTE
4489 * name is NULL, enumerate printers
4490 * Level 2: name!="" enumerates printers, name can't be NULL
4491 * Level 3: doesn't exist
4492 * Level 4: does a local registry lookup
4493 * Level 5: same as Level 2
4496 if (r->in.server) {
4497 name = talloc_strdup_upper(p->mem_ctx, r->in.server);
4498 W_ERROR_HAVE_NO_MEMORY(name);
4501 switch (r->in.level) {
4502 case 0:
4503 result = enumprinters_level0(p->mem_ctx, r->in.flags, name,
4504 r->out.info, r->out.count);
4505 break;
4506 case 1:
4507 result = enumprinters_level1(p->mem_ctx, r->in.flags, name,
4508 r->out.info, r->out.count);
4509 break;
4510 case 2:
4511 result = enumprinters_level2(p->mem_ctx, r->in.flags, name,
4512 r->out.info, r->out.count);
4513 break;
4514 case 4:
4515 result = enumprinters_level4(p->mem_ctx, r->in.flags, name,
4516 r->out.info, r->out.count);
4517 break;
4518 case 5:
4519 result = enumprinters_level5(p->mem_ctx, r->in.flags, name,
4520 r->out.info, r->out.count);
4521 break;
4522 default:
4523 return WERR_UNKNOWN_LEVEL;
4526 if (!W_ERROR_IS_OK(result)) {
4527 return result;
4530 *r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
4531 spoolss_EnumPrinters, NULL,
4532 *r->out.info, r->in.level,
4533 *r->out.count);
4534 *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
4535 *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, 0);
4537 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
4540 /****************************************************************
4541 _spoolss_GetPrinter
4542 ****************************************************************/
4544 WERROR _spoolss_GetPrinter(pipes_struct *p,
4545 struct spoolss_GetPrinter *r)
4547 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
4548 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4549 WERROR result = WERR_OK;
4551 int snum;
4553 /* that's an [in out] buffer */
4555 if (!r->in.buffer && (r->in.offered != 0)) {
4556 return WERR_INVALID_PARAM;
4559 *r->out.needed = 0;
4561 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
4562 return WERR_BADFID;
4565 result = get_a_printer(Printer, &ntprinter, 2,
4566 lp_const_servicename(snum));
4567 if (!W_ERROR_IS_OK(result)) {
4568 return result;
4571 switch (r->in.level) {
4572 case 0:
4573 result = construct_printer_info0(p->mem_ctx, ntprinter,
4574 &r->out.info->info0, snum);
4575 break;
4576 case 1:
4577 result = construct_printer_info1(p->mem_ctx, ntprinter,
4578 PRINTER_ENUM_ICON8,
4579 &r->out.info->info1, snum);
4580 break;
4581 case 2:
4582 result = construct_printer_info2(p->mem_ctx, ntprinter,
4583 &r->out.info->info2, snum);
4584 break;
4585 case 3:
4586 result = construct_printer_info3(p->mem_ctx, ntprinter,
4587 &r->out.info->info3, snum);
4588 break;
4589 case 4:
4590 result = construct_printer_info4(p->mem_ctx, ntprinter,
4591 &r->out.info->info4, snum);
4592 break;
4593 case 5:
4594 result = construct_printer_info5(p->mem_ctx, ntprinter,
4595 &r->out.info->info5, snum);
4596 break;
4597 case 6:
4598 result = construct_printer_info6(p->mem_ctx, ntprinter,
4599 &r->out.info->info6, snum);
4600 break;
4601 case 7:
4602 result = construct_printer_info7(p->mem_ctx, Printer,
4603 &r->out.info->info7, snum);
4604 break;
4605 case 8:
4606 result = construct_printer_info8(p->mem_ctx, ntprinter,
4607 &r->out.info->info8, snum);
4608 break;
4609 default:
4610 result = WERR_UNKNOWN_LEVEL;
4611 break;
4614 free_a_printer(&ntprinter, 2);
4616 if (!W_ERROR_IS_OK(result)) {
4617 TALLOC_FREE(r->out.info);
4618 return result;
4621 *r->out.needed = SPOOLSS_BUFFER_UNION(spoolss_PrinterInfo, NULL,
4622 r->out.info, r->in.level);
4623 r->out.info = SPOOLSS_BUFFER_OK(r->out.info, NULL);
4625 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
4628 /********************************************************************
4629 ********************************************************************/
4631 static const char **string_array_from_driver_info(TALLOC_CTX *mem_ctx,
4632 fstring *fstring_array,
4633 const char *cservername)
4635 int i, num_strings = 0;
4636 const char **array = NULL;
4638 for (i=0; fstring_array && fstring_array[i][0] != '\0'; i++) {
4640 const char *str = talloc_asprintf(mem_ctx, "\\\\%s%s",
4641 cservername, fstring_array[i]);
4642 if (!str) {
4643 TALLOC_FREE(array);
4644 return NULL;
4648 if (!add_string_to_array(mem_ctx, str, &array, &num_strings)) {
4649 TALLOC_FREE(array);
4650 return NULL;
4654 if (i > 0) {
4655 ADD_TO_ARRAY(mem_ctx, const char *, NULL,
4656 &array, &num_strings);
4659 return array;
4662 /********************************************************************
4663 * fill a spoolss_DriverInfo1 struct
4664 ********************************************************************/
4666 static WERROR fill_printer_driver_info1(TALLOC_CTX *mem_ctx,
4667 struct spoolss_DriverInfo1 *r,
4668 const NT_PRINTER_DRIVER_INFO_LEVEL *driver,
4669 const char *servername,
4670 const char *architecture)
4672 r->driver_name = talloc_strdup(mem_ctx, driver->info_3->name);
4673 W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4675 return WERR_OK;
4678 /********************************************************************
4679 * fill a spoolss_DriverInfo2 struct
4680 ********************************************************************/
4682 static WERROR fill_printer_driver_info2(TALLOC_CTX *mem_ctx,
4683 struct spoolss_DriverInfo2 *r,
4684 const NT_PRINTER_DRIVER_INFO_LEVEL *driver,
4685 const char *servername)
4688 const char *cservername = canon_servername(servername);
4690 r->version = driver->info_3->cversion;
4692 r->driver_name = talloc_strdup(mem_ctx, driver->info_3->name);
4693 W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4694 r->architecture = talloc_strdup(mem_ctx, driver->info_3->environment);
4695 W_ERROR_HAVE_NO_MEMORY(r->architecture);
4697 if (strlen(driver->info_3->driverpath)) {
4698 r->driver_path = talloc_asprintf(mem_ctx, "\\\\%s%s",
4699 cservername, driver->info_3->driverpath);
4700 } else {
4701 r->driver_path = talloc_strdup(mem_ctx, "");
4703 W_ERROR_HAVE_NO_MEMORY(r->driver_path);
4705 if (strlen(driver->info_3->datafile)) {
4706 r->data_file = talloc_asprintf(mem_ctx, "\\\\%s%s",
4707 cservername, driver->info_3->datafile);
4708 } else {
4709 r->data_file = talloc_strdup(mem_ctx, "");
4711 W_ERROR_HAVE_NO_MEMORY(r->data_file);
4713 if (strlen(driver->info_3->configfile)) {
4714 r->config_file = talloc_asprintf(mem_ctx, "\\\\%s%s",
4715 cservername, driver->info_3->configfile);
4716 } else {
4717 r->config_file = talloc_strdup(mem_ctx, "");
4719 W_ERROR_HAVE_NO_MEMORY(r->config_file);
4721 return WERR_OK;
4724 /********************************************************************
4725 * fill a spoolss_DriverInfo3 struct
4726 ********************************************************************/
4728 static WERROR fill_printer_driver_info3(TALLOC_CTX *mem_ctx,
4729 struct spoolss_DriverInfo3 *r,
4730 const NT_PRINTER_DRIVER_INFO_LEVEL *driver,
4731 const char *servername)
4733 const char *cservername = canon_servername(servername);
4735 r->version = driver->info_3->cversion;
4737 r->driver_name = talloc_strdup(mem_ctx, driver->info_3->name);
4738 W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4739 r->architecture = talloc_strdup(mem_ctx, driver->info_3->environment);
4740 W_ERROR_HAVE_NO_MEMORY(r->architecture);
4742 if (strlen(driver->info_3->driverpath)) {
4743 r->driver_path = talloc_asprintf(mem_ctx, "\\\\%s%s",
4744 cservername, driver->info_3->driverpath);
4745 } else {
4746 r->driver_path = talloc_strdup(mem_ctx, "");
4748 W_ERROR_HAVE_NO_MEMORY(r->driver_path);
4750 if (strlen(driver->info_3->datafile)) {
4751 r->data_file = talloc_asprintf(mem_ctx, "\\\\%s%s",
4752 cservername, driver->info_3->datafile);
4753 } else {
4754 r->data_file = talloc_strdup(mem_ctx, "");
4756 W_ERROR_HAVE_NO_MEMORY(r->data_file);
4758 if (strlen(driver->info_3->configfile)) {
4759 r->config_file = talloc_asprintf(mem_ctx, "\\\\%s%s",
4760 cservername, driver->info_3->configfile);
4761 } else {
4762 r->config_file = talloc_strdup(mem_ctx, "");
4764 W_ERROR_HAVE_NO_MEMORY(r->config_file);
4766 if (strlen(driver->info_3->helpfile)) {
4767 r->help_file = talloc_asprintf(mem_ctx, "\\\\%s%s",
4768 cservername, driver->info_3->helpfile);
4769 } else {
4770 r->help_file = talloc_strdup(mem_ctx, "");
4772 W_ERROR_HAVE_NO_MEMORY(r->help_file);
4774 r->monitor_name = talloc_strdup(mem_ctx, driver->info_3->monitorname);
4775 W_ERROR_HAVE_NO_MEMORY(r->monitor_name);
4776 r->default_datatype = talloc_strdup(mem_ctx, driver->info_3->defaultdatatype);
4777 W_ERROR_HAVE_NO_MEMORY(r->default_datatype);
4779 r->dependent_files = string_array_from_driver_info(mem_ctx,
4780 driver->info_3->dependentfiles,
4781 cservername);
4782 return WERR_OK;
4785 /********************************************************************
4786 * fill a spoolss_DriverInfo4 struct
4787 ********************************************************************/
4789 static WERROR fill_printer_driver_info4(TALLOC_CTX *mem_ctx,
4790 struct spoolss_DriverInfo4 *r,
4791 const NT_PRINTER_DRIVER_INFO_LEVEL *driver,
4792 const char *servername)
4794 const char *cservername = canon_servername(servername);
4796 r->version = driver->info_3->cversion;
4798 r->driver_name = talloc_strdup(mem_ctx, driver->info_3->name);
4799 W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4800 r->architecture = talloc_strdup(mem_ctx, driver->info_3->environment);
4801 W_ERROR_HAVE_NO_MEMORY(r->architecture);
4803 if (strlen(driver->info_3->driverpath)) {
4804 r->driver_path = talloc_asprintf(mem_ctx, "\\\\%s%s",
4805 cservername, driver->info_3->driverpath);
4806 } else {
4807 r->driver_path = talloc_strdup(mem_ctx, "");
4809 W_ERROR_HAVE_NO_MEMORY(r->driver_path);
4811 if (strlen(driver->info_3->datafile)) {
4812 r->data_file = talloc_asprintf(mem_ctx, "\\\\%s%s",
4813 cservername, driver->info_3->datafile);
4814 } else {
4815 r->data_file = talloc_strdup(mem_ctx, "");
4817 W_ERROR_HAVE_NO_MEMORY(r->data_file);
4819 if (strlen(driver->info_3->configfile)) {
4820 r->config_file = talloc_asprintf(mem_ctx, "\\\\%s%s",
4821 cservername, driver->info_3->configfile);
4822 } else {
4823 r->config_file = talloc_strdup(mem_ctx, "");
4825 W_ERROR_HAVE_NO_MEMORY(r->config_file);
4827 if (strlen(driver->info_3->helpfile)) {
4828 r->help_file = talloc_asprintf(mem_ctx, "\\\\%s%s",
4829 cservername, driver->info_3->helpfile);
4830 } else {
4831 r->help_file = talloc_strdup(mem_ctx, "");
4833 W_ERROR_HAVE_NO_MEMORY(r->help_file);
4835 r->dependent_files = string_array_from_driver_info(mem_ctx,
4836 driver->info_3->dependentfiles,
4837 cservername);
4840 r->monitor_name = talloc_strdup(mem_ctx, driver->info_3->monitorname);
4841 W_ERROR_HAVE_NO_MEMORY(r->monitor_name);
4842 r->default_datatype = talloc_strdup(mem_ctx, driver->info_3->defaultdatatype);
4843 W_ERROR_HAVE_NO_MEMORY(r->default_datatype);
4845 r->previous_names = string_array_from_driver_info(mem_ctx,
4846 NULL,
4847 cservername);
4849 return WERR_OK;
4852 /********************************************************************
4853 * fill a spoolss_DriverInfo5 struct
4854 ********************************************************************/
4856 static WERROR fill_printer_driver_info5(TALLOC_CTX *mem_ctx,
4857 struct spoolss_DriverInfo5 *r,
4858 const NT_PRINTER_DRIVER_INFO_LEVEL *driver,
4859 const char *servername)
4861 const char *cservername = canon_servername(servername);
4863 r->version = driver->info_3->cversion;
4865 r->driver_name = talloc_strdup(mem_ctx, driver->info_3->name);
4866 W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4867 r->architecture = talloc_strdup(mem_ctx, driver->info_3->environment);
4868 W_ERROR_HAVE_NO_MEMORY(r->architecture);
4870 if (strlen(driver->info_3->driverpath)) {
4871 r->driver_path = talloc_asprintf(mem_ctx, "\\\\%s%s",
4872 cservername, driver->info_3->driverpath);
4873 } else {
4874 r->driver_path = talloc_strdup(mem_ctx, "");
4876 W_ERROR_HAVE_NO_MEMORY(r->driver_path);
4878 if (strlen(driver->info_3->datafile)) {
4879 r->data_file = talloc_asprintf(mem_ctx, "\\\\%s%s",
4880 cservername, driver->info_3->datafile);
4881 } else {
4882 r->data_file = talloc_strdup(mem_ctx, "");
4884 W_ERROR_HAVE_NO_MEMORY(r->data_file);
4886 if (strlen(driver->info_3->configfile)) {
4887 r->config_file = talloc_asprintf(mem_ctx, "\\\\%s%s",
4888 cservername, driver->info_3->configfile);
4889 } else {
4890 r->config_file = talloc_strdup(mem_ctx, "");
4892 W_ERROR_HAVE_NO_MEMORY(r->config_file);
4894 r->driver_attributes = 0;
4895 r->config_version = 0;
4896 r->driver_version = 0;
4898 return WERR_OK;
4900 /********************************************************************
4901 * fill a spoolss_DriverInfo6 struct
4902 ********************************************************************/
4904 static WERROR fill_printer_driver_info6(TALLOC_CTX *mem_ctx,
4905 struct spoolss_DriverInfo6 *r,
4906 const NT_PRINTER_DRIVER_INFO_LEVEL *driver,
4907 const char *servername)
4909 const char *cservername = canon_servername(servername);
4911 r->version = driver->info_3->cversion;
4913 r->driver_name = talloc_strdup(mem_ctx, driver->info_3->name);
4914 W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4915 r->architecture = talloc_strdup(mem_ctx, driver->info_3->environment);
4916 W_ERROR_HAVE_NO_MEMORY(r->architecture);
4918 if (strlen(driver->info_3->driverpath)) {
4919 r->driver_path = talloc_asprintf(mem_ctx, "\\\\%s%s",
4920 cservername, driver->info_3->driverpath);
4921 } else {
4922 r->driver_path = talloc_strdup(mem_ctx, "");
4924 W_ERROR_HAVE_NO_MEMORY(r->driver_path);
4926 if (strlen(driver->info_3->datafile)) {
4927 r->data_file = talloc_asprintf(mem_ctx, "\\\\%s%s",
4928 cservername, driver->info_3->datafile);
4929 } else {
4930 r->data_file = talloc_strdup(mem_ctx, "");
4932 W_ERROR_HAVE_NO_MEMORY(r->data_file);
4934 if (strlen(driver->info_3->configfile)) {
4935 r->config_file = talloc_asprintf(mem_ctx, "\\\\%s%s",
4936 cservername, driver->info_3->configfile);
4937 } else {
4938 r->config_file = talloc_strdup(mem_ctx, "");
4940 W_ERROR_HAVE_NO_MEMORY(r->config_file);
4942 if (strlen(driver->info_3->helpfile)) {
4943 r->help_file = talloc_asprintf(mem_ctx, "\\\\%s%s",
4944 cservername, driver->info_3->helpfile);
4945 } else {
4946 r->help_file = talloc_strdup(mem_ctx, "");
4948 W_ERROR_HAVE_NO_MEMORY(r->help_file);
4950 r->monitor_name = talloc_strdup(mem_ctx, driver->info_3->monitorname);
4951 W_ERROR_HAVE_NO_MEMORY(r->monitor_name);
4952 r->default_datatype = talloc_strdup(mem_ctx, driver->info_3->defaultdatatype);
4953 W_ERROR_HAVE_NO_MEMORY(r->default_datatype);
4955 r->dependent_files = string_array_from_driver_info(mem_ctx,
4956 driver->info_3->dependentfiles,
4957 cservername);
4958 r->previous_names = string_array_from_driver_info(mem_ctx,
4959 NULL,
4960 cservername);
4962 r->driver_date = 0;
4963 r->driver_version = 0;
4965 r->manufacturer_name = talloc_strdup(mem_ctx, "");
4966 W_ERROR_HAVE_NO_MEMORY(r->manufacturer_name);
4967 r->manufacturer_url = talloc_strdup(mem_ctx, "");
4968 W_ERROR_HAVE_NO_MEMORY(r->manufacturer_url);
4969 r->hardware_id = talloc_strdup(mem_ctx, "");
4970 W_ERROR_HAVE_NO_MEMORY(r->hardware_id);
4971 r->provider = talloc_strdup(mem_ctx, "");
4972 W_ERROR_HAVE_NO_MEMORY(r->provider);
4974 return WERR_OK;
4977 /********************************************************************
4978 ********************************************************************/
4979 #if 0 /* disabled until marshalling issues are resolved - gd */
4980 static WERROR fill_spoolss_DriverFileInfo(TALLOC_CTX *mem_ctx,
4981 struct spoolss_DriverFileInfo *r,
4982 const char *cservername,
4983 const char *file_name,
4984 enum spoolss_DriverFileType file_type,
4985 uint32_t file_version)
4987 r->file_name = talloc_asprintf(mem_ctx, "\\\\%s%s",
4988 cservername, file_name);
4989 W_ERROR_HAVE_NO_MEMORY(r->file_name);
4990 r->file_type = file_type;
4991 r->file_version = file_version;
4993 return WERR_OK;
4996 /********************************************************************
4997 ********************************************************************/
4999 static WERROR spoolss_DriverFileInfo_from_driver(TALLOC_CTX *mem_ctx,
5000 const NT_PRINTER_DRIVER_INFO_LEVEL *driver,
5001 const char *cservername,
5002 struct spoolss_DriverFileInfo **info_p,
5003 uint32_t *count_p)
5005 struct spoolss_DriverFileInfo *info = NULL;
5006 uint32_t count = 0;
5007 WERROR result;
5008 uint32_t i;
5010 *info_p = NULL;
5011 *count_p = 0;
5013 if (strlen(driver->info_3->driverpath)) {
5014 info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
5015 struct spoolss_DriverFileInfo,
5016 count + 1);
5017 W_ERROR_HAVE_NO_MEMORY(info);
5018 result = fill_spoolss_DriverFileInfo(info,
5019 &info[count],
5020 cservername,
5021 driver->info_3->driverpath,
5022 SPOOLSS_DRIVER_FILE_TYPE_RENDERING,
5024 W_ERROR_NOT_OK_RETURN(result);
5025 count++;
5028 if (strlen(driver->info_3->configfile)) {
5029 info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
5030 struct spoolss_DriverFileInfo,
5031 count + 1);
5032 W_ERROR_HAVE_NO_MEMORY(info);
5033 result = fill_spoolss_DriverFileInfo(info,
5034 &info[count],
5035 cservername,
5036 driver->info_3->configfile,
5037 SPOOLSS_DRIVER_FILE_TYPE_CONFIGURATION,
5039 W_ERROR_NOT_OK_RETURN(result);
5040 count++;
5043 if (strlen(driver->info_3->datafile)) {
5044 info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
5045 struct spoolss_DriverFileInfo,
5046 count + 1);
5047 W_ERROR_HAVE_NO_MEMORY(info);
5048 result = fill_spoolss_DriverFileInfo(info,
5049 &info[count],
5050 cservername,
5051 driver->info_3->datafile,
5052 SPOOLSS_DRIVER_FILE_TYPE_DATA,
5054 W_ERROR_NOT_OK_RETURN(result);
5055 count++;
5058 if (strlen(driver->info_3->helpfile)) {
5059 info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
5060 struct spoolss_DriverFileInfo,
5061 count + 1);
5062 W_ERROR_HAVE_NO_MEMORY(info);
5063 result = fill_spoolss_DriverFileInfo(info,
5064 &info[count],
5065 cservername,
5066 driver->info_3->helpfile,
5067 SPOOLSS_DRIVER_FILE_TYPE_HELP,
5069 W_ERROR_NOT_OK_RETURN(result);
5070 count++;
5073 for (i=0; driver->info_3->dependentfiles[i][0] != '\0'; i++) {
5074 info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
5075 struct spoolss_DriverFileInfo,
5076 count + 1);
5077 W_ERROR_HAVE_NO_MEMORY(info);
5078 result = fill_spoolss_DriverFileInfo(info,
5079 &info[count],
5080 cservername,
5081 driver->info_3->dependentfiles[i],
5082 SPOOLSS_DRIVER_FILE_TYPE_OTHER,
5084 W_ERROR_NOT_OK_RETURN(result);
5085 count++;
5088 *info_p = info;
5089 *count_p = count;
5091 return WERR_OK;
5094 /********************************************************************
5095 * fill a spoolss_DriverInfo101 struct
5096 ********************************************************************/
5098 static WERROR fill_printer_driver_info101(TALLOC_CTX *mem_ctx,
5099 struct spoolss_DriverInfo101 *r,
5100 const NT_PRINTER_DRIVER_INFO_LEVEL *driver,
5101 const char *servername)
5103 const char *cservername = canon_servername(servername);
5104 WERROR result;
5106 r->version = driver->info_3->cversion;
5108 r->driver_name = talloc_strdup(mem_ctx, driver->info_3->name);
5109 W_ERROR_HAVE_NO_MEMORY(r->driver_name);
5110 r->architecture = talloc_strdup(mem_ctx, driver->info_3->environment);
5111 W_ERROR_HAVE_NO_MEMORY(r->architecture);
5113 result = spoolss_DriverFileInfo_from_driver(mem_ctx, driver,
5114 cservername,
5115 &r->file_info,
5116 &r->file_count);
5117 if (!W_ERROR_IS_OK(result)) {
5118 return result;
5121 r->monitor_name = talloc_strdup(mem_ctx, driver->info_3->monitorname);
5122 W_ERROR_HAVE_NO_MEMORY(r->monitor_name);
5124 r->default_datatype = talloc_strdup(mem_ctx, driver->info_3->defaultdatatype);
5125 W_ERROR_HAVE_NO_MEMORY(r->default_datatype);
5127 r->previous_names = string_array_from_driver_info(mem_ctx,
5128 NULL,
5129 cservername);
5130 r->driver_date = 0;
5131 r->driver_version = 0;
5133 r->manufacturer_name = talloc_strdup(mem_ctx, "");
5134 W_ERROR_HAVE_NO_MEMORY(r->manufacturer_name);
5135 r->manufacturer_url = talloc_strdup(mem_ctx, "");
5136 W_ERROR_HAVE_NO_MEMORY(r->manufacturer_url);
5137 r->hardware_id = talloc_strdup(mem_ctx, "");
5138 W_ERROR_HAVE_NO_MEMORY(r->hardware_id);
5139 r->provider = talloc_strdup(mem_ctx, "");
5140 W_ERROR_HAVE_NO_MEMORY(r->provider);
5142 return WERR_OK;
5144 #endif
5145 /********************************************************************
5146 * construct_printer_driver_info_1
5147 ********************************************************************/
5149 static WERROR construct_printer_driver_info_1(TALLOC_CTX *mem_ctx,
5150 struct spoolss_DriverInfo1 *r,
5151 int snum,
5152 const char *servername,
5153 const char *architecture,
5154 uint32_t version)
5156 NT_PRINTER_INFO_LEVEL *printer = NULL;
5157 NT_PRINTER_DRIVER_INFO_LEVEL driver;
5158 WERROR result;
5160 ZERO_STRUCT(driver);
5162 if (!W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, lp_const_servicename(snum))))
5163 return WERR_INVALID_PRINTER_NAME;
5165 if (!W_ERROR_IS_OK(get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version))) {
5166 free_a_printer(&printer, 2);
5167 return WERR_UNKNOWN_PRINTER_DRIVER;
5170 result = fill_printer_driver_info1(mem_ctx, r, &driver, servername, architecture);
5172 free_a_printer(&printer,2);
5174 return result;
5177 /********************************************************************
5178 * construct_printer_driver_info_2
5179 * fill a printer_info_2 struct
5180 ********************************************************************/
5182 static WERROR construct_printer_driver_info_2(TALLOC_CTX *mem_ctx,
5183 struct spoolss_DriverInfo2 *r,
5184 int snum,
5185 const char *servername,
5186 const char *architecture,
5187 uint32_t version)
5189 NT_PRINTER_INFO_LEVEL *printer = NULL;
5190 NT_PRINTER_DRIVER_INFO_LEVEL driver;
5191 WERROR result;
5193 ZERO_STRUCT(printer);
5194 ZERO_STRUCT(driver);
5196 if (!W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, lp_const_servicename(snum))))
5197 return WERR_INVALID_PRINTER_NAME;
5199 if (!W_ERROR_IS_OK(get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version))) {
5200 free_a_printer(&printer, 2);
5201 return WERR_UNKNOWN_PRINTER_DRIVER;
5204 result = fill_printer_driver_info2(mem_ctx, r, &driver, servername);
5206 free_a_printer(&printer,2);
5208 return result;
5211 /********************************************************************
5212 * construct_printer_info_3
5213 * fill a printer_info_3 struct
5214 ********************************************************************/
5216 static WERROR construct_printer_driver_info_3(TALLOC_CTX *mem_ctx,
5217 struct spoolss_DriverInfo3 *r,
5218 int snum,
5219 const char *servername,
5220 const char *architecture,
5221 uint32_t version)
5223 NT_PRINTER_INFO_LEVEL *printer = NULL;
5224 NT_PRINTER_DRIVER_INFO_LEVEL driver;
5225 WERROR status;
5226 ZERO_STRUCT(driver);
5228 status=get_a_printer(NULL, &printer, 2, lp_const_servicename(snum) );
5229 DEBUG(8,("construct_printer_driver_info_3: status: %s\n", win_errstr(status)));
5230 if (!W_ERROR_IS_OK(status))
5231 return WERR_INVALID_PRINTER_NAME;
5233 status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
5234 DEBUG(8,("construct_printer_driver_info_3: status: %s\n", win_errstr(status)));
5236 #if 0 /* JERRY */
5239 * I put this code in during testing. Helpful when commenting out the
5240 * support for DRIVER_INFO_6 in regards to win2k. Not needed in general
5241 * as win2k always queries the driver using an infor level of 6.
5242 * I've left it in (but ifdef'd out) because I'll probably
5243 * use it in experimentation again in the future. --jerry 22/01/2002
5246 if (!W_ERROR_IS_OK(status)) {
5248 * Is this a W2k client ?
5250 if (version == 3) {
5251 /* Yes - try again with a WinNT driver. */
5252 version = 2;
5253 status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
5254 DEBUG(8,("construct_printer_driver_info_3: status: %s\n", win_errstr(status)));
5256 #endif
5258 if (!W_ERROR_IS_OK(status)) {
5259 free_a_printer(&printer,2);
5260 return WERR_UNKNOWN_PRINTER_DRIVER;
5263 #if 0 /* JERRY */
5265 #endif
5268 status = fill_printer_driver_info3(mem_ctx, r, &driver, servername);
5270 free_a_printer(&printer,2);
5272 return status;
5275 /********************************************************************
5276 * construct_printer_info_6
5277 * fill a printer_info_6 struct
5278 ********************************************************************/
5280 static WERROR construct_printer_driver_info_6(TALLOC_CTX *mem_ctx,
5281 struct spoolss_DriverInfo6 *r,
5282 int snum,
5283 const char *servername,
5284 const char *architecture,
5285 uint32_t version)
5287 NT_PRINTER_INFO_LEVEL *printer = NULL;
5288 NT_PRINTER_DRIVER_INFO_LEVEL driver;
5289 WERROR status;
5291 ZERO_STRUCT(driver);
5293 status=get_a_printer(NULL, &printer, 2, lp_const_servicename(snum) );
5295 DEBUG(8,("construct_printer_driver_info_6: status: %s\n", win_errstr(status)));
5297 if (!W_ERROR_IS_OK(status))
5298 return WERR_INVALID_PRINTER_NAME;
5300 status = get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
5302 DEBUG(8,("construct_printer_driver_info_6: status: %s\n", win_errstr(status)));
5304 if (!W_ERROR_IS_OK(status))
5307 * Is this a W2k client ?
5310 if (version < 3) {
5311 free_a_printer(&printer,2);
5312 return WERR_UNKNOWN_PRINTER_DRIVER;
5315 /* Yes - try again with a WinNT driver. */
5316 version = 2;
5317 status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
5318 DEBUG(8,("construct_printer_driver_info_6: status: %s\n", win_errstr(status)));
5319 if (!W_ERROR_IS_OK(status)) {
5320 free_a_printer(&printer,2);
5321 return WERR_UNKNOWN_PRINTER_DRIVER;
5325 status = fill_printer_driver_info6(mem_ctx, r, &driver, servername);
5327 free_a_printer(&printer,2);
5328 free_a_printer_driver(driver, 3);
5330 return status;
5332 #if 0 /* disabled until marshalling issues are resolved - gd */
5333 /********************************************************************
5334 * construct_printer_info_101
5335 * fill a printer_info_101 struct
5336 ********************************************************************/
5338 static WERROR construct_printer_driver_info_101(TALLOC_CTX *mem_ctx,
5339 struct spoolss_DriverInfo101 *r,
5340 int snum,
5341 const char *servername,
5342 const char *architecture,
5343 uint32_t version)
5345 NT_PRINTER_INFO_LEVEL *printer = NULL;
5346 NT_PRINTER_DRIVER_INFO_LEVEL driver;
5347 WERROR result;
5349 ZERO_STRUCT(driver);
5351 result = get_a_printer(NULL, &printer, 2, lp_const_servicename(snum));
5353 DEBUG(8,("construct_printer_driver_info_101: status: %s\n",
5354 win_errstr(result)));
5356 if (!W_ERROR_IS_OK(result)) {
5357 return WERR_INVALID_PRINTER_NAME;
5360 result = get_a_printer_driver(&driver, 3, printer->info_2->drivername,
5361 architecture, version);
5363 DEBUG(8,("construct_printer_driver_info_101: status: %s\n",
5364 win_errstr(result)));
5366 if (!W_ERROR_IS_OK(result)) {
5368 * Is this a W2k client ?
5371 if (version < 3) {
5372 free_a_printer(&printer, 2);
5373 return WERR_UNKNOWN_PRINTER_DRIVER;
5376 /* Yes - try again with a WinNT driver. */
5377 version = 2;
5378 result = get_a_printer_driver(&driver, 3, printer->info_2->drivername,
5379 architecture, version);
5380 DEBUG(8,("construct_printer_driver_info_6: status: %s\n",
5381 win_errstr(result)));
5382 if (!W_ERROR_IS_OK(result)) {
5383 free_a_printer(&printer, 2);
5384 return WERR_UNKNOWN_PRINTER_DRIVER;
5388 result = fill_printer_driver_info101(mem_ctx, r, &driver, servername);
5390 free_a_printer(&printer, 2);
5391 free_a_printer_driver(driver, 3);
5393 return result;
5395 #endif
5396 /****************************************************************
5397 _spoolss_GetPrinterDriver2
5398 ****************************************************************/
5400 WERROR _spoolss_GetPrinterDriver2(pipes_struct *p,
5401 struct spoolss_GetPrinterDriver2 *r)
5403 Printer_entry *printer;
5404 WERROR result;
5406 const char *servername;
5407 int snum;
5409 /* that's an [in out] buffer */
5411 if (!r->in.buffer && (r->in.offered != 0)) {
5412 return WERR_INVALID_PARAM;
5415 DEBUG(4,("_spoolss_GetPrinterDriver2\n"));
5417 if (!(printer = find_printer_index_by_hnd(p, r->in.handle))) {
5418 DEBUG(0,("_spoolss_GetPrinterDriver2: invalid printer handle!\n"));
5419 return WERR_INVALID_PRINTER_NAME;
5422 *r->out.needed = 0;
5423 *r->out.server_major_version = 0;
5424 *r->out.server_minor_version = 0;
5426 servername = get_server_name(printer);
5428 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
5429 return WERR_BADFID;
5432 switch (r->in.level) {
5433 case 1:
5434 result = construct_printer_driver_info_1(p->mem_ctx,
5435 &r->out.info->info1,
5436 snum,
5437 servername,
5438 r->in.architecture,
5439 r->in.client_major_version);
5440 break;
5441 case 2:
5442 result = construct_printer_driver_info_2(p->mem_ctx,
5443 &r->out.info->info2,
5444 snum,
5445 servername,
5446 r->in.architecture,
5447 r->in.client_major_version);
5448 break;
5449 case 3:
5450 result = construct_printer_driver_info_3(p->mem_ctx,
5451 &r->out.info->info3,
5452 snum,
5453 servername,
5454 r->in.architecture,
5455 r->in.client_major_version);
5456 break;
5457 case 6:
5458 result = construct_printer_driver_info_6(p->mem_ctx,
5459 &r->out.info->info6,
5460 snum,
5461 servername,
5462 r->in.architecture,
5463 r->in.client_major_version);
5464 break;
5465 #if 0 /* disabled until marshalling issues are resolved - gd */
5466 case 101:
5467 result = construct_printer_driver_info_101(p->mem_ctx,
5468 &r->out.info->info101,
5469 snum,
5470 servername,
5471 r->in.architecture,
5472 r->in.client_major_version);
5473 break;
5474 #endif
5475 default:
5476 result = WERR_UNKNOWN_LEVEL;
5477 break;
5480 if (!W_ERROR_IS_OK(result)) {
5481 TALLOC_FREE(r->out.info);
5482 return result;
5485 *r->out.needed = SPOOLSS_BUFFER_UNION(spoolss_DriverInfo, NULL,
5486 r->out.info, r->in.level);
5487 r->out.info = SPOOLSS_BUFFER_OK(r->out.info, NULL);
5489 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
5493 /****************************************************************
5494 _spoolss_StartPagePrinter
5495 ****************************************************************/
5497 WERROR _spoolss_StartPagePrinter(pipes_struct *p,
5498 struct spoolss_StartPagePrinter *r)
5500 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
5502 if (!Printer) {
5503 DEBUG(3,("_spoolss_StartPagePrinter: "
5504 "Error in startpageprinter printer handle\n"));
5505 return WERR_BADFID;
5508 Printer->page_started = true;
5509 return WERR_OK;
5512 /****************************************************************
5513 _spoolss_EndPagePrinter
5514 ****************************************************************/
5516 WERROR _spoolss_EndPagePrinter(pipes_struct *p,
5517 struct spoolss_EndPagePrinter *r)
5519 int snum;
5521 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
5523 if (!Printer) {
5524 DEBUG(2,("_spoolss_EndPagePrinter: Invalid handle (%s:%u:%u).\n",
5525 OUR_HANDLE(r->in.handle)));
5526 return WERR_BADFID;
5529 if (!get_printer_snum(p, r->in.handle, &snum, NULL))
5530 return WERR_BADFID;
5532 Printer->page_started = false;
5533 print_job_endpage(snum, Printer->jobid);
5535 return WERR_OK;
5538 /****************************************************************
5539 _spoolss_StartDocPrinter
5540 ****************************************************************/
5542 WERROR _spoolss_StartDocPrinter(pipes_struct *p,
5543 struct spoolss_StartDocPrinter *r)
5545 struct spoolss_DocumentInfo1 *info_1;
5546 int snum;
5547 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
5549 if (!Printer) {
5550 DEBUG(2,("_spoolss_StartDocPrinter: "
5551 "Invalid handle (%s:%u:%u)\n",
5552 OUR_HANDLE(r->in.handle)));
5553 return WERR_BADFID;
5556 if (r->in.level != 1) {
5557 return WERR_UNKNOWN_LEVEL;
5560 info_1 = r->in.info.info1;
5563 * a nice thing with NT is it doesn't listen to what you tell it.
5564 * when asked to send _only_ RAW datas, it tries to send datas
5565 * in EMF format.
5567 * So I add checks like in NT Server ...
5570 if (info_1->datatype) {
5571 if (strcmp(info_1->datatype, "RAW") != 0) {
5572 *r->out.job_id = 0;
5573 return WERR_INVALID_DATATYPE;
5577 /* get the share number of the printer */
5578 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
5579 return WERR_BADFID;
5582 Printer->jobid = print_job_start(p->server_info, snum,
5583 info_1->document_name,
5584 Printer->nt_devmode);
5586 /* An error occured in print_job_start() so return an appropriate
5587 NT error code. */
5589 if (Printer->jobid == -1) {
5590 return map_werror_from_unix(errno);
5593 Printer->document_started = true;
5594 *r->out.job_id = Printer->jobid;
5596 return WERR_OK;
5599 /****************************************************************
5600 _spoolss_EndDocPrinter
5601 ****************************************************************/
5603 WERROR _spoolss_EndDocPrinter(pipes_struct *p,
5604 struct spoolss_EndDocPrinter *r)
5606 return _spoolss_enddocprinter_internal(p, r->in.handle);
5609 /****************************************************************
5610 _spoolss_WritePrinter
5611 ****************************************************************/
5613 WERROR _spoolss_WritePrinter(pipes_struct *p,
5614 struct spoolss_WritePrinter *r)
5616 uint32_t buffer_written;
5617 int snum;
5618 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
5620 if (!Printer) {
5621 DEBUG(2,("_spoolss_WritePrinter: Invalid handle (%s:%u:%u)\n",
5622 OUR_HANDLE(r->in.handle)));
5623 *r->out.num_written = r->in._data_size;
5624 return WERR_BADFID;
5627 if (!get_printer_snum(p, r->in.handle, &snum, NULL))
5628 return WERR_BADFID;
5630 buffer_written = (uint32_t)print_job_write(snum, Printer->jobid,
5631 (const char *)r->in.data.data,
5632 (SMB_OFF_T)-1,
5633 (size_t)r->in._data_size);
5634 if (buffer_written == (uint32_t)-1) {
5635 *r->out.num_written = 0;
5636 if (errno == ENOSPC)
5637 return WERR_NO_SPOOL_SPACE;
5638 else
5639 return WERR_ACCESS_DENIED;
5642 *r->out.num_written = r->in._data_size;
5644 return WERR_OK;
5647 /********************************************************************
5648 * api_spoolss_getprinter
5649 * called from the spoolss dispatcher
5651 ********************************************************************/
5653 static WERROR control_printer(struct policy_handle *handle, uint32_t command,
5654 pipes_struct *p)
5656 int snum;
5657 WERROR errcode = WERR_BADFUNC;
5658 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5660 if (!Printer) {
5661 DEBUG(2,("control_printer: Invalid handle (%s:%u:%u)\n",
5662 OUR_HANDLE(handle)));
5663 return WERR_BADFID;
5666 if (!get_printer_snum(p, handle, &snum, NULL))
5667 return WERR_BADFID;
5669 switch (command) {
5670 case SPOOLSS_PRINTER_CONTROL_PAUSE:
5671 errcode = print_queue_pause(p->server_info, snum);
5672 break;
5673 case SPOOLSS_PRINTER_CONTROL_RESUME:
5674 case SPOOLSS_PRINTER_CONTROL_UNPAUSE:
5675 errcode = print_queue_resume(p->server_info, snum);
5676 break;
5677 case SPOOLSS_PRINTER_CONTROL_PURGE:
5678 errcode = print_queue_purge(p->server_info, snum);
5679 break;
5680 default:
5681 return WERR_UNKNOWN_LEVEL;
5684 return errcode;
5688 /****************************************************************
5689 _spoolss_AbortPrinter
5690 * From MSDN: "Deletes printer's spool file if printer is configured
5691 * for spooling"
5692 ****************************************************************/
5694 WERROR _spoolss_AbortPrinter(pipes_struct *p,
5695 struct spoolss_AbortPrinter *r)
5697 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
5698 int snum;
5699 WERROR errcode = WERR_OK;
5701 if (!Printer) {
5702 DEBUG(2,("_spoolss_AbortPrinter: Invalid handle (%s:%u:%u)\n",
5703 OUR_HANDLE(r->in.handle)));
5704 return WERR_BADFID;
5707 if (!get_printer_snum(p, r->in.handle, &snum, NULL))
5708 return WERR_BADFID;
5710 print_job_delete(p->server_info, snum, Printer->jobid, &errcode );
5712 return errcode;
5715 /********************************************************************
5716 * called by spoolss_api_setprinter
5717 * when updating a printer description
5718 ********************************************************************/
5720 static WERROR update_printer_sec(struct policy_handle *handle,
5721 pipes_struct *p, SEC_DESC_BUF *secdesc_ctr)
5723 SEC_DESC_BUF *new_secdesc_ctr = NULL, *old_secdesc_ctr = NULL;
5724 WERROR result;
5725 int snum;
5727 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5729 if (!Printer || !get_printer_snum(p, handle, &snum, NULL)) {
5730 DEBUG(2,("update_printer_sec: Invalid handle (%s:%u:%u)\n",
5731 OUR_HANDLE(handle)));
5733 result = WERR_BADFID;
5734 goto done;
5737 if (!secdesc_ctr) {
5738 DEBUG(10,("update_printer_sec: secdesc_ctr is NULL !\n"));
5739 result = WERR_INVALID_PARAM;
5740 goto done;
5743 /* Check the user has permissions to change the security
5744 descriptor. By experimentation with two NT machines, the user
5745 requires Full Access to the printer to change security
5746 information. */
5748 if ( Printer->access_granted != PRINTER_ACCESS_ADMINISTER ) {
5749 DEBUG(4,("update_printer_sec: updated denied by printer permissions\n"));
5750 result = WERR_ACCESS_DENIED;
5751 goto done;
5754 /* NT seems to like setting the security descriptor even though
5755 nothing may have actually changed. */
5757 if ( !nt_printing_getsec(p->mem_ctx, Printer->sharename, &old_secdesc_ctr)) {
5758 DEBUG(2,("update_printer_sec: nt_printing_getsec() failed\n"));
5759 result = WERR_BADFID;
5760 goto done;
5763 if (DEBUGLEVEL >= 10) {
5764 SEC_ACL *the_acl;
5765 int i;
5767 the_acl = old_secdesc_ctr->sd->dacl;
5768 DEBUG(10, ("old_secdesc_ctr for %s has %d aces:\n",
5769 PRINTERNAME(snum), the_acl->num_aces));
5771 for (i = 0; i < the_acl->num_aces; i++) {
5772 DEBUG(10, ("%s 0x%08x\n", sid_string_dbg(
5773 &the_acl->aces[i].trustee),
5774 the_acl->aces[i].access_mask));
5777 the_acl = secdesc_ctr->sd->dacl;
5779 if (the_acl) {
5780 DEBUG(10, ("secdesc_ctr for %s has %d aces:\n",
5781 PRINTERNAME(snum), the_acl->num_aces));
5783 for (i = 0; i < the_acl->num_aces; i++) {
5784 DEBUG(10, ("%s 0x%08x\n", sid_string_dbg(
5785 &the_acl->aces[i].trustee),
5786 the_acl->aces[i].access_mask));
5788 } else {
5789 DEBUG(10, ("dacl for secdesc_ctr is NULL\n"));
5793 new_secdesc_ctr = sec_desc_merge(p->mem_ctx, secdesc_ctr, old_secdesc_ctr);
5794 if (!new_secdesc_ctr) {
5795 result = WERR_NOMEM;
5796 goto done;
5799 if (sec_desc_equal(new_secdesc_ctr->sd, old_secdesc_ctr->sd)) {
5800 result = WERR_OK;
5801 goto done;
5804 result = nt_printing_setsec(Printer->sharename, new_secdesc_ctr);
5806 done:
5808 return result;
5811 /********************************************************************
5812 Canonicalize printer info from a client
5814 ATTN: It does not matter what we set the servername to hear
5815 since we do the necessary work in get_a_printer() to set it to
5816 the correct value based on what the client sent in the
5817 _spoolss_open_printer_ex().
5818 ********************************************************************/
5820 static bool check_printer_ok(NT_PRINTER_INFO_LEVEL_2 *info, int snum)
5822 fstring printername;
5823 const char *p;
5825 DEBUG(5,("check_printer_ok: servername=%s printername=%s sharename=%s "
5826 "portname=%s drivername=%s comment=%s location=%s\n",
5827 info->servername, info->printername, info->sharename,
5828 info->portname, info->drivername, info->comment, info->location));
5830 /* we force some elements to "correct" values */
5831 slprintf(info->servername, sizeof(info->servername)-1, "\\\\%s", global_myname());
5832 fstrcpy(info->sharename, lp_servicename(snum));
5834 /* check to see if we allow printername != sharename */
5836 if ( lp_force_printername(snum) ) {
5837 slprintf(info->printername, sizeof(info->printername)-1, "\\\\%s\\%s",
5838 global_myname(), info->sharename );
5839 } else {
5841 /* make sure printername is in \\server\printername format */
5843 fstrcpy( printername, info->printername );
5844 p = printername;
5845 if ( printername[0] == '\\' && printername[1] == '\\' ) {
5846 if ( (p = strchr_m( &printername[2], '\\' )) != NULL )
5847 p++;
5850 slprintf(info->printername, sizeof(info->printername)-1, "\\\\%s\\%s",
5851 global_myname(), p );
5854 info->attributes |= PRINTER_ATTRIBUTE_SAMBA;
5855 info->attributes &= ~PRINTER_ATTRIBUTE_NOT_SAMBA;
5859 return true;
5862 /****************************************************************************
5863 ****************************************************************************/
5865 WERROR add_port_hook(TALLOC_CTX *ctx, NT_USER_TOKEN *token, const char *portname, const char *uri )
5867 char *cmd = lp_addport_cmd();
5868 char *command = NULL;
5869 int ret;
5870 SE_PRIV se_printop = SE_PRINT_OPERATOR;
5871 bool is_print_op = false;
5873 if ( !*cmd ) {
5874 return WERR_ACCESS_DENIED;
5877 command = talloc_asprintf(ctx,
5878 "%s \"%s\" \"%s\"", cmd, portname, uri );
5879 if (!command) {
5880 return WERR_NOMEM;
5883 if ( token )
5884 is_print_op = user_has_privileges( token, &se_printop );
5886 DEBUG(10,("Running [%s]\n", command));
5888 /********* BEGIN SePrintOperatorPrivilege **********/
5890 if ( is_print_op )
5891 become_root();
5893 ret = smbrun(command, NULL);
5895 if ( is_print_op )
5896 unbecome_root();
5898 /********* END SePrintOperatorPrivilege **********/
5900 DEBUGADD(10,("returned [%d]\n", ret));
5902 TALLOC_FREE(command);
5904 if ( ret != 0 ) {
5905 return WERR_ACCESS_DENIED;
5908 return WERR_OK;
5911 /****************************************************************************
5912 ****************************************************************************/
5914 bool add_printer_hook(TALLOC_CTX *ctx, NT_USER_TOKEN *token, NT_PRINTER_INFO_LEVEL *printer)
5916 char *cmd = lp_addprinter_cmd();
5917 char **qlines;
5918 char *command = NULL;
5919 int numlines;
5920 int ret;
5921 int fd;
5922 SE_PRIV se_printop = SE_PRINT_OPERATOR;
5923 bool is_print_op = false;
5924 char *remote_machine = talloc_strdup(ctx, "%m");
5926 if (!remote_machine) {
5927 return false;
5929 remote_machine = talloc_sub_basic(ctx,
5930 current_user_info.smb_name,
5931 current_user_info.domain,
5932 remote_machine);
5933 if (!remote_machine) {
5934 return false;
5937 command = talloc_asprintf(ctx,
5938 "%s \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\"",
5939 cmd, printer->info_2->printername, printer->info_2->sharename,
5940 printer->info_2->portname, printer->info_2->drivername,
5941 printer->info_2->location, printer->info_2->comment, remote_machine);
5942 if (!command) {
5943 return false;
5946 if ( token )
5947 is_print_op = user_has_privileges( token, &se_printop );
5949 DEBUG(10,("Running [%s]\n", command));
5951 /********* BEGIN SePrintOperatorPrivilege **********/
5953 if ( is_print_op )
5954 become_root();
5956 if ( (ret = smbrun(command, &fd)) == 0 ) {
5957 /* Tell everyone we updated smb.conf. */
5958 message_send_all(smbd_messaging_context(),
5959 MSG_SMB_CONF_UPDATED, NULL, 0, NULL);
5962 if ( is_print_op )
5963 unbecome_root();
5965 /********* END SePrintOperatorPrivilege **********/
5967 DEBUGADD(10,("returned [%d]\n", ret));
5969 TALLOC_FREE(command);
5970 TALLOC_FREE(remote_machine);
5972 if ( ret != 0 ) {
5973 if (fd != -1)
5974 close(fd);
5975 return false;
5978 /* reload our services immediately */
5979 become_root();
5980 reload_services(false);
5981 unbecome_root();
5983 numlines = 0;
5984 /* Get lines and convert them back to dos-codepage */
5985 qlines = fd_lines_load(fd, &numlines, 0, NULL);
5986 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
5987 close(fd);
5989 /* Set the portname to what the script says the portname should be. */
5990 /* but don't require anything to be return from the script exit a good error code */
5992 if (numlines) {
5993 /* Set the portname to what the script says the portname should be. */
5994 strncpy(printer->info_2->portname, qlines[0], sizeof(printer->info_2->portname));
5995 DEBUGADD(6,("Line[0] = [%s]\n", qlines[0]));
5998 TALLOC_FREE(qlines);
5999 return true;
6003 /********************************************************************
6004 * Called by spoolss_api_setprinter
6005 * when updating a printer description.
6006 ********************************************************************/
6008 static WERROR update_printer(pipes_struct *p, struct policy_handle *handle,
6009 struct spoolss_SetPrinterInfoCtr *info_ctr,
6010 struct spoolss_DeviceMode *devmode)
6012 int snum;
6013 NT_PRINTER_INFO_LEVEL *printer = NULL, *old_printer = NULL;
6014 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
6015 WERROR result;
6016 UNISTR2 buffer;
6017 fstring asc_buffer;
6019 DEBUG(8,("update_printer\n"));
6021 result = WERR_OK;
6023 if (!Printer) {
6024 result = WERR_BADFID;
6025 goto done;
6028 if (!get_printer_snum(p, handle, &snum, NULL)) {
6029 result = WERR_BADFID;
6030 goto done;
6033 if (!W_ERROR_IS_OK(get_a_printer(Printer, &printer, 2, lp_const_servicename(snum))) ||
6034 (!W_ERROR_IS_OK(get_a_printer(Printer, &old_printer, 2, lp_const_servicename(snum))))) {
6035 result = WERR_BADFID;
6036 goto done;
6039 DEBUGADD(8,("Converting info_2 struct\n"));
6042 * convert_printer_info converts the incoming
6043 * info from the client and overwrites the info
6044 * just read from the tdb in the pointer 'printer'.
6047 if (!convert_printer_info(info_ctr, printer)) {
6048 result = WERR_NOMEM;
6049 goto done;
6052 if (devmode) {
6053 /* we have a valid devmode
6054 convert it and link it*/
6056 DEBUGADD(8,("update_printer: Converting the devicemode struct\n"));
6057 if (!convert_devicemode(printer->info_2->printername, devmode,
6058 &printer->info_2->devmode)) {
6059 result = WERR_NOMEM;
6060 goto done;
6064 /* Do sanity check on the requested changes for Samba */
6066 if (!check_printer_ok(printer->info_2, snum)) {
6067 result = WERR_INVALID_PARAM;
6068 goto done;
6071 /* FIXME!!! If the driver has changed we really should verify that
6072 it is installed before doing much else --jerry */
6074 /* Check calling user has permission to update printer description */
6076 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
6077 DEBUG(3, ("update_printer: printer property change denied by handle\n"));
6078 result = WERR_ACCESS_DENIED;
6079 goto done;
6082 /* Call addprinter hook */
6083 /* Check changes to see if this is really needed */
6085 if ( *lp_addprinter_cmd()
6086 && (!strequal(printer->info_2->drivername, old_printer->info_2->drivername)
6087 || !strequal(printer->info_2->comment, old_printer->info_2->comment)
6088 || !strequal(printer->info_2->portname, old_printer->info_2->portname)
6089 || !strequal(printer->info_2->location, old_printer->info_2->location)) )
6091 /* add_printer_hook() will call reload_services() */
6093 if ( !add_printer_hook(p->mem_ctx, p->server_info->ptok,
6094 printer) ) {
6095 result = WERR_ACCESS_DENIED;
6096 goto done;
6101 * When a *new* driver is bound to a printer, the drivername is used to
6102 * lookup previously saved driver initialization info, which is then
6103 * bound to the printer, simulating what happens in the Windows arch.
6105 if (!strequal(printer->info_2->drivername, old_printer->info_2->drivername))
6107 if (!set_driver_init(printer, 2))
6109 DEBUG(5,("update_printer: Error restoring driver initialization data for driver [%s]!\n",
6110 printer->info_2->drivername));
6113 DEBUG(10,("update_printer: changing driver [%s]! Sending event!\n",
6114 printer->info_2->drivername));
6116 notify_printer_driver(snum, printer->info_2->drivername);
6120 * flag which changes actually occured. This is a small subset of
6121 * all the possible changes. We also have to update things in the
6122 * DsSpooler key.
6125 if (!strequal(printer->info_2->comment, old_printer->info_2->comment)) {
6126 init_unistr2( &buffer, printer->info_2->comment, UNI_STR_TERMINATE);
6127 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "description",
6128 REG_SZ, (uint8_t *)buffer.buffer, buffer.uni_str_len*2 );
6130 notify_printer_comment(snum, printer->info_2->comment);
6133 if (!strequal(printer->info_2->sharename, old_printer->info_2->sharename)) {
6134 init_unistr2( &buffer, printer->info_2->sharename, UNI_STR_TERMINATE);
6135 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "shareName",
6136 REG_SZ, (uint8_t *)buffer.buffer, buffer.uni_str_len*2 );
6138 notify_printer_sharename(snum, printer->info_2->sharename);
6141 if (!strequal(printer->info_2->printername, old_printer->info_2->printername)) {
6142 char *pname;
6144 if ( (pname = strchr_m( printer->info_2->printername+2, '\\' )) != NULL )
6145 pname++;
6146 else
6147 pname = printer->info_2->printername;
6150 init_unistr2( &buffer, pname, UNI_STR_TERMINATE);
6151 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "printerName",
6152 REG_SZ, (uint8_t *)buffer.buffer, buffer.uni_str_len*2 );
6154 notify_printer_printername( snum, pname );
6157 if (!strequal(printer->info_2->portname, old_printer->info_2->portname)) {
6158 init_unistr2( &buffer, printer->info_2->portname, UNI_STR_TERMINATE);
6159 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "portName",
6160 REG_SZ, (uint8_t *)buffer.buffer, buffer.uni_str_len*2 );
6162 notify_printer_port(snum, printer->info_2->portname);
6165 if (!strequal(printer->info_2->location, old_printer->info_2->location)) {
6166 init_unistr2( &buffer, printer->info_2->location, UNI_STR_TERMINATE);
6167 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "location",
6168 REG_SZ, (uint8_t *)buffer.buffer, buffer.uni_str_len*2 );
6170 notify_printer_location(snum, printer->info_2->location);
6173 /* here we need to update some more DsSpooler keys */
6174 /* uNCName, serverName, shortServerName */
6176 init_unistr2( &buffer, global_myname(), UNI_STR_TERMINATE);
6177 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "serverName",
6178 REG_SZ, (uint8_t *)buffer.buffer, buffer.uni_str_len*2 );
6179 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "shortServerName",
6180 REG_SZ, (uint8_t *)buffer.buffer, buffer.uni_str_len*2 );
6182 slprintf( asc_buffer, sizeof(asc_buffer)-1, "\\\\%s\\%s",
6183 global_myname(), printer->info_2->sharename );
6184 init_unistr2( &buffer, asc_buffer, UNI_STR_TERMINATE);
6185 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "uNCName",
6186 REG_SZ, (uint8_t *)buffer.buffer, buffer.uni_str_len*2 );
6188 /* Update printer info */
6189 result = mod_a_printer(printer, 2);
6191 done:
6192 free_a_printer(&printer, 2);
6193 free_a_printer(&old_printer, 2);
6196 return result;
6199 /****************************************************************************
6200 ****************************************************************************/
6201 static WERROR publish_or_unpublish_printer(pipes_struct *p,
6202 struct policy_handle *handle,
6203 struct spoolss_SetPrinterInfo7 *info7)
6205 #ifdef HAVE_ADS
6206 int snum;
6207 Printer_entry *Printer;
6209 if ( lp_security() != SEC_ADS ) {
6210 return WERR_UNKNOWN_LEVEL;
6213 Printer = find_printer_index_by_hnd(p, handle);
6215 DEBUG(5,("publish_or_unpublish_printer, action = %d\n",info7->action));
6217 if (!Printer)
6218 return WERR_BADFID;
6220 if (!get_printer_snum(p, handle, &snum, NULL))
6221 return WERR_BADFID;
6223 nt_printer_publish(Printer, snum, info7->action);
6225 return WERR_OK;
6226 #else
6227 return WERR_UNKNOWN_LEVEL;
6228 #endif
6231 /****************************************************************
6232 _spoolss_SetPrinter
6233 ****************************************************************/
6235 WERROR _spoolss_SetPrinter(pipes_struct *p,
6236 struct spoolss_SetPrinter *r)
6238 WERROR result;
6240 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
6242 if (!Printer) {
6243 DEBUG(2,("_spoolss_SetPrinter: Invalid handle (%s:%u:%u)\n",
6244 OUR_HANDLE(r->in.handle)));
6245 return WERR_BADFID;
6248 /* check the level */
6249 switch (r->in.info_ctr->level) {
6250 case 0:
6251 return control_printer(r->in.handle, r->in.command, p);
6252 case 2:
6253 result = update_printer(p, r->in.handle,
6254 r->in.info_ctr,
6255 r->in.devmode_ctr->devmode);
6256 if (!W_ERROR_IS_OK(result))
6257 return result;
6258 if (r->in.secdesc_ctr->sd)
6259 result = update_printer_sec(r->in.handle, p,
6260 r->in.secdesc_ctr);
6261 return result;
6262 case 3:
6263 return update_printer_sec(r->in.handle, p,
6264 r->in.secdesc_ctr);
6265 case 7:
6266 return publish_or_unpublish_printer(p, r->in.handle,
6267 r->in.info_ctr->info.info7);
6268 default:
6269 return WERR_UNKNOWN_LEVEL;
6273 /****************************************************************
6274 _spoolss_FindClosePrinterNotify
6275 ****************************************************************/
6277 WERROR _spoolss_FindClosePrinterNotify(pipes_struct *p,
6278 struct spoolss_FindClosePrinterNotify *r)
6280 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
6282 if (!Printer) {
6283 DEBUG(2,("_spoolss_FindClosePrinterNotify: "
6284 "Invalid handle (%s:%u:%u)\n", OUR_HANDLE(r->in.handle)));
6285 return WERR_BADFID;
6288 if (Printer->notify.client_connected == true) {
6289 int snum = -1;
6291 if ( Printer->printer_type == SPLHND_SERVER)
6292 snum = -1;
6293 else if ( (Printer->printer_type == SPLHND_PRINTER) &&
6294 !get_printer_snum(p, r->in.handle, &snum, NULL) )
6295 return WERR_BADFID;
6297 srv_spoolss_replycloseprinter(snum, &Printer->notify.client_hnd);
6300 Printer->notify.flags=0;
6301 Printer->notify.options=0;
6302 Printer->notify.localmachine[0]='\0';
6303 Printer->notify.printerlocal=0;
6304 TALLOC_FREE(Printer->notify.option);
6305 Printer->notify.client_connected = false;
6307 return WERR_OK;
6310 /****************************************************************
6311 _spoolss_AddJob
6312 ****************************************************************/
6314 WERROR _spoolss_AddJob(pipes_struct *p,
6315 struct spoolss_AddJob *r)
6317 if (!r->in.buffer && (r->in.offered != 0)) {
6318 return WERR_INVALID_PARAM;
6321 /* this is what a NT server returns for AddJob. AddJob must fail on
6322 * non-local printers */
6324 if (r->in.level != 1) {
6325 return WERR_UNKNOWN_LEVEL;
6328 return WERR_INVALID_PARAM;
6331 /****************************************************************************
6332 fill_job_info1
6333 ****************************************************************************/
6335 static WERROR fill_job_info1(TALLOC_CTX *mem_ctx,
6336 struct spoolss_JobInfo1 *r,
6337 const print_queue_struct *queue,
6338 int position, int snum,
6339 const NT_PRINTER_INFO_LEVEL *ntprinter)
6341 struct tm *t;
6343 t = gmtime(&queue->time);
6345 r->job_id = queue->job;
6347 r->printer_name = talloc_strdup(mem_ctx, lp_servicename(snum));
6348 W_ERROR_HAVE_NO_MEMORY(r->printer_name);
6349 r->server_name = talloc_strdup(mem_ctx, ntprinter->info_2->servername);
6350 W_ERROR_HAVE_NO_MEMORY(r->server_name);
6351 r->user_name = talloc_strdup(mem_ctx, queue->fs_user);
6352 W_ERROR_HAVE_NO_MEMORY(r->user_name);
6353 r->document_name = talloc_strdup(mem_ctx, queue->fs_file);
6354 W_ERROR_HAVE_NO_MEMORY(r->document_name);
6355 r->data_type = talloc_strdup(mem_ctx, "RAW");
6356 W_ERROR_HAVE_NO_MEMORY(r->data_type);
6357 r->text_status = talloc_strdup(mem_ctx, "");
6358 W_ERROR_HAVE_NO_MEMORY(r->text_status);
6360 r->status = nt_printj_status(queue->status);
6361 r->priority = queue->priority;
6362 r->position = position;
6363 r->total_pages = queue->page_count;
6364 r->pages_printed = 0; /* ??? */
6366 init_systemtime(&r->submitted, t);
6368 return WERR_OK;
6371 /****************************************************************************
6372 fill_job_info2
6373 ****************************************************************************/
6375 static WERROR fill_job_info2(TALLOC_CTX *mem_ctx,
6376 struct spoolss_JobInfo2 *r,
6377 const print_queue_struct *queue,
6378 int position, int snum,
6379 const NT_PRINTER_INFO_LEVEL *ntprinter,
6380 struct spoolss_DeviceMode *devmode)
6382 struct tm *t;
6384 t = gmtime(&queue->time);
6386 r->job_id = queue->job;
6388 r->printer_name = talloc_strdup(mem_ctx, lp_servicename(snum));
6389 W_ERROR_HAVE_NO_MEMORY(r->printer_name);
6390 r->server_name = talloc_strdup(mem_ctx, ntprinter->info_2->servername);
6391 W_ERROR_HAVE_NO_MEMORY(r->server_name);
6392 r->user_name = talloc_strdup(mem_ctx, queue->fs_user);
6393 W_ERROR_HAVE_NO_MEMORY(r->user_name);
6394 r->document_name = talloc_strdup(mem_ctx, queue->fs_file);
6395 W_ERROR_HAVE_NO_MEMORY(r->document_name);
6396 r->notify_name = talloc_strdup(mem_ctx, queue->fs_user);
6397 W_ERROR_HAVE_NO_MEMORY(r->notify_name);
6398 r->data_type = talloc_strdup(mem_ctx, "RAW");
6399 W_ERROR_HAVE_NO_MEMORY(r->data_type);
6400 r->print_processor = talloc_strdup(mem_ctx, "winprint");
6401 W_ERROR_HAVE_NO_MEMORY(r->print_processor);
6402 r->parameters = talloc_strdup(mem_ctx, "");
6403 W_ERROR_HAVE_NO_MEMORY(r->parameters);
6404 r->driver_name = talloc_strdup(mem_ctx, ntprinter->info_2->drivername);
6405 W_ERROR_HAVE_NO_MEMORY(r->driver_name);
6407 r->devmode = devmode;
6409 r->text_status = talloc_strdup(mem_ctx, "");
6410 W_ERROR_HAVE_NO_MEMORY(r->text_status);
6412 r->secdesc = NULL;
6414 r->status = nt_printj_status(queue->status);
6415 r->priority = queue->priority;
6416 r->position = position;
6417 r->start_time = 0;
6418 r->until_time = 0;
6419 r->total_pages = queue->page_count;
6420 r->size = queue->size;
6421 init_systemtime(&r->submitted, t);
6422 r->time = 0;
6423 r->pages_printed = 0; /* ??? */
6425 return WERR_OK;
6428 /****************************************************************************
6429 fill_job_info3
6430 ****************************************************************************/
6432 static WERROR fill_job_info3(TALLOC_CTX *mem_ctx,
6433 struct spoolss_JobInfo3 *r,
6434 const print_queue_struct *queue,
6435 const print_queue_struct *next_queue,
6436 int position, int snum,
6437 const NT_PRINTER_INFO_LEVEL *ntprinter)
6439 r->job_id = queue->job;
6440 r->next_job_id = 0;
6441 if (next_queue) {
6442 r->next_job_id = next_queue->job;
6444 r->reserved = 0;
6446 return WERR_OK;
6449 /****************************************************************************
6450 Enumjobs at level 1.
6451 ****************************************************************************/
6453 static WERROR enumjobs_level1(TALLOC_CTX *mem_ctx,
6454 const print_queue_struct *queue,
6455 uint32_t num_queues, int snum,
6456 const NT_PRINTER_INFO_LEVEL *ntprinter,
6457 union spoolss_JobInfo **info_p,
6458 uint32_t *count)
6460 union spoolss_JobInfo *info;
6461 int i;
6462 WERROR result = WERR_OK;
6464 info = TALLOC_ARRAY(mem_ctx, union spoolss_JobInfo, num_queues);
6465 W_ERROR_HAVE_NO_MEMORY(info);
6467 *count = num_queues;
6469 for (i=0; i<*count; i++) {
6470 result = fill_job_info1(info,
6471 &info[i].info1,
6472 &queue[i],
6474 snum,
6475 ntprinter);
6476 if (!W_ERROR_IS_OK(result)) {
6477 goto out;
6481 out:
6482 if (!W_ERROR_IS_OK(result)) {
6483 TALLOC_FREE(info);
6484 *count = 0;
6485 return result;
6488 *info_p = info;
6490 return WERR_OK;
6493 /****************************************************************************
6494 Enumjobs at level 2.
6495 ****************************************************************************/
6497 static WERROR enumjobs_level2(TALLOC_CTX *mem_ctx,
6498 const print_queue_struct *queue,
6499 uint32_t num_queues, int snum,
6500 const NT_PRINTER_INFO_LEVEL *ntprinter,
6501 union spoolss_JobInfo **info_p,
6502 uint32_t *count)
6504 union spoolss_JobInfo *info;
6505 int i;
6506 WERROR result = WERR_OK;
6508 info = TALLOC_ARRAY(mem_ctx, union spoolss_JobInfo, num_queues);
6509 W_ERROR_HAVE_NO_MEMORY(info);
6511 *count = num_queues;
6513 for (i=0; i<*count; i++) {
6515 struct spoolss_DeviceMode *devmode;
6517 devmode = construct_dev_mode(info, lp_const_servicename(snum));
6518 if (!devmode) {
6519 result = WERR_NOMEM;
6520 goto out;
6523 result = fill_job_info2(info,
6524 &info[i].info2,
6525 &queue[i],
6527 snum,
6528 ntprinter,
6529 devmode);
6530 if (!W_ERROR_IS_OK(result)) {
6531 goto out;
6535 out:
6536 if (!W_ERROR_IS_OK(result)) {
6537 TALLOC_FREE(info);
6538 *count = 0;
6539 return result;
6542 *info_p = info;
6544 return WERR_OK;
6547 /****************************************************************************
6548 Enumjobs at level 3.
6549 ****************************************************************************/
6551 static WERROR enumjobs_level3(TALLOC_CTX *mem_ctx,
6552 const print_queue_struct *queue,
6553 uint32_t num_queues, int snum,
6554 const NT_PRINTER_INFO_LEVEL *ntprinter,
6555 union spoolss_JobInfo **info_p,
6556 uint32_t *count)
6558 union spoolss_JobInfo *info;
6559 int i;
6560 WERROR result = WERR_OK;
6562 info = TALLOC_ARRAY(mem_ctx, union spoolss_JobInfo, num_queues);
6563 W_ERROR_HAVE_NO_MEMORY(info);
6565 *count = num_queues;
6567 for (i=0; i<*count; i++) {
6568 const print_queue_struct *next_queue = NULL;
6570 if (i+1 < *count) {
6571 next_queue = &queue[i+1];
6574 result = fill_job_info3(info,
6575 &info[i].info3,
6576 &queue[i],
6577 next_queue,
6579 snum,
6580 ntprinter);
6581 if (!W_ERROR_IS_OK(result)) {
6582 goto out;
6586 out:
6587 if (!W_ERROR_IS_OK(result)) {
6588 TALLOC_FREE(info);
6589 *count = 0;
6590 return result;
6593 *info_p = info;
6595 return WERR_OK;
6598 /****************************************************************
6599 _spoolss_EnumJobs
6600 ****************************************************************/
6602 WERROR _spoolss_EnumJobs(pipes_struct *p,
6603 struct spoolss_EnumJobs *r)
6605 WERROR result;
6606 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
6607 int snum;
6608 print_status_struct prt_status;
6609 print_queue_struct *queue = NULL;
6610 uint32_t count;
6612 /* that's an [in out] buffer */
6614 if (!r->in.buffer && (r->in.offered != 0)) {
6615 return WERR_INVALID_PARAM;
6618 DEBUG(4,("_spoolss_EnumJobs\n"));
6620 *r->out.needed = 0;
6621 *r->out.count = 0;
6622 *r->out.info = NULL;
6624 /* lookup the printer snum and tdb entry */
6626 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
6627 return WERR_BADFID;
6630 result = get_a_printer(NULL, &ntprinter, 2, lp_servicename(snum));
6631 if (!W_ERROR_IS_OK(result)) {
6632 return result;
6635 count = print_queue_status(snum, &queue, &prt_status);
6636 DEBUGADD(4,("count:[%d], status:[%d], [%s]\n",
6637 count, prt_status.status, prt_status.message));
6639 if (count == 0) {
6640 SAFE_FREE(queue);
6641 free_a_printer(&ntprinter, 2);
6642 return WERR_OK;
6645 switch (r->in.level) {
6646 case 1:
6647 result = enumjobs_level1(p->mem_ctx, queue, count, snum,
6648 ntprinter, r->out.info, r->out.count);
6649 break;
6650 case 2:
6651 result = enumjobs_level2(p->mem_ctx, queue, count, snum,
6652 ntprinter, r->out.info, r->out.count);
6653 break;
6654 case 3:
6655 result = enumjobs_level3(p->mem_ctx, queue, count, snum,
6656 ntprinter, r->out.info, r->out.count);
6657 break;
6658 default:
6659 result = WERR_UNKNOWN_LEVEL;
6660 break;
6663 SAFE_FREE(queue);
6664 free_a_printer(&ntprinter, 2);
6666 if (!W_ERROR_IS_OK(result)) {
6667 return result;
6670 *r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
6671 spoolss_EnumJobs, NULL,
6672 *r->out.info, r->in.level,
6673 *r->out.count);
6674 *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
6675 *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, 0);
6677 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
6680 /****************************************************************
6681 _spoolss_ScheduleJob
6682 ****************************************************************/
6684 WERROR _spoolss_ScheduleJob(pipes_struct *p,
6685 struct spoolss_ScheduleJob *r)
6687 return WERR_OK;
6690 /****************************************************************
6691 _spoolss_SetJob
6692 ****************************************************************/
6694 WERROR _spoolss_SetJob(pipes_struct *p,
6695 struct spoolss_SetJob *r)
6697 int snum;
6698 WERROR errcode = WERR_BADFUNC;
6700 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
6701 return WERR_BADFID;
6704 if (!print_job_exists(lp_const_servicename(snum), r->in.job_id)) {
6705 return WERR_INVALID_PRINTER_NAME;
6708 switch (r->in.command) {
6709 case SPOOLSS_JOB_CONTROL_CANCEL:
6710 case SPOOLSS_JOB_CONTROL_DELETE:
6711 if (print_job_delete(p->server_info, snum, r->in.job_id, &errcode)) {
6712 errcode = WERR_OK;
6714 break;
6715 case SPOOLSS_JOB_CONTROL_PAUSE:
6716 if (print_job_pause(p->server_info, snum, r->in.job_id, &errcode)) {
6717 errcode = WERR_OK;
6719 break;
6720 case SPOOLSS_JOB_CONTROL_RESTART:
6721 case SPOOLSS_JOB_CONTROL_RESUME:
6722 if (print_job_resume(p->server_info, snum, r->in.job_id, &errcode)) {
6723 errcode = WERR_OK;
6725 break;
6726 default:
6727 return WERR_UNKNOWN_LEVEL;
6730 return errcode;
6733 /****************************************************************************
6734 Enumerates all printer drivers by level.
6735 ****************************************************************************/
6737 static WERROR enumprinterdrivers_level(TALLOC_CTX *mem_ctx,
6738 const char *servername,
6739 const char *architecture,
6740 uint32_t level,
6741 union spoolss_DriverInfo **info_p,
6742 uint32_t *count_p)
6744 int i;
6745 int ndrivers;
6746 uint32_t version;
6747 fstring *list = NULL;
6748 NT_PRINTER_DRIVER_INFO_LEVEL driver;
6749 union spoolss_DriverInfo *info = NULL;
6750 uint32_t count = 0;
6751 WERROR result = WERR_OK;
6753 *count_p = 0;
6754 *info_p = NULL;
6756 for (version=0; version<DRIVER_MAX_VERSION; version++) {
6757 list = NULL;
6758 ndrivers = get_ntdrivers(&list, architecture, version);
6759 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n",
6760 ndrivers, architecture, version));
6762 if (ndrivers == -1) {
6763 result = WERR_NOMEM;
6764 goto out;
6767 if (ndrivers != 0) {
6768 info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
6769 union spoolss_DriverInfo,
6770 count + ndrivers);
6771 if (!info) {
6772 DEBUG(0,("enumprinterdrivers_level1: "
6773 "failed to enlarge driver info buffer!\n"));
6774 result = WERR_NOMEM;
6775 goto out;
6779 for (i=0; i<ndrivers; i++) {
6780 DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
6781 ZERO_STRUCT(driver);
6782 result = get_a_printer_driver(&driver, 3, list[i],
6783 architecture, version);
6784 if (!W_ERROR_IS_OK(result)) {
6785 goto out;
6788 switch (level) {
6789 case 1:
6790 result = fill_printer_driver_info1(info, &info[count+i].info1,
6791 &driver, servername,
6792 architecture);
6793 break;
6794 case 2:
6795 result = fill_printer_driver_info2(info, &info[count+i].info2,
6796 &driver, servername);
6797 break;
6798 case 3:
6799 result = fill_printer_driver_info3(info, &info[count+i].info3,
6800 &driver, servername);
6801 break;
6802 case 4:
6803 result = fill_printer_driver_info4(info, &info[count+i].info4,
6804 &driver, servername);
6805 break;
6806 case 5:
6807 result = fill_printer_driver_info5(info, &info[count+i].info5,
6808 &driver, servername);
6809 break;
6810 case 6:
6811 result = fill_printer_driver_info6(info, &info[count+i].info6,
6812 &driver, servername);
6813 break;
6814 default:
6815 result = WERR_UNKNOWN_LEVEL;
6816 break;
6819 if (!W_ERROR_IS_OK(result)) {
6820 free_a_printer_driver(driver, 3);
6821 goto out;
6823 free_a_printer_driver(driver, 3);
6826 count += ndrivers;
6827 SAFE_FREE(list);
6830 out:
6831 SAFE_FREE(list);
6833 if (!W_ERROR_IS_OK(result)) {
6834 TALLOC_FREE(info);
6835 return result;
6838 *info_p = info;
6839 *count_p = count;
6841 return WERR_OK;
6844 /****************************************************************************
6845 Enumerates all printer drivers at level 1.
6846 ****************************************************************************/
6848 static WERROR enumprinterdrivers_level1(TALLOC_CTX *mem_ctx,
6849 const char *servername,
6850 const char *architecture,
6851 union spoolss_DriverInfo **info_p,
6852 uint32_t *count)
6854 return enumprinterdrivers_level(mem_ctx, servername, architecture, 1,
6855 info_p, count);
6858 /****************************************************************************
6859 Enumerates all printer drivers at level 2.
6860 ****************************************************************************/
6862 static WERROR enumprinterdrivers_level2(TALLOC_CTX *mem_ctx,
6863 const char *servername,
6864 const char *architecture,
6865 union spoolss_DriverInfo **info_p,
6866 uint32_t *count)
6868 return enumprinterdrivers_level(mem_ctx, servername, architecture, 2,
6869 info_p, count);
6872 /****************************************************************************
6873 Enumerates all printer drivers at level 3.
6874 ****************************************************************************/
6876 static WERROR enumprinterdrivers_level3(TALLOC_CTX *mem_ctx,
6877 const char *servername,
6878 const char *architecture,
6879 union spoolss_DriverInfo **info_p,
6880 uint32_t *count)
6882 return enumprinterdrivers_level(mem_ctx, servername, architecture, 3,
6883 info_p, count);
6886 /****************************************************************************
6887 Enumerates all printer drivers at level 4.
6888 ****************************************************************************/
6890 static WERROR enumprinterdrivers_level4(TALLOC_CTX *mem_ctx,
6891 const char *servername,
6892 const char *architecture,
6893 union spoolss_DriverInfo **info_p,
6894 uint32_t *count)
6896 return enumprinterdrivers_level(mem_ctx, servername, architecture, 4,
6897 info_p, count);
6900 /****************************************************************************
6901 Enumerates all printer drivers at level 5.
6902 ****************************************************************************/
6904 static WERROR enumprinterdrivers_level5(TALLOC_CTX *mem_ctx,
6905 const char *servername,
6906 const char *architecture,
6907 union spoolss_DriverInfo **info_p,
6908 uint32_t *count)
6910 return enumprinterdrivers_level(mem_ctx, servername, architecture, 5,
6911 info_p, count);
6914 /****************************************************************************
6915 Enumerates all printer drivers at level 6.
6916 ****************************************************************************/
6918 static WERROR enumprinterdrivers_level6(TALLOC_CTX *mem_ctx,
6919 const char *servername,
6920 const char *architecture,
6921 union spoolss_DriverInfo **info_p,
6922 uint32_t *count)
6924 return enumprinterdrivers_level(mem_ctx, servername, architecture, 6,
6925 info_p, count);
6929 /****************************************************************
6930 _spoolss_EnumPrinterDrivers
6931 ****************************************************************/
6933 WERROR _spoolss_EnumPrinterDrivers(pipes_struct *p,
6934 struct spoolss_EnumPrinterDrivers *r)
6936 const char *cservername;
6937 WERROR result;
6939 /* that's an [in out] buffer */
6941 if (!r->in.buffer && (r->in.offered != 0)) {
6942 return WERR_INVALID_PARAM;
6945 DEBUG(4,("_spoolss_EnumPrinterDrivers\n"));
6947 *r->out.needed = 0;
6948 *r->out.count = 0;
6949 *r->out.info = NULL;
6951 cservername = canon_servername(r->in.server);
6953 if (!is_myname_or_ipaddr(cservername)) {
6954 return WERR_UNKNOWN_PRINTER_DRIVER;
6957 switch (r->in.level) {
6958 case 1:
6959 result = enumprinterdrivers_level1(p->mem_ctx, cservername,
6960 r->in.environment,
6961 r->out.info, r->out.count);
6962 break;
6963 case 2:
6964 result = enumprinterdrivers_level2(p->mem_ctx, cservername,
6965 r->in.environment,
6966 r->out.info, r->out.count);
6967 break;
6968 case 3:
6969 result = enumprinterdrivers_level3(p->mem_ctx, cservername,
6970 r->in.environment,
6971 r->out.info, r->out.count);
6972 break;
6973 case 4:
6974 result = enumprinterdrivers_level4(p->mem_ctx, cservername,
6975 r->in.environment,
6976 r->out.info, r->out.count);
6977 break;
6978 case 5:
6979 result = enumprinterdrivers_level5(p->mem_ctx, cservername,
6980 r->in.environment,
6981 r->out.info, r->out.count);
6982 break;
6983 case 6:
6984 result = enumprinterdrivers_level6(p->mem_ctx, cservername,
6985 r->in.environment,
6986 r->out.info, r->out.count);
6987 break;
6988 default:
6989 return WERR_UNKNOWN_LEVEL;
6992 if (!W_ERROR_IS_OK(result)) {
6993 return result;
6996 *r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
6997 spoolss_EnumPrinterDrivers, NULL,
6998 *r->out.info, r->in.level,
6999 *r->out.count);
7000 *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
7001 *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, 0);
7003 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
7006 /****************************************************************************
7007 ****************************************************************************/
7009 static WERROR fill_form_info_1(TALLOC_CTX *mem_ctx,
7010 struct spoolss_FormInfo1 *r,
7011 const nt_forms_struct *form)
7013 r->form_name = talloc_strdup(mem_ctx, form->name);
7014 W_ERROR_HAVE_NO_MEMORY(r->form_name);
7016 r->flags = form->flag;
7017 r->size.width = form->width;
7018 r->size.height = form->length;
7019 r->area.left = form->left;
7020 r->area.top = form->top;
7021 r->area.right = form->right;
7022 r->area.bottom = form->bottom;
7024 return WERR_OK;
7027 /****************************************************************
7028 spoolss_enumforms_level1
7029 ****************************************************************/
7031 static WERROR spoolss_enumforms_level1(TALLOC_CTX *mem_ctx,
7032 const nt_forms_struct *builtin_forms,
7033 uint32_t num_builtin_forms,
7034 const nt_forms_struct *user_forms,
7035 uint32_t num_user_forms,
7036 union spoolss_FormInfo **info_p,
7037 uint32_t *count)
7039 union spoolss_FormInfo *info;
7040 WERROR result = WERR_OK;
7041 int i;
7043 *count = num_builtin_forms + num_user_forms;
7045 info = TALLOC_ARRAY(mem_ctx, union spoolss_FormInfo, *count);
7046 W_ERROR_HAVE_NO_MEMORY(info);
7048 /* construct the list of form structures */
7049 for (i=0; i<num_builtin_forms; i++) {
7050 DEBUGADD(6,("Filling builtin form number [%d]\n",i));
7051 result = fill_form_info_1(info, &info[i].info1,
7052 &builtin_forms[i]);
7053 if (!W_ERROR_IS_OK(result)) {
7054 goto out;
7058 for (i=0; i<num_user_forms; i++) {
7059 DEBUGADD(6,("Filling user form number [%d]\n",i));
7060 result = fill_form_info_1(info, &info[i+num_builtin_forms].info1,
7061 &user_forms[i]);
7062 if (!W_ERROR_IS_OK(result)) {
7063 goto out;
7067 out:
7068 if (!W_ERROR_IS_OK(result)) {
7069 TALLOC_FREE(info);
7070 *count = 0;
7071 return result;
7074 *info_p = info;
7076 return WERR_OK;
7079 /****************************************************************
7080 _spoolss_EnumForms
7081 ****************************************************************/
7083 WERROR _spoolss_EnumForms(pipes_struct *p,
7084 struct spoolss_EnumForms *r)
7086 WERROR result;
7087 nt_forms_struct *user_forms = NULL;
7088 nt_forms_struct *builtin_forms = NULL;
7089 uint32_t num_user_forms;
7090 uint32_t num_builtin_forms;
7092 *r->out.count = 0;
7093 *r->out.needed = 0;
7094 *r->out.info = NULL;
7096 /* that's an [in out] buffer */
7098 if (!r->in.buffer && (r->in.offered != 0) ) {
7099 return WERR_INVALID_PARAM;
7102 DEBUG(4,("_spoolss_EnumForms\n"));
7103 DEBUGADD(5,("Offered buffer size [%d]\n", r->in.offered));
7104 DEBUGADD(5,("Info level [%d]\n", r->in.level));
7106 num_builtin_forms = get_builtin_ntforms(&builtin_forms);
7107 DEBUGADD(5,("Number of builtin forms [%d]\n", num_builtin_forms));
7108 num_user_forms = get_ntforms(&user_forms);
7109 DEBUGADD(5,("Number of user forms [%d]\n", num_user_forms));
7111 if (num_user_forms + num_builtin_forms == 0) {
7112 SAFE_FREE(builtin_forms);
7113 SAFE_FREE(user_forms);
7114 return WERR_NO_MORE_ITEMS;
7117 switch (r->in.level) {
7118 case 1:
7119 result = spoolss_enumforms_level1(p->mem_ctx,
7120 builtin_forms,
7121 num_builtin_forms,
7122 user_forms,
7123 num_user_forms,
7124 r->out.info,
7125 r->out.count);
7126 break;
7127 default:
7128 result = WERR_UNKNOWN_LEVEL;
7129 break;
7132 SAFE_FREE(user_forms);
7133 SAFE_FREE(builtin_forms);
7135 if (!W_ERROR_IS_OK(result)) {
7136 return result;
7139 *r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
7140 spoolss_EnumForms, NULL,
7141 *r->out.info, r->in.level,
7142 *r->out.count);
7143 *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
7144 *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, 0);
7146 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
7149 /****************************************************************
7150 ****************************************************************/
7152 static WERROR find_form_byname(const char *name,
7153 nt_forms_struct *form)
7155 nt_forms_struct *list = NULL;
7156 int num_forms = 0, i = 0;
7158 if (get_a_builtin_ntform_by_string(name, form)) {
7159 return WERR_OK;
7162 num_forms = get_ntforms(&list);
7163 DEBUGADD(5,("Number of forms [%d]\n", num_forms));
7165 if (num_forms == 0) {
7166 return WERR_BADFID;
7169 /* Check if the requested name is in the list of form structures */
7170 for (i = 0; i < num_forms; i++) {
7172 DEBUG(4,("checking form %s (want %s)\n", list[i].name, name));
7174 if (strequal(name, list[i].name)) {
7175 DEBUGADD(6,("Found form %s number [%d]\n", name, i));
7176 *form = list[i];
7177 SAFE_FREE(list);
7178 return WERR_OK;
7182 SAFE_FREE(list);
7184 return WERR_BADFID;
7187 /****************************************************************
7188 _spoolss_GetForm
7189 ****************************************************************/
7191 WERROR _spoolss_GetForm(pipes_struct *p,
7192 struct spoolss_GetForm *r)
7194 WERROR result;
7195 nt_forms_struct form;
7197 /* that's an [in out] buffer */
7199 if (!r->in.buffer && (r->in.offered != 0)) {
7200 return WERR_INVALID_PARAM;
7203 DEBUG(4,("_spoolss_GetForm\n"));
7204 DEBUGADD(5,("Offered buffer size [%d]\n", r->in.offered));
7205 DEBUGADD(5,("Info level [%d]\n", r->in.level));
7207 result = find_form_byname(r->in.form_name, &form);
7208 if (!W_ERROR_IS_OK(result)) {
7209 TALLOC_FREE(r->out.info);
7210 return result;
7213 switch (r->in.level) {
7214 case 1:
7215 result = fill_form_info_1(p->mem_ctx,
7216 &r->out.info->info1,
7217 &form);
7218 break;
7220 default:
7221 result = WERR_UNKNOWN_LEVEL;
7222 break;
7225 if (!W_ERROR_IS_OK(result)) {
7226 TALLOC_FREE(r->out.info);
7227 return result;
7230 *r->out.needed = SPOOLSS_BUFFER_UNION(spoolss_FormInfo, NULL,
7231 r->out.info, r->in.level);
7232 r->out.info = SPOOLSS_BUFFER_OK(r->out.info, NULL);
7234 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
7237 /****************************************************************************
7238 ****************************************************************************/
7240 static WERROR fill_port_1(TALLOC_CTX *mem_ctx,
7241 struct spoolss_PortInfo1 *r,
7242 const char *name)
7244 r->port_name = talloc_strdup(mem_ctx, name);
7245 W_ERROR_HAVE_NO_MEMORY(r->port_name);
7247 return WERR_OK;
7250 /****************************************************************************
7251 TODO: This probably needs distinguish between TCP/IP and Local ports
7252 somehow.
7253 ****************************************************************************/
7255 static WERROR fill_port_2(TALLOC_CTX *mem_ctx,
7256 struct spoolss_PortInfo2 *r,
7257 const char *name)
7259 r->port_name = talloc_strdup(mem_ctx, name);
7260 W_ERROR_HAVE_NO_MEMORY(r->port_name);
7262 r->monitor_name = talloc_strdup(mem_ctx, "Local Monitor");
7263 W_ERROR_HAVE_NO_MEMORY(r->monitor_name);
7265 r->description = talloc_strdup(mem_ctx, SPL_LOCAL_PORT);
7266 W_ERROR_HAVE_NO_MEMORY(r->description);
7268 r->port_type = SPOOLSS_PORT_TYPE_WRITE;
7269 r->reserved = 0;
7271 return WERR_OK;
7275 /****************************************************************************
7276 wrapper around the enumer ports command
7277 ****************************************************************************/
7279 WERROR enumports_hook(TALLOC_CTX *ctx, int *count, char ***lines )
7281 char *cmd = lp_enumports_cmd();
7282 char **qlines = NULL;
7283 char *command = NULL;
7284 int numlines;
7285 int ret;
7286 int fd;
7288 *count = 0;
7289 *lines = NULL;
7291 /* if no hook then just fill in the default port */
7293 if ( !*cmd ) {
7294 if (!(qlines = TALLOC_ARRAY( NULL, char*, 2 ))) {
7295 return WERR_NOMEM;
7297 if (!(qlines[0] = talloc_strdup(qlines, SAMBA_PRINTER_PORT_NAME ))) {
7298 TALLOC_FREE(qlines);
7299 return WERR_NOMEM;
7301 qlines[1] = NULL;
7302 numlines = 1;
7304 else {
7305 /* we have a valid enumport command */
7307 command = talloc_asprintf(ctx, "%s \"%d\"", cmd, 1);
7308 if (!command) {
7309 return WERR_NOMEM;
7312 DEBUG(10,("Running [%s]\n", command));
7313 ret = smbrun(command, &fd);
7314 DEBUG(10,("Returned [%d]\n", ret));
7315 TALLOC_FREE(command);
7316 if (ret != 0) {
7317 if (fd != -1) {
7318 close(fd);
7320 return WERR_ACCESS_DENIED;
7323 numlines = 0;
7324 qlines = fd_lines_load(fd, &numlines, 0, NULL);
7325 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
7326 close(fd);
7329 *count = numlines;
7330 *lines = qlines;
7332 return WERR_OK;
7335 /****************************************************************************
7336 enumports level 1.
7337 ****************************************************************************/
7339 static WERROR enumports_level_1(TALLOC_CTX *mem_ctx,
7340 union spoolss_PortInfo **info_p,
7341 uint32_t *count)
7343 union spoolss_PortInfo *info = NULL;
7344 int i=0;
7345 WERROR result = WERR_OK;
7346 char **qlines = NULL;
7347 int numlines = 0;
7349 result = enumports_hook(talloc_tos(), &numlines, &qlines );
7350 if (!W_ERROR_IS_OK(result)) {
7351 goto out;
7354 if (numlines) {
7355 info = TALLOC_ARRAY(mem_ctx, union spoolss_PortInfo, numlines);
7356 if (!info) {
7357 DEBUG(10,("Returning WERR_NOMEM\n"));
7358 result = WERR_NOMEM;
7359 goto out;
7362 for (i=0; i<numlines; i++) {
7363 DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
7364 result = fill_port_1(info, &info[i].info1, qlines[i]);
7365 if (!W_ERROR_IS_OK(result)) {
7366 goto out;
7370 TALLOC_FREE(qlines);
7372 out:
7373 if (!W_ERROR_IS_OK(result)) {
7374 TALLOC_FREE(info);
7375 TALLOC_FREE(qlines);
7376 *count = 0;
7377 *info_p = NULL;
7378 return result;
7381 *info_p = info;
7382 *count = numlines;
7384 return WERR_OK;
7387 /****************************************************************************
7388 enumports level 2.
7389 ****************************************************************************/
7391 static WERROR enumports_level_2(TALLOC_CTX *mem_ctx,
7392 union spoolss_PortInfo **info_p,
7393 uint32_t *count)
7395 union spoolss_PortInfo *info = NULL;
7396 int i=0;
7397 WERROR result = WERR_OK;
7398 char **qlines = NULL;
7399 int numlines = 0;
7401 result = enumports_hook(talloc_tos(), &numlines, &qlines );
7402 if (!W_ERROR_IS_OK(result)) {
7403 goto out;
7406 if (numlines) {
7407 info = TALLOC_ARRAY(mem_ctx, union spoolss_PortInfo, numlines);
7408 if (!info) {
7409 DEBUG(10,("Returning WERR_NOMEM\n"));
7410 result = WERR_NOMEM;
7411 goto out;
7414 for (i=0; i<numlines; i++) {
7415 DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
7416 result = fill_port_2(info, &info[i].info2, qlines[i]);
7417 if (!W_ERROR_IS_OK(result)) {
7418 goto out;
7422 TALLOC_FREE(qlines);
7424 out:
7425 if (!W_ERROR_IS_OK(result)) {
7426 TALLOC_FREE(info);
7427 TALLOC_FREE(qlines);
7428 *count = 0;
7429 *info_p = NULL;
7430 return result;
7433 *info_p = info;
7434 *count = numlines;
7436 return WERR_OK;
7439 /****************************************************************
7440 _spoolss_EnumPorts
7441 ****************************************************************/
7443 WERROR _spoolss_EnumPorts(pipes_struct *p,
7444 struct spoolss_EnumPorts *r)
7446 WERROR result;
7448 /* that's an [in out] buffer */
7450 if (!r->in.buffer && (r->in.offered != 0)) {
7451 return WERR_INVALID_PARAM;
7454 DEBUG(4,("_spoolss_EnumPorts\n"));
7456 *r->out.count = 0;
7457 *r->out.needed = 0;
7458 *r->out.info = NULL;
7460 switch (r->in.level) {
7461 case 1:
7462 result = enumports_level_1(p->mem_ctx, r->out.info,
7463 r->out.count);
7464 break;
7465 case 2:
7466 result = enumports_level_2(p->mem_ctx, r->out.info,
7467 r->out.count);
7468 break;
7469 default:
7470 return WERR_UNKNOWN_LEVEL;
7473 if (!W_ERROR_IS_OK(result)) {
7474 return result;
7477 *r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
7478 spoolss_EnumPorts, NULL,
7479 *r->out.info, r->in.level,
7480 *r->out.count);
7481 *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
7482 *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, 0);
7484 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
7487 /****************************************************************************
7488 ****************************************************************************/
7490 static WERROR spoolss_addprinterex_level_2(pipes_struct *p,
7491 const char *server,
7492 struct spoolss_SetPrinterInfoCtr *info_ctr,
7493 struct spoolss_DeviceMode *devmode,
7494 struct security_descriptor *sec_desc,
7495 struct spoolss_UserLevelCtr *user_ctr,
7496 struct policy_handle *handle)
7498 NT_PRINTER_INFO_LEVEL *printer = NULL;
7499 fstring name;
7500 int snum;
7501 WERROR err = WERR_OK;
7503 if ( !(printer = TALLOC_ZERO_P(NULL, NT_PRINTER_INFO_LEVEL)) ) {
7504 DEBUG(0,("spoolss_addprinterex_level_2: malloc fail.\n"));
7505 return WERR_NOMEM;
7508 /* convert from UNICODE to ASCII - this allocates the info_2 struct inside *printer.*/
7509 if (!convert_printer_info(info_ctr, printer)) {
7510 free_a_printer(&printer, 2);
7511 return WERR_NOMEM;
7514 /* check to see if the printer already exists */
7516 if ((snum = print_queue_snum(printer->info_2->sharename)) != -1) {
7517 DEBUG(5, ("spoolss_addprinterex_level_2: Attempted to add a printer named [%s] when one already existed!\n",
7518 printer->info_2->sharename));
7519 free_a_printer(&printer, 2);
7520 return WERR_PRINTER_ALREADY_EXISTS;
7523 /* FIXME!!! smbd should check to see if the driver is installed before
7524 trying to add a printer like this --jerry */
7526 if (*lp_addprinter_cmd() ) {
7527 if ( !add_printer_hook(p->mem_ctx, p->server_info->ptok,
7528 printer) ) {
7529 free_a_printer(&printer,2);
7530 return WERR_ACCESS_DENIED;
7532 } else {
7533 DEBUG(0,("spoolss_addprinterex_level_2: add printer for printer %s called and no"
7534 "smb.conf parameter \"addprinter command\" is defined. This"
7535 "parameter must exist for this call to succeed\n",
7536 printer->info_2->sharename ));
7539 /* use our primary netbios name since get_a_printer() will convert
7540 it to what the client expects on a case by case basis */
7542 slprintf(name, sizeof(name)-1, "\\\\%s\\%s", global_myname(),
7543 printer->info_2->sharename);
7546 if ((snum = print_queue_snum(printer->info_2->sharename)) == -1) {
7547 free_a_printer(&printer,2);
7548 return WERR_ACCESS_DENIED;
7551 /* you must be a printer admin to add a new printer */
7552 if (!print_access_check(p->server_info, snum, PRINTER_ACCESS_ADMINISTER)) {
7553 free_a_printer(&printer,2);
7554 return WERR_ACCESS_DENIED;
7558 * Do sanity check on the requested changes for Samba.
7561 if (!check_printer_ok(printer->info_2, snum)) {
7562 free_a_printer(&printer,2);
7563 return WERR_INVALID_PARAM;
7567 * When a printer is created, the drivername bound to the printer is used
7568 * to lookup previously saved driver initialization info, which is then
7569 * bound to the new printer, simulating what happens in the Windows arch.
7572 if (!devmode)
7574 set_driver_init(printer, 2);
7576 else
7578 /* A valid devmode was included, convert and link it
7580 DEBUGADD(10, ("spoolss_addprinterex_level_2: devmode included, converting\n"));
7582 if (!convert_devicemode(printer->info_2->printername, devmode,
7583 &printer->info_2->devmode)) {
7584 return WERR_NOMEM;
7588 /* write the ASCII on disk */
7589 err = mod_a_printer(printer, 2);
7590 if (!W_ERROR_IS_OK(err)) {
7591 free_a_printer(&printer,2);
7592 return err;
7595 if (!open_printer_hnd(p, handle, name, PRINTER_ACCESS_ADMINISTER)) {
7596 /* Handle open failed - remove addition. */
7597 del_a_printer(printer->info_2->sharename);
7598 free_a_printer(&printer,2);
7599 ZERO_STRUCTP(handle);
7600 return WERR_ACCESS_DENIED;
7603 update_c_setprinter(false);
7604 free_a_printer(&printer,2);
7606 return WERR_OK;
7609 /****************************************************************
7610 _spoolss_AddPrinterEx
7611 ****************************************************************/
7613 WERROR _spoolss_AddPrinterEx(pipes_struct *p,
7614 struct spoolss_AddPrinterEx *r)
7616 switch (r->in.info_ctr->level) {
7617 case 1:
7618 /* we don't handle yet */
7619 /* but I know what to do ... */
7620 return WERR_UNKNOWN_LEVEL;
7621 case 2:
7622 return spoolss_addprinterex_level_2(p, r->in.server,
7623 r->in.info_ctr,
7624 r->in.devmode_ctr->devmode,
7625 r->in.secdesc_ctr->sd,
7626 r->in.userlevel_ctr,
7627 r->out.handle);
7628 default:
7629 return WERR_UNKNOWN_LEVEL;
7633 /****************************************************************
7634 _spoolss_AddPrinterDriver
7635 ****************************************************************/
7637 WERROR _spoolss_AddPrinterDriver(pipes_struct *p,
7638 struct spoolss_AddPrinterDriver *r)
7640 uint32_t level = r->in.info_ctr->level;
7641 struct spoolss_AddDriverInfoCtr *info = r->in.info_ctr;
7642 WERROR err = WERR_OK;
7643 NT_PRINTER_DRIVER_INFO_LEVEL driver;
7644 const char *driver_name = NULL;
7645 uint32_t version;
7646 const char *fn;
7648 switch (p->hdr_req.opnum) {
7649 case NDR_SPOOLSS_ADDPRINTERDRIVER:
7650 fn = "_spoolss_AddPrinterDriver";
7651 break;
7652 case NDR_SPOOLSS_ADDPRINTERDRIVEREX:
7653 fn = "_spoolss_AddPrinterDriverEx";
7654 break;
7655 default:
7656 return WERR_INVALID_PARAM;
7660 /* FIXME */
7661 if (level != 3 && level != 6) {
7662 /* Clever hack from Martin Zielinski <mz@seh.de>
7663 * to allow downgrade from level 8 (Vista).
7665 DEBUG(0,("%s: level %d not yet implemented\n", fn, level));
7666 return WERR_UNKNOWN_LEVEL;
7669 ZERO_STRUCT(driver);
7671 if (!convert_printer_driver_info(info, &driver, level)) {
7672 err = WERR_NOMEM;
7673 goto done;
7676 DEBUG(5,("Cleaning driver's information\n"));
7677 err = clean_up_driver_struct(p, driver, level);
7678 if (!W_ERROR_IS_OK(err))
7679 goto done;
7681 DEBUG(5,("Moving driver to final destination\n"));
7682 if( !W_ERROR_IS_OK(err = move_driver_to_download_area(p, driver, level,
7683 &err)) ) {
7684 goto done;
7687 if (add_a_printer_driver(driver, level)!=0) {
7688 err = WERR_ACCESS_DENIED;
7689 goto done;
7692 switch(level) {
7693 case 3:
7694 driver_name = driver.info_3->name ? driver.info_3->name : "";
7695 break;
7696 case 6:
7697 driver_name = driver.info_6->name ? driver.info_6->name : "";
7698 break;
7702 * I think this is where he DrvUpgradePrinter() hook would be
7703 * be called in a driver's interface DLL on a Windows NT 4.0/2k
7704 * server. Right now, we just need to send ourselves a message
7705 * to update each printer bound to this driver. --jerry
7708 if (!srv_spoolss_drv_upgrade_printer(driver_name)) {
7709 DEBUG(0,("%s: Failed to send message about upgrading driver [%s]!\n",
7710 fn, driver_name));
7714 * Based on the version (e.g. driver destination dir: 0=9x,2=Nt/2k,3=2k/Xp),
7715 * decide if the driver init data should be deleted. The rules are:
7716 * 1) never delete init data if it is a 9x driver, they don't use it anyway
7717 * 2) delete init data only if there is no 2k/Xp driver
7718 * 3) always delete init data
7719 * The generalized rule is always use init data from the highest order driver.
7720 * It is necessary to follow the driver install by an initialization step to
7721 * finish off this process.
7723 if (level == 3)
7724 version = driver.info_3->cversion;
7725 else if (level == 6)
7726 version = driver.info_6->version;
7727 else
7728 version = -1;
7729 switch (version) {
7731 * 9x printer driver - never delete init data
7733 case 0:
7734 DEBUG(10,("%s: init data not deleted for 9x driver [%s]\n",
7735 fn, driver_name));
7736 break;
7739 * Nt or 2k (compatiblity mode) printer driver - only delete init data if
7740 * there is no 2k/Xp driver init data for this driver name.
7742 case 2:
7744 NT_PRINTER_DRIVER_INFO_LEVEL driver1;
7746 if (!W_ERROR_IS_OK(get_a_printer_driver(&driver1, 3, driver_name, "Windows NT x86", 3))) {
7748 * No 2k/Xp driver found, delete init data (if any) for the new Nt driver.
7750 if (!del_driver_init(driver_name))
7751 DEBUG(6,("%s: del_driver_init(%s) Nt failed!\n",
7752 fn, driver_name));
7753 } else {
7755 * a 2k/Xp driver was found, don't delete init data because Nt driver will use it.
7757 free_a_printer_driver(driver1,3);
7758 DEBUG(10,("%s: init data not deleted for Nt driver [%s]\n",
7759 fn, driver_name));
7762 break;
7765 * 2k or Xp printer driver - always delete init data
7767 case 3:
7768 if (!del_driver_init(driver_name))
7769 DEBUG(6,("%s: del_driver_init(%s) 2k/Xp failed!\n",
7770 fn, driver_name));
7771 break;
7773 default:
7774 DEBUG(0,("%s: invalid level=%d\n", fn, level));
7775 break;
7779 done:
7780 free_a_printer_driver(driver, level);
7781 return err;
7784 /****************************************************************
7785 _spoolss_AddPrinterDriverEx
7786 ****************************************************************/
7788 WERROR _spoolss_AddPrinterDriverEx(pipes_struct *p,
7789 struct spoolss_AddPrinterDriverEx *r)
7791 struct spoolss_AddPrinterDriver a;
7794 * we only support the semantics of AddPrinterDriver()
7795 * i.e. only copy files that are newer than existing ones
7798 if (r->in.flags != APD_COPY_NEW_FILES) {
7799 return WERR_ACCESS_DENIED;
7802 a.in.servername = r->in.servername;
7803 a.in.info_ctr = r->in.info_ctr;
7805 return _spoolss_AddPrinterDriver(p, &a);
7808 /****************************************************************************
7809 ****************************************************************************/
7811 struct _spoolss_paths {
7812 int type;
7813 const char *share;
7814 const char *dir;
7817 enum { SPOOLSS_DRIVER_PATH, SPOOLSS_PRTPROCS_PATH };
7819 static const struct _spoolss_paths spoolss_paths[]= {
7820 { SPOOLSS_DRIVER_PATH, "print$", "DRIVERS" },
7821 { SPOOLSS_PRTPROCS_PATH, "prnproc$", "PRTPROCS" }
7824 static WERROR compose_spoolss_server_path(TALLOC_CTX *mem_ctx,
7825 const char *servername,
7826 const char *environment,
7827 int component,
7828 char **path)
7830 const char *pservername = NULL;
7831 const char *long_archi = SPOOLSS_ARCHITECTURE_NT_X86;
7832 const char *short_archi;
7834 *path = NULL;
7836 /* environment may be empty */
7837 if (environment && strlen(environment)) {
7838 long_archi = environment;
7841 /* servername may be empty */
7842 if (servername && strlen(servername)) {
7843 pservername = canon_servername(servername);
7845 if (!is_myname_or_ipaddr(pservername)) {
7846 return WERR_INVALID_PARAM;
7850 if (!(short_archi = get_short_archi(long_archi))) {
7851 return WERR_INVALID_ENVIRONMENT;
7854 switch (component) {
7855 case SPOOLSS_PRTPROCS_PATH:
7856 case SPOOLSS_DRIVER_PATH:
7857 if (pservername) {
7858 *path = talloc_asprintf(mem_ctx,
7859 "\\\\%s\\%s\\%s",
7860 pservername,
7861 spoolss_paths[component].share,
7862 short_archi);
7863 } else {
7864 *path = talloc_asprintf(mem_ctx, "%s\\%s\\%s",
7865 SPOOLSS_DEFAULT_SERVER_PATH,
7866 spoolss_paths[component].dir,
7867 short_archi);
7869 break;
7870 default:
7871 return WERR_INVALID_PARAM;
7874 if (!*path) {
7875 return WERR_NOMEM;
7878 return WERR_OK;
7881 /****************************************************************************
7882 ****************************************************************************/
7884 static WERROR getprinterdriverdir_level_1(TALLOC_CTX *mem_ctx,
7885 const char *servername,
7886 const char *environment,
7887 struct spoolss_DriverDirectoryInfo1 *r)
7889 WERROR werr;
7890 char *path = NULL;
7892 werr = compose_spoolss_server_path(mem_ctx,
7893 servername,
7894 environment,
7895 SPOOLSS_DRIVER_PATH,
7896 &path);
7897 if (!W_ERROR_IS_OK(werr)) {
7898 return werr;
7901 DEBUG(4,("printer driver directory: [%s]\n", path));
7903 r->directory_name = path;
7905 return WERR_OK;
7908 /****************************************************************
7909 _spoolss_GetPrinterDriverDirectory
7910 ****************************************************************/
7912 WERROR _spoolss_GetPrinterDriverDirectory(pipes_struct *p,
7913 struct spoolss_GetPrinterDriverDirectory *r)
7915 WERROR werror;
7917 /* that's an [in out] buffer */
7919 if (!r->in.buffer && (r->in.offered != 0)) {
7920 return WERR_INVALID_PARAM;
7923 DEBUG(5,("_spoolss_GetPrinterDriverDirectory: level %d\n",
7924 r->in.level));
7926 *r->out.needed = 0;
7928 /* r->in.level is ignored */
7930 werror = getprinterdriverdir_level_1(p->mem_ctx,
7931 r->in.server,
7932 r->in.environment,
7933 &r->out.info->info1);
7934 if (!W_ERROR_IS_OK(werror)) {
7935 TALLOC_FREE(r->out.info);
7936 return werror;
7939 *r->out.needed = SPOOLSS_BUFFER_UNION(spoolss_DriverDirectoryInfo, NULL,
7940 r->out.info, r->in.level);
7941 r->out.info = SPOOLSS_BUFFER_OK(r->out.info, NULL);
7943 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
7946 /****************************************************************
7947 _spoolss_EnumPrinterData
7948 ****************************************************************/
7950 WERROR _spoolss_EnumPrinterData(pipes_struct *p,
7951 struct spoolss_EnumPrinterData *r)
7953 NT_PRINTER_INFO_LEVEL *printer = NULL;
7954 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
7955 int snum;
7956 WERROR result;
7957 REGISTRY_VALUE *val = NULL;
7958 NT_PRINTER_DATA *p_data;
7959 int i, key_index, num_values;
7960 int name_length;
7962 *r->out.value_needed = 0;
7963 *r->out.type = REG_NONE;
7964 *r->out.data_needed = 0;
7966 DEBUG(5,("_spoolss_EnumPrinterData\n"));
7968 if (!Printer) {
7969 DEBUG(2,("_spoolss_EnumPrinterData: Invalid handle (%s:%u:%u).\n",
7970 OUR_HANDLE(r->in.handle)));
7971 return WERR_BADFID;
7974 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
7975 return WERR_BADFID;
7978 result = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
7979 if (!W_ERROR_IS_OK(result)) {
7980 return result;
7983 p_data = printer->info_2->data;
7984 key_index = lookup_printerkey( p_data, SPOOL_PRINTERDATA_KEY );
7986 result = WERR_OK;
7989 * The NT machine wants to know the biggest size of value and data
7991 * cf: MSDN EnumPrinterData remark section
7994 if (!r->in.value_offered && !r->in.data_offered && (key_index != -1)) {
7996 uint32_t biggest_valuesize = 0;
7997 uint32_t biggest_datasize = 0;
7999 DEBUGADD(6,("Activating NT mega-hack to find sizes\n"));
8001 num_values = regval_ctr_numvals( p_data->keys[key_index].values );
8003 for ( i=0; i<num_values; i++ )
8005 val = regval_ctr_specific_value( p_data->keys[key_index].values, i );
8007 name_length = strlen(val->valuename);
8008 if ( strlen(val->valuename) > biggest_valuesize )
8009 biggest_valuesize = name_length;
8011 if ( val->size > biggest_datasize )
8012 biggest_datasize = val->size;
8014 DEBUG(6,("current values: [%d], [%d]\n", biggest_valuesize,
8015 biggest_datasize));
8018 /* the value is an UNICODE string but real_value_size is the length
8019 in bytes including the trailing 0 */
8021 *r->out.value_needed = 2 * (1 + biggest_valuesize);
8022 *r->out.data_needed = biggest_datasize;
8024 DEBUG(6,("final values: [%d], [%d]\n",
8025 *r->out.value_needed, *r->out.data_needed));
8027 goto done;
8031 * the value len is wrong in NT sp3
8032 * that's the number of bytes not the number of unicode chars
8035 if (key_index != -1) {
8036 val = regval_ctr_specific_value(p_data->keys[key_index].values,
8037 r->in.enum_index);
8040 if (!val) {
8042 /* out_value should default to "" or else NT4 has
8043 problems unmarshalling the response */
8045 if (r->in.value_offered) {
8046 *r->out.value_needed = 1;
8047 r->out.value_name = talloc_strdup(r, "");
8048 if (!r->out.value_name) {
8049 result = WERR_NOMEM;
8050 goto done;
8052 } else {
8053 r->out.value_name = NULL;
8054 *r->out.value_needed = 0;
8057 /* the data is counted in bytes */
8059 *r->out.data_needed = r->in.data_offered;
8061 result = WERR_NO_MORE_ITEMS;
8062 } else {
8064 * the value is:
8065 * - counted in bytes in the request
8066 * - counted in UNICODE chars in the max reply
8067 * - counted in bytes in the real size
8069 * take a pause *before* coding not *during* coding
8072 /* name */
8073 if (r->in.value_offered) {
8074 r->out.value_name = talloc_strdup(r, regval_name(val));
8075 if (!r->out.value_name) {
8076 result = WERR_NOMEM;
8077 goto done;
8079 *r->out.value_needed = strlen_m_term(regval_name(val)) * 2;
8080 } else {
8081 r->out.value_name = NULL;
8082 *r->out.value_needed = 0;
8085 /* type */
8087 *r->out.type = regval_type(val);
8089 /* data - counted in bytes */
8092 * See the section "Dynamically Typed Query Parameters"
8093 * in MS-RPRN.
8096 if (r->out.data && regval_data_p(val) &&
8097 regval_size(val) && r->in.data_offered) {
8098 memcpy(r->out.data, regval_data_p(val),
8099 MIN(regval_size(val),r->in.data_offered));
8102 *r->out.data_needed = regval_size(val);
8105 done:
8106 free_a_printer(&printer, 2);
8107 return result;
8110 /****************************************************************
8111 _spoolss_SetPrinterData
8112 ****************************************************************/
8114 WERROR _spoolss_SetPrinterData(pipes_struct *p,
8115 struct spoolss_SetPrinterData *r)
8117 struct spoolss_SetPrinterDataEx r2;
8119 r2.in.handle = r->in.handle;
8120 r2.in.key_name = "PrinterDriverData";
8121 r2.in.value_name = r->in.value_name;
8122 r2.in.type = r->in.type;
8123 r2.in.data = r->in.data;
8124 r2.in.offered = r->in.offered;
8126 return _spoolss_SetPrinterDataEx(p, &r2);
8129 /****************************************************************
8130 _spoolss_ResetPrinter
8131 ****************************************************************/
8133 WERROR _spoolss_ResetPrinter(pipes_struct *p,
8134 struct spoolss_ResetPrinter *r)
8136 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
8137 int snum;
8139 DEBUG(5,("_spoolss_ResetPrinter\n"));
8142 * All we do is to check to see if the handle and queue is valid.
8143 * This call really doesn't mean anything to us because we only
8144 * support RAW printing. --jerry
8147 if (!Printer) {
8148 DEBUG(2,("_spoolss_ResetPrinter: Invalid handle (%s:%u:%u).\n",
8149 OUR_HANDLE(r->in.handle)));
8150 return WERR_BADFID;
8153 if (!get_printer_snum(p, r->in.handle, &snum, NULL))
8154 return WERR_BADFID;
8157 /* blindly return success */
8158 return WERR_OK;
8161 /****************************************************************
8162 _spoolss_DeletePrinterData
8163 ****************************************************************/
8165 WERROR _spoolss_DeletePrinterData(pipes_struct *p,
8166 struct spoolss_DeletePrinterData *r)
8168 struct spoolss_DeletePrinterDataEx r2;
8170 r2.in.handle = r->in.handle;
8171 r2.in.key_name = "PrinterDriverData";
8172 r2.in.value_name = r->in.value_name;
8174 return _spoolss_DeletePrinterDataEx(p, &r2);
8177 /****************************************************************
8178 _spoolss_AddForm
8179 ****************************************************************/
8181 WERROR _spoolss_AddForm(pipes_struct *p,
8182 struct spoolss_AddForm *r)
8184 struct spoolss_AddFormInfo1 *form = r->in.info.info1;
8185 nt_forms_struct tmpForm;
8186 int snum = -1;
8187 WERROR status = WERR_OK;
8188 NT_PRINTER_INFO_LEVEL *printer = NULL;
8189 SE_PRIV se_printop = SE_PRINT_OPERATOR;
8191 int count=0;
8192 nt_forms_struct *list=NULL;
8193 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
8195 DEBUG(5,("_spoolss_AddForm\n"));
8197 if (!Printer) {
8198 DEBUG(2,("_spoolss_AddForm: Invalid handle (%s:%u:%u).\n",
8199 OUR_HANDLE(r->in.handle)));
8200 return WERR_BADFID;
8204 /* forms can be added on printer of on the print server handle */
8206 if ( Printer->printer_type == SPLHND_PRINTER )
8208 if (!get_printer_snum(p, r->in.handle, &snum, NULL))
8209 return WERR_BADFID;
8211 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8212 if (!W_ERROR_IS_OK(status))
8213 goto done;
8216 /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
8217 and not a printer admin, then fail */
8219 if ((p->server_info->utok.uid != sec_initial_uid()) &&
8220 !user_has_privileges(p->server_info->ptok, &se_printop) &&
8221 !token_contains_name_in_list(uidtoname(p->server_info->utok.uid),
8222 pdb_get_domain(p->server_info->sam_account),
8223 NULL,
8224 p->server_info->ptok,
8225 lp_printer_admin(snum))) {
8226 DEBUG(2,("_spoolss_Addform: denied by insufficient permissions.\n"));
8227 return WERR_ACCESS_DENIED;
8230 /* can't add if builtin */
8232 if (get_a_builtin_ntform_by_string(form->form_name, &tmpForm)) {
8233 status = WERR_FILE_EXISTS;
8234 goto done;
8237 count = get_ntforms(&list);
8239 if(!add_a_form(&list, form, &count)) {
8240 status = WERR_NOMEM;
8241 goto done;
8244 become_root();
8245 write_ntforms(&list, count);
8246 unbecome_root();
8249 * ChangeID must always be set if this is a printer
8252 if ( Printer->printer_type == SPLHND_PRINTER )
8253 status = mod_a_printer(printer, 2);
8255 done:
8256 if ( printer )
8257 free_a_printer(&printer, 2);
8258 SAFE_FREE(list);
8260 return status;
8263 /****************************************************************
8264 _spoolss_DeleteForm
8265 ****************************************************************/
8267 WERROR _spoolss_DeleteForm(pipes_struct *p,
8268 struct spoolss_DeleteForm *r)
8270 const char *form_name = r->in.form_name;
8271 nt_forms_struct tmpForm;
8272 int count=0;
8273 nt_forms_struct *list=NULL;
8274 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
8275 int snum = -1;
8276 WERROR status = WERR_OK;
8277 NT_PRINTER_INFO_LEVEL *printer = NULL;
8278 SE_PRIV se_printop = SE_PRINT_OPERATOR;
8279 bool ret = false;
8281 DEBUG(5,("_spoolss_DeleteForm\n"));
8283 if (!Printer) {
8284 DEBUG(2,("_spoolss_DeleteForm: Invalid handle (%s:%u:%u).\n",
8285 OUR_HANDLE(r->in.handle)));
8286 return WERR_BADFID;
8289 /* forms can be deleted on printer of on the print server handle */
8291 if ( Printer->printer_type == SPLHND_PRINTER )
8293 if (!get_printer_snum(p, r->in.handle, &snum, NULL))
8294 return WERR_BADFID;
8296 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8297 if (!W_ERROR_IS_OK(status))
8298 goto done;
8301 if ((p->server_info->utok.uid != sec_initial_uid()) &&
8302 !user_has_privileges(p->server_info->ptok, &se_printop) &&
8303 !token_contains_name_in_list(uidtoname(p->server_info->utok.uid),
8304 pdb_get_domain(p->server_info->sam_account),
8305 NULL,
8306 p->server_info->ptok,
8307 lp_printer_admin(snum))) {
8308 DEBUG(2,("_spoolss_DeleteForm: denied by insufficient permissions.\n"));
8309 return WERR_ACCESS_DENIED;
8313 /* can't delete if builtin */
8315 if (get_a_builtin_ntform_by_string(form_name,&tmpForm)) {
8316 status = WERR_INVALID_PARAM;
8317 goto done;
8320 count = get_ntforms(&list);
8322 become_root();
8323 ret = delete_a_form(&list, form_name, &count, &status);
8324 unbecome_root();
8325 if (ret == false) {
8326 goto done;
8330 * ChangeID must always be set if this is a printer
8333 if ( Printer->printer_type == SPLHND_PRINTER )
8334 status = mod_a_printer(printer, 2);
8336 done:
8337 if ( printer )
8338 free_a_printer(&printer, 2);
8339 SAFE_FREE(list);
8341 return status;
8344 /****************************************************************
8345 _spoolss_SetForm
8346 ****************************************************************/
8348 WERROR _spoolss_SetForm(pipes_struct *p,
8349 struct spoolss_SetForm *r)
8351 struct spoolss_AddFormInfo1 *form = r->in.info.info1;
8352 nt_forms_struct tmpForm;
8353 int snum = -1;
8354 WERROR status = WERR_OK;
8355 NT_PRINTER_INFO_LEVEL *printer = NULL;
8356 SE_PRIV se_printop = SE_PRINT_OPERATOR;
8358 int count=0;
8359 nt_forms_struct *list=NULL;
8360 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
8362 DEBUG(5,("_spoolss_SetForm\n"));
8364 if (!Printer) {
8365 DEBUG(2,("_spoolss_SetForm: Invalid handle (%s:%u:%u).\n",
8366 OUR_HANDLE(r->in.handle)));
8367 return WERR_BADFID;
8370 /* forms can be modified on printer of on the print server handle */
8372 if ( Printer->printer_type == SPLHND_PRINTER )
8374 if (!get_printer_snum(p, r->in.handle, &snum, NULL))
8375 return WERR_BADFID;
8377 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8378 if (!W_ERROR_IS_OK(status))
8379 goto done;
8382 /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
8383 and not a printer admin, then fail */
8385 if ((p->server_info->utok.uid != sec_initial_uid()) &&
8386 !user_has_privileges(p->server_info->ptok, &se_printop) &&
8387 !token_contains_name_in_list(uidtoname(p->server_info->utok.uid),
8388 pdb_get_domain(p->server_info->sam_account),
8389 NULL,
8390 p->server_info->ptok,
8391 lp_printer_admin(snum))) {
8392 DEBUG(2,("_spoolss_Setform: denied by insufficient permissions.\n"));
8393 return WERR_ACCESS_DENIED;
8396 /* can't set if builtin */
8397 if (get_a_builtin_ntform_by_string(form->form_name, &tmpForm)) {
8398 status = WERR_INVALID_PARAM;
8399 goto done;
8402 count = get_ntforms(&list);
8403 update_a_form(&list, form, count);
8404 become_root();
8405 write_ntforms(&list, count);
8406 unbecome_root();
8409 * ChangeID must always be set if this is a printer
8412 if ( Printer->printer_type == SPLHND_PRINTER )
8413 status = mod_a_printer(printer, 2);
8416 done:
8417 if ( printer )
8418 free_a_printer(&printer, 2);
8419 SAFE_FREE(list);
8421 return status;
8424 /****************************************************************************
8425 fill_print_processor1
8426 ****************************************************************************/
8428 static WERROR fill_print_processor1(TALLOC_CTX *mem_ctx,
8429 struct spoolss_PrintProcessorInfo1 *r,
8430 const char *print_processor_name)
8432 r->print_processor_name = talloc_strdup(mem_ctx, print_processor_name);
8433 W_ERROR_HAVE_NO_MEMORY(r->print_processor_name);
8435 return WERR_OK;
8438 /****************************************************************************
8439 enumprintprocessors level 1.
8440 ****************************************************************************/
8442 static WERROR enumprintprocessors_level_1(TALLOC_CTX *mem_ctx,
8443 union spoolss_PrintProcessorInfo **info_p,
8444 uint32_t *count)
8446 union spoolss_PrintProcessorInfo *info;
8447 WERROR result;
8449 info = TALLOC_ARRAY(mem_ctx, union spoolss_PrintProcessorInfo, 1);
8450 W_ERROR_HAVE_NO_MEMORY(info);
8452 *count = 1;
8454 result = fill_print_processor1(info, &info[0].info1, "winprint");
8455 if (!W_ERROR_IS_OK(result)) {
8456 goto out;
8459 out:
8460 if (!W_ERROR_IS_OK(result)) {
8461 TALLOC_FREE(info);
8462 *count = 0;
8463 return result;
8466 *info_p = info;
8468 return WERR_OK;
8471 /****************************************************************
8472 _spoolss_EnumPrintProcessors
8473 ****************************************************************/
8475 WERROR _spoolss_EnumPrintProcessors(pipes_struct *p,
8476 struct spoolss_EnumPrintProcessors *r)
8478 WERROR result;
8480 /* that's an [in out] buffer */
8482 if (!r->in.buffer && (r->in.offered != 0)) {
8483 return WERR_INVALID_PARAM;
8486 DEBUG(5,("_spoolss_EnumPrintProcessors\n"));
8489 * Enumerate the print processors ...
8491 * Just reply with "winprint", to keep NT happy
8492 * and I can use my nice printer checker.
8495 *r->out.count = 0;
8496 *r->out.needed = 0;
8497 *r->out.info = NULL;
8499 switch (r->in.level) {
8500 case 1:
8501 result = enumprintprocessors_level_1(p->mem_ctx, r->out.info,
8502 r->out.count);
8503 break;
8504 default:
8505 return WERR_UNKNOWN_LEVEL;
8508 if (!W_ERROR_IS_OK(result)) {
8509 return result;
8512 *r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
8513 spoolss_EnumPrintProcessors, NULL,
8514 *r->out.info, r->in.level,
8515 *r->out.count);
8516 *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
8517 *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, 0);
8519 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
8522 /****************************************************************************
8523 fill_printprocdatatype1
8524 ****************************************************************************/
8526 static WERROR fill_printprocdatatype1(TALLOC_CTX *mem_ctx,
8527 struct spoolss_PrintProcDataTypesInfo1 *r,
8528 const char *name_array)
8530 r->name_array = talloc_strdup(mem_ctx, name_array);
8531 W_ERROR_HAVE_NO_MEMORY(r->name_array);
8533 return WERR_OK;
8536 /****************************************************************************
8537 enumprintprocdatatypes level 1.
8538 ****************************************************************************/
8540 static WERROR enumprintprocdatatypes_level_1(TALLOC_CTX *mem_ctx,
8541 union spoolss_PrintProcDataTypesInfo **info_p,
8542 uint32_t *count)
8544 WERROR result;
8545 union spoolss_PrintProcDataTypesInfo *info;
8547 info = TALLOC_ARRAY(mem_ctx, union spoolss_PrintProcDataTypesInfo, 1);
8548 W_ERROR_HAVE_NO_MEMORY(info);
8550 *count = 1;
8552 result = fill_printprocdatatype1(info, &info[0].info1, "RAW");
8553 if (!W_ERROR_IS_OK(result)) {
8554 goto out;
8557 out:
8558 if (!W_ERROR_IS_OK(result)) {
8559 TALLOC_FREE(info);
8560 *count = 0;
8561 return result;
8564 *info_p = info;
8566 return WERR_OK;
8569 /****************************************************************
8570 _spoolss_EnumPrintProcDataTypes
8571 ****************************************************************/
8573 WERROR _spoolss_EnumPrintProcDataTypes(pipes_struct *p,
8574 struct spoolss_EnumPrintProcDataTypes *r)
8576 WERROR result;
8578 /* that's an [in out] buffer */
8580 if (!r->in.buffer && (r->in.offered != 0)) {
8581 return WERR_INVALID_PARAM;
8584 DEBUG(5,("_spoolss_EnumPrintProcDataTypes\n"));
8586 *r->out.count = 0;
8587 *r->out.needed = 0;
8588 *r->out.info = NULL;
8590 switch (r->in.level) {
8591 case 1:
8592 result = enumprintprocdatatypes_level_1(p->mem_ctx, r->out.info,
8593 r->out.count);
8594 break;
8595 default:
8596 return WERR_UNKNOWN_LEVEL;
8599 *r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
8600 spoolss_EnumPrintProcDataTypes, NULL,
8601 *r->out.info, r->in.level,
8602 *r->out.count);
8603 *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
8604 *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, 0);
8606 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
8609 /****************************************************************************
8610 fill_monitor_1
8611 ****************************************************************************/
8613 static WERROR fill_monitor_1(TALLOC_CTX *mem_ctx,
8614 struct spoolss_MonitorInfo1 *r,
8615 const char *monitor_name)
8617 r->monitor_name = talloc_strdup(mem_ctx, monitor_name);
8618 W_ERROR_HAVE_NO_MEMORY(r->monitor_name);
8620 return WERR_OK;
8623 /****************************************************************************
8624 fill_monitor_2
8625 ****************************************************************************/
8627 static WERROR fill_monitor_2(TALLOC_CTX *mem_ctx,
8628 struct spoolss_MonitorInfo2 *r,
8629 const char *monitor_name,
8630 const char *environment,
8631 const char *dll_name)
8633 r->monitor_name = talloc_strdup(mem_ctx, monitor_name);
8634 W_ERROR_HAVE_NO_MEMORY(r->monitor_name);
8635 r->environment = talloc_strdup(mem_ctx, environment);
8636 W_ERROR_HAVE_NO_MEMORY(r->environment);
8637 r->dll_name = talloc_strdup(mem_ctx, dll_name);
8638 W_ERROR_HAVE_NO_MEMORY(r->dll_name);
8640 return WERR_OK;
8643 /****************************************************************************
8644 enumprintmonitors level 1.
8645 ****************************************************************************/
8647 static WERROR enumprintmonitors_level_1(TALLOC_CTX *mem_ctx,
8648 union spoolss_MonitorInfo **info_p,
8649 uint32_t *count)
8651 union spoolss_MonitorInfo *info;
8652 WERROR result = WERR_OK;
8654 info = TALLOC_ARRAY(mem_ctx, union spoolss_MonitorInfo, 2);
8655 W_ERROR_HAVE_NO_MEMORY(info);
8657 *count = 2;
8659 result = fill_monitor_1(info, &info[0].info1,
8660 SPL_LOCAL_PORT);
8661 if (!W_ERROR_IS_OK(result)) {
8662 goto out;
8665 result = fill_monitor_1(info, &info[1].info1,
8666 SPL_TCPIP_PORT);
8667 if (!W_ERROR_IS_OK(result)) {
8668 goto out;
8671 out:
8672 if (!W_ERROR_IS_OK(result)) {
8673 TALLOC_FREE(info);
8674 *count = 0;
8675 return result;
8678 *info_p = info;
8680 return WERR_OK;
8683 /****************************************************************************
8684 enumprintmonitors level 2.
8685 ****************************************************************************/
8687 static WERROR enumprintmonitors_level_2(TALLOC_CTX *mem_ctx,
8688 union spoolss_MonitorInfo **info_p,
8689 uint32_t *count)
8691 union spoolss_MonitorInfo *info;
8692 WERROR result = WERR_OK;
8694 info = TALLOC_ARRAY(mem_ctx, union spoolss_MonitorInfo, 2);
8695 W_ERROR_HAVE_NO_MEMORY(info);
8697 *count = 2;
8699 result = fill_monitor_2(info, &info[0].info2,
8700 SPL_LOCAL_PORT,
8701 "Windows NT X86", /* FIXME */
8702 "localmon.dll");
8703 if (!W_ERROR_IS_OK(result)) {
8704 goto out;
8707 result = fill_monitor_2(info, &info[1].info2,
8708 SPL_TCPIP_PORT,
8709 "Windows NT X86", /* FIXME */
8710 "tcpmon.dll");
8711 if (!W_ERROR_IS_OK(result)) {
8712 goto out;
8715 out:
8716 if (!W_ERROR_IS_OK(result)) {
8717 TALLOC_FREE(info);
8718 *count = 0;
8719 return result;
8722 *info_p = info;
8724 return WERR_OK;
8727 /****************************************************************
8728 _spoolss_EnumMonitors
8729 ****************************************************************/
8731 WERROR _spoolss_EnumMonitors(pipes_struct *p,
8732 struct spoolss_EnumMonitors *r)
8734 WERROR result;
8736 /* that's an [in out] buffer */
8738 if (!r->in.buffer && (r->in.offered != 0)) {
8739 return WERR_INVALID_PARAM;
8742 DEBUG(5,("_spoolss_EnumMonitors\n"));
8745 * Enumerate the print monitors ...
8747 * Just reply with "Local Port", to keep NT happy
8748 * and I can use my nice printer checker.
8751 *r->out.count = 0;
8752 *r->out.needed = 0;
8753 *r->out.info = NULL;
8755 switch (r->in.level) {
8756 case 1:
8757 result = enumprintmonitors_level_1(p->mem_ctx, r->out.info,
8758 r->out.count);
8759 break;
8760 case 2:
8761 result = enumprintmonitors_level_2(p->mem_ctx, r->out.info,
8762 r->out.count);
8763 break;
8764 default:
8765 return WERR_UNKNOWN_LEVEL;
8768 if (!W_ERROR_IS_OK(result)) {
8769 return result;
8772 *r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
8773 spoolss_EnumMonitors, NULL,
8774 *r->out.info, r->in.level,
8775 *r->out.count);
8776 *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
8777 *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, 0);
8779 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
8782 /****************************************************************************
8783 ****************************************************************************/
8785 static WERROR getjob_level_1(TALLOC_CTX *mem_ctx,
8786 const print_queue_struct *queue,
8787 int count, int snum,
8788 const NT_PRINTER_INFO_LEVEL *ntprinter,
8789 uint32_t jobid,
8790 struct spoolss_JobInfo1 *r)
8792 int i = 0;
8793 bool found = false;
8795 for (i=0; i<count && found == false; i++) {
8796 if (queue[i].job == (int)jobid) {
8797 found = true;
8801 if (found == false) {
8802 /* NT treats not found as bad param... yet another bad choice */
8803 return WERR_INVALID_PARAM;
8806 return fill_job_info1(mem_ctx,
8808 &queue[i-1],
8810 snum,
8811 ntprinter);
8814 /****************************************************************************
8815 ****************************************************************************/
8817 static WERROR getjob_level_2(TALLOC_CTX *mem_ctx,
8818 const print_queue_struct *queue,
8819 int count, int snum,
8820 const NT_PRINTER_INFO_LEVEL *ntprinter,
8821 uint32_t jobid,
8822 struct spoolss_JobInfo2 *r)
8824 int i = 0;
8825 bool found = false;
8826 struct spoolss_DeviceMode *devmode;
8827 NT_DEVICEMODE *nt_devmode;
8828 WERROR result;
8830 for (i=0; i<count && found == false; i++) {
8831 if (queue[i].job == (int)jobid) {
8832 found = true;
8836 if (found == false) {
8837 /* NT treats not found as bad param... yet another bad
8838 choice */
8839 return WERR_INVALID_PARAM;
8843 * if the print job does not have a DEVMODE associated with it,
8844 * just use the one for the printer. A NULL devicemode is not
8845 * a failure condition
8848 nt_devmode = print_job_devmode(lp_const_servicename(snum), jobid);
8849 if (nt_devmode) {
8850 devmode = TALLOC_ZERO_P(mem_ctx, struct spoolss_DeviceMode);
8851 W_ERROR_HAVE_NO_MEMORY(devmode);
8852 result = convert_nt_devicemode(devmode, devmode, nt_devmode);
8853 if (!W_ERROR_IS_OK(result)) {
8854 return result;
8856 } else {
8857 devmode = construct_dev_mode(mem_ctx, lp_const_servicename(snum));
8858 W_ERROR_HAVE_NO_MEMORY(devmode);
8861 return fill_job_info2(mem_ctx,
8863 &queue[i-1],
8865 snum,
8866 ntprinter,
8867 devmode);
8870 /****************************************************************
8871 _spoolss_GetJob
8872 ****************************************************************/
8874 WERROR _spoolss_GetJob(pipes_struct *p,
8875 struct spoolss_GetJob *r)
8877 WERROR result = WERR_OK;
8878 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
8879 int snum;
8880 int count;
8881 print_queue_struct *queue = NULL;
8882 print_status_struct prt_status;
8884 /* that's an [in out] buffer */
8886 if (!r->in.buffer && (r->in.offered != 0)) {
8887 return WERR_INVALID_PARAM;
8890 DEBUG(5,("_spoolss_GetJob\n"));
8892 *r->out.needed = 0;
8894 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
8895 return WERR_BADFID;
8898 result = get_a_printer(NULL, &ntprinter, 2, lp_servicename(snum));
8899 if (!W_ERROR_IS_OK(result)) {
8900 return result;
8903 count = print_queue_status(snum, &queue, &prt_status);
8905 DEBUGADD(4,("count:[%d], prt_status:[%d], [%s]\n",
8906 count, prt_status.status, prt_status.message));
8908 switch (r->in.level) {
8909 case 1:
8910 result = getjob_level_1(p->mem_ctx,
8911 queue, count, snum, ntprinter,
8912 r->in.job_id, &r->out.info->info1);
8913 break;
8914 case 2:
8915 result = getjob_level_2(p->mem_ctx,
8916 queue, count, snum, ntprinter,
8917 r->in.job_id, &r->out.info->info2);
8918 break;
8919 default:
8920 result = WERR_UNKNOWN_LEVEL;
8921 break;
8924 SAFE_FREE(queue);
8925 free_a_printer(&ntprinter, 2);
8927 if (!W_ERROR_IS_OK(result)) {
8928 TALLOC_FREE(r->out.info);
8929 return result;
8932 *r->out.needed = SPOOLSS_BUFFER_UNION(spoolss_JobInfo, NULL,
8933 r->out.info, r->in.level);
8934 r->out.info = SPOOLSS_BUFFER_OK(r->out.info, NULL);
8936 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
8939 /****************************************************************
8940 _spoolss_GetPrinterDataEx
8941 ****************************************************************/
8943 WERROR _spoolss_GetPrinterDataEx(pipes_struct *p,
8944 struct spoolss_GetPrinterDataEx *r)
8947 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
8948 REGISTRY_VALUE *val = NULL;
8949 NT_PRINTER_INFO_LEVEL *printer = NULL;
8950 int snum = 0;
8951 WERROR result = WERR_OK;
8952 DATA_BLOB blob;
8954 DEBUG(4,("_spoolss_GetPrinterDataEx\n"));
8956 DEBUG(10, ("_spoolss_GetPrinterDataEx: key => [%s], value => [%s]\n",
8957 r->in.key_name, r->in.value_name));
8959 /* in case of problem, return some default values */
8961 *r->out.needed = 0;
8962 *r->out.type = REG_NONE;
8964 if (!Printer) {
8965 DEBUG(2,("_spoolss_GetPrinterDataEx: Invalid handle (%s:%u:%u).\n",
8966 OUR_HANDLE(r->in.handle)));
8967 result = WERR_BADFID;
8968 goto done;
8971 /* Is the handle to a printer or to the server? */
8973 if (Printer->printer_type == SPLHND_SERVER) {
8975 union spoolss_PrinterData data;
8977 result = getprinterdata_printer_server(p->mem_ctx,
8978 r->in.value_name,
8979 r->out.type,
8980 &data);
8981 if (!W_ERROR_IS_OK(result)) {
8982 goto done;
8985 result = push_spoolss_PrinterData(p->mem_ctx, &blob,
8986 *r->out.type, &data);
8987 if (!W_ERROR_IS_OK(result)) {
8988 goto done;
8991 *r->out.needed = blob.length;
8993 if (r->in.offered >= *r->out.needed) {
8994 memcpy(r->out.data, blob.data, blob.length);
8997 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_MORE_DATA);
9000 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9001 result = WERR_BADFID;
9002 goto done;
9005 result = get_a_printer(Printer, &printer, 2, lp_servicename(snum));
9006 if (!W_ERROR_IS_OK(result)) {
9007 goto done;
9010 /* check to see if the keyname is valid */
9011 if (!strlen(r->in.key_name)) {
9012 result = WERR_INVALID_PARAM;
9013 goto done;
9016 /* XP sends this and wants to change id value from the PRINTER_INFO_0 */
9018 if (strequal(r->in.key_name, SPOOL_PRINTERDATA_KEY) &&
9019 strequal(r->in.value_name, "ChangeId")) {
9020 *r->out.type = REG_DWORD;
9021 *r->out.needed = 4;
9022 if (r->in.offered >= *r->out.needed) {
9023 SIVAL(r->out.data, 0, printer->info_2->changeid);
9024 result = WERR_OK;
9026 goto done;
9029 if (lookup_printerkey(printer->info_2->data, r->in.key_name) == -1) {
9030 DEBUG(4,("_spoolss_GetPrinterDataEx: "
9031 "Invalid keyname [%s]\n", r->in.key_name ));
9032 result = WERR_BADFILE;
9033 goto done;
9036 val = get_printer_data(printer->info_2,
9037 r->in.key_name, r->in.value_name);
9038 if (!val) {
9039 result = WERR_BADFILE;
9040 goto done;
9043 *r->out.needed = regval_size(val);
9044 *r->out.type = regval_type(val);
9046 if (r->in.offered >= *r->out.needed) {
9047 memcpy(r->out.data, regval_data_p(val), regval_size(val));
9049 done:
9050 if (printer) {
9051 free_a_printer(&printer, 2);
9054 if (!W_ERROR_IS_OK(result)) {
9055 return result;
9058 *r->out.type = SPOOLSS_BUFFER_OK(*r->out.type, REG_NONE);
9059 r->out.data = SPOOLSS_BUFFER_OK(r->out.data, r->out.data);
9061 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_MORE_DATA);
9064 /****************************************************************
9065 _spoolss_SetPrinterDataEx
9066 ****************************************************************/
9068 WERROR _spoolss_SetPrinterDataEx(pipes_struct *p,
9069 struct spoolss_SetPrinterDataEx *r)
9071 NT_PRINTER_INFO_LEVEL *printer = NULL;
9072 int snum = 0;
9073 WERROR result = WERR_OK;
9074 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
9075 char *oid_string;
9077 DEBUG(4,("_spoolss_SetPrinterDataEx\n"));
9079 /* From MSDN documentation of SetPrinterDataEx: pass request to
9080 SetPrinterData if key is "PrinterDriverData" */
9082 if (!Printer) {
9083 DEBUG(2,("_spoolss_SetPrinterDataEx: Invalid handle (%s:%u:%u).\n",
9084 OUR_HANDLE(r->in.handle)));
9085 return WERR_BADFID;
9088 if (Printer->printer_type == SPLHND_SERVER) {
9089 DEBUG(10,("_spoolss_SetPrinterDataEx: "
9090 "Not implemented for server handles yet\n"));
9091 return WERR_INVALID_PARAM;
9094 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9095 return WERR_BADFID;
9099 * Access check : NT returns "access denied" if you make a
9100 * SetPrinterData call without the necessary privildge.
9101 * we were originally returning OK if nothing changed
9102 * which made Win2k issue **a lot** of SetPrinterData
9103 * when connecting to a printer --jerry
9106 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
9107 DEBUG(3, ("_spoolss_SetPrinterDataEx: "
9108 "change denied by handle access permissions\n"));
9109 return WERR_ACCESS_DENIED;
9112 result = get_a_printer(Printer, &printer, 2, lp_servicename(snum));
9113 if (!W_ERROR_IS_OK(result)) {
9114 return result;
9117 /* check for OID in valuename */
9119 oid_string = strchr(r->in.value_name, ',');
9120 if (oid_string) {
9121 *oid_string = '\0';
9122 oid_string++;
9126 * When client side code sets a magic printer data key, detect it and save
9127 * the current printer data and the magic key's data (its the DEVMODE) for
9128 * future printer/driver initializations.
9130 if ((r->in.type == REG_BINARY) && strequal(r->in.value_name, PHANTOM_DEVMODE_KEY)) {
9131 /* Set devmode and printer initialization info */
9132 result = save_driver_init(printer, 2, r->in.data, r->in.offered);
9134 srv_spoolss_reset_printerdata(printer->info_2->drivername);
9136 goto done;
9139 /* save the registry data */
9141 result = set_printer_dataex(printer, r->in.key_name, r->in.value_name,
9142 r->in.type, r->in.data, r->in.offered);
9144 if (W_ERROR_IS_OK(result)) {
9145 /* save the OID if one was specified */
9146 if (oid_string) {
9147 char *str = talloc_asprintf(p->mem_ctx, "%s\\%s",
9148 r->in.key_name, SPOOL_OID_KEY);
9149 if (!str) {
9150 result = WERR_NOMEM;
9151 goto done;
9155 * I'm not checking the status here on purpose. Don't know
9156 * if this is right, but I'm returning the status from the
9157 * previous set_printer_dataex() call. I have no idea if
9158 * this is right. --jerry
9161 set_printer_dataex(printer, str, r->in.value_name,
9162 REG_SZ, (uint8_t *)oid_string,
9163 strlen(oid_string)+1);
9166 result = mod_a_printer(printer, 2);
9169 done:
9170 free_a_printer(&printer, 2);
9172 return result;
9175 /****************************************************************
9176 _spoolss_DeletePrinterDataEx
9177 ****************************************************************/
9179 WERROR _spoolss_DeletePrinterDataEx(pipes_struct *p,
9180 struct spoolss_DeletePrinterDataEx *r)
9182 NT_PRINTER_INFO_LEVEL *printer = NULL;
9183 int snum=0;
9184 WERROR status = WERR_OK;
9185 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
9187 DEBUG(5,("_spoolss_DeletePrinterDataEx\n"));
9189 if (!Printer) {
9190 DEBUG(2,("_spoolss_DeletePrinterDataEx: "
9191 "Invalid handle (%s:%u:%u).\n",
9192 OUR_HANDLE(r->in.handle)));
9193 return WERR_BADFID;
9196 if (!get_printer_snum(p, r->in.handle, &snum, NULL))
9197 return WERR_BADFID;
9199 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
9200 DEBUG(3, ("_spoolss_DeletePrinterDataEx: "
9201 "printer properties change denied by handle\n"));
9202 return WERR_ACCESS_DENIED;
9205 if (!r->in.value_name || !r->in.key_name) {
9206 return WERR_NOMEM;
9209 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
9210 if (!W_ERROR_IS_OK(status))
9211 return status;
9213 status = delete_printer_dataex( printer, r->in.key_name, r->in.value_name );
9215 if ( W_ERROR_IS_OK(status) )
9216 mod_a_printer( printer, 2 );
9218 free_a_printer(&printer, 2);
9220 return status;
9223 /****************************************************************
9224 _spoolss_EnumPrinterKey
9225 ****************************************************************/
9227 WERROR _spoolss_EnumPrinterKey(pipes_struct *p,
9228 struct spoolss_EnumPrinterKey *r)
9230 fstring *keynames = NULL;
9231 int num_keys;
9232 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
9233 NT_PRINTER_DATA *data;
9234 NT_PRINTER_INFO_LEVEL *printer = NULL;
9235 int snum = 0;
9236 WERROR result = WERR_BADFILE;
9237 int i;
9238 const char **array = NULL;
9239 DATA_BLOB blob;
9241 DEBUG(4,("_spoolss_EnumPrinterKey\n"));
9243 if (!Printer) {
9244 DEBUG(2,("_spoolss_EnumPrinterKey: Invalid handle (%s:%u:%u).\n",
9245 OUR_HANDLE(r->in.handle)));
9246 return WERR_BADFID;
9249 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9250 return WERR_BADFID;
9253 result = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
9254 if (!W_ERROR_IS_OK(result)) {
9255 return result;
9258 /* get the list of subkey names */
9260 data = printer->info_2->data;
9262 num_keys = get_printer_subkeys(data, r->in.key_name, &keynames);
9263 if (num_keys == -1) {
9264 result = WERR_BADFILE;
9265 goto done;
9268 array = talloc_zero_array(r->out.key_buffer, const char *, num_keys + 2);
9269 if (!array) {
9270 result = WERR_NOMEM;
9271 goto done;
9274 if (!num_keys) {
9275 array[0] = talloc_strdup(array, "");
9276 if (!array[0]) {
9277 result = WERR_NOMEM;
9278 goto done;
9282 for (i=0; i < num_keys; i++) {
9284 DEBUG(10,("_spoolss_EnumPrinterKey: adding keyname: %s\n",
9285 keynames[i]));
9287 array[i] = talloc_strdup(array, keynames[i]);
9288 if (!array[i]) {
9289 result = WERR_NOMEM;
9290 goto done;
9294 if (!push_reg_multi_sz(p->mem_ctx, &blob, array)) {
9295 result = WERR_NOMEM;
9296 goto done;
9299 *r->out._ndr_size = r->in.offered / 2;
9300 *r->out.needed = blob.length;
9302 if (r->in.offered < *r->out.needed) {
9303 result = WERR_MORE_DATA;
9304 } else {
9305 result = WERR_OK;
9306 r->out.key_buffer->string_array = array;
9309 done:
9310 if (!W_ERROR_IS_OK(result)) {
9311 TALLOC_FREE(array);
9312 if (!W_ERROR_EQUAL(result, WERR_MORE_DATA)) {
9313 *r->out.needed = 0;
9317 free_a_printer(&printer, 2);
9318 SAFE_FREE(keynames);
9320 return result;
9323 /****************************************************************
9324 _spoolss_DeletePrinterKey
9325 ****************************************************************/
9327 WERROR _spoolss_DeletePrinterKey(pipes_struct *p,
9328 struct spoolss_DeletePrinterKey *r)
9330 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
9331 NT_PRINTER_INFO_LEVEL *printer = NULL;
9332 int snum=0;
9333 WERROR status;
9335 DEBUG(5,("_spoolss_DeletePrinterKey\n"));
9337 if (!Printer) {
9338 DEBUG(2,("_spoolss_DeletePrinterKey: Invalid handle (%s:%u:%u).\n",
9339 OUR_HANDLE(r->in.handle)));
9340 return WERR_BADFID;
9343 /* if keyname == NULL, return error */
9345 if ( !r->in.key_name )
9346 return WERR_INVALID_PARAM;
9348 if (!get_printer_snum(p, r->in.handle, &snum, NULL))
9349 return WERR_BADFID;
9351 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
9352 DEBUG(3, ("_spoolss_DeletePrinterKey: "
9353 "printer properties change denied by handle\n"));
9354 return WERR_ACCESS_DENIED;
9357 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
9358 if (!W_ERROR_IS_OK(status))
9359 return status;
9361 /* delete the key and all subneys */
9363 status = delete_all_printer_data( printer->info_2, r->in.key_name );
9365 if ( W_ERROR_IS_OK(status) )
9366 status = mod_a_printer(printer, 2);
9368 free_a_printer( &printer, 2 );
9370 return status;
9373 /****************************************************************
9374 ****************************************************************/
9376 static WERROR registry_value_to_printer_enum_value(TALLOC_CTX *mem_ctx,
9377 REGISTRY_VALUE *v,
9378 struct spoolss_PrinterEnumValues *r)
9380 r->data = TALLOC_ZERO_P(mem_ctx, DATA_BLOB);
9381 W_ERROR_HAVE_NO_MEMORY(r->data);
9383 r->value_name = talloc_strdup(mem_ctx, regval_name(v));
9384 W_ERROR_HAVE_NO_MEMORY(r->value_name);
9386 r->type = regval_type(v);
9387 r->data_length = regval_size(v);
9389 if (r->data_length) {
9390 *r->data = data_blob_talloc(r->data, regval_data_p(v), regval_size(v));
9393 return WERR_OK;
9396 /****************************************************************
9397 _spoolss_EnumPrinterDataEx
9398 ****************************************************************/
9400 WERROR _spoolss_EnumPrinterDataEx(pipes_struct *p,
9401 struct spoolss_EnumPrinterDataEx *r)
9403 uint32_t count = 0;
9404 NT_PRINTER_INFO_LEVEL *printer = NULL;
9405 struct spoolss_PrinterEnumValues *info = NULL;
9406 NT_PRINTER_DATA *p_data;
9407 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
9408 int snum;
9409 WERROR result;
9410 int key_index;
9411 int i;
9413 DEBUG(4,("_spoolss_EnumPrinterDataEx\n"));
9415 *r->out.count = 0;
9416 *r->out.needed = 0;
9417 *r->out.info = NULL;
9419 if (!Printer) {
9420 DEBUG(2,("_spoolss_EnumPrinterDataEx: Invalid handle (%s:%u:%u1<).\n",
9421 OUR_HANDLE(r->in.handle)));
9422 return WERR_BADFID;
9426 * first check for a keyname of NULL or "". Win2k seems to send
9427 * this a lot and we should send back WERR_INVALID_PARAM
9428 * no need to spend time looking up the printer in this case.
9429 * --jerry
9432 if (!strlen(r->in.key_name)) {
9433 result = WERR_INVALID_PARAM;
9434 goto done;
9437 /* get the printer off of disk */
9439 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9440 return WERR_BADFID;
9443 ZERO_STRUCT(printer);
9444 result = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
9445 if (!W_ERROR_IS_OK(result)) {
9446 return result;
9449 /* now look for a match on the key name */
9451 p_data = printer->info_2->data;
9453 key_index = lookup_printerkey(p_data, r->in.key_name);
9454 if (key_index == -1) {
9455 DEBUG(10,("_spoolss_EnumPrinterDataEx: Unknown keyname [%s]\n",
9456 r->in.key_name));
9457 result = WERR_INVALID_PARAM;
9458 goto done;
9461 /* allocate the memory for the array of pointers -- if necessary */
9463 count = regval_ctr_numvals(p_data->keys[key_index].values);
9464 if (!count) {
9465 result = WERR_OK; /* ??? */
9466 goto done;
9469 info = TALLOC_ZERO_ARRAY(p->mem_ctx,
9470 struct spoolss_PrinterEnumValues,
9471 count);
9472 if (!info) {
9473 DEBUG(0,("_spoolss_EnumPrinterDataEx: talloc() failed\n"));
9474 result = WERR_NOMEM;
9475 goto done;
9479 * loop through all params and build the array to pass
9480 * back to the client
9483 for (i=0; i < count; i++) {
9485 REGISTRY_VALUE *val;
9487 /* lookup the registry value */
9489 val = regval_ctr_specific_value(p_data->keys[key_index].values, i);
9491 DEBUG(10,("retrieved value number [%d] [%s]\n", i, regval_name(val)));
9493 /* copy the data */
9495 result = registry_value_to_printer_enum_value(info, val, &info[i]);
9496 if (!W_ERROR_IS_OK(result)) {
9497 goto done;
9501 #if 0 /* FIXME - gd */
9502 /* housekeeping information in the reply */
9504 /* Fix from Martin Zielinski <mz@seh.de> - ensure
9505 * the hand marshalled container size is a multiple
9506 * of 4 bytes for RPC alignment.
9509 if (needed % 4) {
9510 needed += 4-(needed % 4);
9512 #endif
9513 *r->out.count = count;
9514 *r->out.info = info;
9516 done:
9518 if (printer) {
9519 free_a_printer(&printer, 2);
9522 if (!W_ERROR_IS_OK(result)) {
9523 return result;
9526 *r->out.needed = SPOOLSS_BUFFER_ARRAY(p->mem_ctx,
9527 spoolss_EnumPrinterDataEx, NULL,
9528 *r->out.info,
9529 *r->out.count);
9530 *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
9531 *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, *r->out.count);
9533 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_MORE_DATA);
9536 /****************************************************************************
9537 ****************************************************************************/
9539 static WERROR getprintprocessordirectory_level_1(TALLOC_CTX *mem_ctx,
9540 const char *servername,
9541 const char *environment,
9542 struct spoolss_PrintProcessorDirectoryInfo1 *r)
9544 WERROR werr;
9545 char *path = NULL;
9547 werr = compose_spoolss_server_path(mem_ctx,
9548 servername,
9549 environment,
9550 SPOOLSS_PRTPROCS_PATH,
9551 &path);
9552 if (!W_ERROR_IS_OK(werr)) {
9553 return werr;
9556 DEBUG(4,("print processor directory: [%s]\n", path));
9558 r->directory_name = path;
9560 return WERR_OK;
9563 /****************************************************************
9564 _spoolss_GetPrintProcessorDirectory
9565 ****************************************************************/
9567 WERROR _spoolss_GetPrintProcessorDirectory(pipes_struct *p,
9568 struct spoolss_GetPrintProcessorDirectory *r)
9570 WERROR result;
9572 /* that's an [in out] buffer */
9574 if (!r->in.buffer && (r->in.offered != 0)) {
9575 return WERR_INVALID_PARAM;
9578 DEBUG(5,("_spoolss_GetPrintProcessorDirectory: level %d\n",
9579 r->in.level));
9581 *r->out.needed = 0;
9583 /* r->in.level is ignored */
9585 /* We always should reply with a local print processor directory so that
9586 * users are not forced to have a [prnproc$] share on the Samba spoolss
9587 * server - Guenther */
9589 result = getprintprocessordirectory_level_1(p->mem_ctx,
9590 NULL, /* r->in.server */
9591 r->in.environment,
9592 &r->out.info->info1);
9593 if (!W_ERROR_IS_OK(result)) {
9594 TALLOC_FREE(r->out.info);
9595 return result;
9598 *r->out.needed = SPOOLSS_BUFFER_UNION(spoolss_PrintProcessorDirectoryInfo, NULL,
9599 r->out.info, r->in.level);
9600 r->out.info = SPOOLSS_BUFFER_OK(r->out.info, NULL);
9602 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
9605 /*******************************************************************
9606 ********************************************************************/
9608 static bool push_monitorui_buf(TALLOC_CTX *mem_ctx, DATA_BLOB *buf,
9609 const char *dllname)
9611 enum ndr_err_code ndr_err;
9612 struct spoolss_MonitorUi ui;
9614 ui.dll_name = dllname;
9616 ndr_err = ndr_push_struct_blob(buf, mem_ctx, NULL, &ui,
9617 (ndr_push_flags_fn_t)ndr_push_spoolss_MonitorUi);
9618 if (NDR_ERR_CODE_IS_SUCCESS(ndr_err) && (DEBUGLEVEL >= 10)) {
9619 NDR_PRINT_DEBUG(spoolss_MonitorUi, &ui);
9621 return NDR_ERR_CODE_IS_SUCCESS(ndr_err);
9624 /*******************************************************************
9625 Streams the monitor UI DLL name in UNICODE
9626 *******************************************************************/
9628 static WERROR xcvtcp_monitorui(TALLOC_CTX *mem_ctx,
9629 NT_USER_TOKEN *token, DATA_BLOB *in,
9630 DATA_BLOB *out, uint32_t *needed)
9632 const char *dllname = "tcpmonui.dll";
9634 *needed = (strlen(dllname)+1) * 2;
9636 if (out->length < *needed) {
9637 return WERR_INSUFFICIENT_BUFFER;
9640 if (!push_monitorui_buf(mem_ctx, out, dllname)) {
9641 return WERR_NOMEM;
9644 return WERR_OK;
9647 /*******************************************************************
9648 ********************************************************************/
9650 static bool pull_port_data_1(TALLOC_CTX *mem_ctx,
9651 struct spoolss_PortData1 *port1,
9652 const DATA_BLOB *buf)
9654 enum ndr_err_code ndr_err;
9655 ndr_err = ndr_pull_struct_blob(buf, mem_ctx, NULL, port1,
9656 (ndr_pull_flags_fn_t)ndr_pull_spoolss_PortData1);
9657 if (NDR_ERR_CODE_IS_SUCCESS(ndr_err) && (DEBUGLEVEL >= 10)) {
9658 NDR_PRINT_DEBUG(spoolss_PortData1, port1);
9660 return NDR_ERR_CODE_IS_SUCCESS(ndr_err);
9663 /*******************************************************************
9664 ********************************************************************/
9666 static bool pull_port_data_2(TALLOC_CTX *mem_ctx,
9667 struct spoolss_PortData2 *port2,
9668 const DATA_BLOB *buf)
9670 enum ndr_err_code ndr_err;
9671 ndr_err = ndr_pull_struct_blob(buf, mem_ctx, NULL, port2,
9672 (ndr_pull_flags_fn_t)ndr_pull_spoolss_PortData2);
9673 if (NDR_ERR_CODE_IS_SUCCESS(ndr_err) && (DEBUGLEVEL >= 10)) {
9674 NDR_PRINT_DEBUG(spoolss_PortData2, port2);
9676 return NDR_ERR_CODE_IS_SUCCESS(ndr_err);
9679 /*******************************************************************
9680 Create a new TCP/IP port
9681 *******************************************************************/
9683 static WERROR xcvtcp_addport(TALLOC_CTX *mem_ctx,
9684 NT_USER_TOKEN *token, DATA_BLOB *in,
9685 DATA_BLOB *out, uint32_t *needed)
9687 struct spoolss_PortData1 port1;
9688 struct spoolss_PortData2 port2;
9689 char *device_uri = NULL;
9690 uint32_t version;
9692 const char *portname;
9693 const char *hostaddress;
9694 const char *queue;
9695 uint32_t port_number;
9696 uint32_t protocol;
9698 /* peek for spoolss_PortData version */
9700 if (!in || (in->length < (128 + 4))) {
9701 return WERR_GENERAL_FAILURE;
9704 version = IVAL(in->data, 128);
9706 switch (version) {
9707 case 1:
9708 ZERO_STRUCT(port1);
9710 if (!pull_port_data_1(mem_ctx, &port1, in)) {
9711 return WERR_NOMEM;
9714 portname = port1.portname;
9715 hostaddress = port1.hostaddress;
9716 queue = port1.queue;
9717 protocol = port1.protocol;
9718 port_number = port1.port_number;
9720 break;
9721 case 2:
9722 ZERO_STRUCT(port2);
9724 if (!pull_port_data_2(mem_ctx, &port2, in)) {
9725 return WERR_NOMEM;
9728 portname = port2.portname;
9729 hostaddress = port2.hostaddress;
9730 queue = port2.queue;
9731 protocol = port2.protocol;
9732 port_number = port2.port_number;
9734 break;
9735 default:
9736 DEBUG(1,("xcvtcp_addport: "
9737 "unknown version of port_data: %d\n", version));
9738 return WERR_UNKNOWN_PORT;
9741 /* create the device URI and call the add_port_hook() */
9743 switch (protocol) {
9744 case PROTOCOL_RAWTCP_TYPE:
9745 device_uri = talloc_asprintf(mem_ctx,
9746 "socket://%s:%d/", hostaddress,
9747 port_number);
9748 break;
9750 case PROTOCOL_LPR_TYPE:
9751 device_uri = talloc_asprintf(mem_ctx,
9752 "lpr://%s/%s", hostaddress, queue );
9753 break;
9755 default:
9756 return WERR_UNKNOWN_PORT;
9759 if (!device_uri) {
9760 return WERR_NOMEM;
9763 return add_port_hook(mem_ctx, token, portname, device_uri);
9766 /*******************************************************************
9767 *******************************************************************/
9769 struct xcv_api_table xcvtcp_cmds[] = {
9770 { "MonitorUI", xcvtcp_monitorui },
9771 { "AddPort", xcvtcp_addport},
9772 { NULL, NULL }
9775 static WERROR process_xcvtcp_command(TALLOC_CTX *mem_ctx,
9776 NT_USER_TOKEN *token, const char *command,
9777 DATA_BLOB *inbuf,
9778 DATA_BLOB *outbuf,
9779 uint32_t *needed )
9781 int i;
9783 DEBUG(10,("process_xcvtcp_command: Received command \"%s\"\n", command));
9785 for ( i=0; xcvtcp_cmds[i].name; i++ ) {
9786 if ( strcmp( command, xcvtcp_cmds[i].name ) == 0 )
9787 return xcvtcp_cmds[i].fn(mem_ctx, token, inbuf, outbuf, needed);
9790 return WERR_BADFUNC;
9793 /*******************************************************************
9794 *******************************************************************/
9795 #if 0 /* don't support management using the "Local Port" monitor */
9797 static WERROR xcvlocal_monitorui(TALLOC_CTX *mem_ctx,
9798 NT_USER_TOKEN *token, DATA_BLOB *in,
9799 DATA_BLOB *out, uint32_t *needed)
9801 const char *dllname = "localui.dll";
9803 *needed = (strlen(dllname)+1) * 2;
9805 if (out->length < *needed) {
9806 return WERR_INSUFFICIENT_BUFFER;
9809 if (!push_monitorui_buf(mem_ctx, out, dllname)) {
9810 return WERR_NOMEM;
9813 return WERR_OK;
9816 /*******************************************************************
9817 *******************************************************************/
9819 struct xcv_api_table xcvlocal_cmds[] = {
9820 { "MonitorUI", xcvlocal_monitorui },
9821 { NULL, NULL }
9823 #else
9824 struct xcv_api_table xcvlocal_cmds[] = {
9825 { NULL, NULL }
9827 #endif
9831 /*******************************************************************
9832 *******************************************************************/
9834 static WERROR process_xcvlocal_command(TALLOC_CTX *mem_ctx,
9835 NT_USER_TOKEN *token, const char *command,
9836 DATA_BLOB *inbuf, DATA_BLOB *outbuf,
9837 uint32_t *needed)
9839 int i;
9841 DEBUG(10,("process_xcvlocal_command: Received command \"%s\"\n", command));
9843 for ( i=0; xcvlocal_cmds[i].name; i++ ) {
9844 if ( strcmp( command, xcvlocal_cmds[i].name ) == 0 )
9845 return xcvlocal_cmds[i].fn(mem_ctx, token, inbuf, outbuf, needed);
9847 return WERR_BADFUNC;
9850 /****************************************************************
9851 _spoolss_XcvData
9852 ****************************************************************/
9854 WERROR _spoolss_XcvData(pipes_struct *p,
9855 struct spoolss_XcvData *r)
9857 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
9858 DATA_BLOB out_data = data_blob_null;
9859 WERROR werror;
9861 if (!Printer) {
9862 DEBUG(2,("_spoolss_XcvData: Invalid handle (%s:%u:%u).\n",
9863 OUR_HANDLE(r->in.handle)));
9864 return WERR_BADFID;
9867 /* Has to be a handle to the TCP/IP port monitor */
9869 if ( !(Printer->printer_type & (SPLHND_PORTMON_LOCAL|SPLHND_PORTMON_TCP)) ) {
9870 DEBUG(2,("_spoolss_XcvData: Call only valid for Port Monitors\n"));
9871 return WERR_BADFID;
9874 /* requires administrative access to the server */
9876 if ( !(Printer->access_granted & SERVER_ACCESS_ADMINISTER) ) {
9877 DEBUG(2,("_spoolss_XcvData: denied by handle permissions.\n"));
9878 return WERR_ACCESS_DENIED;
9881 /* Allocate the outgoing buffer */
9883 if (r->in.out_data_size) {
9884 out_data = data_blob_talloc_zero(p->mem_ctx, r->in.out_data_size);
9885 if (out_data.data == NULL) {
9886 return WERR_NOMEM;
9890 switch ( Printer->printer_type ) {
9891 case SPLHND_PORTMON_TCP:
9892 werror = process_xcvtcp_command(p->mem_ctx,
9893 p->server_info->ptok,
9894 r->in.function_name,
9895 &r->in.in_data, &out_data,
9896 r->out.needed);
9897 break;
9898 case SPLHND_PORTMON_LOCAL:
9899 werror = process_xcvlocal_command(p->mem_ctx,
9900 p->server_info->ptok,
9901 r->in.function_name,
9902 &r->in.in_data, &out_data,
9903 r->out.needed);
9904 break;
9905 default:
9906 werror = WERR_INVALID_PRINT_MONITOR;
9909 if (!W_ERROR_IS_OK(werror)) {
9910 return werror;
9913 *r->out.status_code = 0;
9915 if (r->out.out_data && out_data.data && r->in.out_data_size && out_data.length) {
9916 memcpy(r->out.out_data, out_data.data,
9917 MIN(r->in.out_data_size, out_data.length));
9920 return WERR_OK;
9923 /****************************************************************
9924 _spoolss_AddPrintProcessor
9925 ****************************************************************/
9927 WERROR _spoolss_AddPrintProcessor(pipes_struct *p,
9928 struct spoolss_AddPrintProcessor *r)
9930 /* for now, just indicate success and ignore the add. We'll
9931 automatically set the winprint processor for printer
9932 entries later. Used to debug the LexMark Optra S 1855 PCL
9933 driver --jerry */
9935 return WERR_OK;
9938 /****************************************************************
9939 _spoolss_AddPort
9940 ****************************************************************/
9942 WERROR _spoolss_AddPort(pipes_struct *p,
9943 struct spoolss_AddPort *r)
9945 /* do what w2k3 does */
9947 return WERR_NOT_SUPPORTED;
9950 /****************************************************************
9951 _spoolss_AddPrinter
9952 ****************************************************************/
9954 WERROR _spoolss_AddPrinter(pipes_struct *p,
9955 struct spoolss_AddPrinter *r)
9957 p->rng_fault_state = true;
9958 return WERR_NOT_SUPPORTED;
9961 /****************************************************************
9962 _spoolss_GetPrinterDriver
9963 ****************************************************************/
9965 WERROR _spoolss_GetPrinterDriver(pipes_struct *p,
9966 struct spoolss_GetPrinterDriver *r)
9968 p->rng_fault_state = true;
9969 return WERR_NOT_SUPPORTED;
9972 /****************************************************************
9973 _spoolss_ReadPrinter
9974 ****************************************************************/
9976 WERROR _spoolss_ReadPrinter(pipes_struct *p,
9977 struct spoolss_ReadPrinter *r)
9979 p->rng_fault_state = true;
9980 return WERR_NOT_SUPPORTED;
9983 /****************************************************************
9984 _spoolss_WaitForPrinterChange
9985 ****************************************************************/
9987 WERROR _spoolss_WaitForPrinterChange(pipes_struct *p,
9988 struct spoolss_WaitForPrinterChange *r)
9990 p->rng_fault_state = true;
9991 return WERR_NOT_SUPPORTED;
9994 /****************************************************************
9995 _spoolss_ConfigurePort
9996 ****************************************************************/
9998 WERROR _spoolss_ConfigurePort(pipes_struct *p,
9999 struct spoolss_ConfigurePort *r)
10001 p->rng_fault_state = true;
10002 return WERR_NOT_SUPPORTED;
10005 /****************************************************************
10006 _spoolss_DeletePort
10007 ****************************************************************/
10009 WERROR _spoolss_DeletePort(pipes_struct *p,
10010 struct spoolss_DeletePort *r)
10012 p->rng_fault_state = true;
10013 return WERR_NOT_SUPPORTED;
10016 /****************************************************************
10017 _spoolss_CreatePrinterIC
10018 ****************************************************************/
10020 WERROR _spoolss_CreatePrinterIC(pipes_struct *p,
10021 struct spoolss_CreatePrinterIC *r)
10023 p->rng_fault_state = true;
10024 return WERR_NOT_SUPPORTED;
10027 /****************************************************************
10028 _spoolss_PlayGDIScriptOnPrinterIC
10029 ****************************************************************/
10031 WERROR _spoolss_PlayGDIScriptOnPrinterIC(pipes_struct *p,
10032 struct spoolss_PlayGDIScriptOnPrinterIC *r)
10034 p->rng_fault_state = true;
10035 return WERR_NOT_SUPPORTED;
10038 /****************************************************************
10039 _spoolss_DeletePrinterIC
10040 ****************************************************************/
10042 WERROR _spoolss_DeletePrinterIC(pipes_struct *p,
10043 struct spoolss_DeletePrinterIC *r)
10045 p->rng_fault_state = true;
10046 return WERR_NOT_SUPPORTED;
10049 /****************************************************************
10050 _spoolss_AddPrinterConnection
10051 ****************************************************************/
10053 WERROR _spoolss_AddPrinterConnection(pipes_struct *p,
10054 struct spoolss_AddPrinterConnection *r)
10056 p->rng_fault_state = true;
10057 return WERR_NOT_SUPPORTED;
10060 /****************************************************************
10061 _spoolss_DeletePrinterConnection
10062 ****************************************************************/
10064 WERROR _spoolss_DeletePrinterConnection(pipes_struct *p,
10065 struct spoolss_DeletePrinterConnection *r)
10067 p->rng_fault_state = true;
10068 return WERR_NOT_SUPPORTED;
10071 /****************************************************************
10072 _spoolss_PrinterMessageBox
10073 ****************************************************************/
10075 WERROR _spoolss_PrinterMessageBox(pipes_struct *p,
10076 struct spoolss_PrinterMessageBox *r)
10078 p->rng_fault_state = true;
10079 return WERR_NOT_SUPPORTED;
10082 /****************************************************************
10083 _spoolss_AddMonitor
10084 ****************************************************************/
10086 WERROR _spoolss_AddMonitor(pipes_struct *p,
10087 struct spoolss_AddMonitor *r)
10089 p->rng_fault_state = true;
10090 return WERR_NOT_SUPPORTED;
10093 /****************************************************************
10094 _spoolss_DeleteMonitor
10095 ****************************************************************/
10097 WERROR _spoolss_DeleteMonitor(pipes_struct *p,
10098 struct spoolss_DeleteMonitor *r)
10100 p->rng_fault_state = true;
10101 return WERR_NOT_SUPPORTED;
10104 /****************************************************************
10105 _spoolss_DeletePrintProcessor
10106 ****************************************************************/
10108 WERROR _spoolss_DeletePrintProcessor(pipes_struct *p,
10109 struct spoolss_DeletePrintProcessor *r)
10111 p->rng_fault_state = true;
10112 return WERR_NOT_SUPPORTED;
10115 /****************************************************************
10116 _spoolss_AddPrintProvidor
10117 ****************************************************************/
10119 WERROR _spoolss_AddPrintProvidor(pipes_struct *p,
10120 struct spoolss_AddPrintProvidor *r)
10122 p->rng_fault_state = true;
10123 return WERR_NOT_SUPPORTED;
10126 /****************************************************************
10127 _spoolss_DeletePrintProvidor
10128 ****************************************************************/
10130 WERROR _spoolss_DeletePrintProvidor(pipes_struct *p,
10131 struct spoolss_DeletePrintProvidor *r)
10133 p->rng_fault_state = true;
10134 return WERR_NOT_SUPPORTED;
10137 /****************************************************************
10138 _spoolss_FindFirstPrinterChangeNotification
10139 ****************************************************************/
10141 WERROR _spoolss_FindFirstPrinterChangeNotification(pipes_struct *p,
10142 struct spoolss_FindFirstPrinterChangeNotification *r)
10144 p->rng_fault_state = true;
10145 return WERR_NOT_SUPPORTED;
10148 /****************************************************************
10149 _spoolss_FindNextPrinterChangeNotification
10150 ****************************************************************/
10152 WERROR _spoolss_FindNextPrinterChangeNotification(pipes_struct *p,
10153 struct spoolss_FindNextPrinterChangeNotification *r)
10155 p->rng_fault_state = true;
10156 return WERR_NOT_SUPPORTED;
10159 /****************************************************************
10160 _spoolss_RouterFindFirstPrinterChangeNotificationOld
10161 ****************************************************************/
10163 WERROR _spoolss_RouterFindFirstPrinterChangeNotificationOld(pipes_struct *p,
10164 struct spoolss_RouterFindFirstPrinterChangeNotificationOld *r)
10166 p->rng_fault_state = true;
10167 return WERR_NOT_SUPPORTED;
10170 /****************************************************************
10171 _spoolss_ReplyOpenPrinter
10172 ****************************************************************/
10174 WERROR _spoolss_ReplyOpenPrinter(pipes_struct *p,
10175 struct spoolss_ReplyOpenPrinter *r)
10177 p->rng_fault_state = true;
10178 return WERR_NOT_SUPPORTED;
10181 /****************************************************************
10182 _spoolss_RouterReplyPrinter
10183 ****************************************************************/
10185 WERROR _spoolss_RouterReplyPrinter(pipes_struct *p,
10186 struct spoolss_RouterReplyPrinter *r)
10188 p->rng_fault_state = true;
10189 return WERR_NOT_SUPPORTED;
10192 /****************************************************************
10193 _spoolss_ReplyClosePrinter
10194 ****************************************************************/
10196 WERROR _spoolss_ReplyClosePrinter(pipes_struct *p,
10197 struct spoolss_ReplyClosePrinter *r)
10199 p->rng_fault_state = true;
10200 return WERR_NOT_SUPPORTED;
10203 /****************************************************************
10204 _spoolss_AddPortEx
10205 ****************************************************************/
10207 WERROR _spoolss_AddPortEx(pipes_struct *p,
10208 struct spoolss_AddPortEx *r)
10210 p->rng_fault_state = true;
10211 return WERR_NOT_SUPPORTED;
10214 /****************************************************************
10215 _spoolss_RouterFindFirstPrinterChangeNotification
10216 ****************************************************************/
10218 WERROR _spoolss_RouterFindFirstPrinterChangeNotification(pipes_struct *p,
10219 struct spoolss_RouterFindFirstPrinterChangeNotification *r)
10221 p->rng_fault_state = true;
10222 return WERR_NOT_SUPPORTED;
10225 /****************************************************************
10226 _spoolss_SpoolerInit
10227 ****************************************************************/
10229 WERROR _spoolss_SpoolerInit(pipes_struct *p,
10230 struct spoolss_SpoolerInit *r)
10232 p->rng_fault_state = true;
10233 return WERR_NOT_SUPPORTED;
10236 /****************************************************************
10237 _spoolss_ResetPrinterEx
10238 ****************************************************************/
10240 WERROR _spoolss_ResetPrinterEx(pipes_struct *p,
10241 struct spoolss_ResetPrinterEx *r)
10243 p->rng_fault_state = true;
10244 return WERR_NOT_SUPPORTED;
10247 /****************************************************************
10248 _spoolss_RouterReplyPrinterEx
10249 ****************************************************************/
10251 WERROR _spoolss_RouterReplyPrinterEx(pipes_struct *p,
10252 struct spoolss_RouterReplyPrinterEx *r)
10254 p->rng_fault_state = true;
10255 return WERR_NOT_SUPPORTED;
10258 /****************************************************************
10259 _spoolss_44
10260 ****************************************************************/
10262 WERROR _spoolss_44(pipes_struct *p,
10263 struct spoolss_44 *r)
10265 p->rng_fault_state = true;
10266 return WERR_NOT_SUPPORTED;
10269 /****************************************************************
10270 _spoolss_47
10271 ****************************************************************/
10273 WERROR _spoolss_47(pipes_struct *p,
10274 struct spoolss_47 *r)
10276 p->rng_fault_state = true;
10277 return WERR_NOT_SUPPORTED;
10280 /****************************************************************
10281 _spoolss_4a
10282 ****************************************************************/
10284 WERROR _spoolss_4a(pipes_struct *p,
10285 struct spoolss_4a *r)
10287 p->rng_fault_state = true;
10288 return WERR_NOT_SUPPORTED;
10291 /****************************************************************
10292 _spoolss_4b
10293 ****************************************************************/
10295 WERROR _spoolss_4b(pipes_struct *p,
10296 struct spoolss_4b *r)
10298 p->rng_fault_state = true;
10299 return WERR_NOT_SUPPORTED;
10302 /****************************************************************
10303 _spoolss_4c
10304 ****************************************************************/
10306 WERROR _spoolss_4c(pipes_struct *p,
10307 struct spoolss_4c *r)
10309 p->rng_fault_state = true;
10310 return WERR_NOT_SUPPORTED;
10313 /****************************************************************
10314 _spoolss_53
10315 ****************************************************************/
10317 WERROR _spoolss_53(pipes_struct *p,
10318 struct spoolss_53 *r)
10320 p->rng_fault_state = true;
10321 return WERR_NOT_SUPPORTED;
10324 /****************************************************************
10325 _spoolss_55
10326 ****************************************************************/
10328 WERROR _spoolss_55(pipes_struct *p,
10329 struct spoolss_55 *r)
10331 p->rng_fault_state = true;
10332 return WERR_NOT_SUPPORTED;
10335 /****************************************************************
10336 _spoolss_56
10337 ****************************************************************/
10339 WERROR _spoolss_56(pipes_struct *p,
10340 struct spoolss_56 *r)
10342 p->rng_fault_state = true;
10343 return WERR_NOT_SUPPORTED;
10346 /****************************************************************
10347 _spoolss_57
10348 ****************************************************************/
10350 WERROR _spoolss_57(pipes_struct *p,
10351 struct spoolss_57 *r)
10353 p->rng_fault_state = true;
10354 return WERR_NOT_SUPPORTED;
10357 /****************************************************************
10358 _spoolss_5a
10359 ****************************************************************/
10361 WERROR _spoolss_5a(pipes_struct *p,
10362 struct spoolss_5a *r)
10364 p->rng_fault_state = true;
10365 return WERR_NOT_SUPPORTED;
10368 /****************************************************************
10369 _spoolss_5b
10370 ****************************************************************/
10372 WERROR _spoolss_5b(pipes_struct *p,
10373 struct spoolss_5b *r)
10375 p->rng_fault_state = true;
10376 return WERR_NOT_SUPPORTED;
10379 /****************************************************************
10380 _spoolss_5c
10381 ****************************************************************/
10383 WERROR _spoolss_5c(pipes_struct *p,
10384 struct spoolss_5c *r)
10386 p->rng_fault_state = true;
10387 return WERR_NOT_SUPPORTED;
10390 /****************************************************************
10391 _spoolss_5d
10392 ****************************************************************/
10394 WERROR _spoolss_5d(pipes_struct *p,
10395 struct spoolss_5d *r)
10397 p->rng_fault_state = true;
10398 return WERR_NOT_SUPPORTED;
10401 /****************************************************************
10402 _spoolss_5e
10403 ****************************************************************/
10405 WERROR _spoolss_5e(pipes_struct *p,
10406 struct spoolss_5e *r)
10408 p->rng_fault_state = true;
10409 return WERR_NOT_SUPPORTED;
10412 /****************************************************************
10413 _spoolss_5f
10414 ****************************************************************/
10416 WERROR _spoolss_5f(pipes_struct *p,
10417 struct spoolss_5f *r)
10419 p->rng_fault_state = true;
10420 return WERR_NOT_SUPPORTED;