/* [<][>][^][v][top][bottom][index][help] */
DEFINITIONS
This source file includes following definitions.
- canon_servername
- nt_printj_status
- nt_printq_status
- srv_spoolss_replycloseprinter
- printer_entry_destructor
- find_printer_index_by_hnd
- close_printer_handle
- delete_printer_hook
- delete_printer_handle
- get_printer_snum
- set_printer_hnd_printertype
- set_printer_hnd_name
- open_printer_hnd
- is_monitoring_event_flags
- is_monitoring_event
- init_systemtime_buffer
- notify_one_value
- notify_string
- notify_system_time
- notify_msg_ctr_init
- notify_msg_ctr_destroy
- notify_ctr_getctx
- notify_ctr_getgroup
- notify_msg_ctr_numgroups
- notify_msg_ctr_addmsg
- send_notify2_changes
- notify2_unpack_msg
- receive_notify2_message_list
- srv_spoolss_drv_upgrade_printer
- do_drv_upgrade_printer
- update_monitored_printq_cache
- srv_spoolss_reset_printerdata
- reset_all_printerdata
- _spoolss_OpenPrinter
- convert_devicemode
- _spoolss_OpenPrinterEx
- printer_info2_to_nt_printer_info2
- convert_printer_info
- string_array_to_fstring_array
- driver_info3_to_nt_driver_info3
- driver_info6_to_nt_driver_info6
- convert_printer_driver_info
- _spoolss_enddocprinter_internal
- _spoolss_ClosePrinter
- _spoolss_DeletePrinter
- get_version_id
- _spoolss_DeletePrinterDriver
- _spoolss_DeletePrinterDriverEx
- delete_printer_dataex
- set_printer_dataex
- getprinterdata_printer_server
- _spoolss_GetPrinterData
- spoolss_connect_to_client
- srv_spoolss_replyopenprinter
- dup_spoolss_NotifyOption
- _spoolss_RemoteFindFirstPrinterChangeNotifyEx
- spoolss_notify_server_name
- spoolss_notify_printer_name
- spoolss_notify_share_name
- spoolss_notify_port_name
- spoolss_notify_driver_name
- spoolss_notify_comment
- spoolss_notify_location
- spoolss_notify_devmode
- spoolss_notify_sepfile
- spoolss_notify_print_processor
- spoolss_notify_parameters
- spoolss_notify_datatype
- spoolss_notify_security_desc
- spoolss_notify_attributes
- spoolss_notify_priority
- spoolss_notify_default_priority
- spoolss_notify_start_time
- spoolss_notify_until_time
- spoolss_notify_status
- spoolss_notify_cjobs
- spoolss_notify_average_ppm
- spoolss_notify_username
- spoolss_notify_job_status
- spoolss_notify_job_name
- spoolss_notify_job_status_string
- spoolss_notify_job_time
- spoolss_notify_job_size
- spoolss_notify_total_pages
- spoolss_notify_pages_printed
- spoolss_notify_job_position
- spoolss_notify_submitted_time
- variable_type_of_notify_info_data
- search_notify
- construct_info_data
- construct_notify_printer_info
- construct_notify_jobs_info
- printserver_notify_info
- printer_notify_info
- _spoolss_RouterRefreshPrinterChangeNotify
- construct_printer_info0
- convert_nt_devicemode
- construct_dev_mode
- construct_printer_info3
- construct_printer_info4
- construct_printer_info5
- construct_printer_info6
- construct_printer_info7
- construct_printer_info8
- construct_printer_info1
- construct_printer_info2
- snum_is_shared_printer
- enum_all_printers_info_level
- enumprinters_level0
- enum_all_printers_info_1
- enum_all_printers_info_1_local
- enum_all_printers_info_1_name
- enum_all_printers_info_1_network
- enum_all_printers_info_2
- enumprinters_level1
- enumprinters_level2
- enumprinters_level4
- enumprinters_level5
- _spoolss_EnumPrinters
- _spoolss_GetPrinter
- string_array_from_driver_info
- fill_printer_driver_info1
- fill_printer_driver_info2
- fill_printer_driver_info3
- fill_printer_driver_info4
- fill_printer_driver_info5
- fill_printer_driver_info6
- fill_spoolss_DriverFileInfo
- spoolss_DriverFileInfo_from_driver
- fill_printer_driver_info101
- construct_printer_driver_info_1
- construct_printer_driver_info_2
- construct_printer_driver_info_3
- construct_printer_driver_info_6
- construct_printer_driver_info_101
- _spoolss_GetPrinterDriver2
- _spoolss_StartPagePrinter
- _spoolss_EndPagePrinter
- _spoolss_StartDocPrinter
- _spoolss_EndDocPrinter
- _spoolss_WritePrinter
- control_printer
- _spoolss_AbortPrinter
- update_printer_sec
- check_printer_ok
- add_port_hook
- add_printer_hook
- update_printer
- publish_or_unpublish_printer
- _spoolss_SetPrinter
- _spoolss_FindClosePrinterNotify
- _spoolss_AddJob
- fill_job_info1
- fill_job_info2
- enumjobs_level1
- enumjobs_level2
- _spoolss_EnumJobs
- _spoolss_ScheduleJob
- _spoolss_SetJob
- enumprinterdrivers_level
- enumprinterdrivers_level1
- enumprinterdrivers_level2
- enumprinterdrivers_level3
- enumprinterdrivers_level4
- enumprinterdrivers_level5
- enumprinterdrivers_level6
- _spoolss_EnumPrinterDrivers
- fill_form_info_1
- spoolss_enumforms_level1
- _spoolss_EnumForms
- find_form_byname
- _spoolss_GetForm
- fill_port_1
- fill_port_2
- enumports_hook
- enumports_level_1
- enumports_level_2
- _spoolss_EnumPorts
- spoolss_addprinterex_level_2
- _spoolss_AddPrinterEx
- _spoolss_AddPrinterDriver
- _spoolss_AddPrinterDriverEx
- compose_spoolss_server_path
- getprinterdriverdir_level_1
- _spoolss_GetPrinterDriverDirectory
- _spoolss_EnumPrinterData
- _spoolss_SetPrinterData
- _spoolss_ResetPrinter
- _spoolss_DeletePrinterData
- _spoolss_AddForm
- _spoolss_DeleteForm
- _spoolss_SetForm
- fill_print_processor1
- enumprintprocessors_level_1
- _spoolss_EnumPrintProcessors
- fill_printprocdatatype1
- enumprintprocdatatypes_level_1
- _spoolss_EnumPrintProcDataTypes
- fill_monitor_1
- fill_monitor_2
- enumprintmonitors_level_1
- enumprintmonitors_level_2
- _spoolss_EnumMonitors
- getjob_level_1
- getjob_level_2
- _spoolss_GetJob
- _spoolss_GetPrinterDataEx
- _spoolss_SetPrinterDataEx
- _spoolss_DeletePrinterDataEx
- _spoolss_EnumPrinterKey
- _spoolss_DeletePrinterKey
- registry_value_to_printer_enum_value
- _spoolss_EnumPrinterDataEx
- getprintprocessordirectory_level_1
- _spoolss_GetPrintProcessorDirectory
- push_monitorui_buf
- xcvtcp_monitorui
- pull_port_data_1
- pull_port_data_2
- xcvtcp_addport
- process_xcvtcp_command
- xcvlocal_monitorui
- process_xcvlocal_command
- _spoolss_XcvData
- _spoolss_AddPrintProcessor
- _spoolss_AddPort
- _spoolss_AddPrinter
- _spoolss_GetPrinterDriver
- _spoolss_ReadPrinter
- _spoolss_WaitForPrinterChange
- _spoolss_ConfigurePort
- _spoolss_DeletePort
- _spoolss_CreatePrinterIC
- _spoolss_PlayGDIScriptOnPrinterIC
- _spoolss_DeletePrinterIC
- _spoolss_AddPrinterConnection
- _spoolss_DeletePrinterConnection
- _spoolss_PrinterMessageBox
- _spoolss_AddMonitor
- _spoolss_DeleteMonitor
- _spoolss_DeletePrintProcessor
- _spoolss_AddPrintProvidor
- _spoolss_DeletePrintProvidor
- _spoolss_FindFirstPrinterChangeNotification
- _spoolss_FindNextPrinterChangeNotification
- _spoolss_RouterFindFirstPrinterChangeNotificationOld
- _spoolss_ReplyOpenPrinter
- _spoolss_RouterReplyPrinter
- _spoolss_ReplyClosePrinter
- _spoolss_AddPortEx
- _spoolss_RouterFindFirstPrinterChangeNotification
- _spoolss_SpoolerInit
- _spoolss_ResetPrinterEx
- _spoolss_RouterReplyPrinterEx
- _spoolss_44
- _spoolss_47
- _spoolss_4a
- _spoolss_4b
- _spoolss_4c
- _spoolss_53
- _spoolss_55
- _spoolss_56
- _spoolss_57
- _spoolss_5a
- _spoolss_5b
- _spoolss_5c
- _spoolss_5d
- _spoolss_5e
- _spoolss_5f
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.
11 *
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.
16 *
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.
21 *
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/>.
24 */
25
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. */
28
29 #include "includes.h"
30
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)
34
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)
37
38 #define SPOOLSS_BUFFER_ARRAY(mem_ctx,fn,ic,info,count) \
39 ((info)?ndr_size_##fn##_info(mem_ctx, ic, count, info):0)
40
41 #define SPOOLSS_BUFFER_OK(val_true,val_false) ((r->in.offered >= *r->out.needed)?val_true:val_false)
42
43
44 extern userdom_struct current_user_info;
45
46 #undef DBGC_CLASS
47 #define DBGC_CLASS DBGC_RPC_SRV
48
49 #ifndef MAX_OPEN_PRINTER_EXS
50 #define MAX_OPEN_PRINTER_EXS 50
51 #endif
52
53 #define MAGIC_DISPLAY_FREQUENCY 0xfade2bad
54 #define PHANTOM_DEVMODE_KEY "_p_f_a_n_t_0_m_"
55
56 static Printer_entry *printers_list;
57
58 typedef struct _counter_printer_0 {
59 struct _counter_printer_0 *next;
60 struct _counter_printer_0 *prev;
61
62 int snum;
63 uint32_t counter;
64 } counter_printer_0;
65
66 static counter_printer_0 *counter_list;
67
68 static struct rpc_pipe_client *notify_cli_pipe; /* print notify back-channel pipe handle*/
69 static uint32_t smb_connections = 0;
70
71
72 /* in printing/nt_printing.c */
73
74 extern struct standard_mapping printer_std_mapping, printserver_std_mapping;
75
76 /* API table for Xcv Monitor functions */
77
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);
81 };
82
83 /********************************************************************
84 * Canonicalize servername.
85 ********************************************************************/
86
87 static const char *canon_servername(const char *servername)
/* [<][>][^][v][top][bottom][index][help] */
88 {
89 const char *pservername = servername;
90 while (*pservername == '\\') {
91 pservername++;
92 }
93 return pservername;
94 }
95
96 /* translate between internal status numbers and NT status numbers */
97 static int nt_printj_status(int v)
/* [<][>][^][v][top][bottom][index][help] */
98 {
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;
124 }
125 return 0;
126 }
127
128 static int nt_printq_status(int v)
/* [<][>][^][v][top][bottom][index][help] */
129 {
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;
137 }
138 return 0;
139 }
140
141 /***************************************************************************
142 Disconnect from the client
143 ****************************************************************************/
144
145 static void srv_spoolss_replycloseprinter(int snum, struct policy_handle *handle)
/* [<][>][^][v][top][bottom][index][help] */
146 {
147 WERROR result;
148 NTSTATUS status;
149
150 /*
151 * Tell the specific printing tdb we no longer want messages for this printer
152 * by deregistering our PID.
153 */
154
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) ));
157
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;
162 }
163
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)));
170
171 /* if it's the last connection, deconnect the IPC$ share */
172 if (smb_connections==1) {
173
174 cli_shutdown( rpc_pipe_np_smb_conn(notify_cli_pipe) );
175 notify_cli_pipe = NULL; /* The above call shuts downn the pipe also. */
176
177 messaging_deregister(smbd_messaging_context(),
178 MSG_PRINTER_NOTIFY2, NULL);
179
180 /* Tell the connections db we're no longer interested in
181 * printer notify messages. */
182
183 register_message_flags(false, FLAG_MSG_PRINT_NOTIFY);
184 }
185
186 smb_connections--;
187 }
188
189 /****************************************************************************
190 Functions to free a printer entry datastruct.
191 ****************************************************************************/
192
193 static int printer_entry_destructor(Printer_entry *Printer)
/* [<][>][^][v][top][bottom][index][help] */
194 {
195 if (Printer->notify.client_connected == true) {
196 int snum = -1;
197
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);
206 }
207 }
208
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;
215
216 free_nt_devicemode( &Printer->nt_devmode );
217 free_a_printer( &Printer->printer_info, 2 );
218
219 /* Remove from the internal list. */
220 DLIST_REMOVE(printers_list, Printer);
221 return 0;
222 }
223
224 /****************************************************************************
225 find printer index by handle
226 ****************************************************************************/
227
228 static Printer_entry *find_printer_index_by_hnd(pipes_struct *p,
/* [<][>][^][v][top][bottom][index][help] */
229 struct policy_handle *hnd)
230 {
231 Printer_entry *find_printer = NULL;
232
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;
236 }
237
238 return find_printer;
239 }
240
241 /****************************************************************************
242 Close printer index by handle.
243 ****************************************************************************/
244
245 static bool close_printer_handle(pipes_struct *p, struct policy_handle *hnd)
/* [<][>][^][v][top][bottom][index][help] */
246 {
247 Printer_entry *Printer = find_printer_index_by_hnd(p, hnd);
248
249 if (!Printer) {
250 DEBUG(2,("close_printer_handle: Invalid handle (%s:%u:%u)\n",
251 OUR_HANDLE(hnd)));
252 return false;
253 }
254
255 close_policy_hnd(p, hnd);
256
257 return true;
258 }
259
260 /****************************************************************************
261 Delete a printer given a handle.
262 ****************************************************************************/
263
264 WERROR delete_printer_hook(TALLOC_CTX *ctx, NT_USER_TOKEN *token, const char *sharename )
/* [<][>][^][v][top][bottom][index][help] */
265 {
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;
271
272 /* can't fail if we don't try */
273
274 if ( !*cmd )
275 return WERR_OK;
276
277 command = talloc_asprintf(ctx,
278 "%s \"%s\"",
279 cmd, sharename);
280 if (!command) {
281 return WERR_NOMEM;
282 }
283 if ( token )
284 is_print_op = user_has_privileges( token, &se_printop );
285
286 DEBUG(10,("Running [%s]\n", command));
287
288 /********** BEGIN SePrintOperatorPrivlege BLOCK **********/
289
290 if ( is_print_op )
291 become_root();
292
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);
297 }
298
299 if ( is_print_op )
300 unbecome_root();
301
302 /********** END SePrintOperatorPrivlege BLOCK **********/
303
304 DEBUGADD(10,("returned [%d]\n", ret));
305
306 TALLOC_FREE(command);
307
308 if (ret != 0)
309 return WERR_BADFID; /* What to return here? */
310
311 /* go ahead and re-read the services immediately */
312 become_root();
313 reload_services(false);
314 unbecome_root();
315
316 if ( lp_servicenumber( sharename ) < 0 )
317 return WERR_ACCESS_DENIED;
318
319 return WERR_OK;
320 }
321
322 /****************************************************************************
323 Delete a printer given a handle.
324 ****************************************************************************/
325
326 static WERROR delete_printer_handle(pipes_struct *p, struct policy_handle *hnd)
/* [<][>][^][v][top][bottom][index][help] */
327 {
328 Printer_entry *Printer = find_printer_index_by_hnd(p, hnd);
329
330 if (!Printer) {
331 DEBUG(2,("delete_printer_handle: Invalid handle (%s:%u:%u)\n",
332 OUR_HANDLE(hnd)));
333 return WERR_BADFID;
334 }
335
336 /*
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.
341 */
342
343 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
344 DEBUG(3, ("delete_printer_handle: denied by handle\n"));
345 return WERR_ACCESS_DENIED;
346 }
347
348 /* this does not need a become root since the access check has been
349 done on the handle already */
350
351 if (del_a_printer( Printer->sharename ) != 0) {
352 DEBUG(3,("Error deleting printer %s\n", Printer->sharename));
353 return WERR_BADFID;
354 }
355
356 return delete_printer_hook(p->mem_ctx, p->server_info->ptok,
357 Printer->sharename );
358 }
359
360 /****************************************************************************
361 Return the snum of a printer corresponding to an handle.
362 ****************************************************************************/
363
364 static bool get_printer_snum(pipes_struct *p, struct policy_handle *hnd,
/* [<][>][^][v][top][bottom][index][help] */
365 int *number, struct share_params **params)
366 {
367 Printer_entry *Printer = find_printer_index_by_hnd(p, hnd);
368
369 if (!Printer) {
370 DEBUG(2,("get_printer_snum: Invalid handle (%s:%u:%u)\n",
371 OUR_HANDLE(hnd)));
372 return false;
373 }
374
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;
384 }
385 }
386
387 /****************************************************************************
388 Set printer handle type.
389 Check if it's \\server or \\server\printer
390 ****************************************************************************/
391
392 static bool set_printer_hnd_printertype(Printer_entry *Printer, const char *handlename)
/* [<][>][^][v][top][bottom][index][help] */
393 {
394 DEBUG(3,("Setting printer type=%s\n", handlename));
395
396 if ( strlen(handlename) < 3 ) {
397 DEBUGADD(4,("A print server must have at least 1 char ! %s\n", handlename));
398 return false;
399 }
400
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;
405 }
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;
410 }
411
412 return true;
413 }
414
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 ****************************************************************************/
421
422 static bool set_printer_hnd_name(Printer_entry *Printer, const char *handlename)
/* [<][>][^][v][top][bottom][index][help] */
423 {
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;
432
433 DEBUG(4,("Setting printer name=%s (len=%lu)\n", handlename,
434 (unsigned long)strlen(handlename)));
435
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++;
442 }
443 } else {
444 servername = global_myname();
445 }
446
447 /* save the servername to fill in replies on this handle */
448
449 if ( !is_myname_or_ipaddr( servername ) )
450 return false;
451
452 fstrcpy( Printer->servername, servername );
453
454 if ( Printer->printer_type == SPLHND_SERVER )
455 return true;
456
457 if ( Printer->printer_type != SPLHND_PRINTER )
458 return false;
459
460 DEBUGADD(5, ("searching for [%s]\n", aprinter ));
461
462 /* check for the Port Monitor Interface */
463
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;
468 }
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;
473 }
474
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() */
478
479 /* do another loop to look for printernames */
480
481 for (snum=0; !found && snum<n_services; snum++) {
482
483 /* no point going on if this is not a printer */
484
485 if ( !(lp_snum_ok(snum) && lp_print_ok(snum)) )
486 continue;
487
488 fstrcpy(sname, lp_servicename(snum));
489 if ( strequal( aprinter, sname ) ) {
490 found = true;
491 break;
492 }
493
494 /* no point looking up the printer object if
495 we aren't allowing printername != sharename */
496
497 if ( lp_force_printername(snum) )
498 continue;
499
500 fstrcpy(sname, lp_servicename(snum));
501
502 printer = NULL;
503
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.
507 */
508
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;
514 }
515
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;
522 }
523
524 printername++;
525
526 if ( strequal(printername, aprinter) ) {
527 free_a_printer( &printer, 2);
528 found = true;
529 break;
530 }
531
532 DEBUGADD(10, ("printername: %s\n", printername));
533
534 free_a_printer( &printer, 2);
535 }
536
537 free_a_printer( &printer, 2);
538
539 if ( !found ) {
540 DEBUGADD(4,("Printer not found\n"));
541 return false;
542 }
543
544 DEBUGADD(4,("set_printer_hnd_name: Printer found: %s -> %s\n", aprinter, sname));
545
546 fstrcpy(Printer->sharename, sname);
547
548 return true;
549 }
550
551 /****************************************************************************
552 Find first available printer slot. creates a printer handle for you.
553 ****************************************************************************/
554
555 static bool open_printer_hnd(pipes_struct *p, struct policy_handle *hnd,
/* [<][>][^][v][top][bottom][index][help] */
556 const char *name, uint32_t access_granted)
557 {
558 Printer_entry *new_printer;
559
560 DEBUG(10,("open_printer_hnd: name [%s]\n", name));
561
562 new_printer = TALLOC_ZERO_P(NULL, Printer_entry);
563 if (new_printer == NULL) {
564 return false;
565 }
566 talloc_set_destructor(new_printer, printer_entry_destructor);
567
568 if (!create_policy_hnd(p, hnd, new_printer)) {
569 TALLOC_FREE(new_printer);
570 return false;
571 }
572
573 /* Add to the internal list. */
574 DLIST_ADD(printers_list, new_printer);
575
576 new_printer->notify.option=NULL;
577
578 if (!set_printer_hnd_printertype(new_printer, name)) {
579 close_printer_handle(p, hnd);
580 return false;
581 }
582
583 if (!set_printer_hnd_name(new_printer, name)) {
584 close_printer_handle(p, hnd);
585 return false;
586 }
587
588 new_printer->access_granted = access_granted;
589
590 DEBUG(5, ("%d printer handles active\n", (int)p->pipe_handles->count ));
591
592 return true;
593 }
594
595 /***************************************************************************
596 check to see if the client motify handle is monitoring the notification
597 given by (notify_type, notify_field).
598 **************************************************************************/
599
600 static bool is_monitoring_event_flags(uint32_t flags, uint16_t notify_type,
/* [<][>][^][v][top][bottom][index][help] */
601 uint16_t notify_field)
602 {
603 return true;
604 }
605
606 static bool is_monitoring_event(Printer_entry *p, uint16_t notify_type,
/* [<][>][^][v][top][bottom][index][help] */
607 uint16_t notify_field)
608 {
609 struct spoolss_NotifyOption *option = p->notify.option;
610 uint32_t i, j;
611
612 /*
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
617 */
618
619 if (!option) {
620 return false;
621 }
622
623 if (p->notify.flags)
624 return is_monitoring_event_flags(
625 p->notify.flags, notify_type, notify_field);
626
627 for (i = 0; i < option->count; i++) {
628
629 /* Check match for notify_type */
630
631 if (option->types[i].type != notify_type)
632 continue;
633
634 /* Check match for field */
635
636 for (j = 0; j < option->types[i].count; j++) {
637 if (option->types[i].fields[j].field == notify_field) {
638 return true;
639 }
640 }
641 }
642
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));
645
646 return false;
647 }
648
649 #define SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(_data, _integer) \
650 _data->data.integer[0] = _integer; \
651 _data->data.integer[1] = 0;
652
653
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; \
658 } \
659 _data->data.string.size = strlen_m_term(_p) * 2;
660
661 #define SETUP_SPOOLSS_NOTIFY_DATA_DEVMODE(_data, _devmode) \
662 _data->data.devmode.devmode = _devmode;
663
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; \
668 } \
669 _data->data.sd.sd_size = _size;
670
671 static void init_systemtime_buffer(TALLOC_CTX *mem_ctx,
/* [<][>][^][v][top][bottom][index][help] */
672 struct tm *t,
673 const char **pp,
674 uint32_t *plen)
675 {
676 struct spoolss_Time st;
677 uint32_t len = 16;
678 char *p;
679
680 if (!init_systemtime(&st, t)) {
681 return;
682 }
683
684 p = talloc_array(mem_ctx, char, len);
685 if (!p) {
686 return;
687 }
688
689 /*
690 * Systemtime must be linearized as a set of UINT16's.
691 * Fix from Benjamin (Bj) Kuit bj@it.uts.edu.au
692 */
693
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);
702
703 *pp = p;
704 *plen = len;
705 }
706
707 /* Convert a notification message to a struct spoolss_Notify */
708
709 static void notify_one_value(struct spoolss_notify_msg *msg,
/* [<][>][^][v][top][bottom][index][help] */
710 struct spoolss_Notify *data,
711 TALLOC_CTX *mem_ctx)
712 {
713 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, msg->notify.value[0]);
714 }
715
716 static void notify_string(struct spoolss_notify_msg *msg,
/* [<][>][^][v][top][bottom][index][help] */
717 struct spoolss_Notify *data,
718 TALLOC_CTX *mem_ctx)
719 {
720 /* The length of the message includes the trailing \0 */
721
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;
727 }
728 }
729
730 static void notify_system_time(struct spoolss_notify_msg *msg,
/* [<][>][^][v][top][bottom][index][help] */
731 struct spoolss_Notify *data,
732 TALLOC_CTX *mem_ctx)
733 {
734 data->data.string.string = NULL;
735 data->data.string.size = 0;
736
737 if (msg->len != sizeof(time_t)) {
738 DEBUG(5, ("notify_system_time: received wrong sized message (%d)\n",
739 msg->len));
740 return;
741 }
742
743 init_systemtime_buffer(mem_ctx, gmtime((time_t *)msg->notify.data),
744 &data->data.string.string,
745 &data->data.string.size);
746 }
747
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);
752 };
753
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 },
774 };
775
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 },
801 };
802
803
804 /***********************************************************************
805 Allocate talloc context for container object
806 **********************************************************************/
807
808 static void notify_msg_ctr_init( SPOOLSS_NOTIFY_MSG_CTR *ctr )
/* [<][>][^][v][top][bottom][index][help] */
809 {
810 if ( !ctr )
811 return;
812
813 ctr->ctx = talloc_init("notify_msg_ctr_init %p", ctr);
814
815 return;
816 }
817
818 /***********************************************************************
819 release all allocated memory and zero out structure
820 **********************************************************************/
821
822 static void notify_msg_ctr_destroy( SPOOLSS_NOTIFY_MSG_CTR *ctr )
/* [<][>][^][v][top][bottom][index][help] */
823 {
824 if ( !ctr )
825 return;
826
827 if ( ctr->ctx )
828 talloc_destroy(ctr->ctx);
829
830 ZERO_STRUCTP(ctr);
831
832 return;
833 }
834
835 /***********************************************************************
836 **********************************************************************/
837
838 static TALLOC_CTX* notify_ctr_getctx( SPOOLSS_NOTIFY_MSG_CTR *ctr )
/* [<][>][^][v][top][bottom][index][help] */
839 {
840 if ( !ctr )
841 return NULL;
842
843 return ctr->ctx;
844 }
845
846 /***********************************************************************
847 **********************************************************************/
848
849 static SPOOLSS_NOTIFY_MSG_GROUP* notify_ctr_getgroup( SPOOLSS_NOTIFY_MSG_CTR *ctr, uint32_t idx )
/* [<][>][^][v][top][bottom][index][help] */
850 {
851 if ( !ctr || !ctr->msg_groups )
852 return NULL;
853
854 if ( idx >= ctr->num_groups )
855 return NULL;
856
857 return &ctr->msg_groups[idx];
858
859 }
860
861 /***********************************************************************
862 How many groups of change messages do we have ?
863 **********************************************************************/
864
865 static int notify_msg_ctr_numgroups( SPOOLSS_NOTIFY_MSG_CTR *ctr )
/* [<][>][^][v][top][bottom][index][help] */
866 {
867 if ( !ctr )
868 return 0;
869
870 return ctr->num_groups;
871 }
872
873 /***********************************************************************
874 Add a SPOOLSS_NOTIFY_MSG_CTR to the correct group
875 **********************************************************************/
876
877 static int notify_msg_ctr_addmsg( SPOOLSS_NOTIFY_MSG_CTR *ctr, SPOOLSS_NOTIFY_MSG *msg )
/* [<][>][^][v][top][bottom][index][help] */
878 {
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;
883
884 if ( !ctr || !msg )
885 return 0;
886
887 /* loop over all groups looking for a matching printer name */
888
889 for ( i=0; i<ctr->num_groups; i++ ) {
890 if ( strcmp(ctr->msg_groups[i].printername, msg->printer) == 0 )
891 break;
892 }
893
894 /* add a new group? */
895
896 if ( i == ctr->num_groups ) {
897 ctr->num_groups++;
898
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;
902 }
903 ctr->msg_groups = groups;
904
905 /* clear the new entry and set the printer name */
906
907 ZERO_STRUCT( ctr->msg_groups[ctr->num_groups-1] );
908 fstrcpy( ctr->msg_groups[ctr->num_groups-1].printername, msg->printer );
909 }
910
911 /* add the change messages; 'i' is the correct index now regardless */
912
913 msg_grp = &ctr->msg_groups[i];
914
915 msg_grp->num_msgs++;
916
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;
920 }
921 msg_grp->msgs = msg_list;
922
923 new_slot = msg_grp->num_msgs-1;
924 memcpy( &msg_grp->msgs[new_slot], msg, sizeof(SPOOLSS_NOTIFY_MSG) );
925
926 /* need to allocate own copy of data */
927
928 if ( msg->len != 0 )
929 msg_grp->msgs[new_slot].notify.data = (char *)
930 TALLOC_MEMDUP( ctr->ctx, msg->notify.data, msg->len );
931
932 return ctr->num_groups;
933 }
934
935 /***********************************************************************
936 Send a change notication message on all handles which have a call
937 back registered
938 **********************************************************************/
939
940 static void send_notify2_changes( SPOOLSS_NOTIFY_MSG_CTR *ctr, uint32_t idx )
/* [<][>][^][v][top][bottom][index][help] */
941 {
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;
947
948 if ( !msg_group ) {
949 DEBUG(5,("send_notify2_changes() called with no msg group!\n"));
950 return;
951 }
952
953 messages = msg_group->msgs;
954
955 if ( !messages ) {
956 DEBUG(5,("send_notify2_changes() called with no messages!\n"));
957 return;
958 }
959
960 DEBUG(8,("send_notify2_changes: Enter...[%s]\n", msg_group->printername));
961
962 /* loop over all printers */
963
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;
969
970 /* Is there notification on this handle? */
971
972 if ( !p->notify.client_connected )
973 continue;
974
975 DEBUG(10,("Client connected! [\\\\%s\\%s]\n", p->servername, p->sharename));
976
977 /* For this printer? Print servers always receive
978 notifications. */
979
980 if ( ( p->printer_type == SPLHND_PRINTER ) &&
981 ( !strequal(msg_group->printername, p->sharename) ) )
982 continue;
983
984 DEBUG(10,("Our printer\n"));
985
986 /* allocate the max entries possible */
987
988 notifies = TALLOC_ZERO_ARRAY(mem_ctx, struct spoolss_Notify, msg_group->num_msgs);
989 if (!notifies) {
990 return;
991 }
992
993 /* build the array of change notifications */
994
995 sending_msg_count = 0;
996
997 for ( i=0; i<msg_group->num_msgs; i++ ) {
998 SPOOLSS_NOTIFY_MSG *msg = &messages[i];
999
1000 /* Are we monitoring this event? */
1001
1002 if (!is_monitoring_event(p, msg->type, msg->field))
1003 continue;
1004
1005 sending_msg_count++;
1006
1007
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));
1010
1011 /*
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.
1015 *
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.
1020 *
1021 * --jerry
1022 */
1023
1024 if ( ( p->printer_type == SPLHND_PRINTER ) && ( msg->type == PRINTER_NOTIFY_TYPE ) )
1025 id = 0;
1026 else
1027 id = msg->id;
1028
1029
1030 /* Convert unix jobid to smb jobid */
1031
1032 if (msg->flags & SPOOLSS_NOTIFY_MSG_UNIX_JOBID) {
1033 id = sysjob_to_jobid(msg->id);
1034
1035 if (id == -1) {
1036 DEBUG(3, ("no such unix jobid %d\n", msg->id));
1037 goto done;
1038 }
1039 }
1040
1041 construct_info_data( ¬ifies[count], msg->type, msg->field, id );
1042
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, ¬ifies[count], mem_ctx);
1047 break;
1048
1049 case JOB_NOTIFY_TYPE:
1050 if ( job_notify_table[msg->field].fn )
1051 job_notify_table[msg->field].fn(msg, ¬ifies[count], mem_ctx);
1052 break;
1053
1054 default:
1055 DEBUG(5, ("Unknown notification type %d\n", msg->type));
1056 goto done;
1057 }
1058
1059 count++;
1060 }
1061
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;
1068
1069 info0.version = 0x2;
1070 info0.flags = count ? 0x00020000 /* ??? */ : PRINTER_NOTIFY_INFO_DISCARDED;
1071 info0.count = count;
1072 info0.notifies = notifies;
1073
1074 info.info0 = &info0;
1075
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)));
1088 }
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;
1098 }
1099 }
1100 }
1101
1102 done:
1103 DEBUG(8,("send_notify2_changes: Exit...\n"));
1104 return;
1105 }
1106
1107 /***********************************************************************
1108 **********************************************************************/
1109
1110 static bool notify2_unpack_msg( SPOOLSS_NOTIFY_MSG *msg, struct timeval *tv, void *buf, size_t len )
/* [<][>][^][v][top][bottom][index][help] */
1111 {
1112
1113 uint32_t tv_sec, tv_usec;
1114 size_t offset = 0;
1115
1116 /* Unpack message */
1117
1118 offset += tdb_unpack((uint8_t *)buf + offset, len - offset, "f",
1119 msg->printer);
1120
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);
1124
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);
1131
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));
1134
1135 tv->tv_sec = tv_sec;
1136 tv->tv_usec = tv_usec;
1137
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);
1143
1144 return true;
1145 }
1146
1147 /********************************************************************
1148 Receive a notify2 message list
1149 ********************************************************************/
1150
1151 static void receive_notify2_message_list(struct messaging_context *msg,
/* [<][>][^][v][top][bottom][index][help] */
1152 void *private_data,
1153 uint32_t msg_type,
1154 struct server_id server_id,
1155 DATA_BLOB *data)
1156 {
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;
1164
1165 if (data->length < 4) {
1166 DEBUG(0,("receive_notify2_message_list: bad message format (len < 4)!\n"));
1167 return;
1168 }
1169
1170 msg_count = IVAL(buf, 0);
1171 msg_ptr = buf + 4;
1172
1173 DEBUG(5, ("receive_notify2_message_list: got %lu messages in list\n", (unsigned long)msg_count));
1174
1175 if (msg_count == 0) {
1176 DEBUG(0,("receive_notify2_message_list: bad message format (msg_count == 0) !\n"));
1177 return;
1178 }
1179
1180 /* initialize the container */
1181
1182 ZERO_STRUCT( messages );
1183 notify_msg_ctr_init( &messages );
1184
1185 /*
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.
1190 */
1191
1192 for ( i=0; i<msg_count; i++ ) {
1193 struct timeval msg_tv;
1194
1195 if (msg_ptr + 4 - buf > data->length) {
1196 DEBUG(0,("receive_notify2_message_list: bad message format (len > buf_size) !\n"));
1197 return;
1198 }
1199
1200 msg_len = IVAL(msg_ptr,0);
1201 msg_ptr += 4;
1202
1203 if (msg_ptr + msg_len - buf > data->length) {
1204 DEBUG(0,("receive_notify2_message_list: bad message format (bad len) !\n"));
1205 return;
1206 }
1207
1208 /* unpack messages */
1209
1210 ZERO_STRUCT( notify );
1211 notify2_unpack_msg( ¬ify, &msg_tv, msg_ptr, msg_len );
1212 msg_ptr += msg_len;
1213
1214 /* add to correct list in container */
1215
1216 notify_msg_ctr_addmsg( &messages, ¬ify );
1217
1218 /* free memory that might have been allocated by notify2_unpack_msg() */
1219
1220 if ( notify.len != 0 )
1221 SAFE_FREE( notify.notify.data );
1222 }
1223
1224 /* process each group of messages */
1225
1226 num_groups = notify_msg_ctr_numgroups( &messages );
1227 for ( i=0; i<num_groups; i++ )
1228 send_notify2_changes( &messages, i );
1229
1230
1231 /* cleanup */
1232
1233 DEBUG(10,("receive_notify2_message_list: processed %u messages\n",
1234 (uint32_t)msg_count ));
1235
1236 notify_msg_ctr_destroy( &messages );
1237
1238 return;
1239 }
1240
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 ********************************************************************/
1246
1247 static bool srv_spoolss_drv_upgrade_printer(const char *drivername)
/* [<][>][^][v][top][bottom][index][help] */
1248 {
1249 int len = strlen(drivername);
1250
1251 if (!len)
1252 return false;
1253
1254 DEBUG(10,("srv_spoolss_drv_upgrade_printer: Sending message about driver upgrade [%s]\n",
1255 drivername));
1256
1257 messaging_send_buf(smbd_messaging_context(), procid_self(),
1258 MSG_PRINTER_DRVUPGRADE,
1259 (uint8_t *)drivername, len+1);
1260
1261 return true;
1262 }
1263
1264 /**********************************************************************
1265 callback to receive a MSG_PRINTER_DRVUPGRADE message and interate
1266 over all printers, upgrading ones as necessary
1267 **********************************************************************/
1268
1269 void do_drv_upgrade_printer(struct messaging_context *msg,
/* [<][>][^][v][top][bottom][index][help] */
1270 void *private_data,
1271 uint32_t msg_type,
1272 struct server_id server_id,
1273 DATA_BLOB *data)
1274 {
1275 fstring drivername;
1276 int snum;
1277 int n_services = lp_numservices();
1278 size_t len;
1279
1280 len = MIN(data->length,sizeof(drivername)-1);
1281 strncpy(drivername, (const char *)data->data, len);
1282
1283 DEBUG(10,("do_drv_upgrade_printer: Got message for new driver [%s]\n", drivername ));
1284
1285 /* Iterate the printer list */
1286
1287 for (snum=0; snum<n_services; snum++)
1288 {
1289 if (lp_snum_ok(snum) && lp_print_ok(snum) )
1290 {
1291 WERROR result;
1292 NT_PRINTER_INFO_LEVEL *printer = NULL;
1293
1294 result = get_a_printer(NULL, &printer, 2, lp_const_servicename(snum));
1295 if (!W_ERROR_IS_OK(result))
1296 continue;
1297
1298 if (printer && printer->info_2 && !strcmp(drivername, printer->info_2->drivername))
1299 {
1300 DEBUG(6,("Updating printer [%s]\n", printer->info_2->printername));
1301
1302 /* all we care about currently is the change_id */
1303
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)));
1308 }
1309 }
1310
1311 free_a_printer(&printer, 2);
1312 }
1313 }
1314
1315 /* all done */
1316 }
1317
1318 /********************************************************************
1319 Update the cache for all printq's with a registered client
1320 connection
1321 ********************************************************************/
1322
1323 void update_monitored_printq_cache( void )
/* [<][>][^][v][top][bottom][index][help] */
1324 {
1325 Printer_entry *printer = printers_list;
1326 int snum;
1327
1328 /* loop through all printers and update the cache where
1329 client_connected == true */
1330 while ( printer )
1331 {
1332 if ( (printer->printer_type == SPLHND_PRINTER)
1333 && printer->notify.client_connected )
1334 {
1335 snum = print_queue_snum(printer->sharename);
1336 print_queue_status( snum, NULL, NULL );
1337 }
1338
1339 printer = printer->next;
1340 }
1341
1342 return;
1343 }
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 ********************************************************************/
1349
1350 static bool srv_spoolss_reset_printerdata(char* drivername)
/* [<][>][^][v][top][bottom][index][help] */
1351 {
1352 int len = strlen(drivername);
1353
1354 if (!len)
1355 return false;
1356
1357 DEBUG(10,("srv_spoolss_reset_printerdata: Sending message about resetting printerdata [%s]\n",
1358 drivername));
1359
1360 messaging_send_buf(smbd_messaging_context(), procid_self(),
1361 MSG_PRINTERDATA_INIT_RESET,
1362 (uint8_t *)drivername, len+1);
1363
1364 return true;
1365 }
1366
1367 /**********************************************************************
1368 callback to receive a MSG_PRINTERDATA_INIT_RESET message and interate
1369 over all printers, resetting printer data as neessary
1370 **********************************************************************/
1371
1372 void reset_all_printerdata(struct messaging_context *msg,
/* [<][>][^][v][top][bottom][index][help] */
1373 void *private_data,
1374 uint32_t msg_type,
1375 struct server_id server_id,
1376 DATA_BLOB *data)
1377 {
1378 fstring drivername;
1379 int snum;
1380 int n_services = lp_numservices();
1381 size_t len;
1382
1383 len = MIN( data->length, sizeof(drivername)-1 );
1384 strncpy( drivername, (const char *)data->data, len );
1385
1386 DEBUG(10,("reset_all_printerdata: Got message for new driver [%s]\n", drivername ));
1387
1388 /* Iterate the printer list */
1389
1390 for ( snum=0; snum<n_services; snum++ )
1391 {
1392 if ( lp_snum_ok(snum) && lp_print_ok(snum) )
1393 {
1394 WERROR result;
1395 NT_PRINTER_INFO_LEVEL *printer = NULL;
1396
1397 result = get_a_printer( NULL, &printer, 2, lp_const_servicename(snum) );
1398 if ( !W_ERROR_IS_OK(result) )
1399 continue;
1400
1401 /*
1402 * if the printer is bound to the driver,
1403 * then reset to the new driver initdata
1404 */
1405
1406 if ( printer && printer->info_2 && !strcmp(drivername, printer->info_2->drivername) )
1407 {
1408 DEBUG(6,("reset_all_printerdata: Updating printer [%s]\n", printer->info_2->printername));
1409
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));
1413 }
1414
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)));
1419 }
1420 }
1421
1422 free_a_printer( &printer, 2 );
1423 }
1424 }
1425
1426 /* all done */
1427
1428 return;
1429 }
1430
1431 /****************************************************************
1432 _spoolss_OpenPrinter
1433 ****************************************************************/
1434
1435 WERROR _spoolss_OpenPrinter(pipes_struct *p,
/* [<][>][^][v][top][bottom][index][help] */
1436 struct spoolss_OpenPrinter *r)
1437 {
1438 struct spoolss_OpenPrinterEx e;
1439 WERROR werr;
1440
1441 ZERO_STRUCT(e.in.userlevel);
1442
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;
1448
1449 e.out.handle = r->out.handle;
1450
1451 werr = _spoolss_OpenPrinterEx(p, &e);
1452
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.
1457 */
1458 werr = WERR_INVALID_PRINTER_NAME;
1459 }
1460
1461 return werr;
1462 }
1463
1464 /********************************************************************
1465 ********************************************************************/
1466
1467 bool convert_devicemode(const char *printername,
/* [<][>][^][v][top][bottom][index][help] */
1468 const struct spoolss_DeviceMode *devmode,
1469 NT_DEVICEMODE **pp_nt_devmode)
1470 {
1471 NT_DEVICEMODE *nt_devmode = *pp_nt_devmode;
1472
1473 /*
1474 * Ensure nt_devmode is a valid pointer
1475 * as we will be overwriting it.
1476 */
1477
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;
1482 }
1483
1484 rpcstr_push(nt_devmode->devicename, devmode->devicename, 31, 0);
1485 rpcstr_push(nt_devmode->formname, devmode->formname, 31, 0);
1486
1487 nt_devmode->specversion = devmode->specversion;
1488 nt_devmode->driverversion = devmode->driverversion;
1489 nt_devmode->size = devmode->size;
1490 nt_devmode->fields = devmode->fields;
1491 nt_devmode->orientation = devmode->orientation;
1492 nt_devmode->papersize = devmode->papersize;
1493 nt_devmode->paperlength = devmode->paperlength;
1494 nt_devmode->paperwidth = devmode->paperwidth;
1495 nt_devmode->scale = devmode->scale;
1496 nt_devmode->copies = devmode->copies;
1497 nt_devmode->defaultsource = devmode->defaultsource;
1498 nt_devmode->printquality = devmode->printquality;
1499 nt_devmode->color = devmode->color;
1500 nt_devmode->duplex = devmode->duplex;
1501 nt_devmode->yresolution = devmode->yresolution;
1502 nt_devmode->ttoption = devmode->ttoption;
1503 nt_devmode->collate = devmode->collate;
1504
1505 nt_devmode->logpixels = devmode->logpixels;
1506 nt_devmode->bitsperpel = devmode->bitsperpel;
1507 nt_devmode->pelswidth = devmode->pelswidth;
1508 nt_devmode->pelsheight = devmode->pelsheight;
1509 nt_devmode->displayflags = devmode->displayflags;
1510 nt_devmode->displayfrequency = devmode->displayfrequency;
1511 nt_devmode->icmmethod = devmode->icmmethod;
1512 nt_devmode->icmintent = devmode->icmintent;
1513 nt_devmode->mediatype = devmode->mediatype;
1514 nt_devmode->dithertype = devmode->dithertype;
1515 nt_devmode->reserved1 = devmode->reserved1;
1516 nt_devmode->reserved2 = devmode->reserved2;
1517 nt_devmode->panningwidth = devmode->panningwidth;
1518 nt_devmode->panningheight = devmode->panningheight;
1519
1520 /*
1521 * Only change private and driverextra if the incoming devmode
1522 * has a new one. JRA.
1523 */
1524
1525 if ((devmode->__driverextra_length != 0) && (devmode->driverextra_data.data != NULL)) {
1526 SAFE_FREE(nt_devmode->nt_dev_private);
1527 nt_devmode->driverextra = devmode->__driverextra_length;
1528 if((nt_devmode->nt_dev_private = SMB_MALLOC_ARRAY(uint8_t, nt_devmode->driverextra)) == NULL)
1529 return false;
1530 memcpy(nt_devmode->nt_dev_private, devmode->driverextra_data.data, nt_devmode->driverextra);
1531 }
1532
1533 *pp_nt_devmode = nt_devmode;
1534
1535 return true;
1536 }
1537
1538 /****************************************************************
1539 _spoolss_OpenPrinterEx
1540 ****************************************************************/
1541
1542 WERROR _spoolss_OpenPrinterEx(pipes_struct *p,
/* [<][>][^][v][top][bottom][index][help] */
1543 struct spoolss_OpenPrinterEx *r)
1544 {
1545 int snum;
1546 Printer_entry *Printer=NULL;
1547
1548 if (!r->in.printername) {
1549 return WERR_INVALID_PARAM;
1550 }
1551
1552 /* some sanity check because you can open a printer or a print server */
1553 /* aka: \\server\printer or \\server */
1554
1555 DEBUGADD(3,("checking name: %s\n", r->in.printername));
1556
1557 if (!open_printer_hnd(p, r->out.handle, r->in.printername, 0)) {
1558 ZERO_STRUCTP(r->out.handle);
1559 return WERR_INVALID_PARAM;
1560 }
1561
1562 Printer = find_printer_index_by_hnd(p, r->out.handle);
1563 if ( !Printer ) {
1564 DEBUG(0,("_spoolss_OpenPrinterEx: logic error. Can't find printer "
1565 "handle we created for printer %s\n", r->in.printername));
1566 close_printer_handle(p, r->out.handle);
1567 ZERO_STRUCTP(r->out.handle);
1568 return WERR_INVALID_PARAM;
1569 }
1570
1571 /*
1572 * First case: the user is opening the print server:
1573 *
1574 * Disallow MS AddPrinterWizard if parameter disables it. A Win2k
1575 * client 1st tries an OpenPrinterEx with access==0, MUST be allowed.
1576 *
1577 * Then both Win2k and WinNT clients try an OpenPrinterEx with
1578 * SERVER_ALL_ACCESS, which we allow only if the user is root (uid=0)
1579 * or if the user is listed in the smb.conf printer admin parameter.
1580 *
1581 * Then they try OpenPrinterEx with SERVER_READ which we allow. This lets the
1582 * client view printer folder, but does not show the MSAPW.
1583 *
1584 * Note: this test needs code to check access rights here too. Jeremy
1585 * could you look at this?
1586 *
1587 * Second case: the user is opening a printer:
1588 * NT doesn't let us connect to a printer if the connecting user
1589 * doesn't have print permission.
1590 *
1591 * Third case: user is opening a Port Monitor
1592 * access checks same as opening a handle to the print server.
1593 */
1594
1595 switch (Printer->printer_type )
1596 {
1597 case SPLHND_SERVER:
1598 case SPLHND_PORTMON_TCP:
1599 case SPLHND_PORTMON_LOCAL:
1600 /* Printserver handles use global struct... */
1601
1602 snum = -1;
1603
1604 /* Map standard access rights to object specific access rights */
1605
1606 se_map_standard(&r->in.access_mask,
1607 &printserver_std_mapping);
1608
1609 /* Deny any object specific bits that don't apply to print
1610 servers (i.e printer and job specific bits) */
1611
1612 r->in.access_mask &= SPECIFIC_RIGHTS_MASK;
1613
1614 if (r->in.access_mask &
1615 ~(SERVER_ACCESS_ADMINISTER | SERVER_ACCESS_ENUMERATE)) {
1616 DEBUG(3, ("access DENIED for non-printserver bits\n"));
1617 close_printer_handle(p, r->out.handle);
1618 ZERO_STRUCTP(r->out.handle);
1619 return WERR_ACCESS_DENIED;
1620 }
1621
1622 /* Allow admin access */
1623
1624 if ( r->in.access_mask & SERVER_ACCESS_ADMINISTER )
1625 {
1626 SE_PRIV se_printop = SE_PRINT_OPERATOR;
1627
1628 if (!lp_ms_add_printer_wizard()) {
1629 close_printer_handle(p, r->out.handle);
1630 ZERO_STRUCTP(r->out.handle);
1631 return WERR_ACCESS_DENIED;
1632 }
1633
1634 /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
1635 and not a printer admin, then fail */
1636
1637 if ((p->server_info->utok.uid != sec_initial_uid()) &&
1638 !user_has_privileges(p->server_info->ptok,
1639 &se_printop ) &&
1640 !token_contains_name_in_list(
1641 uidtoname(p->server_info->utok.uid),
1642 NULL, NULL,
1643 p->server_info->ptok,
1644 lp_printer_admin(snum))) {
1645 close_printer_handle(p, r->out.handle);
1646 ZERO_STRUCTP(r->out.handle);
1647 return WERR_ACCESS_DENIED;
1648 }
1649
1650 r->in.access_mask = SERVER_ACCESS_ADMINISTER;
1651 }
1652 else
1653 {
1654 r->in.access_mask = SERVER_ACCESS_ENUMERATE;
1655 }
1656
1657 DEBUG(4,("Setting print server access = %s\n", (r->in.access_mask == SERVER_ACCESS_ADMINISTER)
1658 ? "SERVER_ACCESS_ADMINISTER" : "SERVER_ACCESS_ENUMERATE" ));
1659
1660 /* We fall through to return WERR_OK */
1661 break;
1662
1663 case SPLHND_PRINTER:
1664 /* NT doesn't let us connect to a printer if the connecting user
1665 doesn't have print permission. */
1666
1667 if (!get_printer_snum(p, r->out.handle, &snum, NULL)) {
1668 close_printer_handle(p, r->out.handle);
1669 ZERO_STRUCTP(r->out.handle);
1670 return WERR_BADFID;
1671 }
1672
1673 se_map_standard(&r->in.access_mask, &printer_std_mapping);
1674
1675 /* map an empty access mask to the minimum access mask */
1676 if (r->in.access_mask == 0x0)
1677 r->in.access_mask = PRINTER_ACCESS_USE;
1678
1679 /*
1680 * If we are not serving the printer driver for this printer,
1681 * map PRINTER_ACCESS_ADMINISTER to PRINTER_ACCESS_USE. This
1682 * will keep NT clients happy --jerry
1683 */
1684
1685 if (lp_use_client_driver(snum)
1686 && (r->in.access_mask & PRINTER_ACCESS_ADMINISTER))
1687 {
1688 r->in.access_mask = PRINTER_ACCESS_USE;
1689 }
1690
1691 /* check smb.conf parameters and the the sec_desc */
1692
1693 if ( !check_access(get_client_fd(), lp_hostsallow(snum), lp_hostsdeny(snum)) ) {
1694 DEBUG(3, ("access DENIED (hosts allow/deny) for printer open\n"));
1695 ZERO_STRUCTP(r->out.handle);
1696 return WERR_ACCESS_DENIED;
1697 }
1698
1699 if (!user_ok_token(uidtoname(p->server_info->utok.uid), NULL,
1700 p->server_info->ptok, snum) ||
1701 !print_access_check(p->server_info, snum,
1702 r->in.access_mask)) {
1703 DEBUG(3, ("access DENIED for printer open\n"));
1704 close_printer_handle(p, r->out.handle);
1705 ZERO_STRUCTP(r->out.handle);
1706 return WERR_ACCESS_DENIED;
1707 }
1708
1709 if ((r->in.access_mask & SPECIFIC_RIGHTS_MASK)& ~(PRINTER_ACCESS_ADMINISTER|PRINTER_ACCESS_USE)) {
1710 DEBUG(3, ("access DENIED for printer open - unknown bits\n"));
1711 close_printer_handle(p, r->out.handle);
1712 ZERO_STRUCTP(r->out.handle);
1713 return WERR_ACCESS_DENIED;
1714 }
1715
1716 if (r->in.access_mask & PRINTER_ACCESS_ADMINISTER)
1717 r->in.access_mask = PRINTER_ACCESS_ADMINISTER;
1718 else
1719 r->in.access_mask = PRINTER_ACCESS_USE;
1720
1721 DEBUG(4,("Setting printer access = %s\n", (r->in.access_mask == PRINTER_ACCESS_ADMINISTER)
1722 ? "PRINTER_ACCESS_ADMINISTER" : "PRINTER_ACCESS_USE" ));
1723
1724 break;
1725
1726 default:
1727 /* sanity check to prevent programmer error */
1728 ZERO_STRUCTP(r->out.handle);
1729 return WERR_BADFID;
1730 }
1731
1732 Printer->access_granted = r->in.access_mask;
1733
1734 /*
1735 * If the client sent a devmode in the OpenPrinter() call, then
1736 * save it here in case we get a job submission on this handle
1737 */
1738
1739 if ((Printer->printer_type != SPLHND_SERVER) &&
1740 r->in.devmode_ctr.devmode) {
1741 convert_devicemode(Printer->sharename,
1742 r->in.devmode_ctr.devmode,
1743 &Printer->nt_devmode);
1744 }
1745
1746 #if 0 /* JERRY -- I'm doubtful this is really effective */
1747 /* HACK ALERT!!! Sleep for 1/3 of a second to try trigger a LAN/WAN
1748 optimization in Windows 2000 clients --jerry */
1749
1750 if ( (r->in.access_mask == PRINTER_ACCESS_ADMINISTER)
1751 && (RA_WIN2K == get_remote_arch()) )
1752 {
1753 DEBUG(10,("_spoolss_OpenPrinterEx: Enabling LAN/WAN hack for Win2k clients.\n"));
1754 sys_usleep( 500000 );
1755 }
1756 #endif
1757
1758 return WERR_OK;
1759 }
1760
1761 /****************************************************************************
1762 ****************************************************************************/
1763
1764 static bool printer_info2_to_nt_printer_info2(struct spoolss_SetPrinterInfo2 *r,
/* [<][>][^][v][top][bottom][index][help] */
1765 NT_PRINTER_INFO_LEVEL_2 *d)
1766 {
1767 DEBUG(7,("printer_info2_to_nt_printer_info2\n"));
1768
1769 if (!r || !d) {
1770 return false;
1771 }
1772
1773 d->attributes = r->attributes;
1774 d->priority = r->priority;
1775 d->default_priority = r->defaultpriority;
1776 d->starttime = r->starttime;
1777 d->untiltime = r->untiltime;
1778 d->status = r->status;
1779 d->cjobs = r->cjobs;
1780
1781 fstrcpy(d->servername, r->servername);
1782 fstrcpy(d->printername, r->printername);
1783 fstrcpy(d->sharename, r->sharename);
1784 fstrcpy(d->portname, r->portname);
1785 fstrcpy(d->drivername, r->drivername);
1786 slprintf(d->comment, sizeof(d->comment)-1, "%s", r->comment);
1787 fstrcpy(d->location, r->location);
1788 fstrcpy(d->sepfile, r->sepfile);
1789 fstrcpy(d->printprocessor, r->printprocessor);
1790 fstrcpy(d->datatype, r->datatype);
1791 fstrcpy(d->parameters, r->parameters);
1792
1793 return true;
1794 }
1795
1796 /****************************************************************************
1797 ****************************************************************************/
1798
1799 static bool convert_printer_info(struct spoolss_SetPrinterInfoCtr *info_ctr,
/* [<][>][^][v][top][bottom][index][help] */
1800 NT_PRINTER_INFO_LEVEL *printer)
1801 {
1802 bool ret;
1803
1804 switch (info_ctr->level) {
1805 case 2:
1806 /* allocate memory if needed. Messy because
1807 convert_printer_info is used to update an existing
1808 printer or build a new one */
1809
1810 if (!printer->info_2) {
1811 printer->info_2 = TALLOC_ZERO_P(printer, NT_PRINTER_INFO_LEVEL_2);
1812 if (!printer->info_2) {
1813 DEBUG(0,("convert_printer_info: "
1814 "talloc() failed!\n"));
1815 return false;
1816 }
1817 }
1818
1819 ret = printer_info2_to_nt_printer_info2(info_ctr->info.info2,
1820 printer->info_2);
1821 printer->info_2->setuptime = time(NULL);
1822 return ret;
1823 }
1824
1825 return false;
1826 }
1827
1828 /*******************************************************************
1829 ********************************************************************/
1830
1831 static bool string_array_to_fstring_array(const char **sarray, fstring **farray)
/* [<][>][^][v][top][bottom][index][help] */
1832 {
1833 int i;
1834
1835 if (!sarray) {
1836 *farray = NULL;
1837 return true;
1838 }
1839
1840 *farray = SMB_MALLOC_ARRAY(fstring, 1);
1841 if (!*farray) {
1842 return false;
1843 }
1844
1845 for (i=0; sarray[i] != NULL; i++) {
1846 *farray = SMB_REALLOC_ARRAY(*farray, fstring, i+2);
1847 if (!*farray) {
1848 return false;
1849 }
1850 fstrcpy((*farray)[i], sarray[i]);
1851 }
1852
1853 fstrcpy((*farray)[i], "");
1854
1855 return true;
1856 }
1857
1858 /*******************************************************************
1859 ********************************************************************/
1860
1861 static bool driver_info3_to_nt_driver_info3(struct spoolss_AddDriverInfo3 *r,
/* [<][>][^][v][top][bottom][index][help] */
1862 NT_PRINTER_DRIVER_INFO_LEVEL_3 **p)
1863 {
1864 NT_PRINTER_DRIVER_INFO_LEVEL_3 *d;
1865
1866 DEBUG(7,("driver_info3_to_nt_driver_info3: Converting from UNICODE to ASCII\n"));
1867
1868 if (*p == NULL) {
1869 *p = SMB_MALLOC_P(NT_PRINTER_DRIVER_INFO_LEVEL_3);
1870 if (*p == NULL) {
1871 return false;
1872 }
1873 ZERO_STRUCTP(*p);
1874 }
1875
1876 d = *p;
1877
1878 d->cversion = r->version;
1879
1880 fstrcpy(d->name, r->driver_name);
1881 fstrcpy(d->environment, r->architecture);
1882 fstrcpy(d->driverpath, r->driver_path);
1883 fstrcpy(d->datafile, r->data_file);
1884 fstrcpy(d->configfile, r->config_file);
1885 fstrcpy(d->helpfile, r->help_file);
1886 fstrcpy(d->monitorname, r->monitor_name);
1887 fstrcpy(d->defaultdatatype, r->default_datatype);
1888
1889 DEBUGADD(8,( "version: %d\n", d->cversion));
1890 DEBUGADD(8,( "name: %s\n", d->name));
1891 DEBUGADD(8,( "environment: %s\n", d->environment));
1892 DEBUGADD(8,( "driverpath: %s\n", d->driverpath));
1893 DEBUGADD(8,( "datafile: %s\n", d->datafile));
1894 DEBUGADD(8,( "configfile: %s\n", d->configfile));
1895 DEBUGADD(8,( "helpfile: %s\n", d->helpfile));
1896 DEBUGADD(8,( "monitorname: %s\n", d->monitorname));
1897 DEBUGADD(8,( "defaultdatatype: %s\n", d->defaultdatatype));
1898
1899 if (r->dependent_files) {
1900 if (!string_array_to_fstring_array(r->dependent_files->string,
1901 &d->dependentfiles)) {
1902 SAFE_FREE(*p);
1903 return false;
1904 }
1905 }
1906
1907 return true;
1908 }
1909
1910 /*******************************************************************
1911 ********************************************************************/
1912
1913 static bool driver_info6_to_nt_driver_info6(struct spoolss_AddDriverInfo6 *r,
/* [<][>][^][v][top][bottom][index][help] */
1914 NT_PRINTER_DRIVER_INFO_LEVEL_6 **p)
1915 {
1916 NT_PRINTER_DRIVER_INFO_LEVEL_6 *d;
1917
1918 DEBUG(7,("driver_info6_to_nt_driver_info6: Converting from UNICODE to ASCII\n"));
1919
1920 if (*p == NULL) {
1921 *p = SMB_MALLOC_P(NT_PRINTER_DRIVER_INFO_LEVEL_6);
1922 if (*p == NULL) {
1923 return false;
1924 }
1925 ZERO_STRUCTP(*p);
1926 }
1927
1928 d = *p;
1929
1930 d->version = r->version;
1931
1932 fstrcpy(d->name, r->driver_name);
1933 fstrcpy(d->environment, r->architecture);
1934 fstrcpy(d->driverpath, r->driver_path);
1935 fstrcpy(d->datafile, r->data_file);
1936 fstrcpy(d->configfile, r->config_file);
1937 fstrcpy(d->helpfile, r->help_file);
1938 fstrcpy(d->monitorname, r->monitor_name);
1939 fstrcpy(d->defaultdatatype, r->default_datatype);
1940
1941 DEBUGADD(8,( "version: %d\n", d->version));
1942 DEBUGADD(8,( "name: %s\n", d->name));
1943 DEBUGADD(8,( "environment: %s\n", d->environment));
1944 DEBUGADD(8,( "driverpath: %s\n", d->driverpath));
1945 DEBUGADD(8,( "datafile: %s\n", d->datafile));
1946 DEBUGADD(8,( "configfile: %s\n", d->configfile));
1947 DEBUGADD(8,( "helpfile: %s\n", d->helpfile));
1948 DEBUGADD(8,( "monitorname: %s\n", d->monitorname));
1949 DEBUGADD(8,( "defaultdatatype: %s\n", d->defaultdatatype));
1950
1951 if (r->dependent_files) {
1952 if (!string_array_to_fstring_array(r->dependent_files->string,
1953 &d->dependentfiles)) {
1954 goto error;
1955 }
1956 }
1957
1958 if (r->previous_names) {
1959 if (!string_array_to_fstring_array(r->previous_names->string,
1960 &d->previousnames)) {
1961 goto error;
1962 }
1963 }
1964
1965 return true;
1966
1967 error:
1968 SAFE_FREE(*p);
1969 return false;
1970 }
1971
1972 /********************************************************************
1973 ********************************************************************/
1974
1975 static bool convert_printer_driver_info(const struct spoolss_AddDriverInfoCtr *r,
/* [<][>][^][v][top][bottom][index][help] */
1976 NT_PRINTER_DRIVER_INFO_LEVEL *printer,
1977 uint32_t level)
1978 {
1979 switch (level) {
1980 case 3:
1981 printer->info_3 = NULL;
1982 if (!driver_info3_to_nt_driver_info3(r->info.info3, &printer->info_3)) {
1983 return false;
1984 }
1985 break;
1986 case 6:
1987 printer->info_6 = NULL;
1988 if (!driver_info6_to_nt_driver_info6(r->info.info6, &printer->info_6)) {
1989 return false;
1990 }
1991 break;
1992 default:
1993 return false;
1994 }
1995
1996 return true;
1997 }
1998
1999 /********************************************************************
2000 * _spoolss_enddocprinter_internal.
2001 ********************************************************************/
2002
2003 static WERROR _spoolss_enddocprinter_internal(pipes_struct *p,
/* [<][>][^][v][top][bottom][index][help] */
2004 struct policy_handle *handle)
2005 {
2006 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
2007 int snum;
2008
2009 if (!Printer) {
2010 DEBUG(2,("_spoolss_enddocprinter_internal: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
2011 return WERR_BADFID;
2012 }
2013
2014 if (!get_printer_snum(p, handle, &snum, NULL))
2015 return WERR_BADFID;
2016
2017 Printer->document_started = false;
2018 print_job_end(snum, Printer->jobid,NORMAL_CLOSE);
2019 /* error codes unhandled so far ... */
2020
2021 return WERR_OK;
2022 }
2023
2024 /****************************************************************
2025 _spoolss_ClosePrinter
2026 ****************************************************************/
2027
2028 WERROR _spoolss_ClosePrinter(pipes_struct *p,
/* [<][>][^][v][top][bottom][index][help] */
2029 struct spoolss_ClosePrinter *r)
2030 {
2031 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
2032
2033 if (Printer && Printer->document_started)
2034 _spoolss_enddocprinter_internal(p, r->in.handle); /* print job was not closed */
2035
2036 if (!close_printer_handle(p, r->in.handle))
2037 return WERR_BADFID;
2038
2039 /* clear the returned printer handle. Observed behavior
2040 from Win2k server. Don't think this really matters.
2041 Previous code just copied the value of the closed
2042 handle. --jerry */
2043
2044 ZERO_STRUCTP(r->out.handle);
2045
2046 return WERR_OK;
2047 }
2048
2049 /****************************************************************
2050 _spoolss_DeletePrinter
2051 ****************************************************************/
2052
2053 WERROR _spoolss_DeletePrinter(pipes_struct *p,
/* [<][>][^][v][top][bottom][index][help] */
2054 struct spoolss_DeletePrinter *r)
2055 {
2056 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
2057 WERROR result;
2058
2059 if (Printer && Printer->document_started)
2060 _spoolss_enddocprinter_internal(p, r->in.handle); /* print job was not closed */
2061
2062 result = delete_printer_handle(p, r->in.handle);
2063
2064 update_c_setprinter(false);
2065
2066 return result;
2067 }
2068
2069 /*******************************************************************
2070 * static function to lookup the version id corresponding to an
2071 * long architecture string
2072 ******************************************************************/
2073
2074 static int get_version_id(const char *arch)
/* [<][>][^][v][top][bottom][index][help] */
2075 {
2076 int i;
2077 struct print_architecture_table_node archi_table[]= {
2078
2079 {"Windows 4.0", "WIN40", 0 },
2080 {"Windows NT x86", "W32X86", 2 },
2081 {"Windows NT R4000", "W32MIPS", 2 },
2082 {"Windows NT Alpha_AXP", "W32ALPHA", 2 },
2083 {"Windows NT PowerPC", "W32PPC", 2 },
2084 {"Windows IA64", "IA64", 3 },
2085 {"Windows x64", "x64", 3 },
2086 {NULL, "", -1 }
2087 };
2088
2089 for (i=0; archi_table[i].long_archi != NULL; i++)
2090 {
2091 if (strcmp(arch, archi_table[i].long_archi) == 0)
2092 return (archi_table[i].version);
2093 }
2094
2095 return -1;
2096 }
2097
2098 /****************************************************************
2099 _spoolss_DeletePrinterDriver
2100 ****************************************************************/
2101
2102 WERROR _spoolss_DeletePrinterDriver(pipes_struct *p,
/* [<][>][^][v][top][bottom][index][help] */
2103 struct spoolss_DeletePrinterDriver *r)
2104 {
2105 NT_PRINTER_DRIVER_INFO_LEVEL info;
2106 NT_PRINTER_DRIVER_INFO_LEVEL info_win2k;
2107 int version;
2108 WERROR status;
2109 WERROR status_win2k = WERR_ACCESS_DENIED;
2110 SE_PRIV se_printop = SE_PRINT_OPERATOR;
2111
2112 /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
2113 and not a printer admin, then fail */
2114
2115 if ( (p->server_info->utok.uid != sec_initial_uid())
2116 && !user_has_privileges(p->server_info->ptok, &se_printop )
2117 && !token_contains_name_in_list(
2118 uidtoname(p->server_info->utok.uid), NULL,
2119 NULL, p->server_info->ptok,
2120 lp_printer_admin(-1)) )
2121 {
2122 return WERR_ACCESS_DENIED;
2123 }
2124
2125 /* check that we have a valid driver name first */
2126
2127 if ((version = get_version_id(r->in.architecture)) == -1)
2128 return WERR_INVALID_ENVIRONMENT;
2129
2130 ZERO_STRUCT(info);
2131 ZERO_STRUCT(info_win2k);
2132
2133 if (!W_ERROR_IS_OK(get_a_printer_driver(&info, 3, r->in.driver,
2134 r->in.architecture,
2135 version)))
2136 {
2137 /* try for Win2k driver if "Windows NT x86" */
2138
2139 if ( version == 2 ) {
2140 version = 3;
2141 if (!W_ERROR_IS_OK(get_a_printer_driver(&info, 3,
2142 r->in.driver,
2143 r->in.architecture,
2144 version))) {
2145 status = WERR_UNKNOWN_PRINTER_DRIVER;
2146 goto done;
2147 }
2148 }
2149 /* otherwise it was a failure */
2150 else {
2151 status = WERR_UNKNOWN_PRINTER_DRIVER;
2152 goto done;
2153 }
2154
2155 }
2156
2157 if (printer_driver_in_use(info.info_3)) {
2158 status = WERR_PRINTER_DRIVER_IN_USE;
2159 goto done;
2160 }
2161
2162 if ( version == 2 )
2163 {
2164 if (W_ERROR_IS_OK(get_a_printer_driver(&info_win2k, 3,
2165 r->in.driver,
2166 r->in.architecture, 3)))
2167 {
2168 /* if we get to here, we now have 2 driver info structures to remove */
2169 /* remove the Win2k driver first*/
2170
2171 status_win2k = delete_printer_driver(
2172 p, info_win2k.info_3, 3, false);
2173 free_a_printer_driver( info_win2k, 3 );
2174
2175 /* this should not have failed---if it did, report to client */
2176 if ( !W_ERROR_IS_OK(status_win2k) )
2177 {
2178 status = status_win2k;
2179 goto done;
2180 }
2181 }
2182 }
2183
2184 status = delete_printer_driver(p, info.info_3, version, false);
2185
2186 /* if at least one of the deletes succeeded return OK */
2187
2188 if ( W_ERROR_IS_OK(status) || W_ERROR_IS_OK(status_win2k) )
2189 status = WERR_OK;
2190
2191 done:
2192 free_a_printer_driver( info, 3 );
2193
2194 return status;
2195 }
2196
2197 /****************************************************************
2198 _spoolss_DeletePrinterDriverEx
2199 ****************************************************************/
2200
2201 WERROR _spoolss_DeletePrinterDriverEx(pipes_struct *p,
/* [<][>][^][v][top][bottom][index][help] */
2202 struct spoolss_DeletePrinterDriverEx *r)
2203 {
2204 NT_PRINTER_DRIVER_INFO_LEVEL info;
2205 NT_PRINTER_DRIVER_INFO_LEVEL info_win2k;
2206 int version;
2207 bool delete_files;
2208 WERROR status;
2209 WERROR status_win2k = WERR_ACCESS_DENIED;
2210 SE_PRIV se_printop = SE_PRINT_OPERATOR;
2211
2212 /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
2213 and not a printer admin, then fail */
2214
2215 if ( (p->server_info->utok.uid != sec_initial_uid())
2216 && !user_has_privileges(p->server_info->ptok, &se_printop )
2217 && !token_contains_name_in_list(
2218 uidtoname(p->server_info->utok.uid), NULL, NULL,
2219 p->server_info->ptok, lp_printer_admin(-1)) )
2220 {
2221 return WERR_ACCESS_DENIED;
2222 }
2223
2224 /* check that we have a valid driver name first */
2225 if ((version = get_version_id(r->in.architecture)) == -1) {
2226 /* this is what NT returns */
2227 return WERR_INVALID_ENVIRONMENT;
2228 }
2229
2230 if (r->in.delete_flags & DPD_DELETE_SPECIFIC_VERSION)
2231 version = r->in.version;
2232
2233 ZERO_STRUCT(info);
2234 ZERO_STRUCT(info_win2k);
2235
2236 status = get_a_printer_driver(&info, 3, r->in.driver,
2237 r->in.architecture, version);
2238
2239 if ( !W_ERROR_IS_OK(status) )
2240 {
2241 /*
2242 * if the client asked for a specific version,
2243 * or this is something other than Windows NT x86,
2244 * then we've failed
2245 */
2246
2247 if ( (r->in.delete_flags & DPD_DELETE_SPECIFIC_VERSION) || (version !=2) )
2248 goto done;
2249
2250 /* try for Win2k driver if "Windows NT x86" */
2251
2252 version = 3;
2253 if (!W_ERROR_IS_OK(get_a_printer_driver(&info, 3, r->in.driver,
2254 r->in.architecture,
2255 version))) {
2256 status = WERR_UNKNOWN_PRINTER_DRIVER;
2257 goto done;
2258 }
2259 }
2260
2261 if ( printer_driver_in_use(info.info_3) ) {
2262 status = WERR_PRINTER_DRIVER_IN_USE;
2263 goto done;
2264 }
2265
2266 /*
2267 * we have a couple of cases to consider.
2268 * (1) Are any files in use? If so and DPD_DELTE_ALL_FILE is set,
2269 * then the delete should fail if **any** files overlap with
2270 * other drivers
2271 * (2) If DPD_DELTE_UNUSED_FILES is sert, then delete all
2272 * non-overlapping files
2273 * (3) If neither DPD_DELTE_ALL_FILE nor DPD_DELTE_ALL_FILES
2274 * is set, the do not delete any files
2275 * Refer to MSDN docs on DeletePrinterDriverEx() for details.
2276 */
2277
2278 delete_files = r->in.delete_flags & (DPD_DELETE_ALL_FILES|DPD_DELETE_UNUSED_FILES);
2279
2280 /* fail if any files are in use and DPD_DELETE_ALL_FILES is set */
2281
2282 if ( delete_files && printer_driver_files_in_use(info.info_3) & (r->in.delete_flags & DPD_DELETE_ALL_FILES) ) {
2283 /* no idea of the correct error here */
2284 status = WERR_ACCESS_DENIED;
2285 goto done;
2286 }
2287
2288
2289 /* also check for W32X86/3 if necessary; maybe we already have? */
2290
2291 if ( (version == 2) && ((r->in.delete_flags & DPD_DELETE_SPECIFIC_VERSION) != DPD_DELETE_SPECIFIC_VERSION) ) {
2292 if (W_ERROR_IS_OK(get_a_printer_driver(&info_win2k, 3,
2293 r->in.driver,
2294 r->in.architecture, 3)))
2295 {
2296
2297 if ( delete_files && printer_driver_files_in_use(info_win2k.info_3) & (r->in.delete_flags & DPD_DELETE_ALL_FILES) ) {
2298 /* no idea of the correct error here */
2299 free_a_printer_driver( info_win2k, 3 );
2300 status = WERR_ACCESS_DENIED;
2301 goto done;
2302 }
2303
2304 /* if we get to here, we now have 2 driver info structures to remove */
2305 /* remove the Win2k driver first*/
2306
2307 status_win2k = delete_printer_driver(
2308 p, info_win2k.info_3, 3, delete_files);
2309 free_a_printer_driver( info_win2k, 3 );
2310
2311 /* this should not have failed---if it did, report to client */
2312
2313 if ( !W_ERROR_IS_OK(status_win2k) )
2314 goto done;
2315 }
2316 }
2317
2318 status = delete_printer_driver(p, info.info_3, version, delete_files);
2319
2320 if ( W_ERROR_IS_OK(status) || W_ERROR_IS_OK(status_win2k) )
2321 status = WERR_OK;
2322 done:
2323 free_a_printer_driver( info, 3 );
2324
2325 return status;
2326 }
2327
2328
2329 /****************************************************************************
2330 Internal routine for removing printerdata
2331 ***************************************************************************/
2332
2333 static WERROR delete_printer_dataex( NT_PRINTER_INFO_LEVEL *printer, const char *key, const char *value )
/* [<][>][^][v][top][bottom][index][help] */
2334 {
2335 return delete_printer_data( printer->info_2, key, value );
2336 }
2337
2338 /****************************************************************************
2339 Internal routine for storing printerdata
2340 ***************************************************************************/
2341
2342 WERROR set_printer_dataex(NT_PRINTER_INFO_LEVEL *printer,
/* [<][>][^][v][top][bottom][index][help] */
2343 const char *key, const char *value,
2344 uint32_t type, uint8_t *data, int real_len)
2345 {
2346 /* the registry objects enforce uniqueness based on value name */
2347
2348 return add_printer_data( printer->info_2, key, value, type, data, real_len );
2349 }
2350
2351 /********************************************************************
2352 GetPrinterData on a printer server Handle.
2353 ********************************************************************/
2354
2355 static WERROR getprinterdata_printer_server(TALLOC_CTX *mem_ctx,
/* [<][>][^][v][top][bottom][index][help] */
2356 const char *value,
2357 enum winreg_Type *type,
2358 union spoolss_PrinterData *data)
2359 {
2360 DEBUG(8,("getprinterdata_printer_server:%s\n", value));
2361
2362 if (!StrCaseCmp(value, "W3SvcInstalled")) {
2363 *type = REG_DWORD;
2364 data->value = 0x00;
2365 return WERR_OK;
2366 }
2367
2368 if (!StrCaseCmp(value, "BeepEnabled")) {
2369 *type = REG_DWORD;
2370 data->value = 0x00;
2371 return WERR_OK;
2372 }
2373
2374 if (!StrCaseCmp(value, "EventLog")) {
2375 *type = REG_DWORD;
2376 /* formally was 0x1b */
2377 data->value = 0x00;
2378 return WERR_OK;
2379 }
2380
2381 if (!StrCaseCmp(value, "NetPopup")) {
2382 *type = REG_DWORD;
2383 data->value = 0x00;
2384 return WERR_OK;
2385 }
2386
2387 if (!StrCaseCmp(value, "MajorVersion")) {
2388 *type = REG_DWORD;
2389
2390 /* Windows NT 4.0 seems to not allow uploading of drivers
2391 to a server that reports 0x3 as the MajorVersion.
2392 need to investigate more how Win2k gets around this .
2393 -- jerry */
2394
2395 if (RA_WINNT == get_remote_arch()) {
2396 data->value = 0x02;
2397 } else {
2398 data->value = 0x03;
2399 }
2400
2401 return WERR_OK;
2402 }
2403
2404 if (!StrCaseCmp(value, "MinorVersion")) {
2405 *type = REG_DWORD;
2406 data->value = 0x00;
2407 return WERR_OK;
2408 }
2409
2410 /* REG_BINARY
2411 * uint32_t size = 0x114
2412 * uint32_t major = 5
2413 * uint32_t minor = [0|1]
2414 * uint32_t build = [2195|2600]
2415 * extra unicode string = e.g. "Service Pack 3"
2416 */
2417 if (!StrCaseCmp(value, "OSVersion")) {
2418 DATA_BLOB blob;
2419 enum ndr_err_code ndr_err;
2420 struct spoolss_OSVersion os;
2421
2422 os.major = 5; /* Windows 2000 == 5.0 */
2423 os.minor = 0;
2424 os.build = 2195; /* build */
2425 os.extra_string = ""; /* leave extra string empty */
2426
2427 ndr_err = ndr_push_struct_blob(&blob, mem_ctx, NULL, &os,
2428 (ndr_push_flags_fn_t)ndr_push_spoolss_OSVersion);
2429 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
2430 return WERR_GENERAL_FAILURE;
2431 }
2432
2433 *type = REG_BINARY;
2434 data->binary = blob;
2435
2436 return WERR_OK;
2437 }
2438
2439
2440 if (!StrCaseCmp(value, "DefaultSpoolDirectory")) {
2441 *type = REG_SZ;
2442
2443 data->string = talloc_strdup(mem_ctx, "C:\\PRINTERS");
2444 W_ERROR_HAVE_NO_MEMORY(data->string);
2445
2446 return WERR_OK;
2447 }
2448
2449 if (!StrCaseCmp(value, "Architecture")) {
2450 *type = REG_SZ;
2451
2452 data->string = talloc_strdup(mem_ctx, "Windows NT x86");
2453 W_ERROR_HAVE_NO_MEMORY(data->string);
2454
2455 return WERR_OK;
2456 }
2457
2458 if (!StrCaseCmp(value, "DsPresent")) {
2459 *type = REG_DWORD;
2460
2461 /* only show the publish check box if we are a
2462 member of a AD domain */
2463
2464 if (lp_security() == SEC_ADS) {
2465 data->value = 0x01;
2466 } else {
2467 data->value = 0x00;
2468 }
2469 return WERR_OK;
2470 }
2471
2472 if (!StrCaseCmp(value, "DNSMachineName")) {
2473 const char *hostname = get_mydnsfullname();
2474
2475 if (!hostname) {
2476 return WERR_BADFILE;
2477 }
2478
2479 *type = REG_SZ;
2480 data->string = talloc_strdup(mem_ctx, hostname);
2481 W_ERROR_HAVE_NO_MEMORY(data->string);
2482
2483 return WERR_OK;
2484 }
2485
2486 return WERR_INVALID_PARAM;
2487 }
2488
2489 /****************************************************************
2490 _spoolss_GetPrinterData
2491 ****************************************************************/
2492
2493 WERROR _spoolss_GetPrinterData(pipes_struct *p,
/* [<][>][^][v][top][bottom][index][help] */
2494 struct spoolss_GetPrinterData *r)
2495 {
2496 WERROR result;
2497 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
2498 NT_PRINTER_INFO_LEVEL *printer = NULL;
2499 int snum = 0;
2500
2501 /*
2502 * Reminder: when it's a string, the length is in BYTES
2503 * even if UNICODE is negociated.
2504 *
2505 * JFM, 4/19/1999
2506 */
2507
2508 /* in case of problem, return some default values */
2509
2510 *r->out.needed = 0;
2511 *r->out.type = 0;
2512
2513 DEBUG(4,("_spoolss_GetPrinterData\n"));
2514
2515 if (!Printer) {
2516 DEBUG(2,("_spoolss_GetPrinterData: Invalid handle (%s:%u:%u).\n",
2517 OUR_HANDLE(r->in.handle)));
2518 result = WERR_BADFID;
2519 goto done;
2520 }
2521
2522 if (Printer->printer_type == SPLHND_SERVER) {
2523 result = getprinterdata_printer_server(p->mem_ctx,
2524 r->in.value_name,
2525 r->out.type,
2526 r->out.data);
2527 } else {
2528 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
2529 result = WERR_BADFID;
2530 goto done;
2531 }
2532
2533 result = get_a_printer(Printer, &printer, 2, lp_servicename(snum));
2534 if (!W_ERROR_IS_OK(result)) {
2535 goto done;
2536 }
2537
2538 /* XP sends this and wants to change id value from the PRINTER_INFO_0 */
2539
2540 if (strequal(r->in.value_name, "ChangeId")) {
2541 *r->out.type = REG_DWORD;
2542 r->out.data->value = printer->info_2->changeid;
2543 result = WERR_OK;
2544 } else {
2545 REGISTRY_VALUE *v;
2546 DATA_BLOB blob;
2547
2548 v = get_printer_data(printer->info_2,
2549 SPOOL_PRINTERDATA_KEY,
2550 r->in.value_name);
2551 if (!v) {
2552 result = WERR_BADFILE;
2553 goto done;
2554 }
2555
2556 *r->out.type = v->type;
2557
2558 blob = data_blob_const(v->data_p, v->size);
2559
2560 result = pull_spoolss_PrinterData(p->mem_ctx, &blob,
2561 r->out.data,
2562 *r->out.type);
2563 }
2564 }
2565
2566 done:
2567 /* cleanup & exit */
2568
2569 if (printer) {
2570 free_a_printer(&printer, 2);
2571 }
2572
2573 if (!W_ERROR_IS_OK(result)) {
2574 return result;
2575 }
2576
2577 *r->out.needed = ndr_size_spoolss_PrinterData(r->out.data, *r->out.type, NULL, 0);
2578 *r->out.type = SPOOLSS_BUFFER_OK(*r->out.type, REG_NONE);
2579 r->out.data = SPOOLSS_BUFFER_OK(r->out.data, r->out.data);
2580
2581 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_MORE_DATA);
2582 }
2583
2584 /*********************************************************
2585 Connect to the client machine.
2586 **********************************************************/
2587
2588 static bool spoolss_connect_to_client(struct rpc_pipe_client **pp_pipe,
/* [<][>][^][v][top][bottom][index][help] */
2589 struct sockaddr_storage *client_ss, const char *remote_machine)
2590 {
2591 NTSTATUS ret;
2592 struct cli_state *the_cli;
2593 struct sockaddr_storage rm_addr;
2594
2595 if ( is_zero_addr((struct sockaddr *)client_ss) ) {
2596 if ( !resolve_name( remote_machine, &rm_addr, 0x20) ) {
2597 DEBUG(2,("spoolss_connect_to_client: Can't resolve address for %s\n", remote_machine));
2598 return false;
2599 }
2600
2601 if (ismyaddr((struct sockaddr *)&rm_addr)) {
2602 DEBUG(0,("spoolss_connect_to_client: Machine %s is one of our addresses. Cannot add to ourselves.\n", remote_machine));
2603 return false;
2604 }
2605 } else {
2606 char addr[INET6_ADDRSTRLEN];
2607 rm_addr = *client_ss;
2608 print_sockaddr(addr, sizeof(addr), &rm_addr);
2609 DEBUG(5,("spoolss_connect_to_client: Using address %s (no name resolution necessary)\n",
2610 addr));
2611 }
2612
2613 /* setup the connection */
2614
2615 ret = cli_full_connection( &the_cli, global_myname(), remote_machine,
2616 &rm_addr, 0, "IPC$", "IPC",
2617 "", /* username */
2618 "", /* domain */
2619 "", /* password */
2620 0, lp_client_signing(), NULL );
2621
2622 if ( !NT_STATUS_IS_OK( ret ) ) {
2623 DEBUG(2,("spoolss_connect_to_client: connection to [%s] failed!\n",
2624 remote_machine ));
2625 return false;
2626 }
2627
2628 if ( the_cli->protocol != PROTOCOL_NT1 ) {
2629 DEBUG(0,("spoolss_connect_to_client: machine %s didn't negotiate NT protocol.\n", remote_machine));
2630 cli_shutdown(the_cli);
2631 return false;
2632 }
2633
2634 /*
2635 * Ok - we have an anonymous connection to the IPC$ share.
2636 * Now start the NT Domain stuff :-).
2637 */
2638
2639 ret = cli_rpc_pipe_open_noauth(the_cli, &ndr_table_spoolss.syntax_id, pp_pipe);
2640 if (!NT_STATUS_IS_OK(ret)) {
2641 DEBUG(2,("spoolss_connect_to_client: unable to open the spoolss pipe on machine %s. Error was : %s.\n",
2642 remote_machine, nt_errstr(ret)));
2643 cli_shutdown(the_cli);
2644 return false;
2645 }
2646
2647 return true;
2648 }
2649
2650 /***************************************************************************
2651 Connect to the client.
2652 ****************************************************************************/
2653
2654 static bool srv_spoolss_replyopenprinter(int snum, const char *printer,
/* [<][>][^][v][top][bottom][index][help] */
2655 uint32_t localprinter, uint32_t type,
2656 struct policy_handle *handle,
2657 struct sockaddr_storage *client_ss)
2658 {
2659 WERROR result;
2660 NTSTATUS status;
2661
2662 /*
2663 * If it's the first connection, contact the client
2664 * and connect to the IPC$ share anonymously
2665 */
2666 if (smb_connections==0) {
2667 fstring unix_printer;
2668
2669 fstrcpy(unix_printer, printer+2); /* the +2 is to strip the leading 2 backslashs */
2670
2671 if ( !spoolss_connect_to_client( ¬ify_cli_pipe, client_ss, unix_printer ))
2672 return false;
2673
2674 messaging_register(smbd_messaging_context(), NULL,
2675 MSG_PRINTER_NOTIFY2,
2676 receive_notify2_message_list);
2677 /* Tell the connections db we're now interested in printer
2678 * notify messages. */
2679 register_message_flags(true, FLAG_MSG_PRINT_NOTIFY);
2680 }
2681
2682 /*
2683 * Tell the specific printing tdb we want messages for this printer
2684 * by registering our PID.
2685 */
2686
2687 if (!print_notify_register_pid(snum))
2688 DEBUG(0,("print_notify_register_pid: Failed to register our pid for printer %s\n", printer ));
2689
2690 smb_connections++;
2691
2692 status = rpccli_spoolss_ReplyOpenPrinter(notify_cli_pipe, talloc_tos(),
2693 printer,
2694 localprinter,
2695 type,
2696 0,
2697 NULL,
2698 handle,
2699 &result);
2700 if (!NT_STATUS_IS_OK(status) || !W_ERROR_IS_OK(result))
2701 DEBUG(5,("srv_spoolss_reply_open_printer: Client RPC returned [%s]\n",
2702 win_errstr(result)));
2703
2704 return (W_ERROR_IS_OK(result));
2705 }
2706
2707 /****************************************************************
2708 ****************************************************************/
2709
2710 static struct spoolss_NotifyOption *dup_spoolss_NotifyOption(TALLOC_CTX *mem_ctx,
/* [<][>][^][v][top][bottom][index][help] */
2711 const struct spoolss_NotifyOption *r)
2712 {
2713 struct spoolss_NotifyOption *option;
2714 uint32_t i,k;
2715
2716 if (!r) {
2717 return NULL;
2718 }
2719
2720 option = talloc_zero(mem_ctx, struct spoolss_NotifyOption);
2721 if (!option) {
2722 return NULL;
2723 }
2724
2725 *option = *r;
2726
2727 if (!option->count) {
2728 return option;
2729 }
2730
2731 option->types = talloc_zero_array(option,
2732 struct spoolss_NotifyOptionType, option->count);
2733 if (!option->types) {
2734 talloc_free(option);
2735 return NULL;
2736 }
2737
2738 for (i=0; i < option->count; i++) {
2739 option->types[i] = r->types[i];
2740
2741 if (option->types[i].count) {
2742 option->types[i].fields = talloc_zero_array(option,
2743 union spoolss_Field, option->types[i].count);
2744 if (!option->types[i].fields) {
2745 talloc_free(option);
2746 return NULL;
2747 }
2748 for (k=0; k<option->types[i].count; k++) {
2749 option->types[i].fields[k] =
2750 r->types[i].fields[k];
2751 }
2752 }
2753 }
2754
2755 return option;
2756 }
2757
2758 /****************************************************************
2759 * _spoolss_RemoteFindFirstPrinterChangeNotifyEx
2760 *
2761 * before replying OK: status=0 a rpc call is made to the workstation
2762 * asking ReplyOpenPrinter
2763 *
2764 * in fact ReplyOpenPrinter is the changenotify equivalent on the spoolss pipe
2765 * called from api_spoolss_rffpcnex
2766 ****************************************************************/
2767
2768 WERROR _spoolss_RemoteFindFirstPrinterChangeNotifyEx(pipes_struct *p,
/* [<][>][^][v][top][bottom][index][help] */
2769 struct spoolss_RemoteFindFirstPrinterChangeNotifyEx *r)
2770 {
2771 int snum = -1;
2772 struct spoolss_NotifyOption *option = r->in.notify_options;
2773 struct sockaddr_storage client_ss;
2774
2775 /* store the notify value in the printer struct */
2776
2777 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
2778
2779 if (!Printer) {
2780 DEBUG(2,("_spoolss_RemoteFindFirstPrinterChangeNotifyEx: "
2781 "Invalid handle (%s:%u:%u).\n",
2782 OUR_HANDLE(r->in.handle)));
2783 return WERR_BADFID;
2784 }
2785
2786 Printer->notify.flags = r->in.flags;
2787 Printer->notify.options = r->in.options;
2788 Printer->notify.printerlocal = r->in.printer_local;
2789
2790 TALLOC_FREE(Printer->notify.option);
2791 Printer->notify.option = dup_spoolss_NotifyOption(Printer, option);
2792
2793 fstrcpy(Printer->notify.localmachine, r->in.local_machine);
2794
2795 /* Connect to the client machine and send a ReplyOpenPrinter */
2796
2797 if ( Printer->printer_type == SPLHND_SERVER)
2798 snum = -1;
2799 else if ( (Printer->printer_type == SPLHND_PRINTER) &&
2800 !get_printer_snum(p, r->in.handle, &snum, NULL) )
2801 return WERR_BADFID;
2802
2803 if (!interpret_string_addr(&client_ss, p->client_address,
2804 AI_NUMERICHOST)) {
2805 return WERR_SERVER_UNAVAILABLE;
2806 }
2807
2808 if(!srv_spoolss_replyopenprinter(snum, Printer->notify.localmachine,
2809 Printer->notify.printerlocal, 1,
2810 &Printer->notify.client_hnd, &client_ss))
2811 return WERR_SERVER_UNAVAILABLE;
2812
2813 Printer->notify.client_connected = true;
2814
2815 return WERR_OK;
2816 }
2817
2818 /*******************************************************************
2819 * fill a notify_info_data with the servername
2820 ********************************************************************/
2821
2822 void spoolss_notify_server_name(int snum,
/* [<][>][^][v][top][bottom][index][help] */
2823 struct spoolss_Notify *data,
2824 print_queue_struct *queue,
2825 NT_PRINTER_INFO_LEVEL *printer,
2826 TALLOC_CTX *mem_ctx)
2827 {
2828 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, printer->info_2->servername);
2829 }
2830
2831 /*******************************************************************
2832 * fill a notify_info_data with the printername (not including the servername).
2833 ********************************************************************/
2834
2835 void spoolss_notify_printer_name(int snum,
/* [<][>][^][v][top][bottom][index][help] */
2836 struct spoolss_Notify *data,
2837 print_queue_struct *queue,
2838 NT_PRINTER_INFO_LEVEL *printer,
2839 TALLOC_CTX *mem_ctx)
2840 {
2841 /* the notify name should not contain the \\server\ part */
2842 char *p = strrchr(printer->info_2->printername, '\\');
2843
2844 if (!p) {
2845 p = printer->info_2->printername;
2846 } else {
2847 p++;
2848 }
2849
2850 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, p);
2851 }
2852
2853 /*******************************************************************
2854 * fill a notify_info_data with the servicename
2855 ********************************************************************/
2856
2857 void spoolss_notify_share_name(int snum,
/* [<][>][^][v][top][bottom][index][help] */
2858 struct spoolss_Notify *data,
2859 print_queue_struct *queue,
2860 NT_PRINTER_INFO_LEVEL *printer,
2861 TALLOC_CTX *mem_ctx)
2862 {
2863 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, lp_servicename(snum));
2864 }
2865
2866 /*******************************************************************
2867 * fill a notify_info_data with the port name
2868 ********************************************************************/
2869
2870 void spoolss_notify_port_name(int snum,
/* [<][>][^][v][top][bottom][index][help] */
2871 struct spoolss_Notify *data,
2872 print_queue_struct *queue,
2873 NT_PRINTER_INFO_LEVEL *printer,
2874 TALLOC_CTX *mem_ctx)
2875 {
2876 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, printer->info_2->portname);
2877 }
2878
2879 /*******************************************************************
2880 * fill a notify_info_data with the printername
2881 * but it doesn't exist, have to see what to do
2882 ********************************************************************/
2883
2884 void spoolss_notify_driver_name(int snum,
/* [<][>][^][v][top][bottom][index][help] */
2885 struct spoolss_Notify *data,
2886 print_queue_struct *queue,
2887 NT_PRINTER_INFO_LEVEL *printer,
2888 TALLOC_CTX *mem_ctx)
2889 {
2890 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, printer->info_2->drivername);
2891 }
2892
2893 /*******************************************************************
2894 * fill a notify_info_data with the comment
2895 ********************************************************************/
2896
2897 void spoolss_notify_comment(int snum,
/* [<][>][^][v][top][bottom][index][help] */
2898 struct spoolss_Notify *data,
2899 print_queue_struct *queue,
2900 NT_PRINTER_INFO_LEVEL *printer,
2901 TALLOC_CTX *mem_ctx)
2902 {
2903 char *p;
2904
2905 if (*printer->info_2->comment == '\0') {
2906 p = lp_comment(snum);
2907 } else {
2908 p = printer->info_2->comment;
2909 }
2910
2911 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, printer->info_2->comment);
2912 }
2913
2914 /*******************************************************************
2915 * fill a notify_info_data with the comment
2916 * location = "Room 1, floor 2, building 3"
2917 ********************************************************************/
2918
2919 void spoolss_notify_location(int snum,
/* [<][>][^][v][top][bottom][index][help] */
2920 struct spoolss_Notify *data,
2921 print_queue_struct *queue,
2922 NT_PRINTER_INFO_LEVEL *printer,
2923 TALLOC_CTX *mem_ctx)
2924 {
2925 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, printer->info_2->location);
2926 }
2927
2928 /*******************************************************************
2929 * fill a notify_info_data with the device mode
2930 * jfm:xxxx don't to it for know but that's a real problem !!!
2931 ********************************************************************/
2932
2933 static void spoolss_notify_devmode(int snum,
/* [<][>][^][v][top][bottom][index][help] */
2934 struct spoolss_Notify *data,
2935 print_queue_struct *queue,
2936 NT_PRINTER_INFO_LEVEL *printer,
2937 TALLOC_CTX *mem_ctx)
2938 {
2939 /* for a dummy implementation we have to zero the fields */
2940 SETUP_SPOOLSS_NOTIFY_DATA_DEVMODE(data, NULL);
2941 }
2942
2943 /*******************************************************************
2944 * fill a notify_info_data with the separator file name
2945 ********************************************************************/
2946
2947 void spoolss_notify_sepfile(int snum,
/* [<][>][^][v][top][bottom][index][help] */
2948 struct spoolss_Notify *data,
2949 print_queue_struct *queue,
2950 NT_PRINTER_INFO_LEVEL *printer,
2951 TALLOC_CTX *mem_ctx)
2952 {
2953 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, printer->info_2->sepfile);
2954 }
2955
2956 /*******************************************************************
2957 * fill a notify_info_data with the print processor
2958 * jfm:xxxx return always winprint to indicate we don't do anything to it
2959 ********************************************************************/
2960
2961 void spoolss_notify_print_processor(int snum,
/* [<][>][^][v][top][bottom][index][help] */
2962 struct spoolss_Notify *data,
2963 print_queue_struct *queue,
2964 NT_PRINTER_INFO_LEVEL *printer,
2965 TALLOC_CTX *mem_ctx)
2966 {
2967 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, printer->info_2->printprocessor);
2968 }
2969
2970 /*******************************************************************
2971 * fill a notify_info_data with the print processor options
2972 * jfm:xxxx send an empty string
2973 ********************************************************************/
2974
2975 void spoolss_notify_parameters(int snum,
/* [<][>][^][v][top][bottom][index][help] */
2976 struct spoolss_Notify *data,
2977 print_queue_struct *queue,
2978 NT_PRINTER_INFO_LEVEL *printer,
2979 TALLOC_CTX *mem_ctx)
2980 {
2981 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, printer->info_2->parameters);
2982 }
2983
2984 /*******************************************************************
2985 * fill a notify_info_data with the data type
2986 * jfm:xxxx always send RAW as data type
2987 ********************************************************************/
2988
2989 void spoolss_notify_datatype(int snum,
/* [<][>][^][v][top][bottom][index][help] */
2990 struct spoolss_Notify *data,
2991 print_queue_struct *queue,
2992 NT_PRINTER_INFO_LEVEL *printer,
2993 TALLOC_CTX *mem_ctx)
2994 {
2995 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, printer->info_2->datatype);
2996 }
2997
2998 /*******************************************************************
2999 * fill a notify_info_data with the security descriptor
3000 * jfm:xxxx send an null pointer to say no security desc
3001 * have to implement security before !
3002 ********************************************************************/
3003
3004 static void spoolss_notify_security_desc(int snum,
/* [<][>][^][v][top][bottom][index][help] */
3005 struct spoolss_Notify *data,
3006 print_queue_struct *queue,
3007 NT_PRINTER_INFO_LEVEL *printer,
3008 TALLOC_CTX *mem_ctx)
3009 {
3010 SETUP_SPOOLSS_NOTIFY_DATA_SECDESC(data,
3011 printer->info_2->secdesc_buf->sd_size,
3012 printer->info_2->secdesc_buf->sd);
3013 }
3014
3015 /*******************************************************************
3016 * fill a notify_info_data with the attributes
3017 * jfm:xxxx a samba printer is always shared
3018 ********************************************************************/
3019
3020 void spoolss_notify_attributes(int snum,
/* [<][>][^][v][top][bottom][index][help] */
3021 struct spoolss_Notify *data,
3022 print_queue_struct *queue,
3023 NT_PRINTER_INFO_LEVEL *printer,
3024 TALLOC_CTX *mem_ctx)
3025 {
3026 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, printer->info_2->attributes);
3027 }
3028
3029 /*******************************************************************
3030 * fill a notify_info_data with the priority
3031 ********************************************************************/
3032
3033 static void spoolss_notify_priority(int snum,
/* [<][>][^][v][top][bottom][index][help] */
3034 struct spoolss_Notify *data,
3035 print_queue_struct *queue,
3036 NT_PRINTER_INFO_LEVEL *printer,
3037 TALLOC_CTX *mem_ctx)
3038 {
3039 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, printer->info_2->priority);
3040 }
3041
3042 /*******************************************************************
3043 * fill a notify_info_data with the default priority
3044 ********************************************************************/
3045
3046 static void spoolss_notify_default_priority(int snum,
/* [<][>][^][v][top][bottom][index][help] */
3047 struct spoolss_Notify *data,
3048 print_queue_struct *queue,
3049 NT_PRINTER_INFO_LEVEL *printer,
3050 TALLOC_CTX *mem_ctx)
3051 {
3052 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, printer->info_2->default_priority);
3053 }
3054
3055 /*******************************************************************
3056 * fill a notify_info_data with the start time
3057 ********************************************************************/
3058
3059 static void spoolss_notify_start_time(int snum,
/* [<][>][^][v][top][bottom][index][help] */
3060 struct spoolss_Notify *data,
3061 print_queue_struct *queue,
3062 NT_PRINTER_INFO_LEVEL *printer,
3063 TALLOC_CTX *mem_ctx)
3064 {
3065 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, printer->info_2->starttime);
3066 }
3067
3068 /*******************************************************************
3069 * fill a notify_info_data with the until time
3070 ********************************************************************/
3071
3072 static void spoolss_notify_until_time(int snum,
/* [<][>][^][v][top][bottom][index][help] */
3073 struct spoolss_Notify *data,
3074 print_queue_struct *queue,
3075 NT_PRINTER_INFO_LEVEL *printer,
3076 TALLOC_CTX *mem_ctx)
3077 {
3078 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, printer->info_2->untiltime);
3079 }
3080
3081 /*******************************************************************
3082 * fill a notify_info_data with the status
3083 ********************************************************************/
3084
3085 static void spoolss_notify_status(int snum,
/* [<][>][^][v][top][bottom][index][help] */
3086 struct spoolss_Notify *data,
3087 print_queue_struct *queue,
3088 NT_PRINTER_INFO_LEVEL *printer,
3089 TALLOC_CTX *mem_ctx)
3090 {
3091 print_status_struct status;
3092
3093 print_queue_length(snum, &status);
3094 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, status.status);
3095 }
3096
3097 /*******************************************************************
3098 * fill a notify_info_data with the number of jobs queued
3099 ********************************************************************/
3100
3101 void spoolss_notify_cjobs(int snum,
/* [<][>][^][v][top][bottom][index][help] */
3102 struct spoolss_Notify *data,
3103 print_queue_struct *queue,
3104 NT_PRINTER_INFO_LEVEL *printer,
3105 TALLOC_CTX *mem_ctx)
3106 {
3107 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, print_queue_length(snum, NULL));
3108 }
3109
3110 /*******************************************************************
3111 * fill a notify_info_data with the average ppm
3112 ********************************************************************/
3113
3114 static void spoolss_notify_average_ppm(int snum,
/* [<][>][^][v][top][bottom][index][help] */
3115 struct spoolss_Notify *data,
3116 print_queue_struct *queue,
3117 NT_PRINTER_INFO_LEVEL *printer,
3118 TALLOC_CTX *mem_ctx)
3119 {
3120 /* always respond 8 pages per minutes */
3121 /* a little hard ! */
3122 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, printer->info_2->averageppm);
3123 }
3124
3125 /*******************************************************************
3126 * fill a notify_info_data with username
3127 ********************************************************************/
3128
3129 static void spoolss_notify_username(int snum,
/* [<][>][^][v][top][bottom][index][help] */
3130 struct spoolss_Notify *data,
3131 print_queue_struct *queue,
3132 NT_PRINTER_INFO_LEVEL *printer,
3133 TALLOC_CTX *mem_ctx)
3134 {
3135 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, queue->fs_user);
3136 }
3137
3138 /*******************************************************************
3139 * fill a notify_info_data with job status
3140 ********************************************************************/
3141
3142 static void spoolss_notify_job_status(int snum,
/* [<][>][^][v][top][bottom][index][help] */
3143 struct spoolss_Notify *data,
3144 print_queue_struct *queue,
3145 NT_PRINTER_INFO_LEVEL *printer,
3146 TALLOC_CTX *mem_ctx)
3147 {
3148 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, nt_printj_status(queue->status));
3149 }
3150
3151 /*******************************************************************
3152 * fill a notify_info_data with job name
3153 ********************************************************************/
3154
3155 static void spoolss_notify_job_name(int snum,
/* [<][>][^][v][top][bottom][index][help] */
3156 struct spoolss_Notify *data,
3157 print_queue_struct *queue,
3158 NT_PRINTER_INFO_LEVEL *printer,
3159 TALLOC_CTX *mem_ctx)
3160 {
3161 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, queue->fs_file);
3162 }
3163
3164 /*******************************************************************
3165 * fill a notify_info_data with job status
3166 ********************************************************************/
3167
3168 static void spoolss_notify_job_status_string(int snum,
/* [<][>][^][v][top][bottom][index][help] */
3169 struct spoolss_Notify *data,
3170 print_queue_struct *queue,
3171 NT_PRINTER_INFO_LEVEL *printer,
3172 TALLOC_CTX *mem_ctx)
3173 {
3174 /*
3175 * Now we're returning job status codes we just return a "" here. JRA.
3176 */
3177
3178 const char *p = "";
3179
3180 #if 0 /* NO LONGER NEEDED - JRA. 02/22/2001 */
3181 p = "unknown";
3182
3183 switch (queue->status) {
3184 case LPQ_QUEUED:
3185 p = "Queued";
3186 break;
3187 case LPQ_PAUSED:
3188 p = ""; /* NT provides the paused string */
3189 break;
3190 case LPQ_SPOOLING:
3191 p = "Spooling";
3192 break;
3193 case LPQ_PRINTING:
3194 p = "Printing";
3195 break;
3196 }
3197 #endif /* NO LONGER NEEDED. */
3198
3199 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, p);
3200 }
3201
3202 /*******************************************************************
3203 * fill a notify_info_data with job time
3204 ********************************************************************/
3205
3206 static void spoolss_notify_job_time(int snum,
/* [<][>][^][v][top][bottom][index][help] */
3207 struct spoolss_Notify *data,
3208 print_queue_struct *queue,
3209 NT_PRINTER_INFO_LEVEL *printer,
3210 TALLOC_CTX *mem_ctx)
3211 {
3212 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, 0);
3213 }
3214
3215 /*******************************************************************
3216 * fill a notify_info_data with job size
3217 ********************************************************************/
3218
3219 static void spoolss_notify_job_size(int snum,
/* [<][>][^][v][top][bottom][index][help] */
3220 struct spoolss_Notify *data,
3221 print_queue_struct *queue,
3222 NT_PRINTER_INFO_LEVEL *printer,
3223 TALLOC_CTX *mem_ctx)
3224 {
3225 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, queue->size);
3226 }
3227
3228 /*******************************************************************
3229 * fill a notify_info_data with page info
3230 ********************************************************************/
3231 static void spoolss_notify_total_pages(int snum,
/* [<][>][^][v][top][bottom][index][help] */
3232 struct spoolss_Notify *data,
3233 print_queue_struct *queue,
3234 NT_PRINTER_INFO_LEVEL *printer,
3235 TALLOC_CTX *mem_ctx)
3236 {
3237 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, queue->page_count);
3238 }
3239
3240 /*******************************************************************
3241 * fill a notify_info_data with pages printed info.
3242 ********************************************************************/
3243 static void spoolss_notify_pages_printed(int snum,
/* [<][>][^][v][top][bottom][index][help] */
3244 struct spoolss_Notify *data,
3245 print_queue_struct *queue,
3246 NT_PRINTER_INFO_LEVEL *printer,
3247 TALLOC_CTX *mem_ctx)
3248 {
3249 /* Add code when back-end tracks this */
3250 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, 0);
3251 }
3252
3253 /*******************************************************************
3254 Fill a notify_info_data with job position.
3255 ********************************************************************/
3256
3257 static void spoolss_notify_job_position(int snum,
/* [<][>][^][v][top][bottom][index][help] */
3258 struct spoolss_Notify *data,
3259 print_queue_struct *queue,
3260 NT_PRINTER_INFO_LEVEL *printer,
3261 TALLOC_CTX *mem_ctx)
3262 {
3263 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, queue->job);
3264 }
3265
3266 /*******************************************************************
3267 Fill a notify_info_data with submitted time.
3268 ********************************************************************/
3269
3270 static void spoolss_notify_submitted_time(int snum,
/* [<][>][^][v][top][bottom][index][help] */
3271 struct spoolss_Notify *data,
3272 print_queue_struct *queue,
3273 NT_PRINTER_INFO_LEVEL *printer,
3274 TALLOC_CTX *mem_ctx)
3275 {
3276 data->data.string.string = NULL;
3277 data->data.string.size = 0;
3278
3279 init_systemtime_buffer(mem_ctx, gmtime(&queue->time),
3280 &data->data.string.string,
3281 &data->data.string.size);
3282
3283 }
3284
3285 struct s_notify_info_data_table
3286 {
3287 enum spoolss_NotifyType type;
3288 uint16_t field;
3289 const char *name;
3290 enum spoolss_NotifyTable variable_type;
3291 void (*fn) (int snum, struct spoolss_Notify *data,
3292 print_queue_struct *queue,
3293 NT_PRINTER_INFO_LEVEL *printer, TALLOC_CTX *mem_ctx);
3294 };
3295
3296 /* A table describing the various print notification constants and
3297 whether the notification data is a pointer to a variable sized
3298 buffer, a one value uint32_t or a two value uint32_t. */
3299
3300 static const struct s_notify_info_data_table notify_info_data_table[] =
3301 {
3302 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_SERVER_NAME, "PRINTER_NOTIFY_FIELD_SERVER_NAME", NOTIFY_TABLE_STRING, spoolss_notify_server_name },
3303 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PRINTER_NAME, "PRINTER_NOTIFY_FIELD_PRINTER_NAME", NOTIFY_TABLE_STRING, spoolss_notify_printer_name },
3304 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_SHARE_NAME, "PRINTER_NOTIFY_FIELD_SHARE_NAME", NOTIFY_TABLE_STRING, spoolss_notify_share_name },
3305 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PORT_NAME, "PRINTER_NOTIFY_FIELD_PORT_NAME", NOTIFY_TABLE_STRING, spoolss_notify_port_name },
3306 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_DRIVER_NAME, "PRINTER_NOTIFY_FIELD_DRIVER_NAME", NOTIFY_TABLE_STRING, spoolss_notify_driver_name },
3307 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_COMMENT, "PRINTER_NOTIFY_FIELD_COMMENT", NOTIFY_TABLE_STRING, spoolss_notify_comment },
3308 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_LOCATION, "PRINTER_NOTIFY_FIELD_LOCATION", NOTIFY_TABLE_STRING, spoolss_notify_location },
3309 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_DEVMODE, "PRINTER_NOTIFY_FIELD_DEVMODE", NOTIFY_TABLE_DEVMODE, spoolss_notify_devmode },
3310 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_SEPFILE, "PRINTER_NOTIFY_FIELD_SEPFILE", NOTIFY_TABLE_STRING, spoolss_notify_sepfile },
3311 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PRINT_PROCESSOR, "PRINTER_NOTIFY_FIELD_PRINT_PROCESSOR", NOTIFY_TABLE_STRING, spoolss_notify_print_processor },
3312 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PARAMETERS, "PRINTER_NOTIFY_FIELD_PARAMETERS", NOTIFY_TABLE_STRING, spoolss_notify_parameters },
3313 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_DATATYPE, "PRINTER_NOTIFY_FIELD_DATATYPE", NOTIFY_TABLE_STRING, spoolss_notify_datatype },
3314 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_SECURITY_DESCRIPTOR, "PRINTER_NOTIFY_FIELD_SECURITY_DESCRIPTOR", NOTIFY_TABLE_SECURITYDESCRIPTOR, spoolss_notify_security_desc },
3315 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_ATTRIBUTES, "PRINTER_NOTIFY_FIELD_ATTRIBUTES", NOTIFY_TABLE_DWORD, spoolss_notify_attributes },
3316 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PRIORITY, "PRINTER_NOTIFY_FIELD_PRIORITY", NOTIFY_TABLE_DWORD, spoolss_notify_priority },
3317 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_DEFAULT_PRIORITY, "PRINTER_NOTIFY_FIELD_DEFAULT_PRIORITY", NOTIFY_TABLE_DWORD, spoolss_notify_default_priority },
3318 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_START_TIME, "PRINTER_NOTIFY_FIELD_START_TIME", NOTIFY_TABLE_DWORD, spoolss_notify_start_time },
3319 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_UNTIL_TIME, "PRINTER_NOTIFY_FIELD_UNTIL_TIME", NOTIFY_TABLE_DWORD, spoolss_notify_until_time },
3320 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_STATUS, "PRINTER_NOTIFY_FIELD_STATUS", NOTIFY_TABLE_DWORD, spoolss_notify_status },
3321 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_STATUS_STRING, "PRINTER_NOTIFY_FIELD_STATUS_STRING", NOTIFY_TABLE_STRING, NULL },
3322 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_CJOBS, "PRINTER_NOTIFY_FIELD_CJOBS", NOTIFY_TABLE_DWORD, spoolss_notify_cjobs },
3323 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_AVERAGE_PPM, "PRINTER_NOTIFY_FIELD_AVERAGE_PPM", NOTIFY_TABLE_DWORD, spoolss_notify_average_ppm },
3324 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_TOTAL_PAGES, "PRINTER_NOTIFY_FIELD_TOTAL_PAGES", NOTIFY_TABLE_DWORD, NULL },
3325 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PAGES_PRINTED, "PRINTER_NOTIFY_FIELD_PAGES_PRINTED", NOTIFY_TABLE_DWORD, NULL },
3326 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_TOTAL_BYTES, "PRINTER_NOTIFY_FIELD_TOTAL_BYTES", NOTIFY_TABLE_DWORD, NULL },
3327 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_BYTES_PRINTED, "PRINTER_NOTIFY_FIELD_BYTES_PRINTED", NOTIFY_TABLE_DWORD, NULL },
3328 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_PRINTER_NAME, "JOB_NOTIFY_FIELD_PRINTER_NAME", NOTIFY_TABLE_STRING, spoolss_notify_printer_name },
3329 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_MACHINE_NAME, "JOB_NOTIFY_FIELD_MACHINE_NAME", NOTIFY_TABLE_STRING, spoolss_notify_server_name },
3330 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_PORT_NAME, "JOB_NOTIFY_FIELD_PORT_NAME", NOTIFY_TABLE_STRING, spoolss_notify_port_name },
3331 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_USER_NAME, "JOB_NOTIFY_FIELD_USER_NAME", NOTIFY_TABLE_STRING, spoolss_notify_username },
3332 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_NOTIFY_NAME, "JOB_NOTIFY_FIELD_NOTIFY_NAME", NOTIFY_TABLE_STRING, spoolss_notify_username },
3333 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_DATATYPE, "JOB_NOTIFY_FIELD_DATATYPE", NOTIFY_TABLE_STRING, spoolss_notify_datatype },
3334 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_PRINT_PROCESSOR, "JOB_NOTIFY_FIELD_PRINT_PROCESSOR", NOTIFY_TABLE_STRING, spoolss_notify_print_processor },
3335 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_PARAMETERS, "JOB_NOTIFY_FIELD_PARAMETERS", NOTIFY_TABLE_STRING, spoolss_notify_parameters },
3336 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_DRIVER_NAME, "JOB_NOTIFY_FIELD_DRIVER_NAME", NOTIFY_TABLE_STRING, spoolss_notify_driver_name },
3337 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_DEVMODE, "JOB_NOTIFY_FIELD_DEVMODE", NOTIFY_TABLE_DEVMODE, spoolss_notify_devmode },
3338 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_STATUS, "JOB_NOTIFY_FIELD_STATUS", NOTIFY_TABLE_DWORD, spoolss_notify_job_status },
3339 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_STATUS_STRING, "JOB_NOTIFY_FIELD_STATUS_STRING", NOTIFY_TABLE_STRING, spoolss_notify_job_status_string },
3340 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_SECURITY_DESCRIPTOR, "JOB_NOTIFY_FIELD_SECURITY_DESCRIPTOR", NOTIFY_TABLE_SECURITYDESCRIPTOR, NULL },
3341 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_DOCUMENT, "JOB_NOTIFY_FIELD_DOCUMENT", NOTIFY_TABLE_STRING, spoolss_notify_job_name },
3342 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_PRIORITY, "JOB_NOTIFY_FIELD_PRIORITY", NOTIFY_TABLE_DWORD, spoolss_notify_priority },
3343 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_POSITION, "JOB_NOTIFY_FIELD_POSITION", NOTIFY_TABLE_DWORD, spoolss_notify_job_position },
3344 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_SUBMITTED, "JOB_NOTIFY_FIELD_SUBMITTED", NOTIFY_TABLE_TIME, spoolss_notify_submitted_time },
3345 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_START_TIME, "JOB_NOTIFY_FIELD_START_TIME", NOTIFY_TABLE_DWORD, spoolss_notify_start_time },
3346 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_UNTIL_TIME, "JOB_NOTIFY_FIELD_UNTIL_TIME", NOTIFY_TABLE_DWORD, spoolss_notify_until_time },
3347 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_TIME, "JOB_NOTIFY_FIELD_TIME", NOTIFY_TABLE_DWORD, spoolss_notify_job_time },
3348 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_TOTAL_PAGES, "JOB_NOTIFY_FIELD_TOTAL_PAGES", NOTIFY_TABLE_DWORD, spoolss_notify_total_pages },
3349 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_PAGES_PRINTED, "JOB_NOTIFY_FIELD_PAGES_PRINTED", NOTIFY_TABLE_DWORD, spoolss_notify_pages_printed },
3350 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_TOTAL_BYTES, "JOB_NOTIFY_FIELD_TOTAL_BYTES", NOTIFY_TABLE_DWORD, spoolss_notify_job_size },
3351 };
3352
3353 /*******************************************************************
3354 Return the variable_type of info_data structure.
3355 ********************************************************************/
3356
3357 static uint32_t variable_type_of_notify_info_data(enum spoolss_NotifyType type,
/* [<][>][^][v][top][bottom][index][help] */
3358 uint16_t field)
3359 {
3360 int i=0;
3361
3362 for (i = 0; i < ARRAY_SIZE(notify_info_data_table); i++) {
3363 if ( (notify_info_data_table[i].type == type) &&
3364 (notify_info_data_table[i].field == field) ) {
3365 return notify_info_data_table[i].variable_type;
3366 }
3367 }
3368
3369 DEBUG(5, ("invalid notify data type %d/%d\n", type, field));
3370
3371 return 0;
3372 }
3373
3374 /****************************************************************************
3375 ****************************************************************************/
3376
3377 static bool search_notify(enum spoolss_NotifyType type,
/* [<][>][^][v][top][bottom][index][help] */
3378 uint16_t field,
3379 int *value)
3380 {
3381 int i;
3382
3383 for (i = 0; i < ARRAY_SIZE(notify_info_data_table); i++) {
3384 if (notify_info_data_table[i].type == type &&
3385 notify_info_data_table[i].field == field &&
3386 notify_info_data_table[i].fn != NULL) {
3387 *value = i;
3388 return true;
3389 }
3390 }
3391
3392 return false;
3393 }
3394
3395 /****************************************************************************
3396 ****************************************************************************/
3397
3398 void construct_info_data(struct spoolss_Notify *info_data,
/* [<][>][^][v][top][bottom][index][help] */
3399 enum spoolss_NotifyType type,
3400 uint16_t field,
3401 int id)
3402 {
3403 info_data->type = type;
3404 info_data->field.field = field;
3405 info_data->variable_type = variable_type_of_notify_info_data(type, field);
3406 info_data->job_id = id;
3407 }
3408
3409 /*******************************************************************
3410 *
3411 * fill a notify_info struct with info asked
3412 *
3413 ********************************************************************/
3414
3415 static bool construct_notify_printer_info(Printer_entry *print_hnd,
/* [<][>][^][v][top][bottom][index][help] */
3416 struct spoolss_NotifyInfo *info,
3417 int snum,
3418 const struct spoolss_NotifyOptionType *option_type,
3419 uint32_t id,
3420 TALLOC_CTX *mem_ctx)
3421 {
3422 int field_num,j;
3423 enum spoolss_NotifyType type;
3424 uint16_t field;
3425
3426 struct spoolss_Notify *current_data;
3427 NT_PRINTER_INFO_LEVEL *printer = NULL;
3428 print_queue_struct *queue=NULL;
3429
3430 type = option_type->type;
3431
3432 DEBUG(4,("construct_notify_printer_info: Notify type: [%s], number of notify info: [%d] on printer: [%s]\n",
3433 (type == PRINTER_NOTIFY_TYPE ? "PRINTER_NOTIFY_TYPE" : "JOB_NOTIFY_TYPE"),
3434 option_type->count, lp_servicename(snum)));
3435
3436 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &printer, 2, lp_const_servicename(snum))))
3437 return false;
3438
3439 for(field_num=0; field_num < option_type->count; field_num++) {
3440 field = option_type->fields[field_num].field;
3441
3442 DEBUG(4,("construct_notify_printer_info: notify [%d]: type [%x], field [%x]\n", field_num, type, field));
3443
3444 if (!search_notify(type, field, &j) )
3445 continue;
3446
3447 info->notifies = TALLOC_REALLOC_ARRAY(info, info->notifies,
3448 struct spoolss_Notify,
3449 info->count + 1);
3450 if (info->notifies == NULL) {
3451 DEBUG(2,("construct_notify_printer_info: failed to enlarge buffer info->data!\n"));
3452 free_a_printer(&printer, 2);
3453 return false;
3454 }
3455
3456 current_data = &info->notifies[info->count];
3457
3458 construct_info_data(current_data, type, field, id);
3459
3460 DEBUG(10,("construct_notify_printer_info: calling [%s] snum=%d printername=[%s])\n",
3461 notify_info_data_table[j].name, snum, printer->info_2->printername ));
3462
3463 notify_info_data_table[j].fn(snum, current_data, queue,
3464 printer, mem_ctx);
3465
3466 info->count++;
3467 }
3468
3469 free_a_printer(&printer, 2);
3470 return true;
3471 }
3472
3473 /*******************************************************************
3474 *
3475 * fill a notify_info struct with info asked
3476 *
3477 ********************************************************************/
3478
3479 static bool construct_notify_jobs_info(print_queue_struct *queue,
/* [<][>][^][v][top][bottom][index][help] */
3480 struct spoolss_NotifyInfo *info,
3481 NT_PRINTER_INFO_LEVEL *printer,
3482 int snum,
3483 const struct spoolss_NotifyOptionType *option_type,
3484 uint32_t id,
3485 TALLOC_CTX *mem_ctx)
3486 {
3487 int field_num,j;
3488 enum spoolss_NotifyType type;
3489 uint16_t field;
3490 struct spoolss_Notify *current_data;
3491
3492 DEBUG(4,("construct_notify_jobs_info\n"));
3493
3494 type = option_type->type;
3495
3496 DEBUGADD(4,("Notify type: [%s], number of notify info: [%d]\n",
3497 (type == PRINTER_NOTIFY_TYPE ? "PRINTER_NOTIFY_TYPE" : "JOB_NOTIFY_TYPE"),
3498 option_type->count));
3499
3500 for(field_num=0; field_num<option_type->count; field_num++) {
3501 field = option_type->fields[field_num].field;
3502
3503 if (!search_notify(type, field, &j) )
3504 continue;
3505
3506 info->notifies = TALLOC_REALLOC_ARRAY(info, info->notifies,
3507 struct spoolss_Notify,
3508 info->count + 1);
3509 if (info->notifies == NULL) {
3510 DEBUG(2,("construct_notify_jobs_info: failed to enlarg buffer info->data!\n"));
3511 return false;
3512 }
3513
3514 current_data=&(info->notifies[info->count]);
3515
3516 construct_info_data(current_data, type, field, id);
3517 notify_info_data_table[j].fn(snum, current_data, queue,
3518 printer, mem_ctx);
3519 info->count++;
3520 }
3521
3522 return true;
3523 }
3524
3525 /*
3526 * JFM: The enumeration is not that simple, it's even non obvious.
3527 *
3528 * let's take an example: I want to monitor the PRINTER SERVER for
3529 * the printer's name and the number of jobs currently queued.
3530 * So in the NOTIFY_OPTION, I have one NOTIFY_OPTION_TYPE structure.
3531 * Its type is PRINTER_NOTIFY_TYPE and it has 2 fields NAME and CJOBS.
3532 *
3533 * I have 3 printers on the back of my server.
3534 *
3535 * Now the response is a NOTIFY_INFO structure, with 6 NOTIFY_INFO_DATA
3536 * structures.
3537 * Number Data Id
3538 * 1 printer 1 name 1
3539 * 2 printer 1 cjob 1
3540 * 3 printer 2 name 2
3541 * 4 printer 2 cjob 2
3542 * 5 printer 3 name 3
3543 * 6 printer 3 name 3
3544 *
3545 * that's the print server case, the printer case is even worse.
3546 */
3547
3548 /*******************************************************************
3549 *
3550 * enumerate all printers on the printserver
3551 * fill a notify_info struct with info asked
3552 *
3553 ********************************************************************/
3554
3555 static WERROR printserver_notify_info(pipes_struct *p,
/* [<][>][^][v][top][bottom][index][help] */
3556 struct policy_handle *hnd,
3557 struct spoolss_NotifyInfo *info,
3558 TALLOC_CTX *mem_ctx)
3559 {
3560 int snum;
3561 Printer_entry *Printer = find_printer_index_by_hnd(p, hnd);
3562 int n_services=lp_numservices();
3563 int i;
3564 struct spoolss_NotifyOption *option;
3565 struct spoolss_NotifyOptionType option_type;
3566
3567 DEBUG(4,("printserver_notify_info\n"));
3568
3569 if (!Printer)
3570 return WERR_BADFID;
3571
3572 option = Printer->notify.option;
3573
3574 info->version = 2;
3575 info->notifies = NULL;
3576 info->count = 0;
3577
3578 /* a bug in xp sp2 rc2 causes it to send a fnpcn request without
3579 sending a ffpcn() request first */
3580
3581 if ( !option )
3582 return WERR_BADFID;
3583
3584 for (i=0; i<option->count; i++) {
3585 option_type = option->types[i];
3586
3587 if (option_type.type != PRINTER_NOTIFY_TYPE)
3588 continue;
3589
3590 for (snum=0; snum<n_services; snum++)
3591 {
3592 if ( lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) )
3593 construct_notify_printer_info ( Printer, info, snum, &option_type, snum, mem_ctx );
3594 }
3595 }
3596
3597 #if 0
3598 /*
3599 * Debugging information, don't delete.
3600 */
3601
3602 DEBUG(1,("dumping the NOTIFY_INFO\n"));
3603 DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
3604 DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3605
3606 for (i=0; i<info->count; i++) {
3607 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3608 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
3609 info->data[i].id, info->data[i].size, info->data[i].enc_type));
3610 }
3611 #endif
3612
3613 return WERR_OK;
3614 }
3615
3616 /*******************************************************************
3617 *
3618 * fill a notify_info struct with info asked
3619 *
3620 ********************************************************************/
3621
3622 static WERROR printer_notify_info(pipes_struct *p, struct policy_handle *hnd,
/* [<][>][^][v][top][bottom][index][help] */
3623 struct spoolss_NotifyInfo *info,
3624 TALLOC_CTX *mem_ctx)
3625 {
3626 int snum;
3627 Printer_entry *Printer = find_printer_index_by_hnd(p, hnd);
3628 int i;
3629 uint32_t id;
3630 struct spoolss_NotifyOption *option;
3631 struct spoolss_NotifyOptionType option_type;
3632 int count,j;
3633 print_queue_struct *queue=NULL;
3634 print_status_struct status;
3635
3636 DEBUG(4,("printer_notify_info\n"));
3637
3638 if (!Printer)
3639 return WERR_BADFID;
3640
3641 option = Printer->notify.option;
3642 id = 0x0;
3643
3644 info->version = 2;
3645 info->notifies = NULL;
3646 info->count = 0;
3647
3648 /* a bug in xp sp2 rc2 causes it to send a fnpcn request without
3649 sending a ffpcn() request first */
3650
3651 if ( !option )
3652 return WERR_BADFID;
3653
3654 get_printer_snum(p, hnd, &snum, NULL);
3655
3656 for (i=0; i<option->count; i++) {
3657 option_type = option->types[i];
3658
3659 switch (option_type.type) {
3660 case PRINTER_NOTIFY_TYPE:
3661 if(construct_notify_printer_info(Printer, info, snum,
3662 &option_type, id,
3663 mem_ctx))
3664 id--;
3665 break;
3666
3667 case JOB_NOTIFY_TYPE: {
3668 NT_PRINTER_INFO_LEVEL *printer = NULL;
3669
3670 count = print_queue_status(snum, &queue, &status);
3671
3672 if (!W_ERROR_IS_OK(get_a_printer(Printer, &printer, 2, lp_const_servicename(snum))))
3673 goto done;
3674
3675 for (j=0; j<count; j++) {
3676 construct_notify_jobs_info(&queue[j], info,
3677 printer, snum,
3678 &option_type,
3679 queue[j].job,
3680 mem_ctx);
3681 }
3682
3683 free_a_printer(&printer, 2);
3684
3685 done:
3686 SAFE_FREE(queue);
3687 break;
3688 }
3689 }
3690 }
3691
3692 /*
3693 * Debugging information, don't delete.
3694 */
3695 /*
3696 DEBUG(1,("dumping the NOTIFY_INFO\n"));
3697 DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
3698 DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3699
3700 for (i=0; i<info->count; i++) {
3701 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3702 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
3703 info->data[i].id, info->data[i].size, info->data[i].enc_type));
3704 }
3705 */
3706 return WERR_OK;
3707 }
3708
3709 /****************************************************************
3710 _spoolss_RouterRefreshPrinterChangeNotify
3711 ****************************************************************/
3712
3713 WERROR _spoolss_RouterRefreshPrinterChangeNotify(pipes_struct *p,
/* [<][>][^][v][top][bottom][index][help] */
3714 struct spoolss_RouterRefreshPrinterChangeNotify *r)
3715 {
3716 struct spoolss_NotifyInfo *info;
3717
3718 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
3719 WERROR result = WERR_BADFID;
3720
3721 /* we always have a spoolss_NotifyInfo struct */
3722 info = talloc_zero(p->mem_ctx, struct spoolss_NotifyInfo);
3723 if (!info) {
3724 result = WERR_NOMEM;
3725 goto done;
3726 }
3727
3728 *r->out.info = info;
3729
3730 if (!Printer) {
3731 DEBUG(2,("_spoolss_RouterRefreshPrinterChangeNotify: "
3732 "Invalid handle (%s:%u:%u).\n",
3733 OUR_HANDLE(r->in.handle)));
3734 goto done;
3735 }
3736
3737 DEBUG(4,("Printer type %x\n",Printer->printer_type));
3738
3739 /*
3740 * We are now using the change value, and
3741 * I should check for PRINTER_NOTIFY_OPTIONS_REFRESH but as
3742 * I don't have a global notification system, I'm sending back all the
3743 * informations even when _NOTHING_ has changed.
3744 */
3745
3746 /* We need to keep track of the change value to send back in
3747 RRPCN replies otherwise our updates are ignored. */
3748
3749 Printer->notify.fnpcn = true;
3750
3751 if (Printer->notify.client_connected) {
3752 DEBUG(10,("_spoolss_RouterRefreshPrinterChangeNotify: "
3753 "Saving change value in request [%x]\n",
3754 r->in.change_low));
3755 Printer->notify.change = r->in.change_low;
3756 }
3757
3758 /* just ignore the spoolss_NotifyOption */
3759
3760 switch (Printer->printer_type) {
3761 case SPLHND_SERVER:
3762 result = printserver_notify_info(p, r->in.handle,
3763 info, p->mem_ctx);
3764 break;
3765
3766 case SPLHND_PRINTER:
3767 result = printer_notify_info(p, r->in.handle,
3768 info, p->mem_ctx);
3769 break;
3770 }
3771
3772 Printer->notify.fnpcn = false;
3773
3774 done:
3775 return result;
3776 }
3777
3778 /********************************************************************
3779 * construct_printer_info_0
3780 * fill a printer_info_0 struct
3781 ********************************************************************/
3782
3783 static WERROR construct_printer_info0(TALLOC_CTX *mem_ctx,
/* [<][>][^][v][top][bottom][index][help] */
3784 const NT_PRINTER_INFO_LEVEL *ntprinter,
3785 struct spoolss_PrinterInfo0 *r,
3786 int snum)
3787 {
3788 int count;
3789 counter_printer_0 *session_counter;
3790 time_t setuptime;
3791 print_status_struct status;
3792
3793 r->printername = talloc_strdup(mem_ctx, ntprinter->info_2->printername);
3794 W_ERROR_HAVE_NO_MEMORY(r->printername);
3795
3796 r->servername = talloc_strdup(mem_ctx, ntprinter->info_2->servername);
3797 W_ERROR_HAVE_NO_MEMORY(r->servername);
3798
3799 count = print_queue_length(snum, &status);
3800
3801 /* check if we already have a counter for this printer */
3802 for (session_counter = counter_list; session_counter; session_counter = session_counter->next) {
3803 if (session_counter->snum == snum)
3804 break;
3805 }
3806
3807 /* it's the first time, add it to the list */
3808 if (session_counter == NULL) {
3809 session_counter = SMB_MALLOC_P(counter_printer_0);
3810 W_ERROR_HAVE_NO_MEMORY(session_counter);
3811 ZERO_STRUCTP(session_counter);
3812 session_counter->snum = snum;
3813 session_counter->counter = 0;
3814 DLIST_ADD(counter_list, session_counter);
3815 }
3816
3817 /* increment it */
3818 session_counter->counter++;
3819
3820 r->cjobs = count;
3821 r->total_jobs = 0;
3822 r->total_bytes = 0;
3823
3824 setuptime = (time_t)ntprinter->info_2->setuptime;
3825
3826 init_systemtime(&r->time, gmtime(&setuptime));
3827
3828 /* JFM:
3829 * the global_counter should be stored in a TDB as it's common to all the clients
3830 * and should be zeroed on samba startup
3831 */
3832 r->global_counter = session_counter->counter;
3833 r->total_pages = 0;
3834 /* in 2.2 we reported ourselves as 0x0004 and 0x0565 */
3835 r->version = 0x0005; /* NT 5 */
3836 r->free_build = 0x0893; /* build 2195 */
3837 r->spooling = 0;
3838 r->max_spooling = 0;
3839 r->session_counter = session_counter->counter;
3840 r->num_error_out_of_paper = 0x0;
3841 r->num_error_not_ready = 0x0; /* number of print failure */
3842 r->job_error = 0x0;
3843 r->number_of_processors = 0x1;
3844 r->processor_type = PROCESSOR_INTEL_PENTIUM; /* 586 Pentium ? */
3845 r->high_part_total_bytes = 0x0;
3846 r->change_id = ntprinter->info_2->changeid; /* ChangeID in milliseconds*/
3847 r->last_error = WERR_OK;
3848 r->status = nt_printq_status(status.status);
3849 r->enumerate_network_printers = 0x0;
3850 r->c_setprinter = get_c_setprinter(); /* monotonically increasing sum of delta printer counts */
3851 r->processor_architecture = 0x0;
3852 r->processor_level = 0x6; /* 6 ???*/
3853 r->ref_ic = 0;
3854 r->reserved2 = 0;
3855 r->reserved3 = 0;
3856
3857 return WERR_OK;
3858 }
3859
3860 /****************************************************************************
3861 Convert an NT_DEVICEMODE to a spoolss_DeviceMode structure. Both pointers
3862 should be valid upon entry
3863 ****************************************************************************/
3864
3865 static WERROR convert_nt_devicemode(TALLOC_CTX *mem_ctx,
/* [<][>][^][v][top][bottom][index][help] */
3866 struct spoolss_DeviceMode *r,
3867 const NT_DEVICEMODE *ntdevmode)
3868 {
3869 if (!r || !ntdevmode) {
3870 return WERR_INVALID_PARAM;
3871 }
3872
3873 r->devicename = talloc_strdup(mem_ctx, ntdevmode->devicename);
3874 W_ERROR_HAVE_NO_MEMORY(r->devicename);
3875
3876 r->specversion = ntdevmode->specversion;
3877 r->driverversion = ntdevmode->driverversion;
3878 r->size = ntdevmode->size;
3879 r->__driverextra_length = ntdevmode->driverextra;
3880 r->fields = ntdevmode->fields;
3881
3882 r->orientation = ntdevmode->orientation;
3883 r->papersize = ntdevmode->papersize;
3884 r->paperlength = ntdevmode->paperlength;
3885 r->paperwidth = ntdevmode->paperwidth;
3886 r->scale = ntdevmode->scale;
3887 r->copies = ntdevmode->copies;
3888 r->defaultsource = ntdevmode->defaultsource;
3889 r->printquality = ntdevmode->printquality;
3890 r->color = ntdevmode->color;
3891 r->duplex = ntdevmode->duplex;
3892 r->yresolution = ntdevmode->yresolution;
3893 r->ttoption = ntdevmode->ttoption;
3894 r->collate = ntdevmode->collate;
3895
3896 r->formname = talloc_strdup(mem_ctx, ntdevmode->formname);
3897 W_ERROR_HAVE_NO_MEMORY(r->formname);
3898
3899 /* all 0 below are values that have not been set in the old parsing/copy
3900 * function, maybe they should... - gd */
3901
3902 r->logpixels = 0;
3903 r->bitsperpel = 0;
3904 r->pelswidth = 0;
3905 r->pelsheight = 0;
3906 r->displayflags = 0;
3907 r->displayfrequency = 0;
3908 r->icmmethod = ntdevmode->icmmethod;
3909 r->icmintent = ntdevmode->icmintent;
3910 r->mediatype = ntdevmode->mediatype;
3911 r->dithertype = ntdevmode->dithertype;
3912 r->reserved1 = 0;
3913 r->reserved2 = 0;
3914 r->panningwidth = 0;
3915 r->panningheight = 0;
3916
3917 if (ntdevmode->nt_dev_private != NULL) {
3918 r->driverextra_data = data_blob_talloc(mem_ctx,
3919 ntdevmode->nt_dev_private,
3920 ntdevmode->driverextra);
3921 W_ERROR_HAVE_NO_MEMORY(r->driverextra_data.data);
3922 }
3923
3924 return WERR_OK;
3925 }
3926
3927
3928 /****************************************************************************
3929 Create a spoolss_DeviceMode struct. Returns talloced memory.
3930 ****************************************************************************/
3931
3932 struct spoolss_DeviceMode *construct_dev_mode(TALLOC_CTX *mem_ctx,
/* [<][>][^][v][top][bottom][index][help] */
3933 const char *servicename)
3934 {
3935 WERROR result;
3936 NT_PRINTER_INFO_LEVEL *printer = NULL;
3937 struct spoolss_DeviceMode *devmode = NULL;
3938
3939 DEBUG(7,("construct_dev_mode\n"));
3940
3941 DEBUGADD(8,("getting printer characteristics\n"));
3942
3943 if (!W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, servicename)))
3944 return NULL;
3945
3946 if (!printer->info_2->devmode) {
3947 DEBUG(5, ("BONG! There was no device mode!\n"));
3948 goto done;
3949 }
3950
3951 devmode = TALLOC_ZERO_P(mem_ctx, struct spoolss_DeviceMode);
3952 if (!devmode) {
3953 DEBUG(2,("construct_dev_mode: talloc fail.\n"));
3954 goto done;
3955 }
3956
3957 DEBUGADD(8,("loading DEVICEMODE\n"));
3958
3959 result = convert_nt_devicemode(mem_ctx, devmode, printer->info_2->devmode);
3960 if (!W_ERROR_IS_OK(result)) {
3961 TALLOC_FREE(devmode);
3962 }
3963
3964 done:
3965 free_a_printer(&printer,2);
3966
3967 return devmode;
3968 }
3969
3970 /********************************************************************
3971 * construct_printer_info3
3972 * fill a spoolss_PrinterInfo3 struct
3973 ********************************************************************/
3974
3975 static WERROR construct_printer_info3(TALLOC_CTX *mem_ctx,
/* [<][>][^][v][top][bottom][index][help] */
3976 const NT_PRINTER_INFO_LEVEL *ntprinter,
3977 struct spoolss_PrinterInfo3 *r,
3978 int snum)
3979 {
3980 /* These are the components of the SD we are returning. */
3981
3982 if (ntprinter->info_2->secdesc_buf && ntprinter->info_2->secdesc_buf->sd_size != 0) {
3983 /* don't use talloc_steal() here unless you do a deep steal of all
3984 the SEC_DESC members */
3985
3986 r->secdesc = dup_sec_desc(mem_ctx,
3987 ntprinter->info_2->secdesc_buf->sd);
3988 W_ERROR_HAVE_NO_MEMORY(r->secdesc);
3989 }
3990
3991 return WERR_OK;
3992 }
3993
3994 /********************************************************************
3995 * construct_printer_info4
3996 * fill a spoolss_PrinterInfo4 struct
3997 ********************************************************************/
3998
3999 static WERROR construct_printer_info4(TALLOC_CTX *mem_ctx,
/* [<][>][^][v][top][bottom][index][help] */
4000 const NT_PRINTER_INFO_LEVEL *ntprinter,
4001 struct spoolss_PrinterInfo4 *r,
4002 int snum)
4003 {
4004 r->printername = talloc_strdup(mem_ctx, ntprinter->info_2->printername);
4005 W_ERROR_HAVE_NO_MEMORY(r->printername);
4006 r->servername = talloc_strdup(mem_ctx, ntprinter->info_2->servername);
4007 W_ERROR_HAVE_NO_MEMORY(r->servername);
4008
4009 r->attributes = ntprinter->info_2->attributes;
4010
4011 return WERR_OK;
4012 }
4013
4014 /********************************************************************
4015 * construct_printer_info5
4016 * fill a spoolss_PrinterInfo5 struct
4017 ********************************************************************/
4018
4019 static WERROR construct_printer_info5(TALLOC_CTX *mem_ctx,
/* [<][>][^][v][top][bottom][index][help] */
4020 const NT_PRINTER_INFO_LEVEL *ntprinter,
4021 struct spoolss_PrinterInfo5 *r,
4022 int snum)
4023 {
4024 r->printername = talloc_strdup(mem_ctx, ntprinter->info_2->printername);
4025 W_ERROR_HAVE_NO_MEMORY(r->printername);
4026 r->portname = talloc_strdup(mem_ctx, ntprinter->info_2->portname);
4027 W_ERROR_HAVE_NO_MEMORY(r->portname);
4028
4029 r->attributes = ntprinter->info_2->attributes;
4030
4031 /* these two are not used by NT+ according to MSDN */
4032
4033 r->device_not_selected_timeout = 0x0; /* have seen 0x3a98 */
4034 r->transmission_retry_timeout = 0x0; /* have seen 0xafc8 */
4035
4036 return WERR_OK;
4037 }
4038
4039 /********************************************************************
4040 * construct_printer_info_6
4041 * fill a spoolss_PrinterInfo6 struct
4042 ********************************************************************/
4043
4044 static WERROR construct_printer_info6(TALLOC_CTX *mem_ctx,
/* [<][>][^][v][top][bottom][index][help] */
4045 const NT_PRINTER_INFO_LEVEL *ntprinter,
4046 struct spoolss_PrinterInfo6 *r,
4047 int snum)
4048 {
4049 int count;
4050 print_status_struct status;
4051
4052 count = print_queue_length(snum, &status);
4053
4054 r->status = nt_printq_status(status.status);
4055
4056 return WERR_OK;
4057 }
4058
4059 /********************************************************************
4060 * construct_printer_info7
4061 * fill a spoolss_PrinterInfo7 struct
4062 ********************************************************************/
4063
4064 static WERROR construct_printer_info7(TALLOC_CTX *mem_ctx,
/* [<][>][^][v][top][bottom][index][help] */
4065 Printer_entry *print_hnd,
4066 struct spoolss_PrinterInfo7 *r,
4067 int snum)
4068 {
4069 struct GUID guid;
4070
4071 if (is_printer_published(print_hnd, snum, &guid)) {
4072 r->guid = talloc_strdup_upper(mem_ctx, GUID_string2(mem_ctx, &guid));
4073 r->action = DSPRINT_PUBLISH;
4074 } else {
4075 r->guid = talloc_strdup(mem_ctx, "");
4076 r->action = DSPRINT_UNPUBLISH;
4077 }
4078 W_ERROR_HAVE_NO_MEMORY(r->guid);
4079
4080 return WERR_OK;
4081 }
4082
4083 /********************************************************************
4084 * construct_printer_info8
4085 * fill a spoolss_PrinterInfo8 struct
4086 ********************************************************************/
4087
4088 static WERROR construct_printer_info8(TALLOC_CTX *mem_ctx,
/* [<][>][^][v][top][bottom][index][help] */
4089 const NT_PRINTER_INFO_LEVEL *ntprinter,
4090 struct spoolss_DeviceModeInfo *r,
4091 int snum)
4092 {
4093 struct spoolss_DeviceMode *devmode;
4094 WERROR result;
4095
4096 if (!ntprinter->info_2->devmode) {
4097 r->devmode = NULL;
4098 return WERR_OK;
4099 }
4100
4101 devmode = TALLOC_ZERO_P(mem_ctx, struct spoolss_DeviceMode);
4102 W_ERROR_HAVE_NO_MEMORY(devmode);
4103
4104 result = convert_nt_devicemode(mem_ctx, devmode, ntprinter->info_2->devmode);
4105 if (!W_ERROR_IS_OK(result)) {
4106 TALLOC_FREE(devmode);
4107 return result;
4108 }
4109
4110 r->devmode = devmode;
4111
4112 return WERR_OK;
4113 }
4114
4115
4116 /********************************************************************
4117 * construct_printer_info1
4118 * fill a spoolss_PrinterInfo1 struct
4119 ********************************************************************/
4120
4121 static WERROR construct_printer_info1(TALLOC_CTX *mem_ctx,
/* [<][>][^][v][top][bottom][index][help] */
4122 const NT_PRINTER_INFO_LEVEL *ntprinter,
4123 uint32_t flags,
4124 struct spoolss_PrinterInfo1 *r,
4125 int snum)
4126 {
4127 r->flags = flags;
4128
4129 r->description = talloc_asprintf(mem_ctx, "%s,%s,%s",
4130 ntprinter->info_2->printername,
4131 ntprinter->info_2->drivername,
4132 ntprinter->info_2->location);
4133 W_ERROR_HAVE_NO_MEMORY(r->description);
4134
4135 if (*ntprinter->info_2->comment == '\0') {
4136 r->comment = talloc_strdup(mem_ctx, lp_comment(snum));
4137 } else {
4138 r->comment = talloc_strdup(mem_ctx, ntprinter->info_2->comment); /* saved comment */
4139 }
4140 W_ERROR_HAVE_NO_MEMORY(r->comment);
4141
4142 r->name = talloc_strdup(mem_ctx, ntprinter->info_2->printername);
4143 W_ERROR_HAVE_NO_MEMORY(r->name);
4144
4145 return WERR_OK;
4146 }
4147
4148 /********************************************************************
4149 * construct_printer_info2
4150 * fill a spoolss_PrinterInfo2 struct
4151 ********************************************************************/
4152
4153 static WERROR construct_printer_info2(TALLOC_CTX *mem_ctx,
/* [<][>][^][v][top][bottom][index][help] */
4154 const NT_PRINTER_INFO_LEVEL *ntprinter,
4155 struct spoolss_PrinterInfo2 *r,
4156 int snum)
4157 {
4158 int count;
4159
4160 print_status_struct status;
4161
4162 count = print_queue_length(snum, &status);
4163
4164 r->servername = talloc_strdup(mem_ctx, ntprinter->info_2->servername);
4165 W_ERROR_HAVE_NO_MEMORY(r->servername);
4166 r->printername = talloc_strdup(mem_ctx, ntprinter->info_2->printername);
4167 W_ERROR_HAVE_NO_MEMORY(r->printername);
4168 r->sharename = talloc_strdup(mem_ctx, lp_servicename(snum));
4169 W_ERROR_HAVE_NO_MEMORY(r->sharename);
4170 r->portname = talloc_strdup(mem_ctx, ntprinter->info_2->portname);
4171 W_ERROR_HAVE_NO_MEMORY(r->portname);
4172 r->drivername = talloc_strdup(mem_ctx, ntprinter->info_2->drivername);
4173 W_ERROR_HAVE_NO_MEMORY(r->drivername);
4174
4175 if (*ntprinter->info_2->comment == '\0') {
4176 r->comment = talloc_strdup(mem_ctx, lp_comment(snum));
4177 } else {
4178 r->comment = talloc_strdup(mem_ctx, ntprinter->info_2->comment);
4179 }
4180 W_ERROR_HAVE_NO_MEMORY(r->comment);
4181
4182 r->location = talloc_strdup(mem_ctx, ntprinter->info_2->location);
4183 W_ERROR_HAVE_NO_MEMORY(r->location);
4184 r->sepfile = talloc_strdup(mem_ctx, ntprinter->info_2->sepfile);
4185 W_ERROR_HAVE_NO_MEMORY(r->sepfile);
4186 r->printprocessor = talloc_strdup(mem_ctx, ntprinter->info_2->printprocessor);
4187 W_ERROR_HAVE_NO_MEMORY(r->printprocessor);
4188 r->datatype = talloc_strdup(mem_ctx, ntprinter->info_2->datatype);
4189 W_ERROR_HAVE_NO_MEMORY(r->datatype);
4190 r->parameters = talloc_strdup(mem_ctx, ntprinter->info_2->parameters);
4191 W_ERROR_HAVE_NO_MEMORY(r->parameters);
4192
4193 r->attributes = ntprinter->info_2->attributes;
4194
4195 r->priority = ntprinter->info_2->priority;
4196 r->defaultpriority = ntprinter->info_2->default_priority;
4197 r->starttime = ntprinter->info_2->starttime;
4198 r->untiltime = ntprinter->info_2->untiltime;
4199 r->status = nt_printq_status(status.status);
4200 r->cjobs = count;
4201 r->averageppm = ntprinter->info_2->averageppm;
4202
4203 r->devmode = construct_dev_mode(mem_ctx, lp_const_servicename(snum));
4204 if (!r->devmode) {
4205 DEBUG(8,("Returning NULL Devicemode!\n"));
4206 }
4207
4208 r->secdesc = NULL;
4209
4210 if (ntprinter->info_2->secdesc_buf && ntprinter->info_2->secdesc_buf->sd_size != 0) {
4211 /* don't use talloc_steal() here unless you do a deep steal of all
4212 the SEC_DESC members */
4213
4214 r->secdesc = dup_sec_desc(mem_ctx, ntprinter->info_2->secdesc_buf->sd);
4215 }
4216
4217 return WERR_OK;
4218 }
4219
4220 /********************************************************************
4221 ********************************************************************/
4222
4223 static bool snum_is_shared_printer(int snum)
/* [<][>][^][v][top][bottom][index][help] */
4224 {
4225 return (lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum));
4226 }
4227
4228 /********************************************************************
4229 Spoolss_enumprinters.
4230 ********************************************************************/
4231
4232 static WERROR enum_all_printers_info_level(TALLOC_CTX *mem_ctx,
/* [<][>][^][v][top][bottom][index][help] */
4233 uint32_t level,
4234 uint32_t flags,
4235 union spoolss_PrinterInfo **info_p,
4236 uint32_t *count_p)
4237 {
4238 int snum;
4239 int n_services = lp_numservices();
4240 union spoolss_PrinterInfo *info = NULL;
4241 uint32_t count = 0;
4242 WERROR result = WERR_OK;
4243
4244 *count_p = 0;
4245 *info_p = NULL;
4246
4247 for (snum = 0; snum < n_services; snum++) {
4248
4249 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4250
4251 if (!snum_is_shared_printer(snum)) {
4252 continue;
4253 }
4254
4255 DEBUG(4,("Found a printer in smb.conf: %s[%x]\n",
4256 lp_servicename(snum), snum));
4257
4258 info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
4259 union spoolss_PrinterInfo,
4260 count + 1);
4261 if (!info) {
4262 result = WERR_NOMEM;
4263 goto out;
4264 }
4265
4266 result = get_a_printer(NULL, &ntprinter, 2,
4267 lp_const_servicename(snum));
4268 if (!W_ERROR_IS_OK(result)) {
4269 goto out;
4270 }
4271
4272 switch (level) {
4273 case 0:
4274 result = construct_printer_info0(info, ntprinter,
4275 &info[count].info0, snum);
4276 break;
4277 case 1:
4278 result = construct_printer_info1(info, ntprinter, flags,
4279 &info[count].info1, snum);
4280 break;
4281 case 2:
4282 result = construct_printer_info2(info, ntprinter,
4283 &info[count].info2, snum);
4284 break;
4285 case 4:
4286 result = construct_printer_info4(info, ntprinter,
4287 &info[count].info4, snum);
4288 break;
4289 case 5:
4290 result = construct_printer_info5(info, ntprinter,
4291 &info[count].info5, snum);
4292 break;
4293
4294 default:
4295 result = WERR_UNKNOWN_LEVEL;
4296 free_a_printer(&ntprinter, 2);
4297 goto out;
4298 }
4299
4300 free_a_printer(&ntprinter, 2);
4301 if (!W_ERROR_IS_OK(result)) {
4302 goto out;
4303 }
4304
4305 count++;
4306 }
4307
4308 *count_p = count;
4309 *info_p = info;
4310
4311 out:
4312 if (!W_ERROR_IS_OK(result)) {
4313 TALLOC_FREE(info);
4314 return result;
4315 }
4316
4317 *info_p = info;
4318
4319 return WERR_OK;
4320 }
4321
4322 /********************************************************************
4323 * handle enumeration of printers at level 0
4324 ********************************************************************/
4325
4326 static WERROR enumprinters_level0(TALLOC_CTX *mem_ctx,
/* [<][>][^][v][top][bottom][index][help] */
4327 uint32_t flags,
4328 const char *servername,
4329 union spoolss_PrinterInfo **info,
4330 uint32_t *count)
4331 {
4332 DEBUG(4,("enum_all_printers_info_0\n"));
4333
4334 return enum_all_printers_info_level(mem_ctx, 0, flags, info, count);
4335 }
4336
4337
4338 /********************************************************************
4339 ********************************************************************/
4340
4341 static WERROR enum_all_printers_info_1(TALLOC_CTX *mem_ctx,
/* [<][>][^][v][top][bottom][index][help] */
4342 uint32_t flags,
4343 union spoolss_PrinterInfo **info,
4344 uint32_t *count)
4345 {
4346 DEBUG(4,("enum_all_printers_info_1\n"));
4347
4348 return enum_all_printers_info_level(mem_ctx, 1, flags, info, count);
4349 }
4350
4351 /********************************************************************
4352 enum_all_printers_info_1_local.
4353 *********************************************************************/
4354
4355 static WERROR enum_all_printers_info_1_local(TALLOC_CTX *mem_ctx,
/* [<][>][^][v][top][bottom][index][help] */
4356 union spoolss_PrinterInfo **info,
4357 uint32_t *count)
4358 {
4359 DEBUG(4,("enum_all_printers_info_1_local\n"));
4360
4361 return enum_all_printers_info_1(mem_ctx, PRINTER_ENUM_ICON8, info, count);
4362 }
4363
4364 /********************************************************************
4365 enum_all_printers_info_1_name.
4366 *********************************************************************/
4367
4368 static WERROR enum_all_printers_info_1_name(TALLOC_CTX *mem_ctx,
/* [<][>][^][v][top][bottom][index][help] */
4369 const char *name,
4370 union spoolss_PrinterInfo **info,
4371 uint32_t *count)
4372 {
4373 const char *s = name;
4374
4375 DEBUG(4,("enum_all_printers_info_1_name\n"));
4376
4377 if ((name[0] == '\\') && (name[1] == '\\')) {
4378 s = name + 2;
4379 }
4380
4381 if (!is_myname_or_ipaddr(s)) {
4382 return WERR_INVALID_NAME;
4383 }
4384
4385 return enum_all_printers_info_1(mem_ctx, PRINTER_ENUM_ICON8, info, count);
4386 }
4387
4388 /********************************************************************
4389 enum_all_printers_info_1_network.
4390 *********************************************************************/
4391
4392 static WERROR enum_all_printers_info_1_network(TALLOC_CTX *mem_ctx,
/* [<][>][^][v][top][bottom][index][help] */
4393 const char *name,
4394 union spoolss_PrinterInfo **info,
4395 uint32_t *count)
4396 {
4397 const char *s = name;
4398
4399 DEBUG(4,("enum_all_printers_info_1_network\n"));
4400
4401 /* If we respond to a enum_printers level 1 on our name with flags
4402 set to PRINTER_ENUM_REMOTE with a list of printers then these
4403 printers incorrectly appear in the APW browse list.
4404 Specifically the printers for the server appear at the workgroup
4405 level where all the other servers in the domain are
4406 listed. Windows responds to this call with a
4407 WERR_CAN_NOT_COMPLETE so we should do the same. */
4408
4409 if (name[0] == '\\' && name[1] == '\\') {
4410 s = name + 2;
4411 }
4412
4413 if (is_myname_or_ipaddr(s)) {
4414 return WERR_CAN_NOT_COMPLETE;
4415 }
4416
4417 return enum_all_printers_info_1(mem_ctx, PRINTER_ENUM_NAME, info, count);
4418 }
4419
4420 /********************************************************************
4421 * api_spoolss_enumprinters
4422 *
4423 * called from api_spoolss_enumprinters (see this to understand)
4424 ********************************************************************/
4425
4426 static WERROR enum_all_printers_info_2(TALLOC_CTX *mem_ctx,
/* [<][>][^][v][top][bottom][index][help] */
4427 union spoolss_PrinterInfo **info,
4428 uint32_t *count)
4429 {
4430 DEBUG(4,("enum_all_printers_info_2\n"));
4431
4432 return enum_all_printers_info_level(mem_ctx, 2, 0, info, count);
4433 }
4434
4435 /********************************************************************
4436 * handle enumeration of printers at level 1
4437 ********************************************************************/
4438
4439 static WERROR enumprinters_level1(TALLOC_CTX *mem_ctx,
/* [<][>][^][v][top][bottom][index][help] */
4440 uint32_t flags,
4441 const char *name,
4442 union spoolss_PrinterInfo **info,
4443 uint32_t *count)
4444 {
4445 /* Not all the flags are equals */
4446
4447 if (flags & PRINTER_ENUM_LOCAL) {
4448 return enum_all_printers_info_1_local(mem_ctx, info, count);
4449 }
4450
4451 if (flags & PRINTER_ENUM_NAME) {
4452 return enum_all_printers_info_1_name(mem_ctx, name, info, count);
4453 }
4454
4455 if (flags & PRINTER_ENUM_NETWORK) {
4456 return enum_all_printers_info_1_network(mem_ctx, name, info, count);
4457 }
4458
4459 return WERR_OK; /* NT4sp5 does that */
4460 }
4461
4462 /********************************************************************
4463 * handle enumeration of printers at level 2
4464 ********************************************************************/
4465
4466 static WERROR enumprinters_level2(TALLOC_CTX *mem_ctx,
/* [<][>][^][v][top][bottom][index][help] */
4467 uint32_t flags,
4468 const char *servername,
4469 union spoolss_PrinterInfo **info,
4470 uint32_t *count)
4471 {
4472 if (flags & PRINTER_ENUM_LOCAL) {
4473 return enum_all_printers_info_2(mem_ctx, info, count);
4474 }
4475
4476 if (flags & PRINTER_ENUM_NAME) {
4477 if (!is_myname_or_ipaddr(canon_servername(servername))) {
4478 return WERR_INVALID_NAME;
4479 }
4480
4481 return enum_all_printers_info_2(mem_ctx, info, count);
4482 }
4483
4484 if (flags & PRINTER_ENUM_REMOTE) {
4485 return WERR_UNKNOWN_LEVEL;
4486 }
4487
4488 return WERR_OK;
4489 }
4490
4491 /********************************************************************
4492 * handle enumeration of printers at level 4
4493 ********************************************************************/
4494
4495 static WERROR enumprinters_level4(TALLOC_CTX *mem_ctx,
/* [<][>][^][v][top][bottom][index][help] */
4496 uint32_t flags,
4497 const char *servername,
4498 union spoolss_PrinterInfo **info,
4499 uint32_t *count)
4500 {
4501 DEBUG(4,("enum_all_printers_info_4\n"));
4502
4503 return enum_all_printers_info_level(mem_ctx, 4, flags, info, count);
4504 }
4505
4506
4507 /********************************************************************
4508 * handle enumeration of printers at level 5
4509 ********************************************************************/
4510
4511 static WERROR enumprinters_level5(TALLOC_CTX *mem_ctx,
/* [<][>][^][v][top][bottom][index][help] */
4512 uint32_t flags,
4513 const char *servername,
4514 union spoolss_PrinterInfo **info,
4515 uint32_t *count)
4516 {
4517 DEBUG(4,("enum_all_printers_info_5\n"));
4518
4519 return enum_all_printers_info_level(mem_ctx, 5, flags, info, count);
4520 }
4521
4522 /****************************************************************
4523 _spoolss_EnumPrinters
4524 ****************************************************************/
4525
4526 WERROR _spoolss_EnumPrinters(pipes_struct *p,
/* [<][>][^][v][top][bottom][index][help] */
4527 struct spoolss_EnumPrinters *r)
4528 {
4529 const char *name;
4530 WERROR result;
4531
4532 /* that's an [in out] buffer */
4533
4534 if (!r->in.buffer && (r->in.offered != 0)) {
4535 return WERR_INVALID_PARAM;
4536 }
4537
4538 DEBUG(4,("_spoolss_EnumPrinters\n"));
4539
4540 *r->out.needed = 0;
4541 *r->out.count = 0;
4542 *r->out.info = NULL;
4543
4544 /*
4545 * Level 1:
4546 * flags==PRINTER_ENUM_NAME
4547 * if name=="" then enumerates all printers
4548 * if name!="" then enumerate the printer
4549 * flags==PRINTER_ENUM_REMOTE
4550 * name is NULL, enumerate printers
4551 * Level 2: name!="" enumerates printers, name can't be NULL
4552 * Level 3: doesn't exist
4553 * Level 4: does a local registry lookup
4554 * Level 5: same as Level 2
4555 */
4556
4557 name = talloc_strdup_upper(p->mem_ctx, r->in.server);
4558 W_ERROR_HAVE_NO_MEMORY(name);
4559
4560 switch (r->in.level) {
4561 case 0:
4562 result = enumprinters_level0(p->mem_ctx, r->in.flags, name,
4563 r->out.info, r->out.count);
4564 break;
4565 case 1:
4566 result = enumprinters_level1(p->mem_ctx, r->in.flags, name,
4567 r->out.info, r->out.count);
4568 break;
4569 case 2:
4570 result = enumprinters_level2(p->mem_ctx, r->in.flags, name,
4571 r->out.info, r->out.count);
4572 break;
4573 case 4:
4574 result = enumprinters_level4(p->mem_ctx, r->in.flags, name,
4575 r->out.info, r->out.count);
4576 break;
4577 case 5:
4578 result = enumprinters_level5(p->mem_ctx, r->in.flags, name,
4579 r->out.info, r->out.count);
4580 break;
4581 default:
4582 return WERR_UNKNOWN_LEVEL;
4583 }
4584
4585 if (!W_ERROR_IS_OK(result)) {
4586 return result;
4587 }
4588
4589 *r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
4590 spoolss_EnumPrinters, NULL,
4591 *r->out.info, r->in.level,
4592 *r->out.count);
4593 *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
4594 *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, 0);
4595
4596 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
4597 }
4598
4599 /****************************************************************
4600 _spoolss_GetPrinter
4601 ****************************************************************/
4602
4603 WERROR _spoolss_GetPrinter(pipes_struct *p,
/* [<][>][^][v][top][bottom][index][help] */
4604 struct spoolss_GetPrinter *r)
4605 {
4606 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
4607 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4608 WERROR result = WERR_OK;
4609
4610 int snum;
4611
4612 /* that's an [in out] buffer */
4613
4614 if (!r->in.buffer && (r->in.offered != 0)) {
4615 return WERR_INVALID_PARAM;
4616 }
4617
4618 *r->out.needed = 0;
4619
4620 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
4621 return WERR_BADFID;
4622 }
4623
4624 result = get_a_printer(Printer, &ntprinter, 2,
4625 lp_const_servicename(snum));
4626 if (!W_ERROR_IS_OK(result)) {
4627 return result;
4628 }
4629
4630 switch (r->in.level) {
4631 case 0:
4632 result = construct_printer_info0(p->mem_ctx, ntprinter,
4633 &r->out.info->info0, snum);
4634 break;
4635 case 1:
4636 result = construct_printer_info1(p->mem_ctx, ntprinter,
4637 PRINTER_ENUM_ICON8,
4638 &r->out.info->info1, snum);
4639 break;
4640 case 2:
4641 result = construct_printer_info2(p->mem_ctx, ntprinter,
4642 &r->out.info->info2, snum);
4643 break;
4644 case 3:
4645 result = construct_printer_info3(p->mem_ctx, ntprinter,
4646 &r->out.info->info3, snum);
4647 break;
4648 case 4:
4649 result = construct_printer_info4(p->mem_ctx, ntprinter,
4650 &r->out.info->info4, snum);
4651 break;
4652 case 5:
4653 result = construct_printer_info5(p->mem_ctx, ntprinter,
4654 &r->out.info->info5, snum);
4655 break;
4656 case 6:
4657 result = construct_printer_info6(p->mem_ctx, ntprinter,
4658 &r->out.info->info6, snum);
4659 break;
4660 case 7:
4661 result = construct_printer_info7(p->mem_ctx, Printer,
4662 &r->out.info->info7, snum);
4663 break;
4664 case 8:
4665 result = construct_printer_info8(p->mem_ctx, ntprinter,
4666 &r->out.info->info8, snum);
4667 break;
4668 default:
4669 result = WERR_UNKNOWN_LEVEL;
4670 break;
4671 }
4672
4673 free_a_printer(&ntprinter, 2);
4674
4675 if (!W_ERROR_IS_OK(result)) {
4676 TALLOC_FREE(r->out.info);
4677 return result;
4678 }
4679
4680 *r->out.needed = SPOOLSS_BUFFER_UNION(spoolss_PrinterInfo, NULL,
4681 r->out.info, r->in.level);
4682 r->out.info = SPOOLSS_BUFFER_OK(r->out.info, NULL);
4683
4684 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
4685 }
4686
4687 /********************************************************************
4688 ********************************************************************/
4689
4690 static const char **string_array_from_driver_info(TALLOC_CTX *mem_ctx,
/* [<][>][^][v][top][bottom][index][help] */
4691 fstring *fstring_array,
4692 const char *cservername)
4693 {
4694 int i, num_strings = 0;
4695 const char **array = NULL;
4696
4697 for (i=0; fstring_array && fstring_array[i][0] != '\0'; i++) {
4698
4699 const char *str = talloc_asprintf(mem_ctx, "\\\\%s%s",
4700 cservername, fstring_array[i]);
4701 if (!str) {
4702 TALLOC_FREE(array);
4703 return NULL;
4704 }
4705
4706
4707 if (!add_string_to_array(mem_ctx, str, &array, &num_strings)) {
4708 TALLOC_FREE(array);
4709 return NULL;
4710 }
4711 }
4712
4713 if (i > 0) {
4714 ADD_TO_ARRAY(mem_ctx, const char *, NULL,
4715 &array, &num_strings);
4716 }
4717
4718 return array;
4719 }
4720
4721 /********************************************************************
4722 * fill a spoolss_DriverInfo1 struct
4723 ********************************************************************/
4724
4725 static WERROR fill_printer_driver_info1(TALLOC_CTX *mem_ctx,
/* [<][>][^][v][top][bottom][index][help] */
4726 struct spoolss_DriverInfo1 *r,
4727 const NT_PRINTER_DRIVER_INFO_LEVEL *driver,
4728 const char *servername,
4729 const char *architecture)
4730 {
4731 r->driver_name = talloc_strdup(mem_ctx, driver->info_3->name);
4732 W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4733
4734 return WERR_OK;
4735 }
4736
4737 /********************************************************************
4738 * fill a spoolss_DriverInfo2 struct
4739 ********************************************************************/
4740
4741 static WERROR fill_printer_driver_info2(TALLOC_CTX *mem_ctx,
/* [<][>][^][v][top][bottom][index][help] */
4742 struct spoolss_DriverInfo2 *r,
4743 const NT_PRINTER_DRIVER_INFO_LEVEL *driver,
4744 const char *servername)
4745
4746 {
4747 const char *cservername = canon_servername(servername);
4748
4749 r->version = driver->info_3->cversion;
4750
4751 r->driver_name = talloc_strdup(mem_ctx, driver->info_3->name);
4752 W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4753 r->architecture = talloc_strdup(mem_ctx, driver->info_3->environment);
4754 W_ERROR_HAVE_NO_MEMORY(r->architecture);
4755
4756 if (strlen(driver->info_3->driverpath)) {
4757 r->driver_path = talloc_asprintf(mem_ctx, "\\\\%s%s",
4758 cservername, driver->info_3->driverpath);
4759 } else {
4760 r->driver_path = talloc_strdup(mem_ctx, "");
4761 }
4762 W_ERROR_HAVE_NO_MEMORY(r->driver_path);
4763
4764 if (strlen(driver->info_3->datafile)) {
4765 r->data_file = talloc_asprintf(mem_ctx, "\\\\%s%s",
4766 cservername, driver->info_3->datafile);
4767 } else {
4768 r->data_file = talloc_strdup(mem_ctx, "");
4769 }
4770 W_ERROR_HAVE_NO_MEMORY(r->data_file);
4771
4772 if (strlen(driver->info_3->configfile)) {
4773 r->config_file = talloc_asprintf(mem_ctx, "\\\\%s%s",
4774 cservername, driver->info_3->configfile);
4775 } else {
4776 r->config_file = talloc_strdup(mem_ctx, "");
4777 }
4778 W_ERROR_HAVE_NO_MEMORY(r->config_file);
4779
4780 return WERR_OK;
4781 }
4782
4783 /********************************************************************
4784 * fill a spoolss_DriverInfo3 struct
4785 ********************************************************************/
4786
4787 static WERROR fill_printer_driver_info3(TALLOC_CTX *mem_ctx,
/* [<][>][^][v][top][bottom][index][help] */
4788 struct spoolss_DriverInfo3 *r,
4789 const NT_PRINTER_DRIVER_INFO_LEVEL *driver,
4790 const char *servername)
4791 {
4792 const char *cservername = canon_servername(servername);
4793
4794 r->version = driver->info_3->cversion;
4795
4796 r->driver_name = talloc_strdup(mem_ctx, driver->info_3->name);
4797 W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4798 r->architecture = talloc_strdup(mem_ctx, driver->info_3->environment);
4799 W_ERROR_HAVE_NO_MEMORY(r->architecture);
4800
4801 if (strlen(driver->info_3->driverpath)) {
4802 r->driver_path = talloc_asprintf(mem_ctx, "\\\\%s%s",
4803 cservername, driver->info_3->driverpath);
4804 } else {
4805 r->driver_path = talloc_strdup(mem_ctx, "");
4806 }
4807 W_ERROR_HAVE_NO_MEMORY(r->driver_path);
4808
4809 if (strlen(driver->info_3->datafile)) {
4810 r->data_file = talloc_asprintf(mem_ctx, "\\\\%s%s",
4811 cservername, driver->info_3->datafile);
4812 } else {
4813 r->data_file = talloc_strdup(mem_ctx, "");
4814 }
4815 W_ERROR_HAVE_NO_MEMORY(r->data_file);
4816
4817 if (strlen(driver->info_3->configfile)) {
4818 r->config_file = talloc_asprintf(mem_ctx, "\\\\%s%s",
4819 cservername, driver->info_3->configfile);
4820 } else {
4821 r->config_file = talloc_strdup(mem_ctx, "");
4822 }
4823 W_ERROR_HAVE_NO_MEMORY(r->config_file);
4824
4825 if (strlen(driver->info_3->helpfile)) {
4826 r->help_file = talloc_asprintf(mem_ctx, "\\\\%s%s",
4827 cservername, driver->info_3->helpfile);
4828 } else {
4829 r->help_file = talloc_strdup(mem_ctx, "");
4830 }
4831 W_ERROR_HAVE_NO_MEMORY(r->help_file);
4832
4833 r->monitor_name = talloc_strdup(mem_ctx, driver->info_3->monitorname);
4834 W_ERROR_HAVE_NO_MEMORY(r->monitor_name);
4835 r->default_datatype = talloc_strdup(mem_ctx, driver->info_3->defaultdatatype);
4836 W_ERROR_HAVE_NO_MEMORY(r->default_datatype);
4837
4838 r->dependent_files = string_array_from_driver_info(mem_ctx,
4839 driver->info_3->dependentfiles,
4840 cservername);
4841 return WERR_OK;
4842 }
4843
4844 /********************************************************************
4845 * fill a spoolss_DriverInfo4 struct
4846 ********************************************************************/
4847
4848 static WERROR fill_printer_driver_info4(TALLOC_CTX *mem_ctx,
/* [<][>][^][v][top][bottom][index][help] */
4849 struct spoolss_DriverInfo4 *r,
4850 const NT_PRINTER_DRIVER_INFO_LEVEL *driver,
4851 const char *servername)
4852 {
4853 const char *cservername = canon_servername(servername);
4854
4855 r->version = driver->info_3->cversion;
4856
4857 r->driver_name = talloc_strdup(mem_ctx, driver->info_3->name);
4858 W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4859 r->architecture = talloc_strdup(mem_ctx, driver->info_3->environment);
4860 W_ERROR_HAVE_NO_MEMORY(r->architecture);
4861
4862 if (strlen(driver->info_3->driverpath)) {
4863 r->driver_path = talloc_asprintf(mem_ctx, "\\\\%s%s",
4864 cservername, driver->info_3->driverpath);
4865 } else {
4866 r->driver_path = talloc_strdup(mem_ctx, "");
4867 }
4868 W_ERROR_HAVE_NO_MEMORY(r->driver_path);
4869
4870 if (strlen(driver->info_3->datafile)) {
4871 r->data_file = talloc_asprintf(mem_ctx, "\\\\%s%s",
4872 cservername, driver->info_3->datafile);
4873 } else {
4874 r->data_file = talloc_strdup(mem_ctx, "");
4875 }
4876 W_ERROR_HAVE_NO_MEMORY(r->data_file);
4877
4878 if (strlen(driver->info_3->configfile)) {
4879 r->config_file = talloc_asprintf(mem_ctx, "\\\\%s%s",
4880 cservername, driver->info_3->configfile);
4881 } else {
4882 r->config_file = talloc_strdup(mem_ctx, "");
4883 }
4884 W_ERROR_HAVE_NO_MEMORY(r->config_file);
4885
4886 if (strlen(driver->info_3->helpfile)) {
4887 r->help_file = talloc_asprintf(mem_ctx, "\\\\%s%s",
4888 cservername, driver->info_3->helpfile);
4889 } else {
4890 r->help_file = talloc_strdup(mem_ctx, "");
4891 }
4892 W_ERROR_HAVE_NO_MEMORY(r->help_file);
4893
4894 r->dependent_files = string_array_from_driver_info(mem_ctx,
4895 driver->info_3->dependentfiles,
4896 cservername);
4897
4898
4899 r->monitor_name = talloc_strdup(mem_ctx, driver->info_3->monitorname);
4900 W_ERROR_HAVE_NO_MEMORY(r->monitor_name);
4901 r->default_datatype = talloc_strdup(mem_ctx, driver->info_3->defaultdatatype);
4902 W_ERROR_HAVE_NO_MEMORY(r->default_datatype);
4903
4904 r->previous_names = string_array_from_driver_info(mem_ctx,
4905 NULL,
4906 cservername);
4907
4908 return WERR_OK;
4909 }
4910
4911 /********************************************************************
4912 * fill a spoolss_DriverInfo5 struct
4913 ********************************************************************/
4914
4915 static WERROR fill_printer_driver_info5(TALLOC_CTX *mem_ctx,
/* [<][>][^][v][top][bottom][index][help] */
4916 struct spoolss_DriverInfo5 *r,
4917 const NT_PRINTER_DRIVER_INFO_LEVEL *driver,
4918 const char *servername)
4919 {
4920 const char *cservername = canon_servername(servername);
4921
4922 r->version = driver->info_3->cversion;
4923
4924 r->driver_name = talloc_strdup(mem_ctx, driver->info_3->name);
4925 W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4926 r->architecture = talloc_strdup(mem_ctx, driver->info_3->environment);
4927 W_ERROR_HAVE_NO_MEMORY(r->architecture);
4928
4929 if (strlen(driver->info_3->driverpath)) {
4930 r->driver_path = talloc_asprintf(mem_ctx, "\\\\%s%s",
4931 cservername, driver->info_3->driverpath);
4932 } else {
4933 r->driver_path = talloc_strdup(mem_ctx, "");
4934 }
4935 W_ERROR_HAVE_NO_MEMORY(r->driver_path);
4936
4937 if (strlen(driver->info_3->datafile)) {
4938 r->data_file = talloc_asprintf(mem_ctx, "\\\\%s%s",
4939 cservername, driver->info_3->datafile);
4940 } else {
4941 r->data_file = talloc_strdup(mem_ctx, "");
4942 }
4943 W_ERROR_HAVE_NO_MEMORY(r->data_file);
4944
4945 if (strlen(driver->info_3->configfile)) {
4946 r->config_file = talloc_asprintf(mem_ctx, "\\\\%s%s",
4947 cservername, driver->info_3->configfile);
4948 } else {
4949 r->config_file = talloc_strdup(mem_ctx, "");
4950 }
4951 W_ERROR_HAVE_NO_MEMORY(r->config_file);
4952
4953 r->driver_attributes = 0;
4954 r->config_version = 0;
4955 r->driver_version = 0;
4956
4957 return WERR_OK;
4958 }
4959 /********************************************************************
4960 * fill a spoolss_DriverInfo6 struct
4961 ********************************************************************/
4962
4963 static WERROR fill_printer_driver_info6(TALLOC_CTX *mem_ctx,
/* [<][>][^][v][top][bottom][index][help] */
4964 struct spoolss_DriverInfo6 *r,
4965 const NT_PRINTER_DRIVER_INFO_LEVEL *driver,
4966 const char *servername)
4967 {
4968 const char *cservername = canon_servername(servername);
4969
4970 r->version = driver->info_3->cversion;
4971
4972 r->driver_name = talloc_strdup(mem_ctx, driver->info_3->name);
4973 W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4974 r->architecture = talloc_strdup(mem_ctx, driver->info_3->environment);
4975 W_ERROR_HAVE_NO_MEMORY(r->architecture);
4976
4977 if (strlen(driver->info_3->driverpath)) {
4978 r->driver_path = talloc_asprintf(mem_ctx, "\\\\%s%s",
4979 cservername, driver->info_3->driverpath);
4980 } else {
4981 r->driver_path = talloc_strdup(mem_ctx, "");
4982 }
4983 W_ERROR_HAVE_NO_MEMORY(r->driver_path);
4984
4985 if (strlen(driver->info_3->datafile)) {
4986 r->data_file = talloc_asprintf(mem_ctx, "\\\\%s%s",
4987 cservername, driver->info_3->datafile);
4988 } else {
4989 r->data_file = talloc_strdup(mem_ctx, "");
4990 }
4991 W_ERROR_HAVE_NO_MEMORY(r->data_file);
4992
4993 if (strlen(driver->info_3->configfile)) {
4994 r->config_file = talloc_asprintf(mem_ctx, "\\\\%s%s",
4995 cservername, driver->info_3->configfile);
4996 } else {
4997 r->config_file = talloc_strdup(mem_ctx, "");
4998 }
4999 W_ERROR_HAVE_NO_MEMORY(r->config_file);
5000
5001 if (strlen(driver->info_3->helpfile)) {
5002 r->help_file = talloc_asprintf(mem_ctx, "\\\\%s%s",
5003 cservername, driver->info_3->helpfile);
5004 } else {
5005 r->help_file = talloc_strdup(mem_ctx, "");
5006 }
5007 W_ERROR_HAVE_NO_MEMORY(r->help_file);
5008
5009 r->monitor_name = talloc_strdup(mem_ctx, driver->info_3->monitorname);
5010 W_ERROR_HAVE_NO_MEMORY(r->monitor_name);
5011 r->default_datatype = talloc_strdup(mem_ctx, driver->info_3->defaultdatatype);
5012 W_ERROR_HAVE_NO_MEMORY(r->default_datatype);
5013
5014 r->dependent_files = string_array_from_driver_info(mem_ctx,
5015 driver->info_3->dependentfiles,
5016 cservername);
5017 r->previous_names = string_array_from_driver_info(mem_ctx,
5018 NULL,
5019 cservername);
5020
5021 r->driver_date = 0;
5022 r->driver_version = 0;
5023
5024 r->manufacturer_name = talloc_strdup(mem_ctx, "");
5025 W_ERROR_HAVE_NO_MEMORY(r->manufacturer_name);
5026 r->manufacturer_url = talloc_strdup(mem_ctx, "");
5027 W_ERROR_HAVE_NO_MEMORY(r->manufacturer_url);
5028 r->hardware_id = talloc_strdup(mem_ctx, "");
5029 W_ERROR_HAVE_NO_MEMORY(r->hardware_id);
5030 r->provider = talloc_strdup(mem_ctx, "");
5031 W_ERROR_HAVE_NO_MEMORY(r->provider);
5032
5033 return WERR_OK;
5034 }
5035
5036 /********************************************************************
5037 ********************************************************************/
5038
5039 static WERROR fill_spoolss_DriverFileInfo(TALLOC_CTX *mem_ctx,
/* [<][>][^][v][top][bottom][index][help] */
5040 struct spoolss_DriverFileInfo *r,
5041 const char *cservername,
5042 const char *file_name,
5043 enum spoolss_DriverFileType file_type,
5044 uint32_t file_version)
5045 {
5046 r->file_name = talloc_asprintf(mem_ctx, "\\\\%s%s",
5047 cservername, file_name);
5048 W_ERROR_HAVE_NO_MEMORY(r->file_name);
5049 r->file_type = file_type;
5050 r->file_version = file_version;
5051
5052 return WERR_OK;
5053 }
5054
5055 /********************************************************************
5056 ********************************************************************/
5057
5058 static WERROR spoolss_DriverFileInfo_from_driver(TALLOC_CTX *mem_ctx,
/* [<][>][^][v][top][bottom][index][help] */
5059 const NT_PRINTER_DRIVER_INFO_LEVEL *driver,
5060 const char *cservername,
5061 struct spoolss_DriverFileInfo **info_p,
5062 uint32_t *count_p)
5063 {
5064 struct spoolss_DriverFileInfo *info = NULL;
5065 uint32_t count = 0;
5066 WERROR result;
5067 uint32_t i;
5068
5069 *info_p = NULL;
5070 *count_p = 0;
5071
5072 if (strlen(driver->info_3->driverpath)) {
5073 info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
5074 struct spoolss_DriverFileInfo,
5075 count + 1);
5076 W_ERROR_HAVE_NO_MEMORY(info);
5077 result = fill_spoolss_DriverFileInfo(info,
5078 &info[count],
5079 cservername,
5080 driver->info_3->driverpath,
5081 SPOOLSS_DRIVER_FILE_TYPE_RENDERING,
5082 0);
5083 W_ERROR_NOT_OK_RETURN(result);
5084 count++;
5085 }
5086
5087 if (strlen(driver->info_3->configfile)) {
5088 info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
5089 struct spoolss_DriverFileInfo,
5090 count + 1);
5091 W_ERROR_HAVE_NO_MEMORY(info);
5092 result = fill_spoolss_DriverFileInfo(info,
5093 &info[count],
5094 cservername,
5095 driver->info_3->configfile,
5096 SPOOLSS_DRIVER_FILE_TYPE_CONFIGURATION,
5097 0);
5098 W_ERROR_NOT_OK_RETURN(result);
5099 count++;
5100 }
5101
5102 if (strlen(driver->info_3->datafile)) {
5103 info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
5104 struct spoolss_DriverFileInfo,
5105 count + 1);
5106 W_ERROR_HAVE_NO_MEMORY(info);
5107 result = fill_spoolss_DriverFileInfo(info,
5108 &info[count],
5109 cservername,
5110 driver->info_3->datafile,
5111 SPOOLSS_DRIVER_FILE_TYPE_DATA,
5112 0);
5113 W_ERROR_NOT_OK_RETURN(result);
5114 count++;
5115 }
5116
5117 if (strlen(driver->info_3->helpfile)) {
5118 info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
5119 struct spoolss_DriverFileInfo,
5120 count + 1);
5121 W_ERROR_HAVE_NO_MEMORY(info);
5122 result = fill_spoolss_DriverFileInfo(info,
5123 &info[count],
5124 cservername,
5125 driver->info_3->helpfile,
5126 SPOOLSS_DRIVER_FILE_TYPE_HELP,
5127 0);
5128 W_ERROR_NOT_OK_RETURN(result);
5129 count++;
5130 }
5131
5132 for (i=0; driver->info_3->dependentfiles[i][0] != '\0'; i++) {
5133 info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
5134 struct spoolss_DriverFileInfo,
5135 count + 1);
5136 W_ERROR_HAVE_NO_MEMORY(info);
5137 result = fill_spoolss_DriverFileInfo(info,
5138 &info[count],
5139 cservername,
5140 driver->info_3->dependentfiles[i],
5141 SPOOLSS_DRIVER_FILE_TYPE_OTHER,
5142 0);
5143 W_ERROR_NOT_OK_RETURN(result);
5144 count++;
5145 }
5146
5147 *info_p = info;
5148 *count_p = count;
5149
5150 return WERR_OK;
5151 }
5152
5153 /********************************************************************
5154 * fill a spoolss_DriverInfo101 sttruct
5155 ********************************************************************/
5156
5157 static WERROR fill_printer_driver_info101(TALLOC_CTX *mem_ctx,
/* [<][>][^][v][top][bottom][index][help] */
5158 struct spoolss_DriverInfo101 *r,
5159 const NT_PRINTER_DRIVER_INFO_LEVEL *driver,
5160 const char *servername)
5161 {
5162 const char *cservername = canon_servername(servername);
5163 WERROR result;
5164
5165 r->version = driver->info_3->cversion;
5166
5167 r->driver_name = talloc_strdup(mem_ctx, driver->info_3->name);
5168 W_ERROR_HAVE_NO_MEMORY(r->driver_name);
5169 r->architecture = talloc_strdup(mem_ctx, driver->info_3->environment);
5170 W_ERROR_HAVE_NO_MEMORY(r->architecture);
5171
5172 result = spoolss_DriverFileInfo_from_driver(mem_ctx, driver,
5173 cservername,
5174 &r->file_info,
5175 &r->file_count);
5176 if (!W_ERROR_IS_OK(result)) {
5177 return result;
5178 }
5179
5180 r->monitor_name = talloc_strdup(mem_ctx, driver->info_3->monitorname);
5181 W_ERROR_HAVE_NO_MEMORY(r->monitor_name);
5182
5183 r->default_datatype = talloc_strdup(mem_ctx, driver->info_3->defaultdatatype);
5184 W_ERROR_HAVE_NO_MEMORY(r->default_datatype);
5185
5186 r->previous_names = string_array_from_driver_info(mem_ctx,
5187 NULL,
5188 cservername);
5189 r->driver_date = 0;
5190 r->driver_version = 0;
5191
5192 r->manufacturer_name = talloc_strdup(mem_ctx, "");
5193 W_ERROR_HAVE_NO_MEMORY(r->manufacturer_name);
5194 r->manufacturer_url = talloc_strdup(mem_ctx, "");
5195 W_ERROR_HAVE_NO_MEMORY(r->manufacturer_url);
5196 r->hardware_id = talloc_strdup(mem_ctx, "");
5197 W_ERROR_HAVE_NO_MEMORY(r->hardware_id);
5198 r->provider = talloc_strdup(mem_ctx, "");
5199 W_ERROR_HAVE_NO_MEMORY(r->provider);
5200
5201 return WERR_OK;
5202 }
5203
5204 /********************************************************************
5205 * construct_printer_driver_info_1
5206 ********************************************************************/
5207
5208 static WERROR construct_printer_driver_info_1(TALLOC_CTX *mem_ctx,
/* [<][>][^][v][top][bottom][index][help] */
5209 struct spoolss_DriverInfo1 *r,
5210 int snum,
5211 const char *servername,
5212 const char *architecture,
5213 uint32_t version)
5214 {
5215 NT_PRINTER_INFO_LEVEL *printer = NULL;
5216 NT_PRINTER_DRIVER_INFO_LEVEL driver;
5217 WERROR result;
5218
5219 ZERO_STRUCT(driver);
5220
5221 if (!W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, lp_const_servicename(snum))))
5222 return WERR_INVALID_PRINTER_NAME;
5223
5224 if (!W_ERROR_IS_OK(get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version))) {
5225 free_a_printer(&printer, 2);
5226 return WERR_UNKNOWN_PRINTER_DRIVER;
5227 }
5228
5229 result = fill_printer_driver_info1(mem_ctx, r, &driver, servername, architecture);
5230
5231 free_a_printer(&printer,2);
5232
5233 return result;
5234 }
5235
5236 /********************************************************************
5237 * construct_printer_driver_info_2
5238 * fill a printer_info_2 struct
5239 ********************************************************************/
5240
5241 static WERROR construct_printer_driver_info_2(TALLOC_CTX *mem_ctx,
/* [<][>][^][v][top][bottom][index][help] */
5242 struct spoolss_DriverInfo2 *r,
5243 int snum,
5244 const char *servername,
5245 const char *architecture,
5246 uint32_t version)
5247 {
5248 NT_PRINTER_INFO_LEVEL *printer = NULL;
5249 NT_PRINTER_DRIVER_INFO_LEVEL driver;
5250 WERROR result;
5251
5252 ZERO_STRUCT(printer);
5253 ZERO_STRUCT(driver);
5254
5255 if (!W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, lp_const_servicename(snum))))
5256 return WERR_INVALID_PRINTER_NAME;
5257
5258 if (!W_ERROR_IS_OK(get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version))) {
5259 free_a_printer(&printer, 2);
5260 return WERR_UNKNOWN_PRINTER_DRIVER;
5261 }
5262
5263 result = fill_printer_driver_info2(mem_ctx, r, &driver, servername);
5264
5265 free_a_printer(&printer,2);
5266
5267 return result;
5268 }
5269
5270 /********************************************************************
5271 * construct_printer_info_3
5272 * fill a printer_info_3 struct
5273 ********************************************************************/
5274
5275 static WERROR construct_printer_driver_info_3(TALLOC_CTX *mem_ctx,
/* [<][>][^][v][top][bottom][index][help] */
5276 struct spoolss_DriverInfo3 *r,
5277 int snum,
5278 const char *servername,
5279 const char *architecture,
5280 uint32_t version)
5281 {
5282 NT_PRINTER_INFO_LEVEL *printer = NULL;
5283 NT_PRINTER_DRIVER_INFO_LEVEL driver;
5284 WERROR status;
5285 ZERO_STRUCT(driver);
5286
5287 status=get_a_printer(NULL, &printer, 2, lp_const_servicename(snum) );
5288 DEBUG(8,("construct_printer_driver_info_3: status: %s\n", win_errstr(status)));
5289 if (!W_ERROR_IS_OK(status))
5290 return WERR_INVALID_PRINTER_NAME;
5291
5292 status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
5293 DEBUG(8,("construct_printer_driver_info_3: status: %s\n", win_errstr(status)));
5294
5295 #if 0 /* JERRY */
5296
5297 /*
5298 * I put this code in during testing. Helpful when commenting out the
5299 * support for DRIVER_INFO_6 in regards to win2k. Not needed in general
5300 * as win2k always queries the driver using an infor level of 6.
5301 * I've left it in (but ifdef'd out) because I'll probably
5302 * use it in experimentation again in the future. --jerry 22/01/2002
5303 */
5304
5305 if (!W_ERROR_IS_OK(status)) {
5306 /*
5307 * Is this a W2k client ?
5308 */
5309 if (version == 3) {
5310 /* Yes - try again with a WinNT driver. */
5311 version = 2;
5312 status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
5313 DEBUG(8,("construct_printer_driver_info_3: status: %s\n", win_errstr(status)));
5314 }
5315 #endif
5316
5317 if (!W_ERROR_IS_OK(status)) {
5318 free_a_printer(&printer,2);
5319 return WERR_UNKNOWN_PRINTER_DRIVER;
5320 }
5321
5322 #if 0 /* JERRY */
5323 }
5324 #endif
5325
5326
5327 status = fill_printer_driver_info3(mem_ctx, r, &driver, servername);
5328
5329 free_a_printer(&printer,2);
5330
5331 return status;
5332 }
5333
5334 /********************************************************************
5335 * construct_printer_info_6
5336 * fill a printer_info_6 struct
5337 ********************************************************************/
5338
5339 static WERROR construct_printer_driver_info_6(TALLOC_CTX *mem_ctx,
/* [<][>][^][v][top][bottom][index][help] */
5340 struct spoolss_DriverInfo6 *r,
5341 int snum,
5342 const char *servername,
5343 const char *architecture,
5344 uint32_t version)
5345 {
5346 NT_PRINTER_INFO_LEVEL *printer = NULL;
5347 NT_PRINTER_DRIVER_INFO_LEVEL driver;
5348 WERROR status;
5349
5350 ZERO_STRUCT(driver);
5351
5352 status=get_a_printer(NULL, &printer, 2, lp_const_servicename(snum) );
5353
5354 DEBUG(8,("construct_printer_driver_info_6: status: %s\n", win_errstr(status)));
5355
5356 if (!W_ERROR_IS_OK(status))
5357 return WERR_INVALID_PRINTER_NAME;
5358
5359 status = get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
5360
5361 DEBUG(8,("construct_printer_driver_info_6: status: %s\n", win_errstr(status)));
5362
5363 if (!W_ERROR_IS_OK(status))
5364 {
5365 /*
5366 * Is this a W2k client ?
5367 */
5368
5369 if (version < 3) {
5370 free_a_printer(&printer,2);
5371 return WERR_UNKNOWN_PRINTER_DRIVER;
5372 }
5373
5374 /* Yes - try again with a WinNT driver. */
5375 version = 2;
5376 status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
5377 DEBUG(8,("construct_printer_driver_info_6: status: %s\n", win_errstr(status)));
5378 if (!W_ERROR_IS_OK(status)) {
5379 free_a_printer(&printer,2);
5380 return WERR_UNKNOWN_PRINTER_DRIVER;
5381 }
5382 }
5383
5384 status = fill_printer_driver_info6(mem_ctx, r, &driver, servername);
5385
5386 free_a_printer(&printer,2);
5387 free_a_printer_driver(driver, 3);
5388
5389 return status;
5390 }
5391
5392 /********************************************************************
5393 * construct_printer_info_101
5394 * fill a printer_info_101 struct
5395 ********************************************************************/
5396
5397 static WERROR construct_printer_driver_info_101(TALLOC_CTX *mem_ctx,
/* [<][>][^][v][top][bottom][index][help] */
5398 struct spoolss_DriverInfo101 *r,
5399 int snum,
5400 const char *servername,
5401 const char *architecture,
5402 uint32_t version)
5403 {
5404 NT_PRINTER_INFO_LEVEL *printer = NULL;
5405 NT_PRINTER_DRIVER_INFO_LEVEL driver;
5406 WERROR result;
5407
5408 ZERO_STRUCT(driver);
5409
5410 result = get_a_printer(NULL, &printer, 2, lp_const_servicename(snum));
5411
5412 DEBUG(8,("construct_printer_driver_info_101: status: %s\n",
5413 win_errstr(result)));
5414
5415 if (!W_ERROR_IS_OK(result)) {
5416 return WERR_INVALID_PRINTER_NAME;
5417 }
5418
5419 result = get_a_printer_driver(&driver, 3, printer->info_2->drivername,
5420 architecture, version);
5421
5422 DEBUG(8,("construct_printer_driver_info_101: status: %s\n",
5423 win_errstr(result)));
5424
5425 if (!W_ERROR_IS_OK(result)) {
5426 /*
5427 * Is this a W2k client ?
5428 */
5429
5430 if (version < 3) {
5431 free_a_printer(&printer, 2);
5432 return WERR_UNKNOWN_PRINTER_DRIVER;
5433 }
5434
5435 /* Yes - try again with a WinNT driver. */
5436 version = 2;
5437 result = get_a_printer_driver(&driver, 3, printer->info_2->drivername,
5438 architecture, version);
5439 DEBUG(8,("construct_printer_driver_info_6: status: %s\n",
5440 win_errstr(result)));
5441 if (!W_ERROR_IS_OK(result)) {
5442 free_a_printer(&printer, 2);
5443 return WERR_UNKNOWN_PRINTER_DRIVER;
5444 }
5445 }
5446
5447 result = fill_printer_driver_info101(mem_ctx, r, &driver, servername);
5448
5449 free_a_printer(&printer, 2);
5450 free_a_printer_driver(driver, 3);
5451
5452 return result;
5453 }
5454
5455 /****************************************************************
5456 _spoolss_GetPrinterDriver2
5457 ****************************************************************/
5458
5459 WERROR _spoolss_GetPrinterDriver2(pipes_struct *p,
/* [<][>][^][v][top][bottom][index][help] */
5460 struct spoolss_GetPrinterDriver2 *r)
5461 {
5462 Printer_entry *printer;
5463 WERROR result;
5464
5465 const char *servername;
5466 int snum;
5467
5468 /* that's an [in out] buffer */
5469
5470 if (!r->in.buffer && (r->in.offered != 0)) {
5471 return WERR_INVALID_PARAM;
5472 }
5473
5474 DEBUG(4,("_spoolss_GetPrinterDriver2\n"));
5475
5476 if (!(printer = find_printer_index_by_hnd(p, r->in.handle))) {
5477 DEBUG(0,("_spoolss_GetPrinterDriver2: invalid printer handle!\n"));
5478 return WERR_INVALID_PRINTER_NAME;
5479 }
5480
5481 *r->out.needed = 0;
5482 *r->out.server_major_version = 0;
5483 *r->out.server_minor_version = 0;
5484
5485 servername = get_server_name(printer);
5486
5487 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
5488 return WERR_BADFID;
5489 }
5490
5491 switch (r->in.level) {
5492 case 1:
5493 result = construct_printer_driver_info_1(p->mem_ctx,
5494 &r->out.info->info1,
5495 snum,
5496 servername,
5497 r->in.architecture,
5498 r->in.client_major_version);
5499 break;
5500 case 2:
5501 result = construct_printer_driver_info_2(p->mem_ctx,
5502 &r->out.info->info2,
5503 snum,
5504 servername,
5505 r->in.architecture,
5506 r->in.client_major_version);
5507 break;
5508 case 3:
5509 result = construct_printer_driver_info_3(p->mem_ctx,
5510 &r->out.info->info3,
5511 snum,
5512 servername,
5513 r->in.architecture,
5514 r->in.client_major_version);
5515 break;
5516 case 6:
5517 result = construct_printer_driver_info_6(p->mem_ctx,
5518 &r->out.info->info6,
5519 snum,
5520 servername,
5521 r->in.architecture,
5522 r->in.client_major_version);
5523 break;
5524 case 101:
5525 result = construct_printer_driver_info_101(p->mem_ctx,
5526 &r->out.info->info101,
5527 snum,
5528 servername,
5529 r->in.architecture,
5530 r->in.client_major_version);
5531 break;
5532 default:
5533 result = WERR_UNKNOWN_LEVEL;
5534 break;
5535 }
5536
5537 if (!W_ERROR_IS_OK(result)) {
5538 TALLOC_FREE(r->out.info);
5539 return result;
5540 }
5541
5542 *r->out.needed = SPOOLSS_BUFFER_UNION(spoolss_DriverInfo, NULL,
5543 r->out.info, r->in.level);
5544 r->out.info = SPOOLSS_BUFFER_OK(r->out.info, NULL);
5545
5546 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
5547 }
5548
5549
5550 /****************************************************************
5551 _spoolss_StartPagePrinter
5552 ****************************************************************/
5553
5554 WERROR _spoolss_StartPagePrinter(pipes_struct *p,
/* [<][>][^][v][top][bottom][index][help] */
5555 struct spoolss_StartPagePrinter *r)
5556 {
5557 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
5558
5559 if (!Printer) {
5560 DEBUG(3,("_spoolss_StartPagePrinter: "
5561 "Error in startpageprinter printer handle\n"));
5562 return WERR_BADFID;
5563 }
5564
5565 Printer->page_started = true;
5566 return WERR_OK;
5567 }
5568
5569 /****************************************************************
5570 _spoolss_EndPagePrinter
5571 ****************************************************************/
5572
5573 WERROR _spoolss_EndPagePrinter(pipes_struct *p,
/* [<][>][^][v][top][bottom][index][help] */
5574 struct spoolss_EndPagePrinter *r)
5575 {
5576 int snum;
5577
5578 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
5579
5580 if (!Printer) {
5581 DEBUG(2,("_spoolss_EndPagePrinter: Invalid handle (%s:%u:%u).\n",
5582 OUR_HANDLE(r->in.handle)));
5583 return WERR_BADFID;
5584 }
5585
5586 if (!get_printer_snum(p, r->in.handle, &snum, NULL))
5587 return WERR_BADFID;
5588
5589 Printer->page_started = false;
5590 print_job_endpage(snum, Printer->jobid);
5591
5592 return WERR_OK;
5593 }
5594
5595 /****************************************************************
5596 _spoolss_StartDocPrinter
5597 ****************************************************************/
5598
5599 WERROR _spoolss_StartDocPrinter(pipes_struct *p,
/* [<][>][^][v][top][bottom][index][help] */
5600 struct spoolss_StartDocPrinter *r)
5601 {
5602 struct spoolss_DocumentInfo1 *info_1;
5603 int snum;
5604 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
5605
5606 if (!Printer) {
5607 DEBUG(2,("_spoolss_StartDocPrinter: "
5608 "Invalid handle (%s:%u:%u)\n",
5609 OUR_HANDLE(r->in.handle)));
5610 return WERR_BADFID;
5611 }
5612
5613 if (r->in.level != 1) {
5614 return WERR_UNKNOWN_LEVEL;
5615 }
5616
5617 info_1 = r->in.info.info1;
5618
5619 /*
5620 * a nice thing with NT is it doesn't listen to what you tell it.
5621 * when asked to send _only_ RAW datas, it tries to send datas
5622 * in EMF format.
5623 *
5624 * So I add checks like in NT Server ...
5625 */
5626
5627 if (info_1->datatype) {
5628 if (strcmp(info_1->datatype, "RAW") != 0) {
5629 *r->out.job_id = 0;
5630 return WERR_INVALID_DATATYPE;
5631 }
5632 }
5633
5634 /* get the share number of the printer */
5635 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
5636 return WERR_BADFID;
5637 }
5638
5639 Printer->jobid = print_job_start(p->server_info, snum,
5640 info_1->document_name,
5641 Printer->nt_devmode);
5642
5643 /* An error occured in print_job_start() so return an appropriate
5644 NT error code. */
5645
5646 if (Printer->jobid == -1) {
5647 return map_werror_from_unix(errno);
5648 }
5649
5650 Printer->document_started = true;
5651 *r->out.job_id = Printer->jobid;
5652
5653 return WERR_OK;
5654 }
5655
5656 /****************************************************************
5657 _spoolss_EndDocPrinter
5658 ****************************************************************/
5659
5660 WERROR _spoolss_EndDocPrinter(pipes_struct *p,
/* [<][>][^][v][top][bottom][index][help] */
5661 struct spoolss_EndDocPrinter *r)
5662 {
5663 return _spoolss_enddocprinter_internal(p, r->in.handle);
5664 }
5665
5666 /****************************************************************
5667 _spoolss_WritePrinter
5668 ****************************************************************/
5669
5670 WERROR _spoolss_WritePrinter(pipes_struct *p,
/* [<][>][^][v][top][bottom][index][help] */
5671 struct spoolss_WritePrinter *r)
5672 {
5673 uint32_t buffer_written;
5674 int snum;
5675 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
5676
5677 if (!Printer) {
5678 DEBUG(2,("_spoolss_WritePrinter: Invalid handle (%s:%u:%u)\n",
5679 OUR_HANDLE(r->in.handle)));
5680 *r->out.num_written = r->in._data_size;
5681 return WERR_BADFID;
5682 }
5683
5684 if (!get_printer_snum(p, r->in.handle, &snum, NULL))
5685 return WERR_BADFID;
5686
5687 buffer_written = (uint32_t)print_job_write(snum, Printer->jobid,
5688 (const char *)r->in.data.data,
5689 (SMB_OFF_T)-1,
5690 (size_t)r->in._data_size);
5691 if (buffer_written == (uint32_t)-1) {
5692 *r->out.num_written = 0;
5693 if (errno == ENOSPC)
5694 return WERR_NO_SPOOL_SPACE;
5695 else
5696 return WERR_ACCESS_DENIED;
5697 }
5698
5699 *r->out.num_written = r->in._data_size;
5700
5701 return WERR_OK;
5702 }
5703
5704 /********************************************************************
5705 * api_spoolss_getprinter
5706 * called from the spoolss dispatcher
5707 *
5708 ********************************************************************/
5709
5710 static WERROR control_printer(struct policy_handle *handle, uint32_t command,
/* [<][>][^][v][top][bottom][index][help] */
5711 pipes_struct *p)
5712 {
5713 int snum;
5714 WERROR errcode = WERR_BADFUNC;
5715 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5716
5717 if (!Printer) {
5718 DEBUG(2,("control_printer: Invalid handle (%s:%u:%u)\n",
5719 OUR_HANDLE(handle)));
5720 return WERR_BADFID;
5721 }
5722
5723 if (!get_printer_snum(p, handle, &snum, NULL))
5724 return WERR_BADFID;
5725
5726 switch (command) {
5727 case SPOOLSS_PRINTER_CONTROL_PAUSE:
5728 errcode = print_queue_pause(p->server_info, snum);
5729 break;
5730 case SPOOLSS_PRINTER_CONTROL_RESUME:
5731 case SPOOLSS_PRINTER_CONTROL_UNPAUSE:
5732 errcode = print_queue_resume(p->server_info, snum);
5733 break;
5734 case SPOOLSS_PRINTER_CONTROL_PURGE:
5735 errcode = print_queue_purge(p->server_info, snum);
5736 break;
5737 default:
5738 return WERR_UNKNOWN_LEVEL;
5739 }
5740
5741 return errcode;
5742 }
5743
5744
5745 /****************************************************************
5746 _spoolss_AbortPrinter
5747 * From MSDN: "Deletes printer's spool file if printer is configured
5748 * for spooling"
5749 ****************************************************************/
5750
5751 WERROR _spoolss_AbortPrinter(pipes_struct *p,
/* [<][>][^][v][top][bottom][index][help] */
5752 struct spoolss_AbortPrinter *r)
5753 {
5754 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
5755 int snum;
5756 WERROR errcode = WERR_OK;
5757
5758 if (!Printer) {
5759 DEBUG(2,("_spoolss_AbortPrinter: Invalid handle (%s:%u:%u)\n",
5760 OUR_HANDLE(r->in.handle)));
5761 return WERR_BADFID;
5762 }
5763
5764 if (!get_printer_snum(p, r->in.handle, &snum, NULL))
5765 return WERR_BADFID;
5766
5767 print_job_delete(p->server_info, snum, Printer->jobid, &errcode );
5768
5769 return errcode;
5770 }
5771
5772 /********************************************************************
5773 * called by spoolss_api_setprinter
5774 * when updating a printer description
5775 ********************************************************************/
5776
5777 static WERROR update_printer_sec(struct policy_handle *handle,
/* [<][>][^][v][top][bottom][index][help] */
5778 pipes_struct *p, SEC_DESC_BUF *secdesc_ctr)
5779 {
5780 SEC_DESC_BUF *new_secdesc_ctr = NULL, *old_secdesc_ctr = NULL;
5781 WERROR result;
5782 int snum;
5783
5784 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5785
5786 if (!Printer || !get_printer_snum(p, handle, &snum, NULL)) {
5787 DEBUG(2,("update_printer_sec: Invalid handle (%s:%u:%u)\n",
5788 OUR_HANDLE(handle)));
5789
5790 result = WERR_BADFID;
5791 goto done;
5792 }
5793
5794 if (!secdesc_ctr) {
5795 DEBUG(10,("update_printer_sec: secdesc_ctr is NULL !\n"));
5796 result = WERR_INVALID_PARAM;
5797 goto done;
5798 }
5799
5800 /* Check the user has permissions to change the security
5801 descriptor. By experimentation with two NT machines, the user
5802 requires Full Access to the printer to change security
5803 information. */
5804
5805 if ( Printer->access_granted != PRINTER_ACCESS_ADMINISTER ) {
5806 DEBUG(4,("update_printer_sec: updated denied by printer permissions\n"));
5807 result = WERR_ACCESS_DENIED;
5808 goto done;
5809 }
5810
5811 /* NT seems to like setting the security descriptor even though
5812 nothing may have actually changed. */
5813
5814 if ( !nt_printing_getsec(p->mem_ctx, Printer->sharename, &old_secdesc_ctr)) {
5815 DEBUG(2,("update_printer_sec: nt_printing_getsec() failed\n"));
5816 result = WERR_BADFID;
5817 goto done;
5818 }
5819
5820 if (DEBUGLEVEL >= 10) {
5821 SEC_ACL *the_acl;
5822 int i;
5823
5824 the_acl = old_secdesc_ctr->sd->dacl;
5825 DEBUG(10, ("old_secdesc_ctr for %s has %d aces:\n",
5826 PRINTERNAME(snum), the_acl->num_aces));
5827
5828 for (i = 0; i < the_acl->num_aces; i++) {
5829 DEBUG(10, ("%s 0x%08x\n", sid_string_dbg(
5830 &the_acl->aces[i].trustee),
5831 the_acl->aces[i].access_mask));
5832 }
5833
5834 the_acl = secdesc_ctr->sd->dacl;
5835
5836 if (the_acl) {
5837 DEBUG(10, ("secdesc_ctr for %s has %d aces:\n",
5838 PRINTERNAME(snum), the_acl->num_aces));
5839
5840 for (i = 0; i < the_acl->num_aces; i++) {
5841 DEBUG(10, ("%s 0x%08x\n", sid_string_dbg(
5842 &the_acl->aces[i].trustee),
5843 the_acl->aces[i].access_mask));
5844 }
5845 } else {
5846 DEBUG(10, ("dacl for secdesc_ctr is NULL\n"));
5847 }
5848 }
5849
5850 new_secdesc_ctr = sec_desc_merge(p->mem_ctx, secdesc_ctr, old_secdesc_ctr);
5851 if (!new_secdesc_ctr) {
5852 result = WERR_NOMEM;
5853 goto done;
5854 }
5855
5856 if (sec_desc_equal(new_secdesc_ctr->sd, old_secdesc_ctr->sd)) {
5857 result = WERR_OK;
5858 goto done;
5859 }
5860
5861 result = nt_printing_setsec(Printer->sharename, new_secdesc_ctr);
5862
5863 done:
5864
5865 return result;
5866 }
5867
5868 /********************************************************************
5869 Canonicalize printer info from a client
5870
5871 ATTN: It does not matter what we set the servername to hear
5872 since we do the necessary work in get_a_printer() to set it to
5873 the correct value based on what the client sent in the
5874 _spoolss_open_printer_ex().
5875 ********************************************************************/
5876
5877 static bool check_printer_ok(NT_PRINTER_INFO_LEVEL_2 *info, int snum)
/* [<][>][^][v][top][bottom][index][help] */
5878 {
5879 fstring printername;
5880 const char *p;
5881
5882 DEBUG(5,("check_printer_ok: servername=%s printername=%s sharename=%s "
5883 "portname=%s drivername=%s comment=%s location=%s\n",
5884 info->servername, info->printername, info->sharename,
5885 info->portname, info->drivername, info->comment, info->location));
5886
5887 /* we force some elements to "correct" values */
5888 slprintf(info->servername, sizeof(info->servername)-1, "\\\\%s", global_myname());
5889 fstrcpy(info->sharename, lp_servicename(snum));
5890
5891 /* check to see if we allow printername != sharename */
5892
5893 if ( lp_force_printername(snum) ) {
5894 slprintf(info->printername, sizeof(info->printername)-1, "\\\\%s\\%s",
5895 global_myname(), info->sharename );
5896 } else {
5897
5898 /* make sure printername is in \\server\printername format */
5899
5900 fstrcpy( printername, info->printername );
5901 p = printername;
5902 if ( printername[0] == '\\' && printername[1] == '\\' ) {
5903 if ( (p = strchr_m( &printername[2], '\\' )) != NULL )
5904 p++;
5905 }
5906
5907 slprintf(info->printername, sizeof(info->printername)-1, "\\\\%s\\%s",
5908 global_myname(), p );
5909 }
5910
5911 info->attributes |= PRINTER_ATTRIBUTE_SAMBA;
5912 info->attributes &= ~PRINTER_ATTRIBUTE_NOT_SAMBA;
5913
5914
5915
5916 return true;
5917 }
5918
5919 /****************************************************************************
5920 ****************************************************************************/
5921
5922 WERROR add_port_hook(TALLOC_CTX *ctx, NT_USER_TOKEN *token, const char *portname, const char *uri )
/* [<][>][^][v][top][bottom][index][help] */
5923 {
5924 char *cmd = lp_addport_cmd();
5925 char *command = NULL;
5926 int ret;
5927 SE_PRIV se_printop = SE_PRINT_OPERATOR;
5928 bool is_print_op = false;
5929
5930 if ( !*cmd ) {
5931 return WERR_ACCESS_DENIED;
5932 }
5933
5934 command = talloc_asprintf(ctx,
5935 "%s \"%s\" \"%s\"", cmd, portname, uri );
5936 if (!command) {
5937 return WERR_NOMEM;
5938 }
5939
5940 if ( token )
5941 is_print_op = user_has_privileges( token, &se_printop );
5942
5943 DEBUG(10,("Running [%s]\n", command));
5944
5945 /********* BEGIN SePrintOperatorPrivilege **********/
5946
5947 if ( is_print_op )
5948 become_root();
5949
5950 ret = smbrun(command, NULL);
5951
5952 if ( is_print_op )
5953 unbecome_root();
5954
5955 /********* END SePrintOperatorPrivilege **********/
5956
5957 DEBUGADD(10,("returned [%d]\n", ret));
5958
5959 TALLOC_FREE(command);
5960
5961 if ( ret != 0 ) {
5962 return WERR_ACCESS_DENIED;
5963 }
5964
5965 return WERR_OK;
5966 }
5967
5968 /****************************************************************************
5969 ****************************************************************************/
5970
5971 bool add_printer_hook(TALLOC_CTX *ctx, NT_USER_TOKEN *token, NT_PRINTER_INFO_LEVEL *printer)
/* [<][>][^][v][top][bottom][index][help] */
5972 {
5973 char *cmd = lp_addprinter_cmd();
5974 char **qlines;
5975 char *command = NULL;
5976 int numlines;
5977 int ret;
5978 int fd;
5979 SE_PRIV se_printop = SE_PRINT_OPERATOR;
5980 bool is_print_op = false;
5981 char *remote_machine = talloc_strdup(ctx, "%m");
5982
5983 if (!remote_machine) {
5984 return false;
5985 }
5986 remote_machine = talloc_sub_basic(ctx,
5987 current_user_info.smb_name,
5988 current_user_info.domain,
5989 remote_machine);
5990 if (!remote_machine) {
5991 return false;
5992 }
5993
5994 command = talloc_asprintf(ctx,
5995 "%s \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\"",
5996 cmd, printer->info_2->printername, printer->info_2->sharename,
5997 printer->info_2->portname, printer->info_2->drivername,
5998 printer->info_2->location, printer->info_2->comment, remote_machine);
5999 if (!command) {
6000 return false;
6001 }
6002
6003 if ( token )
6004 is_print_op = user_has_privileges( token, &se_printop );
6005
6006 DEBUG(10,("Running [%s]\n", command));
6007
6008 /********* BEGIN SePrintOperatorPrivilege **********/
6009
6010 if ( is_print_op )
6011 become_root();
6012
6013 if ( (ret = smbrun(command, &fd)) == 0 ) {
6014 /* Tell everyone we updated smb.conf. */
6015 message_send_all(smbd_messaging_context(),
6016 MSG_SMB_CONF_UPDATED, NULL, 0, NULL);
6017 }
6018
6019 if ( is_print_op )
6020 unbecome_root();
6021
6022 /********* END SePrintOperatorPrivilege **********/
6023
6024 DEBUGADD(10,("returned [%d]\n", ret));
6025
6026 TALLOC_FREE(command);
6027 TALLOC_FREE(remote_machine);
6028
6029 if ( ret != 0 ) {
6030 if (fd != -1)
6031 close(fd);
6032 return false;
6033 }
6034
6035 /* reload our services immediately */
6036 become_root();
6037 reload_services(false);
6038 unbecome_root();
6039
6040 numlines = 0;
6041 /* Get lines and convert them back to dos-codepage */
6042 qlines = fd_lines_load(fd, &numlines, 0, NULL);
6043 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
6044 close(fd);
6045
6046 /* Set the portname to what the script says the portname should be. */
6047 /* but don't require anything to be return from the script exit a good error code */
6048
6049 if (numlines) {
6050 /* Set the portname to what the script says the portname should be. */
6051 strncpy(printer->info_2->portname, qlines[0], sizeof(printer->info_2->portname));
6052 DEBUGADD(6,("Line[0] = [%s]\n", qlines[0]));
6053 }
6054
6055 TALLOC_FREE(qlines);
6056 return true;
6057 }
6058
6059
6060 /********************************************************************
6061 * Called by spoolss_api_setprinter
6062 * when updating a printer description.
6063 ********************************************************************/
6064
6065 static WERROR update_printer(pipes_struct *p, struct policy_handle *handle,
/* [<][>][^][v][top][bottom][index][help] */
6066 struct spoolss_SetPrinterInfoCtr *info_ctr,
6067 struct spoolss_DeviceMode *devmode)
6068 {
6069 int snum;
6070 NT_PRINTER_INFO_LEVEL *printer = NULL, *old_printer = NULL;
6071 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
6072 WERROR result;
6073 UNISTR2 buffer;
6074 fstring asc_buffer;
6075
6076 DEBUG(8,("update_printer\n"));
6077
6078 result = WERR_OK;
6079
6080 if (!Printer) {
6081 result = WERR_BADFID;
6082 goto done;
6083 }
6084
6085 if (!get_printer_snum(p, handle, &snum, NULL)) {
6086 result = WERR_BADFID;
6087 goto done;
6088 }
6089
6090 if (!W_ERROR_IS_OK(get_a_printer(Printer, &printer, 2, lp_const_servicename(snum))) ||
6091 (!W_ERROR_IS_OK(get_a_printer(Printer, &old_printer, 2, lp_const_servicename(snum))))) {
6092 result = WERR_BADFID;
6093 goto done;
6094 }
6095
6096 DEBUGADD(8,("Converting info_2 struct\n"));
6097
6098 /*
6099 * convert_printer_info converts the incoming
6100 * info from the client and overwrites the info
6101 * just read from the tdb in the pointer 'printer'.
6102 */
6103
6104 if (!convert_printer_info(info_ctr, printer)) {
6105 result = WERR_NOMEM;
6106 goto done;
6107 }
6108
6109 if (devmode) {
6110 /* we have a valid devmode
6111 convert it and link it*/
6112
6113 DEBUGADD(8,("update_printer: Converting the devicemode struct\n"));
6114 if (!convert_devicemode(printer->info_2->printername, devmode,
6115 &printer->info_2->devmode)) {
6116 result = WERR_NOMEM;
6117 goto done;
6118 }
6119 }
6120
6121 /* Do sanity check on the requested changes for Samba */
6122
6123 if (!check_printer_ok(printer->info_2, snum)) {
6124 result = WERR_INVALID_PARAM;
6125 goto done;
6126 }
6127
6128 /* FIXME!!! If the driver has changed we really should verify that
6129 it is installed before doing much else --jerry */
6130
6131 /* Check calling user has permission to update printer description */
6132
6133 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
6134 DEBUG(3, ("update_printer: printer property change denied by handle\n"));
6135 result = WERR_ACCESS_DENIED;
6136 goto done;
6137 }
6138
6139 /* Call addprinter hook */
6140 /* Check changes to see if this is really needed */
6141
6142 if ( *lp_addprinter_cmd()
6143 && (!strequal(printer->info_2->drivername, old_printer->info_2->drivername)
6144 || !strequal(printer->info_2->comment, old_printer->info_2->comment)
6145 || !strequal(printer->info_2->portname, old_printer->info_2->portname)
6146 || !strequal(printer->info_2->location, old_printer->info_2->location)) )
6147 {
6148 /* add_printer_hook() will call reload_services() */
6149
6150 if ( !add_printer_hook(p->mem_ctx, p->server_info->ptok,
6151 printer) ) {
6152 result = WERR_ACCESS_DENIED;
6153 goto done;
6154 }
6155 }
6156
6157 /*
6158 * When a *new* driver is bound to a printer, the drivername is used to
6159 * lookup previously saved driver initialization info, which is then
6160 * bound to the printer, simulating what happens in the Windows arch.
6161 */
6162 if (!strequal(printer->info_2->drivername, old_printer->info_2->drivername))
6163 {
6164 if (!set_driver_init(printer, 2))
6165 {
6166 DEBUG(5,("update_printer: Error restoring driver initialization data for driver [%s]!\n",
6167 printer->info_2->drivername));
6168 }
6169
6170 DEBUG(10,("update_printer: changing driver [%s]! Sending event!\n",
6171 printer->info_2->drivername));
6172
6173 notify_printer_driver(snum, printer->info_2->drivername);
6174 }
6175
6176 /*
6177 * flag which changes actually occured. This is a small subset of
6178 * all the possible changes. We also have to update things in the
6179 * DsSpooler key.
6180 */
6181
6182 if (!strequal(printer->info_2->comment, old_printer->info_2->comment)) {
6183 init_unistr2( &buffer, printer->info_2->comment, UNI_STR_TERMINATE);
6184 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "description",
6185 REG_SZ, (uint8_t *)buffer.buffer, buffer.uni_str_len*2 );
6186
6187 notify_printer_comment(snum, printer->info_2->comment);
6188 }
6189
6190 if (!strequal(printer->info_2->sharename, old_printer->info_2->sharename)) {
6191 init_unistr2( &buffer, printer->info_2->sharename, UNI_STR_TERMINATE);
6192 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "shareName",
6193 REG_SZ, (uint8_t *)buffer.buffer, buffer.uni_str_len*2 );
6194
6195 notify_printer_sharename(snum, printer->info_2->sharename);
6196 }
6197
6198 if (!strequal(printer->info_2->printername, old_printer->info_2->printername)) {
6199 char *pname;
6200
6201 if ( (pname = strchr_m( printer->info_2->printername+2, '\\' )) != NULL )
6202 pname++;
6203 else
6204 pname = printer->info_2->printername;
6205
6206
6207 init_unistr2( &buffer, pname, UNI_STR_TERMINATE);
6208 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "printerName",
6209 REG_SZ, (uint8_t *)buffer.buffer, buffer.uni_str_len*2 );
6210
6211 notify_printer_printername( snum, pname );
6212 }
6213
6214 if (!strequal(printer->info_2->portname, old_printer->info_2->portname)) {
6215 init_unistr2( &buffer, printer->info_2->portname, UNI_STR_TERMINATE);
6216 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "portName",
6217 REG_SZ, (uint8_t *)buffer.buffer, buffer.uni_str_len*2 );
6218
6219 notify_printer_port(snum, printer->info_2->portname);
6220 }
6221
6222 if (!strequal(printer->info_2->location, old_printer->info_2->location)) {
6223 init_unistr2( &buffer, printer->info_2->location, UNI_STR_TERMINATE);
6224 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "location",
6225 REG_SZ, (uint8_t *)buffer.buffer, buffer.uni_str_len*2 );
6226
6227 notify_printer_location(snum, printer->info_2->location);
6228 }
6229
6230 /* here we need to update some more DsSpooler keys */
6231 /* uNCName, serverName, shortServerName */
6232
6233 init_unistr2( &buffer, global_myname(), UNI_STR_TERMINATE);
6234 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "serverName",
6235 REG_SZ, (uint8_t *)buffer.buffer, buffer.uni_str_len*2 );
6236 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "shortServerName",
6237 REG_SZ, (uint8_t *)buffer.buffer, buffer.uni_str_len*2 );
6238
6239 slprintf( asc_buffer, sizeof(asc_buffer)-1, "\\\\%s\\%s",
6240 global_myname(), printer->info_2->sharename );
6241 init_unistr2( &buffer, asc_buffer, UNI_STR_TERMINATE);
6242 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "uNCName",
6243 REG_SZ, (uint8_t *)buffer.buffer, buffer.uni_str_len*2 );
6244
6245 /* Update printer info */
6246 result = mod_a_printer(printer, 2);
6247
6248 done:
6249 free_a_printer(&printer, 2);
6250 free_a_printer(&old_printer, 2);
6251
6252
6253 return result;
6254 }
6255
6256 /****************************************************************************
6257 ****************************************************************************/
6258 static WERROR publish_or_unpublish_printer(pipes_struct *p,
/* [<][>][^][v][top][bottom][index][help] */
6259 struct policy_handle *handle,
6260 struct spoolss_SetPrinterInfo7 *info7)
6261 {
6262 #ifdef HAVE_ADS
6263 int snum;
6264 Printer_entry *Printer;
6265
6266 if ( lp_security() != SEC_ADS ) {
6267 return WERR_UNKNOWN_LEVEL;
6268 }
6269
6270 Printer = find_printer_index_by_hnd(p, handle);
6271
6272 DEBUG(5,("publish_or_unpublish_printer, action = %d\n",info7->action));
6273
6274 if (!Printer)
6275 return WERR_BADFID;
6276
6277 if (!get_printer_snum(p, handle, &snum, NULL))
6278 return WERR_BADFID;
6279
6280 nt_printer_publish(Printer, snum, info7->action);
6281
6282 return WERR_OK;
6283 #else
6284 return WERR_UNKNOWN_LEVEL;
6285 #endif
6286 }
6287
6288 /****************************************************************
6289 _spoolss_SetPrinter
6290 ****************************************************************/
6291
6292 WERROR _spoolss_SetPrinter(pipes_struct *p,
/* [<][>][^][v][top][bottom][index][help] */
6293 struct spoolss_SetPrinter *r)
6294 {
6295 WERROR result;
6296
6297 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
6298
6299 if (!Printer) {
6300 DEBUG(2,("_spoolss_SetPrinter: Invalid handle (%s:%u:%u)\n",
6301 OUR_HANDLE(r->in.handle)));
6302 return WERR_BADFID;
6303 }
6304
6305 /* check the level */
6306 switch (r->in.info_ctr->level) {
6307 case 0:
6308 return control_printer(r->in.handle, r->in.command, p);
6309 case 2:
6310 result = update_printer(p, r->in.handle,
6311 r->in.info_ctr,
6312 r->in.devmode_ctr->devmode);
6313 if (!W_ERROR_IS_OK(result))
6314 return result;
6315 if (r->in.secdesc_ctr->sd)
6316 result = update_printer_sec(r->in.handle, p,
6317 r->in.secdesc_ctr);
6318 return result;
6319 case 3:
6320 return update_printer_sec(r->in.handle, p,
6321 r->in.secdesc_ctr);
6322 case 7:
6323 return publish_or_unpublish_printer(p, r->in.handle,
6324 r->in.info_ctr->info.info7);
6325 default:
6326 return WERR_UNKNOWN_LEVEL;
6327 }
6328 }
6329
6330 /****************************************************************
6331 _spoolss_FindClosePrinterNotify
6332 ****************************************************************/
6333
6334 WERROR _spoolss_FindClosePrinterNotify(pipes_struct *p,
/* [<][>][^][v][top][bottom][index][help] */
6335 struct spoolss_FindClosePrinterNotify *r)
6336 {
6337 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
6338
6339 if (!Printer) {
6340 DEBUG(2,("_spoolss_FindClosePrinterNotify: "
6341 "Invalid handle (%s:%u:%u)\n", OUR_HANDLE(r->in.handle)));
6342 return WERR_BADFID;
6343 }
6344
6345 if (Printer->notify.client_connected == true) {
6346 int snum = -1;
6347
6348 if ( Printer->printer_type == SPLHND_SERVER)
6349 snum = -1;
6350 else if ( (Printer->printer_type == SPLHND_PRINTER) &&
6351 !get_printer_snum(p, r->in.handle, &snum, NULL) )
6352 return WERR_BADFID;
6353
6354 srv_spoolss_replycloseprinter(snum, &Printer->notify.client_hnd);
6355 }
6356
6357 Printer->notify.flags=0;
6358 Printer->notify.options=0;
6359 Printer->notify.localmachine[0]='\0';
6360 Printer->notify.printerlocal=0;
6361 TALLOC_FREE(Printer->notify.option);
6362 Printer->notify.client_connected = false;
6363
6364 return WERR_OK;
6365 }
6366
6367 /****************************************************************
6368 _spoolss_AddJob
6369 ****************************************************************/
6370
6371 WERROR _spoolss_AddJob(pipes_struct *p,
/* [<][>][^][v][top][bottom][index][help] */
6372 struct spoolss_AddJob *r)
6373 {
6374 if (!r->in.buffer && (r->in.offered != 0)) {
6375 return WERR_INVALID_PARAM;
6376 }
6377
6378 /* this is what a NT server returns for AddJob. AddJob must fail on
6379 * non-local printers */
6380
6381 if (r->in.level != 1) {
6382 return WERR_UNKNOWN_LEVEL;
6383 }
6384
6385 return WERR_INVALID_PARAM;
6386 }
6387
6388 /****************************************************************************
6389 fill_job_info1
6390 ****************************************************************************/
6391
6392 static WERROR fill_job_info1(TALLOC_CTX *mem_ctx,
/* [<][>][^][v][top][bottom][index][help] */
6393 struct spoolss_JobInfo1 *r,
6394 const print_queue_struct *queue,
6395 int position, int snum,
6396 const NT_PRINTER_INFO_LEVEL *ntprinter)
6397 {
6398 struct tm *t;
6399
6400 t = gmtime(&queue->time);
6401
6402 r->job_id = queue->job;
6403
6404 r->printer_name = talloc_strdup(mem_ctx, lp_servicename(snum));
6405 W_ERROR_HAVE_NO_MEMORY(r->printer_name);
6406 r->server_name = talloc_strdup(mem_ctx, ntprinter->info_2->servername);
6407 W_ERROR_HAVE_NO_MEMORY(r->server_name);
6408 r->user_name = talloc_strdup(mem_ctx, queue->fs_user);
6409 W_ERROR_HAVE_NO_MEMORY(r->user_name);
6410 r->document_name = talloc_strdup(mem_ctx, queue->fs_file);
6411 W_ERROR_HAVE_NO_MEMORY(r->document_name);
6412 r->data_type = talloc_strdup(mem_ctx, "RAW");
6413 W_ERROR_HAVE_NO_MEMORY(r->data_type);
6414 r->text_status = talloc_strdup(mem_ctx, "");
6415 W_ERROR_HAVE_NO_MEMORY(r->text_status);
6416
6417 r->status = nt_printj_status(queue->status);
6418 r->priority = queue->priority;
6419 r->position = position;
6420 r->total_pages = queue->page_count;
6421 r->pages_printed = 0; /* ??? */
6422
6423 init_systemtime(&r->submitted, t);
6424
6425 return WERR_OK;
6426 }
6427
6428 /****************************************************************************
6429 fill_job_info2
6430 ****************************************************************************/
6431
6432 static WERROR fill_job_info2(TALLOC_CTX *mem_ctx,
/* [<][>][^][v][top][bottom][index][help] */
6433 struct spoolss_JobInfo2 *r,
6434 const print_queue_struct *queue,
6435 int position, int snum,
6436 const NT_PRINTER_INFO_LEVEL *ntprinter,
6437 struct spoolss_DeviceMode *devmode)
6438 {
6439 struct tm *t;
6440
6441 t = gmtime(&queue->time);
6442
6443 r->job_id = queue->job;
6444
6445 r->printer_name = talloc_strdup(mem_ctx, lp_servicename(snum));
6446 W_ERROR_HAVE_NO_MEMORY(r->printer_name);
6447 r->server_name = talloc_strdup(mem_ctx, ntprinter->info_2->servername);
6448 W_ERROR_HAVE_NO_MEMORY(r->server_name);
6449 r->user_name = talloc_strdup(mem_ctx, queue->fs_user);
6450 W_ERROR_HAVE_NO_MEMORY(r->user_name);
6451 r->document_name = talloc_strdup(mem_ctx, queue->fs_file);
6452 W_ERROR_HAVE_NO_MEMORY(r->document_name);
6453 r->notify_name = talloc_strdup(mem_ctx, queue->fs_user);
6454 W_ERROR_HAVE_NO_MEMORY(r->notify_name);
6455 r->data_type = talloc_strdup(mem_ctx, "RAW");
6456 W_ERROR_HAVE_NO_MEMORY(r->data_type);
6457 r->print_processor = talloc_strdup(mem_ctx, "winprint");
6458 W_ERROR_HAVE_NO_MEMORY(r->print_processor);
6459 r->parameters = talloc_strdup(mem_ctx, "");
6460 W_ERROR_HAVE_NO_MEMORY(r->parameters);
6461 r->driver_name = talloc_strdup(mem_ctx, ntprinter->info_2->drivername);
6462 W_ERROR_HAVE_NO_MEMORY(r->driver_name);
6463
6464 r->devmode = devmode;
6465
6466 r->text_status = talloc_strdup(mem_ctx, "");
6467 W_ERROR_HAVE_NO_MEMORY(r->text_status);
6468
6469 r->secdesc = NULL;
6470
6471 r->status = nt_printj_status(queue->status);
6472 r->priority = queue->priority;
6473 r->position = position;
6474 r->start_time = 0;
6475 r->until_time = 0;
6476 r->total_pages = queue->page_count;
6477 r->size = queue->size;
6478 init_systemtime(&r->submitted, t);
6479 r->time = 0;
6480 r->pages_printed = 0; /* ??? */
6481
6482 return WERR_OK;
6483 }
6484
6485 /****************************************************************************
6486 Enumjobs at level 1.
6487 ****************************************************************************/
6488
6489 static WERROR enumjobs_level1(TALLOC_CTX *mem_ctx,
/* [<][>][^][v][top][bottom][index][help] */
6490 const print_queue_struct *queue,
6491 uint32_t num_queues, int snum,
6492 const NT_PRINTER_INFO_LEVEL *ntprinter,
6493 union spoolss_JobInfo **info_p,
6494 uint32_t *count)
6495 {
6496 union spoolss_JobInfo *info;
6497 int i;
6498 WERROR result = WERR_OK;
6499
6500 info = TALLOC_ARRAY(mem_ctx, union spoolss_JobInfo, num_queues);
6501 W_ERROR_HAVE_NO_MEMORY(info);
6502
6503 *count = num_queues;
6504
6505 for (i=0; i<*count; i++) {
6506 result = fill_job_info1(info,
6507 &info[i].info1,
6508 &queue[i],
6509 i,
6510 snum,
6511 ntprinter);
6512 if (!W_ERROR_IS_OK(result)) {
6513 goto out;
6514 }
6515 }
6516
6517 out:
6518 if (!W_ERROR_IS_OK(result)) {
6519 TALLOC_FREE(info);
6520 *count = 0;
6521 return result;
6522 }
6523
6524 *info_p = info;
6525
6526 return WERR_OK;
6527 }
6528
6529 /****************************************************************************
6530 Enumjobs at level 2.
6531 ****************************************************************************/
6532
6533 static WERROR enumjobs_level2(TALLOC_CTX *mem_ctx,
/* [<][>][^][v][top][bottom][index][help] */
6534 const print_queue_struct *queue,
6535 uint32_t num_queues, int snum,
6536 const NT_PRINTER_INFO_LEVEL *ntprinter,
6537 union spoolss_JobInfo **info_p,
6538 uint32_t *count)
6539 {
6540 union spoolss_JobInfo *info;
6541 int i;
6542 WERROR result = WERR_OK;
6543
6544 info = TALLOC_ARRAY(mem_ctx, union spoolss_JobInfo, num_queues);
6545 W_ERROR_HAVE_NO_MEMORY(info);
6546
6547 *count = num_queues;
6548
6549 for (i=0; i<*count; i++) {
6550
6551 struct spoolss_DeviceMode *devmode;
6552
6553 devmode = construct_dev_mode(info, lp_const_servicename(snum));
6554 if (!devmode) {
6555 result = WERR_NOMEM;
6556 goto out;
6557 }
6558
6559 result = fill_job_info2(info,
6560 &info[i].info2,
6561 &queue[i],
6562 i,
6563 snum,
6564 ntprinter,
6565 devmode);
6566 if (!W_ERROR_IS_OK(result)) {
6567 goto out;
6568 }
6569 }
6570
6571 out:
6572 if (!W_ERROR_IS_OK(result)) {
6573 TALLOC_FREE(info);
6574 *count = 0;
6575 return result;
6576 }
6577
6578 *info_p = info;
6579
6580 return WERR_OK;
6581 }
6582
6583 /****************************************************************
6584 _spoolss_EnumJobs
6585 ****************************************************************/
6586
6587 WERROR _spoolss_EnumJobs(pipes_struct *p,
/* [<][>][^][v][top][bottom][index][help] */
6588 struct spoolss_EnumJobs *r)
6589 {
6590 WERROR result;
6591 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
6592 int snum;
6593 print_status_struct prt_status;
6594 print_queue_struct *queue = NULL;
6595 uint32_t count;
6596
6597 /* that's an [in out] buffer */
6598
6599 if (!r->in.buffer && (r->in.offered != 0)) {
6600 return WERR_INVALID_PARAM;
6601 }
6602
6603 DEBUG(4,("_spoolss_EnumJobs\n"));
6604
6605 *r->out.needed = 0;
6606 *r->out.count = 0;
6607 *r->out.info = NULL;
6608
6609 /* lookup the printer snum and tdb entry */
6610
6611 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
6612 return WERR_BADFID;
6613 }
6614
6615 result = get_a_printer(NULL, &ntprinter, 2, lp_servicename(snum));
6616 if (!W_ERROR_IS_OK(result)) {
6617 return result;
6618 }
6619
6620 count = print_queue_status(snum, &queue, &prt_status);
6621 DEBUGADD(4,("count:[%d], status:[%d], [%s]\n",
6622 count, prt_status.status, prt_status.message));
6623
6624 if (count == 0) {
6625 SAFE_FREE(queue);
6626 free_a_printer(&ntprinter, 2);
6627 return WERR_OK;
6628 }
6629
6630 switch (r->in.level) {
6631 case 1:
6632 result = enumjobs_level1(p->mem_ctx, queue, count, snum,
6633 ntprinter, r->out.info, r->out.count);
6634 break;
6635 case 2:
6636 result = enumjobs_level2(p->mem_ctx, queue, count, snum,
6637 ntprinter, r->out.info, r->out.count);
6638 break;
6639 default:
6640 result = WERR_UNKNOWN_LEVEL;
6641 break;
6642 }
6643
6644 SAFE_FREE(queue);
6645 free_a_printer(&ntprinter, 2);
6646
6647 if (!W_ERROR_IS_OK(result)) {
6648 return result;
6649 }
6650
6651 *r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
6652 spoolss_EnumJobs, NULL,
6653 *r->out.info, r->in.level,
6654 *r->out.count);
6655 *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
6656 *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, 0);
6657
6658 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
6659 }
6660
6661 /****************************************************************
6662 _spoolss_ScheduleJob
6663 ****************************************************************/
6664
6665 WERROR _spoolss_ScheduleJob(pipes_struct *p,
/* [<][>][^][v][top][bottom][index][help] */
6666 struct spoolss_ScheduleJob *r)
6667 {
6668 return WERR_OK;
6669 }
6670
6671 /****************************************************************
6672 _spoolss_SetJob
6673 ****************************************************************/
6674
6675 WERROR _spoolss_SetJob(pipes_struct *p,
/* [<][>][^][v][top][bottom][index][help] */
6676 struct spoolss_SetJob *r)
6677 {
6678 int snum;
6679 WERROR errcode = WERR_BADFUNC;
6680
6681 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
6682 return WERR_BADFID;
6683 }
6684
6685 if (!print_job_exists(lp_const_servicename(snum), r->in.job_id)) {
6686 return WERR_INVALID_PRINTER_NAME;
6687 }
6688
6689 switch (r->in.command) {
6690 case SPOOLSS_JOB_CONTROL_CANCEL:
6691 case SPOOLSS_JOB_CONTROL_DELETE:
6692 if (print_job_delete(p->server_info, snum, r->in.job_id, &errcode)) {
6693 errcode = WERR_OK;
6694 }
6695 break;
6696 case SPOOLSS_JOB_CONTROL_PAUSE:
6697 if (print_job_pause(p->server_info, snum, r->in.job_id, &errcode)) {
6698 errcode = WERR_OK;
6699 }
6700 break;
6701 case SPOOLSS_JOB_CONTROL_RESTART:
6702 case SPOOLSS_JOB_CONTROL_RESUME:
6703 if (print_job_resume(p->server_info, snum, r->in.job_id, &errcode)) {
6704 errcode = WERR_OK;
6705 }
6706 break;
6707 default:
6708 return WERR_UNKNOWN_LEVEL;
6709 }
6710
6711 return errcode;
6712 }
6713
6714 /****************************************************************************
6715 Enumerates all printer drivers by level.
6716 ****************************************************************************/
6717
6718 static WERROR enumprinterdrivers_level(TALLOC_CTX *mem_ctx,
/* [<][>][^][v][top][bottom][index][help] */
6719 const char *servername,
6720 const char *architecture,
6721 uint32_t level,
6722 union spoolss_DriverInfo **info_p,
6723 uint32_t *count_p)
6724 {
6725 int i;
6726 int ndrivers;
6727 uint32_t version;
6728 fstring *list = NULL;
6729 NT_PRINTER_DRIVER_INFO_LEVEL driver;
6730 union spoolss_DriverInfo *info = NULL;
6731 uint32_t count = 0;
6732 WERROR result = WERR_OK;
6733
6734 *count_p = 0;
6735 *info_p = NULL;
6736
6737 for (version=0; version<DRIVER_MAX_VERSION; version++) {
6738 list = NULL;
6739 ndrivers = get_ntdrivers(&list, architecture, version);
6740 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n",
6741 ndrivers, architecture, version));
6742
6743 if (ndrivers == -1) {
6744 result = WERR_NOMEM;
6745 goto out;
6746 }
6747
6748 if (ndrivers != 0) {
6749 info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
6750 union spoolss_DriverInfo,
6751 count + ndrivers);
6752 if (!info) {
6753 DEBUG(0,("enumprinterdrivers_level1: "
6754 "failed to enlarge driver info buffer!\n"));
6755 result = WERR_NOMEM;
6756 goto out;
6757 }
6758 }
6759
6760 for (i=0; i<ndrivers; i++) {
6761 DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
6762 ZERO_STRUCT(driver);
6763 result = get_a_printer_driver(&driver, 3, list[i],
6764 architecture, version);
6765 if (!W_ERROR_IS_OK(result)) {
6766 goto out;
6767 }
6768
6769 switch (level) {
6770 case 1:
6771 result = fill_printer_driver_info1(info, &info[count+i].info1,
6772 &driver, servername,
6773 architecture);
6774 break;
6775 case 2:
6776 result = fill_printer_driver_info2(info, &info[count+i].info2,
6777 &driver, servername);
6778 break;
6779 case 3:
6780 result = fill_printer_driver_info3(info, &info[count+i].info3,
6781 &driver, servername);
6782 break;
6783 case 4:
6784 result = fill_printer_driver_info4(info, &info[count+i].info4,
6785 &driver, servername);
6786 break;
6787 case 5:
6788 result = fill_printer_driver_info5(info, &info[count+i].info5,
6789 &driver, servername);
6790 break;
6791 case 6:
6792 result = fill_printer_driver_info6(info, &info[count+i].info6,
6793 &driver, servername);
6794 break;
6795 default:
6796 result = WERR_UNKNOWN_LEVEL;
6797 break;
6798 }
6799
6800 if (!W_ERROR_IS_OK(result)) {
6801 free_a_printer_driver(driver, 3);
6802 goto out;
6803 }
6804 free_a_printer_driver(driver, 3);
6805 }
6806
6807 count += ndrivers;
6808 SAFE_FREE(list);
6809 }
6810
6811 out:
6812 SAFE_FREE(list);
6813
6814 if (!W_ERROR_IS_OK(result)) {
6815 TALLOC_FREE(info);
6816 return result;
6817 }
6818
6819 *info_p = info;
6820 *count_p = count;
6821
6822 return WERR_OK;
6823 }
6824
6825 /****************************************************************************
6826 Enumerates all printer drivers at level 1.
6827 ****************************************************************************/
6828
6829 static WERROR enumprinterdrivers_level1(TALLOC_CTX *mem_ctx,
/* [<][>][^][v][top][bottom][index][help] */
6830 const char *servername,
6831 const char *architecture,
6832 union spoolss_DriverInfo **info_p,
6833 uint32_t *count)
6834 {
6835 return enumprinterdrivers_level(mem_ctx, servername, architecture, 1,
6836 info_p, count);
6837 }
6838
6839 /****************************************************************************
6840 Enumerates all printer drivers at level 2.
6841 ****************************************************************************/
6842
6843 static WERROR enumprinterdrivers_level2(TALLOC_CTX *mem_ctx,
/* [<][>][^][v][top][bottom][index][help] */
6844 const char *servername,
6845 const char *architecture,
6846 union spoolss_DriverInfo **info_p,
6847 uint32_t *count)
6848 {
6849 return enumprinterdrivers_level(mem_ctx, servername, architecture, 2,
6850 info_p, count);
6851 }
6852
6853 /****************************************************************************
6854 Enumerates all printer drivers at level 3.
6855 ****************************************************************************/
6856
6857 static WERROR enumprinterdrivers_level3(TALLOC_CTX *mem_ctx,
/* [<][>][^][v][top][bottom][index][help] */
6858 const char *servername,
6859 const char *architecture,
6860 union spoolss_DriverInfo **info_p,
6861 uint32_t *count)
6862 {
6863 return enumprinterdrivers_level(mem_ctx, servername, architecture, 3,
6864 info_p, count);
6865 }
6866
6867 /****************************************************************************
6868 Enumerates all printer drivers at level 4.
6869 ****************************************************************************/
6870
6871 static WERROR enumprinterdrivers_level4(TALLOC_CTX *mem_ctx,
/* [<][>][^][v][top][bottom][index][help] */
6872 const char *servername,
6873 const char *architecture,
6874 union spoolss_DriverInfo **info_p,
6875 uint32_t *count)
6876 {
6877 return enumprinterdrivers_level(mem_ctx, servername, architecture, 4,
6878 info_p, count);
6879 }
6880
6881 /****************************************************************************
6882 Enumerates all printer drivers at level 5.
6883 ****************************************************************************/
6884
6885 static WERROR enumprinterdrivers_level5(TALLOC_CTX *mem_ctx,
/* [<][>][^][v][top][bottom][index][help] */
6886 const char *servername,
6887 const char *architecture,
6888 union spoolss_DriverInfo **info_p,
6889 uint32_t *count)
6890 {
6891 return enumprinterdrivers_level(mem_ctx, servername, architecture, 5,
6892 info_p, count);
6893 }
6894
6895 /****************************************************************************
6896 Enumerates all printer drivers at level 6.
6897 ****************************************************************************/
6898
6899 static WERROR enumprinterdrivers_level6(TALLOC_CTX *mem_ctx,
/* [<][>][^][v][top][bottom][index][help] */
6900 const char *servername,
6901 const char *architecture,
6902 union spoolss_DriverInfo **info_p,
6903 uint32_t *count)
6904 {
6905 return enumprinterdrivers_level(mem_ctx, servername, architecture, 6,
6906 info_p, count);
6907 }
6908
6909
6910 /****************************************************************
6911 _spoolss_EnumPrinterDrivers
6912 ****************************************************************/
6913
6914 WERROR _spoolss_EnumPrinterDrivers(pipes_struct *p,
/* [<][>][^][v][top][bottom][index][help] */
6915 struct spoolss_EnumPrinterDrivers *r)
6916 {
6917 const char *cservername;
6918 WERROR result;
6919
6920 /* that's an [in out] buffer */
6921
6922 if (!r->in.buffer && (r->in.offered != 0)) {
6923 return WERR_INVALID_PARAM;
6924 }
6925
6926 DEBUG(4,("_spoolss_EnumPrinterDrivers\n"));
6927
6928 *r->out.needed = 0;
6929 *r->out.count = 0;
6930 *r->out.info = NULL;
6931
6932 cservername = canon_servername(r->in.server);
6933
6934 if (!is_myname_or_ipaddr(cservername)) {
6935 return WERR_UNKNOWN_PRINTER_DRIVER;
6936 }
6937
6938 switch (r->in.level) {
6939 case 1:
6940 result = enumprinterdrivers_level1(p->mem_ctx, cservername,
6941 r->in.environment,
6942 r->out.info, r->out.count);
6943 break;
6944 case 2:
6945 result = enumprinterdrivers_level2(p->mem_ctx, cservername,
6946 r->in.environment,
6947 r->out.info, r->out.count);
6948 break;
6949 case 3:
6950 result = enumprinterdrivers_level3(p->mem_ctx, cservername,
6951 r->in.environment,
6952 r->out.info, r->out.count);
6953 break;
6954 case 4:
6955 result = enumprinterdrivers_level4(p->mem_ctx, cservername,
6956 r->in.environment,
6957 r->out.info, r->out.count);
6958 break;
6959 case 5:
6960 result = enumprinterdrivers_level5(p->mem_ctx, cservername,
6961 r->in.environment,
6962 r->out.info, r->out.count);
6963 break;
6964 case 6:
6965 result = enumprinterdrivers_level6(p->mem_ctx, cservername,
6966 r->in.environment,
6967 r->out.info, r->out.count);
6968 break;
6969 default:
6970 return WERR_UNKNOWN_LEVEL;
6971 }
6972
6973 if (!W_ERROR_IS_OK(result)) {
6974 return result;
6975 }
6976
6977 *r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
6978 spoolss_EnumPrinterDrivers, NULL,
6979 *r->out.info, r->in.level,
6980 *r->out.count);
6981 *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
6982 *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, 0);
6983
6984 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
6985 }
6986
6987 /****************************************************************************
6988 ****************************************************************************/
6989
6990 static WERROR fill_form_info_1(TALLOC_CTX *mem_ctx,
/* [<][>][^][v][top][bottom][index][help] */
6991 struct spoolss_FormInfo1 *r,
6992 const nt_forms_struct *form)
6993 {
6994 r->form_name = talloc_strdup(mem_ctx, form->name);
6995 W_ERROR_HAVE_NO_MEMORY(r->form_name);
6996
6997 r->flags = form->flag;
6998 r->size.width = form->width;
6999 r->size.height = form->length;
7000 r->area.left = form->left;
7001 r->area.top = form->top;
7002 r->area.right = form->right;
7003 r->area.bottom = form->bottom;
7004
7005 return WERR_OK;
7006 }
7007
7008 /****************************************************************
7009 spoolss_enumforms_level1
7010 ****************************************************************/
7011
7012 static WERROR spoolss_enumforms_level1(TALLOC_CTX *mem_ctx,
/* [<][>][^][v][top][bottom][index][help] */
7013 const nt_forms_struct *builtin_forms,
7014 uint32_t num_builtin_forms,
7015 const nt_forms_struct *user_forms,
7016 uint32_t num_user_forms,
7017 union spoolss_FormInfo **info_p,
7018 uint32_t *count)
7019 {
7020 union spoolss_FormInfo *info;
7021 WERROR result = WERR_OK;
7022 int i;
7023
7024 *count = num_builtin_forms + num_user_forms;
7025
7026 info = TALLOC_ARRAY(mem_ctx, union spoolss_FormInfo, *count);
7027 W_ERROR_HAVE_NO_MEMORY(info);
7028
7029 /* construct the list of form structures */
7030 for (i=0; i<num_builtin_forms; i++) {
7031 DEBUGADD(6,("Filling builtin form number [%d]\n",i));
7032 result = fill_form_info_1(info, &info[i].info1,
7033 &builtin_forms[i]);
7034 if (!W_ERROR_IS_OK(result)) {
7035 goto out;
7036 }
7037 }
7038
7039 for (i=0; i<num_user_forms; i++) {
7040 DEBUGADD(6,("Filling user form number [%d]\n",i));
7041 result = fill_form_info_1(info, &info[i+num_builtin_forms].info1,
7042 &user_forms[i]);
7043 if (!W_ERROR_IS_OK(result)) {
7044 goto out;
7045 }
7046 }
7047
7048 out:
7049 if (!W_ERROR_IS_OK(result)) {
7050 TALLOC_FREE(info);
7051 *count = 0;
7052 return result;
7053 }
7054
7055 *info_p = info;
7056
7057 return WERR_OK;
7058 }
7059
7060 /****************************************************************
7061 _spoolss_EnumForms
7062 ****************************************************************/
7063
7064 WERROR _spoolss_EnumForms(pipes_struct *p,
/* [<][>][^][v][top][bottom][index][help] */
7065 struct spoolss_EnumForms *r)
7066 {
7067 WERROR result;
7068 nt_forms_struct *user_forms = NULL;
7069 nt_forms_struct *builtin_forms = NULL;
7070 uint32_t num_user_forms;
7071 uint32_t num_builtin_forms;
7072
7073 *r->out.count = 0;
7074 *r->out.needed = 0;
7075 *r->out.info = NULL;
7076
7077 /* that's an [in out] buffer */
7078
7079 if (!r->in.buffer && (r->in.offered != 0) ) {
7080 return WERR_INVALID_PARAM;
7081 }
7082
7083 DEBUG(4,("_spoolss_EnumForms\n"));
7084 DEBUGADD(5,("Offered buffer size [%d]\n", r->in.offered));
7085 DEBUGADD(5,("Info level [%d]\n", r->in.level));
7086
7087 num_builtin_forms = get_builtin_ntforms(&builtin_forms);
7088 DEBUGADD(5,("Number of builtin forms [%d]\n", num_builtin_forms));
7089 num_user_forms = get_ntforms(&user_forms);
7090 DEBUGADD(5,("Number of user forms [%d]\n", num_user_forms));
7091
7092 if (num_user_forms + num_builtin_forms == 0) {
7093 SAFE_FREE(builtin_forms);
7094 SAFE_FREE(user_forms);
7095 return WERR_NO_MORE_ITEMS;
7096 }
7097
7098 switch (r->in.level) {
7099 case 1:
7100 result = spoolss_enumforms_level1(p->mem_ctx,
7101 builtin_forms,
7102 num_builtin_forms,
7103 user_forms,
7104 num_user_forms,
7105 r->out.info,
7106 r->out.count);
7107 break;
7108 default:
7109 result = WERR_UNKNOWN_LEVEL;
7110 break;
7111 }
7112
7113 SAFE_FREE(user_forms);
7114 SAFE_FREE(builtin_forms);
7115
7116 if (!W_ERROR_IS_OK(result)) {
7117 return result;
7118 }
7119
7120 *r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
7121 spoolss_EnumForms, NULL,
7122 *r->out.info, r->in.level,
7123 *r->out.count);
7124 *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
7125 *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, 0);
7126
7127 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
7128 }
7129
7130 /****************************************************************
7131 ****************************************************************/
7132
7133 static WERROR find_form_byname(const char *name,
/* [<][>][^][v][top][bottom][index][help] */
7134 nt_forms_struct *form)
7135 {
7136 nt_forms_struct *list = NULL;
7137 int num_forms = 0, i = 0;
7138
7139 if (get_a_builtin_ntform_by_string(name, form)) {
7140 return WERR_OK;
7141 }
7142
7143 num_forms = get_ntforms(&list);
7144 DEBUGADD(5,("Number of forms [%d]\n", num_forms));
7145
7146 if (num_forms == 0) {
7147 return WERR_BADFID;
7148 }
7149
7150 /* Check if the requested name is in the list of form structures */
7151 for (i = 0; i < num_forms; i++) {
7152
7153 DEBUG(4,("checking form %s (want %s)\n", list[i].name, name));
7154
7155 if (strequal(name, list[i].name)) {
7156 DEBUGADD(6,("Found form %s number [%d]\n", name, i));
7157 *form = list[i];
7158 SAFE_FREE(list);
7159 return WERR_OK;
7160 }
7161 }
7162
7163 SAFE_FREE(list);
7164
7165 return WERR_BADFID;
7166 }
7167
7168 /****************************************************************
7169 _spoolss_GetForm
7170 ****************************************************************/
7171
7172 WERROR _spoolss_GetForm(pipes_struct *p,
/* [<][>][^][v][top][bottom][index][help] */
7173 struct spoolss_GetForm *r)
7174 {
7175 WERROR result;
7176 nt_forms_struct form;
7177
7178 /* that's an [in out] buffer */
7179
7180 if (!r->in.buffer && (r->in.offered != 0)) {
7181 return WERR_INVALID_PARAM;
7182 }
7183
7184 DEBUG(4,("_spoolss_GetForm\n"));
7185 DEBUGADD(5,("Offered buffer size [%d]\n", r->in.offered));
7186 DEBUGADD(5,("Info level [%d]\n", r->in.level));
7187
7188 result = find_form_byname(r->in.form_name, &form);
7189 if (!W_ERROR_IS_OK(result)) {
7190 TALLOC_FREE(r->out.info);
7191 return result;
7192 }
7193
7194 switch (r->in.level) {
7195 case 1:
7196 result = fill_form_info_1(p->mem_ctx,
7197 &r->out.info->info1,
7198 &form);
7199 break;
7200
7201 default:
7202 result = WERR_UNKNOWN_LEVEL;
7203 break;
7204 }
7205
7206 if (!W_ERROR_IS_OK(result)) {
7207 TALLOC_FREE(r->out.info);
7208 return result;
7209 }
7210
7211 *r->out.needed = SPOOLSS_BUFFER_UNION(spoolss_FormInfo, NULL,
7212 r->out.info, r->in.level);
7213 r->out.info = SPOOLSS_BUFFER_OK(r->out.info, NULL);
7214
7215 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
7216 }
7217
7218 /****************************************************************************
7219 ****************************************************************************/
7220
7221 static WERROR fill_port_1(TALLOC_CTX *mem_ctx,
/* [<][>][^][v][top][bottom][index][help] */
7222 struct spoolss_PortInfo1 *r,
7223 const char *name)
7224 {
7225 r->port_name = talloc_strdup(mem_ctx, name);
7226 W_ERROR_HAVE_NO_MEMORY(r->port_name);
7227
7228 return WERR_OK;
7229 }
7230
7231 /****************************************************************************
7232 TODO: This probably needs distinguish between TCP/IP and Local ports
7233 somehow.
7234 ****************************************************************************/
7235
7236 static WERROR fill_port_2(TALLOC_CTX *mem_ctx,
/* [<][>][^][v][top][bottom][index][help] */
7237 struct spoolss_PortInfo2 *r,
7238 const char *name)
7239 {
7240 r->port_name = talloc_strdup(mem_ctx, name);
7241 W_ERROR_HAVE_NO_MEMORY(r->port_name);
7242
7243 r->monitor_name = talloc_strdup(mem_ctx, "Local Monitor");
7244 W_ERROR_HAVE_NO_MEMORY(r->monitor_name);
7245
7246 r->description = talloc_strdup(mem_ctx, SPL_LOCAL_PORT);
7247 W_ERROR_HAVE_NO_MEMORY(r->description);
7248
7249 r->port_type = SPOOLSS_PORT_TYPE_WRITE;
7250 r->reserved = 0;
7251
7252 return WERR_OK;
7253 }
7254
7255
7256 /****************************************************************************
7257 wrapper around the enumer ports command
7258 ****************************************************************************/
7259
7260 WERROR enumports_hook(TALLOC_CTX *ctx, int *count, char ***lines )
/* [<][>][^][v][top][bottom][index][help] */
7261 {
7262 char *cmd = lp_enumports_cmd();
7263 char **qlines = NULL;
7264 char *command = NULL;
7265 int numlines;
7266 int ret;
7267 int fd;
7268
7269 *count = 0;
7270 *lines = NULL;
7271
7272 /* if no hook then just fill in the default port */
7273
7274 if ( !*cmd ) {
7275 if (!(qlines = TALLOC_ARRAY( NULL, char*, 2 ))) {
7276 return WERR_NOMEM;
7277 }
7278 if (!(qlines[0] = talloc_strdup(qlines, SAMBA_PRINTER_PORT_NAME ))) {
7279 TALLOC_FREE(qlines);
7280 return WERR_NOMEM;
7281 }
7282 qlines[1] = NULL;
7283 numlines = 1;
7284 }
7285 else {
7286 /* we have a valid enumport command */
7287
7288 command = talloc_asprintf(ctx, "%s \"%d\"", cmd, 1);
7289 if (!command) {
7290 return WERR_NOMEM;
7291 }
7292
7293 DEBUG(10,("Running [%s]\n", command));
7294 ret = smbrun(command, &fd);
7295 DEBUG(10,("Returned [%d]\n", ret));
7296 TALLOC_FREE(command);
7297 if (ret != 0) {
7298 if (fd != -1) {
7299 close(fd);
7300 }
7301 return WERR_ACCESS_DENIED;
7302 }
7303
7304 numlines = 0;
7305 qlines = fd_lines_load(fd, &numlines, 0, NULL);
7306 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
7307 close(fd);
7308 }
7309
7310 *count = numlines;
7311 *lines = qlines;
7312
7313 return WERR_OK;
7314 }
7315
7316 /****************************************************************************
7317 enumports level 1.
7318 ****************************************************************************/
7319
7320 static WERROR enumports_level_1(TALLOC_CTX *mem_ctx,
/* [<][>][^][v][top][bottom][index][help] */
7321 union spoolss_PortInfo **info_p,
7322 uint32_t *count)
7323 {
7324 union spoolss_PortInfo *info = NULL;
7325 int i=0;
7326 WERROR result = WERR_OK;
7327 char **qlines = NULL;
7328 int numlines = 0;
7329
7330 result = enumports_hook(talloc_tos(), &numlines, &qlines );
7331 if (!W_ERROR_IS_OK(result)) {
7332 goto out;
7333 }
7334
7335 if (numlines) {
7336 info = TALLOC_ARRAY(mem_ctx, union spoolss_PortInfo, numlines);
7337 if (!info) {
7338 DEBUG(10,("Returning WERR_NOMEM\n"));
7339 result = WERR_NOMEM;
7340 goto out;
7341 }
7342
7343 for (i=0; i<numlines; i++) {
7344 DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
7345 result = fill_port_1(info, &info[i].info1, qlines[i]);
7346 if (!W_ERROR_IS_OK(result)) {
7347 goto out;
7348 }
7349 }
7350 }
7351 TALLOC_FREE(qlines);
7352
7353 out:
7354 if (!W_ERROR_IS_OK(result)) {
7355 TALLOC_FREE(info);
7356 TALLOC_FREE(qlines);
7357 *count = 0;
7358 *info_p = NULL;
7359 return result;
7360 }
7361
7362 *info_p = info;
7363 *count = numlines;
7364
7365 return WERR_OK;
7366 }
7367
7368 /****************************************************************************
7369 enumports level 2.
7370 ****************************************************************************/
7371
7372 static WERROR enumports_level_2(TALLOC_CTX *mem_ctx,
/* [<][>][^][v][top][bottom][index][help] */
7373 union spoolss_PortInfo **info_p,
7374 uint32_t *count)
7375 {
7376 union spoolss_PortInfo *info = NULL;
7377 int i=0;
7378 WERROR result = WERR_OK;
7379 char **qlines = NULL;
7380 int numlines = 0;
7381
7382 result = enumports_hook(talloc_tos(), &numlines, &qlines );
7383 if (!W_ERROR_IS_OK(result)) {
7384 goto out;
7385 }
7386
7387 if (numlines) {
7388 info = TALLOC_ARRAY(mem_ctx, union spoolss_PortInfo, numlines);
7389 if (!info) {
7390 DEBUG(10,("Returning WERR_NOMEM\n"));
7391 result = WERR_NOMEM;
7392 goto out;
7393 }
7394
7395 for (i=0; i<numlines; i++) {
7396 DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
7397 result = fill_port_2(info, &info[i].info2, qlines[i]);
7398 if (!W_ERROR_IS_OK(result)) {
7399 goto out;
7400 }
7401 }
7402 }
7403 TALLOC_FREE(qlines);
7404
7405 out:
7406 if (!W_ERROR_IS_OK(result)) {
7407 TALLOC_FREE(info);
7408 TALLOC_FREE(qlines);
7409 *count = 0;
7410 *info_p = NULL;
7411 return result;
7412 }
7413
7414 *info_p = info;
7415 *count = numlines;
7416
7417 return WERR_OK;
7418 }
7419
7420 /****************************************************************
7421 _spoolss_EnumPorts
7422 ****************************************************************/
7423
7424 WERROR _spoolss_EnumPorts(pipes_struct *p,
/* [<][>][^][v][top][bottom][index][help] */
7425 struct spoolss_EnumPorts *r)
7426 {
7427 WERROR result;
7428
7429 /* that's an [in out] buffer */
7430
7431 if (!r->in.buffer && (r->in.offered != 0)) {
7432 return WERR_INVALID_PARAM;
7433 }
7434
7435 DEBUG(4,("_spoolss_EnumPorts\n"));
7436
7437 *r->out.count = 0;
7438 *r->out.needed = 0;
7439 *r->out.info = NULL;
7440
7441 switch (r->in.level) {
7442 case 1:
7443 result = enumports_level_1(p->mem_ctx, r->out.info,
7444 r->out.count);
7445 break;
7446 case 2:
7447 result = enumports_level_2(p->mem_ctx, r->out.info,
7448 r->out.count);
7449 break;
7450 default:
7451 return WERR_UNKNOWN_LEVEL;
7452 }
7453
7454 if (!W_ERROR_IS_OK(result)) {
7455 return result;
7456 }
7457
7458 *r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
7459 spoolss_EnumPorts, NULL,
7460 *r->out.info, r->in.level,
7461 *r->out.count);
7462 *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
7463 *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, 0);
7464
7465 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
7466 }
7467
7468 /****************************************************************************
7469 ****************************************************************************/
7470
7471 static WERROR spoolss_addprinterex_level_2(pipes_struct *p,
/* [<][>][^][v][top][bottom][index][help] */
7472 const char *server,
7473 struct spoolss_SetPrinterInfoCtr *info_ctr,
7474 struct spoolss_DeviceMode *devmode,
7475 struct security_descriptor *sec_desc,
7476 struct spoolss_UserLevelCtr *user_ctr,
7477 struct policy_handle *handle)
7478 {
7479 NT_PRINTER_INFO_LEVEL *printer = NULL;
7480 fstring name;
7481 int snum;
7482 WERROR err = WERR_OK;
7483
7484 if ( !(printer = TALLOC_ZERO_P(NULL, NT_PRINTER_INFO_LEVEL)) ) {
7485 DEBUG(0,("spoolss_addprinterex_level_2: malloc fail.\n"));
7486 return WERR_NOMEM;
7487 }
7488
7489 /* convert from UNICODE to ASCII - this allocates the info_2 struct inside *printer.*/
7490 if (!convert_printer_info(info_ctr, printer)) {
7491 free_a_printer(&printer, 2);
7492 return WERR_NOMEM;
7493 }
7494
7495 /* check to see if the printer already exists */
7496
7497 if ((snum = print_queue_snum(printer->info_2->sharename)) != -1) {
7498 DEBUG(5, ("spoolss_addprinterex_level_2: Attempted to add a printer named [%s] when one already existed!\n",
7499 printer->info_2->sharename));
7500 free_a_printer(&printer, 2);
7501 return WERR_PRINTER_ALREADY_EXISTS;
7502 }
7503
7504 /* FIXME!!! smbd should check to see if the driver is installed before
7505 trying to add a printer like this --jerry */
7506
7507 if (*lp_addprinter_cmd() ) {
7508 if ( !add_printer_hook(p->mem_ctx, p->server_info->ptok,
7509 printer) ) {
7510 free_a_printer(&printer,2);
7511 return WERR_ACCESS_DENIED;
7512 }
7513 } else {
7514 DEBUG(0,("spoolss_addprinterex_level_2: add printer for printer %s called and no"
7515 "smb.conf parameter \"addprinter command\" is defined. This"
7516 "parameter must exist for this call to succeed\n",
7517 printer->info_2->sharename ));
7518 }
7519
7520 /* use our primary netbios name since get_a_printer() will convert
7521 it to what the client expects on a case by case basis */
7522
7523 slprintf(name, sizeof(name)-1, "\\\\%s\\%s", global_myname(),
7524 printer->info_2->sharename);
7525
7526
7527 if ((snum = print_queue_snum(printer->info_2->sharename)) == -1) {
7528 free_a_printer(&printer,2);
7529 return WERR_ACCESS_DENIED;
7530 }
7531
7532 /* you must be a printer admin to add a new printer */
7533 if (!print_access_check(p->server_info, snum, PRINTER_ACCESS_ADMINISTER)) {
7534 free_a_printer(&printer,2);
7535 return WERR_ACCESS_DENIED;
7536 }
7537
7538 /*
7539 * Do sanity check on the requested changes for Samba.
7540 */
7541
7542 if (!check_printer_ok(printer->info_2, snum)) {
7543 free_a_printer(&printer,2);
7544 return WERR_INVALID_PARAM;
7545 }
7546
7547 /*
7548 * When a printer is created, the drivername bound to the printer is used
7549 * to lookup previously saved driver initialization info, which is then
7550 * bound to the new printer, simulating what happens in the Windows arch.
7551 */
7552
7553 if (!devmode)
7554 {
7555 set_driver_init(printer, 2);
7556 }
7557 else
7558 {
7559 /* A valid devmode was included, convert and link it
7560 */
7561 DEBUGADD(10, ("spoolss_addprinterex_level_2: devmode included, converting\n"));
7562
7563 if (!convert_devicemode(printer->info_2->printername, devmode,
7564 &printer->info_2->devmode)) {
7565 return WERR_NOMEM;
7566 }
7567 }
7568
7569 /* write the ASCII on disk */
7570 err = mod_a_printer(printer, 2);
7571 if (!W_ERROR_IS_OK(err)) {
7572 free_a_printer(&printer,2);
7573 return err;
7574 }
7575
7576 if (!open_printer_hnd(p, handle, name, PRINTER_ACCESS_ADMINISTER)) {
7577 /* Handle open failed - remove addition. */
7578 del_a_printer(printer->info_2->sharename);
7579 free_a_printer(&printer,2);
7580 ZERO_STRUCTP(handle);
7581 return WERR_ACCESS_DENIED;
7582 }
7583
7584 update_c_setprinter(false);
7585 free_a_printer(&printer,2);
7586
7587 return WERR_OK;
7588 }
7589
7590 /****************************************************************
7591 _spoolss_AddPrinterEx
7592 ****************************************************************/
7593
7594 WERROR _spoolss_AddPrinterEx(pipes_struct *p,
/* [<][>][^][v][top][bottom][index][help] */
7595 struct spoolss_AddPrinterEx *r)
7596 {
7597 switch (r->in.info_ctr->level) {
7598 case 1:
7599 /* we don't handle yet */
7600 /* but I know what to do ... */
7601 return WERR_UNKNOWN_LEVEL;
7602 case 2:
7603 return spoolss_addprinterex_level_2(p, r->in.server,
7604 r->in.info_ctr,
7605 r->in.devmode_ctr->devmode,
7606 r->in.secdesc_ctr->sd,
7607 r->in.userlevel_ctr,
7608 r->out.handle);
7609 default:
7610 return WERR_UNKNOWN_LEVEL;
7611 }
7612 }
7613
7614 /****************************************************************
7615 _spoolss_AddPrinterDriver
7616 ****************************************************************/
7617
7618 WERROR _spoolss_AddPrinterDriver(pipes_struct *p,
/* [<][>][^][v][top][bottom][index][help] */
7619 struct spoolss_AddPrinterDriver *r)
7620 {
7621 uint32_t level = r->in.info_ctr->level;
7622 struct spoolss_AddDriverInfoCtr *info = r->in.info_ctr;
7623 WERROR err = WERR_OK;
7624 NT_PRINTER_DRIVER_INFO_LEVEL driver;
7625 const char *driver_name = NULL;
7626 uint32_t version;
7627 const char *fn;
7628
7629 switch (p->hdr_req.opnum) {
7630 case NDR_SPOOLSS_ADDPRINTERDRIVER:
7631 fn = "_spoolss_AddPrinterDriver";
7632 break;
7633 case NDR_SPOOLSS_ADDPRINTERDRIVEREX:
7634 fn = "_spoolss_AddPrinterDriverEx";
7635 break;
7636 default:
7637 return WERR_INVALID_PARAM;
7638 }
7639
7640
7641 /* FIXME */
7642 if (level != 3 && level != 6) {
7643 /* Clever hack from Martin Zielinski <mz@seh.de>
7644 * to allow downgrade from level 8 (Vista).
7645 */
7646 DEBUG(0,("%s: level %d not yet implemented\n", fn, level));
7647 return WERR_UNKNOWN_LEVEL;
7648 }
7649
7650 ZERO_STRUCT(driver);
7651
7652 if (!convert_printer_driver_info(info, &driver, level)) {
7653 err = WERR_NOMEM;
7654 goto done;
7655 }
7656
7657 DEBUG(5,("Cleaning driver's information\n"));
7658 err = clean_up_driver_struct(p, driver, level);
7659 if (!W_ERROR_IS_OK(err))
7660 goto done;
7661
7662 DEBUG(5,("Moving driver to final destination\n"));
7663 if( !W_ERROR_IS_OK(err = move_driver_to_download_area(p, driver, level,
7664 &err)) ) {
7665 goto done;
7666 }
7667
7668 if (add_a_printer_driver(driver, level)!=0) {
7669 err = WERR_ACCESS_DENIED;
7670 goto done;
7671 }
7672
7673 switch(level) {
7674 case 3:
7675 driver_name = driver.info_3->name ? driver.info_3->name : "";
7676 break;
7677 case 6:
7678 driver_name = driver.info_6->name ? driver.info_6->name : "";
7679 break;
7680 }
7681
7682 /*
7683 * I think this is where he DrvUpgradePrinter() hook would be
7684 * be called in a driver's interface DLL on a Windows NT 4.0/2k
7685 * server. Right now, we just need to send ourselves a message
7686 * to update each printer bound to this driver. --jerry
7687 */
7688
7689 if (!srv_spoolss_drv_upgrade_printer(driver_name)) {
7690 DEBUG(0,("%s: Failed to send message about upgrading driver [%s]!\n",
7691 fn, driver_name));
7692 }
7693
7694 /*
7695 * Based on the version (e.g. driver destination dir: 0=9x,2=Nt/2k,3=2k/Xp),
7696 * decide if the driver init data should be deleted. The rules are:
7697 * 1) never delete init data if it is a 9x driver, they don't use it anyway
7698 * 2) delete init data only if there is no 2k/Xp driver
7699 * 3) always delete init data
7700 * The generalized rule is always use init data from the highest order driver.
7701 * It is necessary to follow the driver install by an initialization step to
7702 * finish off this process.
7703 */
7704 if (level == 3)
7705 version = driver.info_3->cversion;
7706 else if (level == 6)
7707 version = driver.info_6->version;
7708 else
7709 version = -1;
7710 switch (version) {
7711 /*
7712 * 9x printer driver - never delete init data
7713 */
7714 case 0:
7715 DEBUG(10,("%s: init data not deleted for 9x driver [%s]\n",
7716 fn, driver_name));
7717 break;
7718
7719 /*
7720 * Nt or 2k (compatiblity mode) printer driver - only delete init data if
7721 * there is no 2k/Xp driver init data for this driver name.
7722 */
7723 case 2:
7724 {
7725 NT_PRINTER_DRIVER_INFO_LEVEL driver1;
7726
7727 if (!W_ERROR_IS_OK(get_a_printer_driver(&driver1, 3, driver_name, "Windows NT x86", 3))) {
7728 /*
7729 * No 2k/Xp driver found, delete init data (if any) for the new Nt driver.
7730 */
7731 if (!del_driver_init(driver_name))
7732 DEBUG(6,("%s: del_driver_init(%s) Nt failed!\n",
7733 fn, driver_name));
7734 } else {
7735 /*
7736 * a 2k/Xp driver was found, don't delete init data because Nt driver will use it.
7737 */
7738 free_a_printer_driver(driver1,3);
7739 DEBUG(10,("%s: init data not deleted for Nt driver [%s]\n",
7740 fn, driver_name));
7741 }
7742 }
7743 break;
7744
7745 /*
7746 * 2k or Xp printer driver - always delete init data
7747 */
7748 case 3:
7749 if (!del_driver_init(driver_name))
7750 DEBUG(6,("%s: del_driver_init(%s) 2k/Xp failed!\n",
7751 fn, driver_name));
7752 break;
7753
7754 default:
7755 DEBUG(0,("%s: invalid level=%d\n", fn, level));
7756 break;
7757 }
7758
7759
7760 done:
7761 free_a_printer_driver(driver, level);
7762 return err;
7763 }
7764
7765 /****************************************************************
7766 _spoolss_AddPrinterDriverEx
7767 ****************************************************************/
7768
7769 WERROR _spoolss_AddPrinterDriverEx(pipes_struct *p,
/* [<][>][^][v][top][bottom][index][help] */
7770 struct spoolss_AddPrinterDriverEx *r)
7771 {
7772 struct spoolss_AddPrinterDriver a;
7773
7774 /*
7775 * we only support the semantics of AddPrinterDriver()
7776 * i.e. only copy files that are newer than existing ones
7777 */
7778
7779 if (r->in.flags != APD_COPY_NEW_FILES) {
7780 return WERR_ACCESS_DENIED;
7781 }
7782
7783 a.in.servername = r->in.servername;
7784 a.in.info_ctr = r->in.info_ctr;
7785
7786 return _spoolss_AddPrinterDriver(p, &a);
7787 }
7788
7789 /****************************************************************************
7790 ****************************************************************************/
7791
7792 struct _spoolss_paths {
7793 int type;
7794 const char *share;
7795 const char *dir;
7796 };
7797
7798 enum { SPOOLSS_DRIVER_PATH, SPOOLSS_PRTPROCS_PATH };
7799
7800 static const struct _spoolss_paths spoolss_paths[]= {
7801 { SPOOLSS_DRIVER_PATH, "print$", "DRIVERS" },
7802 { SPOOLSS_PRTPROCS_PATH, "prnproc$", "PRTPROCS" }
7803 };
7804
7805 static WERROR compose_spoolss_server_path(TALLOC_CTX *mem_ctx,
/* [<][>][^][v][top][bottom][index][help] */
7806 const char *servername,
7807 const char *environment,
7808 int component,
7809 char **path)
7810 {
7811 const char *pservername = NULL;
7812 const char *long_archi = SPOOLSS_ARCHITECTURE_NT_X86;
7813 const char *short_archi;
7814
7815 *path = NULL;
7816
7817 /* environment may be empty */
7818 if (environment && strlen(environment)) {
7819 long_archi = environment;
7820 }
7821
7822 /* servername may be empty */
7823 if (servername && strlen(servername)) {
7824 pservername = canon_servername(servername);
7825
7826 if (!is_myname_or_ipaddr(pservername)) {
7827 return WERR_INVALID_PARAM;
7828 }
7829 }
7830
7831 if (!(short_archi = get_short_archi(long_archi))) {
7832 return WERR_INVALID_ENVIRONMENT;
7833 }
7834
7835 switch (component) {
7836 case SPOOLSS_PRTPROCS_PATH:
7837 case SPOOLSS_DRIVER_PATH:
7838 if (pservername) {
7839 *path = talloc_asprintf(mem_ctx,
7840 "\\\\%s\\%s\\%s",
7841 pservername,
7842 spoolss_paths[component].share,
7843 short_archi);
7844 } else {
7845 *path = talloc_asprintf(mem_ctx, "%s\\%s\\%s",
7846 SPOOLSS_DEFAULT_SERVER_PATH,
7847 spoolss_paths[component].dir,
7848 short_archi);
7849 }
7850 break;
7851 default:
7852 return WERR_INVALID_PARAM;
7853 }
7854
7855 if (!*path) {
7856 return WERR_NOMEM;
7857 }
7858
7859 return WERR_OK;
7860 }
7861
7862 /****************************************************************************
7863 ****************************************************************************/
7864
7865 static WERROR getprinterdriverdir_level_1(TALLOC_CTX *mem_ctx,
/* [<][>][^][v][top][bottom][index][help] */
7866 const char *servername,
7867 const char *environment,
7868 struct spoolss_DriverDirectoryInfo1 *r)
7869 {
7870 WERROR werr;
7871 char *path = NULL;
7872
7873 werr = compose_spoolss_server_path(mem_ctx,
7874 servername,
7875 environment,
7876 SPOOLSS_DRIVER_PATH,
7877 &path);
7878 if (!W_ERROR_IS_OK(werr)) {
7879 return werr;
7880 }
7881
7882 DEBUG(4,("printer driver directory: [%s]\n", path));
7883
7884 r->directory_name = path;
7885
7886 return WERR_OK;
7887 }
7888
7889 /****************************************************************
7890 _spoolss_GetPrinterDriverDirectory
7891 ****************************************************************/
7892
7893 WERROR _spoolss_GetPrinterDriverDirectory(pipes_struct *p,
/* [<][>][^][v][top][bottom][index][help] */
7894 struct spoolss_GetPrinterDriverDirectory *r)
7895 {
7896 WERROR werror;
7897
7898 /* that's an [in out] buffer */
7899
7900 if (!r->in.buffer && (r->in.offered != 0)) {
7901 return WERR_INVALID_PARAM;
7902 }
7903
7904 DEBUG(5,("_spoolss_GetPrinterDriverDirectory: level %d\n",
7905 r->in.level));
7906
7907 *r->out.needed = 0;
7908
7909 /* r->in.level is ignored */
7910
7911 werror = getprinterdriverdir_level_1(p->mem_ctx,
7912 r->in.server,
7913 r->in.environment,
7914 &r->out.info->info1);
7915 if (!W_ERROR_IS_OK(werror)) {
7916 TALLOC_FREE(r->out.info);
7917 return werror;
7918 }
7919
7920 *r->out.needed = SPOOLSS_BUFFER_UNION(spoolss_DriverDirectoryInfo, NULL,
7921 r->out.info, r->in.level);
7922 r->out.info = SPOOLSS_BUFFER_OK(r->out.info, NULL);
7923
7924 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
7925 }
7926
7927 /****************************************************************
7928 _spoolss_EnumPrinterData
7929 ****************************************************************/
7930
7931 WERROR _spoolss_EnumPrinterData(pipes_struct *p,
/* [<][>][^][v][top][bottom][index][help] */
7932 struct spoolss_EnumPrinterData *r)
7933 {
7934 NT_PRINTER_INFO_LEVEL *printer = NULL;
7935 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
7936 int snum;
7937 WERROR result;
7938 REGISTRY_VALUE *val = NULL;
7939 NT_PRINTER_DATA *p_data;
7940 int i, key_index, num_values;
7941 int name_length;
7942
7943 *r->out.value_needed = 0;
7944 *r->out.type = REG_NONE;
7945 *r->out.data_needed = 0;
7946
7947 DEBUG(5,("_spoolss_EnumPrinterData\n"));
7948
7949 if (!Printer) {
7950 DEBUG(2,("_spoolss_EnumPrinterData: Invalid handle (%s:%u:%u).\n",
7951 OUR_HANDLE(r->in.handle)));
7952 return WERR_BADFID;
7953 }
7954
7955 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
7956 return WERR_BADFID;
7957 }
7958
7959 result = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
7960 if (!W_ERROR_IS_OK(result)) {
7961 return result;
7962 }
7963
7964 p_data = printer->info_2->data;
7965 key_index = lookup_printerkey( p_data, SPOOL_PRINTERDATA_KEY );
7966
7967 result = WERR_OK;
7968
7969 /*
7970 * The NT machine wants to know the biggest size of value and data
7971 *
7972 * cf: MSDN EnumPrinterData remark section
7973 */
7974
7975 if (!r->in.value_offered && !r->in.data_offered && (key_index != -1)) {
7976
7977 uint32_t biggest_valuesize = 0;
7978 uint32_t biggest_datasize = 0;
7979
7980 DEBUGADD(6,("Activating NT mega-hack to find sizes\n"));
7981
7982 num_values = regval_ctr_numvals( p_data->keys[key_index].values );
7983
7984 for ( i=0; i<num_values; i++ )
7985 {
7986 val = regval_ctr_specific_value( p_data->keys[key_index].values, i );
7987
7988 name_length = strlen(val->valuename);
7989 if ( strlen(val->valuename) > biggest_valuesize )
7990 biggest_valuesize = name_length;
7991
7992 if ( val->size > biggest_datasize )
7993 biggest_datasize = val->size;
7994
7995 DEBUG(6,("current values: [%d], [%d]\n", biggest_valuesize,
7996 biggest_datasize));
7997 }
7998
7999 /* the value is an UNICODE string but real_value_size is the length
8000 in bytes including the trailing 0 */
8001
8002 *r->out.value_needed = 2 * (1 + biggest_valuesize);
8003 *r->out.data_needed = biggest_datasize;
8004
8005 DEBUG(6,("final values: [%d], [%d]\n",
8006 *r->out.value_needed, *r->out.data_needed));
8007
8008 goto done;
8009 }
8010
8011 /*
8012 * the value len is wrong in NT sp3
8013 * that's the number of bytes not the number of unicode chars
8014 */
8015
8016 if (key_index != -1) {
8017 val = regval_ctr_specific_value(p_data->keys[key_index].values,
8018 r->in.enum_index);
8019 }
8020
8021 if (!val) {
8022
8023 /* out_value should default to "" or else NT4 has
8024 problems unmarshalling the response */
8025
8026 if (r->in.value_offered) {
8027 *r->out.value_needed = 1;
8028 r->out.value_name = talloc_strdup(r, "");
8029 if (!r->out.value_name) {
8030 result = WERR_NOMEM;
8031 goto done;
8032 }
8033 } else {
8034 r->out.value_name = NULL;
8035 *r->out.value_needed = 0;
8036 }
8037
8038 /* the data is counted in bytes */
8039
8040 *r->out.data_needed = r->in.data_offered;
8041
8042 result = WERR_NO_MORE_ITEMS;
8043 } else {
8044 /*
8045 * the value is:
8046 * - counted in bytes in the request
8047 * - counted in UNICODE chars in the max reply
8048 * - counted in bytes in the real size
8049 *
8050 * take a pause *before* coding not *during* coding
8051 */
8052
8053 /* name */
8054 if (r->in.value_offered) {
8055 r->out.value_name = talloc_strdup(r, regval_name(val));
8056 if (!r->out.value_name) {
8057 result = WERR_NOMEM;
8058 goto done;
8059 }
8060 *r->out.value_needed = strlen_m(regval_name(val));
8061 } else {
8062 r->out.value_name = NULL;
8063 *r->out.value_needed = 0;
8064 }
8065
8066 /* type */
8067
8068 *r->out.type = regval_type(val);
8069
8070 /* data - counted in bytes */
8071
8072 if (r->out.data && regval_size(val)) {
8073 memcpy(r->out.data, regval_data_p(val), regval_size(val));
8074 }
8075
8076 *r->out.data_needed = regval_size(val);
8077 }
8078
8079 done:
8080 free_a_printer(&printer, 2);
8081 return result;
8082 }
8083
8084 /****************************************************************
8085 _spoolss_SetPrinterData
8086 ****************************************************************/
8087
8088 WERROR _spoolss_SetPrinterData(pipes_struct *p,
/* [<][>][^][v][top][bottom][index][help] */
8089 struct spoolss_SetPrinterData *r)
8090 {
8091 NT_PRINTER_INFO_LEVEL *printer = NULL;
8092 int snum=0;
8093 WERROR result = WERR_OK;
8094 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
8095 DATA_BLOB blob;
8096
8097 DEBUG(5,("_spoolss_SetPrinterData\n"));
8098
8099 if (!Printer) {
8100 DEBUG(2,("_spoolss_SetPrinterData: Invalid handle (%s:%u:%u).\n",
8101 OUR_HANDLE(r->in.handle)));
8102 return WERR_BADFID;
8103 }
8104
8105 if (Printer->printer_type == SPLHND_SERVER) {
8106 DEBUG(10,("_spoolss_SetPrinterData: "
8107 "Not implemented for server handles yet\n"));
8108 return WERR_INVALID_PARAM;
8109 }
8110
8111 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
8112 return WERR_BADFID;
8113 }
8114
8115 /*
8116 * Access check : NT returns "access denied" if you make a
8117 * SetPrinterData call without the necessary privildge.
8118 * we were originally returning OK if nothing changed
8119 * which made Win2k issue **a lot** of SetPrinterData
8120 * when connecting to a printer --jerry
8121 */
8122
8123 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
8124 DEBUG(3,("_spoolss_SetPrinterData: "
8125 "change denied by handle access permissions\n"));
8126 result = WERR_ACCESS_DENIED;
8127 goto done;
8128 }
8129
8130 result = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8131 if (!W_ERROR_IS_OK(result)) {
8132 return result;
8133 }
8134
8135 result = push_spoolss_PrinterData(p->mem_ctx, &blob,
8136 r->in.type, &r->in.data);
8137 if (!W_ERROR_IS_OK(result)) {
8138 goto done;
8139 }
8140
8141 /*
8142 * When client side code sets a magic printer data key, detect it and save
8143 * the current printer data and the magic key's data (its the DEVMODE) for
8144 * future printer/driver initializations.
8145 */
8146 if ((r->in.type == REG_BINARY) && strequal(r->in.value_name, PHANTOM_DEVMODE_KEY)) {
8147 /* Set devmode and printer initialization info */
8148 result = save_driver_init(printer, 2, blob.data, blob.length);
8149
8150 srv_spoolss_reset_printerdata(printer->info_2->drivername);
8151
8152 goto done;
8153 }
8154
8155 result = set_printer_dataex(printer, SPOOL_PRINTERDATA_KEY,
8156 r->in.value_name, r->in.type,
8157 blob.data, blob.length);
8158 if (W_ERROR_IS_OK(result)) {
8159 result = mod_a_printer(printer, 2);
8160 }
8161
8162 done:
8163 free_a_printer(&printer, 2);
8164
8165 return result;
8166 }
8167
8168 /****************************************************************
8169 _spoolss_ResetPrinter
8170 ****************************************************************/
8171
8172 WERROR _spoolss_ResetPrinter(pipes_struct *p,
/* [<][>][^][v][top][bottom][index][help] */
8173 struct spoolss_ResetPrinter *r)
8174 {
8175 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
8176 int snum;
8177
8178 DEBUG(5,("_spoolss_ResetPrinter\n"));
8179
8180 /*
8181 * All we do is to check to see if the handle and queue is valid.
8182 * This call really doesn't mean anything to us because we only
8183 * support RAW printing. --jerry
8184 */
8185
8186 if (!Printer) {
8187 DEBUG(2,("_spoolss_ResetPrinter: Invalid handle (%s:%u:%u).\n",
8188 OUR_HANDLE(r->in.handle)));
8189 return WERR_BADFID;
8190 }
8191
8192 if (!get_printer_snum(p, r->in.handle, &snum, NULL))
8193 return WERR_BADFID;
8194
8195
8196 /* blindly return success */
8197 return WERR_OK;
8198 }
8199
8200 /****************************************************************
8201 _spoolss_DeletePrinterData
8202 ****************************************************************/
8203
8204 WERROR _spoolss_DeletePrinterData(pipes_struct *p,
/* [<][>][^][v][top][bottom][index][help] */
8205 struct spoolss_DeletePrinterData *r)
8206 {
8207 NT_PRINTER_INFO_LEVEL *printer = NULL;
8208 int snum=0;
8209 WERROR status = WERR_OK;
8210 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
8211
8212 DEBUG(5,("_spoolss_DeletePrinterData\n"));
8213
8214 if (!Printer) {
8215 DEBUG(2,("_spoolss_DeletePrinterData: Invalid handle (%s:%u:%u).\n",
8216 OUR_HANDLE(r->in.handle)));
8217 return WERR_BADFID;
8218 }
8219
8220 if (!get_printer_snum(p, r->in.handle, &snum, NULL))
8221 return WERR_BADFID;
8222
8223 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
8224 DEBUG(3, ("_spoolss_DeletePrinterData: "
8225 "printer properties change denied by handle\n"));
8226 return WERR_ACCESS_DENIED;
8227 }
8228
8229 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8230 if (!W_ERROR_IS_OK(status))
8231 return status;
8232
8233 if (!r->in.value_name) {
8234 free_a_printer(&printer, 2);
8235 return WERR_NOMEM;
8236 }
8237
8238 status = delete_printer_dataex( printer, SPOOL_PRINTERDATA_KEY,
8239 r->in.value_name );
8240
8241 if ( W_ERROR_IS_OK(status) )
8242 mod_a_printer( printer, 2 );
8243
8244 free_a_printer(&printer, 2);
8245
8246 return status;
8247 }
8248
8249 /****************************************************************
8250 _spoolss_AddForm
8251 ****************************************************************/
8252
8253 WERROR _spoolss_AddForm(pipes_struct *p,
/* [<][>][^][v][top][bottom][index][help] */
8254 struct spoolss_AddForm *r)
8255 {
8256 struct spoolss_AddFormInfo1 *form = r->in.info.info1;
8257 nt_forms_struct tmpForm;
8258 int snum = -1;
8259 WERROR status = WERR_OK;
8260 NT_PRINTER_INFO_LEVEL *printer = NULL;
8261 SE_PRIV se_printop = SE_PRINT_OPERATOR;
8262
8263 int count=0;
8264 nt_forms_struct *list=NULL;
8265 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
8266
8267 DEBUG(5,("_spoolss_AddForm\n"));
8268
8269 if (!Printer) {
8270 DEBUG(2,("_spoolss_AddForm: Invalid handle (%s:%u:%u).\n",
8271 OUR_HANDLE(r->in.handle)));
8272 return WERR_BADFID;
8273 }
8274
8275
8276 /* forms can be added on printer of on the print server handle */
8277
8278 if ( Printer->printer_type == SPLHND_PRINTER )
8279 {
8280 if (!get_printer_snum(p, r->in.handle, &snum, NULL))
8281 return WERR_BADFID;
8282
8283 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8284 if (!W_ERROR_IS_OK(status))
8285 goto done;
8286 }
8287
8288 /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
8289 and not a printer admin, then fail */
8290
8291 if ((p->server_info->utok.uid != sec_initial_uid()) &&
8292 !user_has_privileges(p->server_info->ptok, &se_printop) &&
8293 !token_contains_name_in_list(uidtoname(p->server_info->utok.uid),
8294 NULL, NULL,
8295 p->server_info->ptok,
8296 lp_printer_admin(snum))) {
8297 DEBUG(2,("_spoolss_Addform: denied by insufficient permissions.\n"));
8298 return WERR_ACCESS_DENIED;
8299 }
8300
8301 /* can't add if builtin */
8302
8303 if (get_a_builtin_ntform_by_string(form->form_name, &tmpForm)) {
8304 status = WERR_FILE_EXISTS;
8305 goto done;
8306 }
8307
8308 count = get_ntforms(&list);
8309
8310 if(!add_a_form(&list, form, &count)) {
8311 status = WERR_NOMEM;
8312 goto done;
8313 }
8314
8315 become_root();
8316 write_ntforms(&list, count);
8317 unbecome_root();
8318
8319 /*
8320 * ChangeID must always be set if this is a printer
8321 */
8322
8323 if ( Printer->printer_type == SPLHND_PRINTER )
8324 status = mod_a_printer(printer, 2);
8325
8326 done:
8327 if ( printer )
8328 free_a_printer(&printer, 2);
8329 SAFE_FREE(list);
8330
8331 return status;
8332 }
8333
8334 /****************************************************************
8335 _spoolss_DeleteForm
8336 ****************************************************************/
8337
8338 WERROR _spoolss_DeleteForm(pipes_struct *p,
/* [<][>][^][v][top][bottom][index][help] */
8339 struct spoolss_DeleteForm *r)
8340 {
8341 const char *form_name = r->in.form_name;
8342 nt_forms_struct tmpForm;
8343 int count=0;
8344 nt_forms_struct *list=NULL;
8345 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
8346 int snum = -1;
8347 WERROR status = WERR_OK;
8348 NT_PRINTER_INFO_LEVEL *printer = NULL;
8349 SE_PRIV se_printop = SE_PRINT_OPERATOR;
8350 bool ret = false;
8351
8352 DEBUG(5,("_spoolss_DeleteForm\n"));
8353
8354 if (!Printer) {
8355 DEBUG(2,("_spoolss_DeleteForm: Invalid handle (%s:%u:%u).\n",
8356 OUR_HANDLE(r->in.handle)));
8357 return WERR_BADFID;
8358 }
8359
8360 /* forms can be deleted on printer of on the print server handle */
8361
8362 if ( Printer->printer_type == SPLHND_PRINTER )
8363 {
8364 if (!get_printer_snum(p, r->in.handle, &snum, NULL))
8365 return WERR_BADFID;
8366
8367 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8368 if (!W_ERROR_IS_OK(status))
8369 goto done;
8370 }
8371
8372 if ((p->server_info->utok.uid != sec_initial_uid()) &&
8373 !user_has_privileges(p->server_info->ptok, &se_printop) &&
8374 !token_contains_name_in_list(uidtoname(p->server_info->utok.uid),
8375 NULL, NULL,
8376 p->server_info->ptok,
8377 lp_printer_admin(snum))) {
8378 DEBUG(2,("_spoolss_DeleteForm: denied by insufficient permissions.\n"));
8379 return WERR_ACCESS_DENIED;
8380 }
8381
8382
8383 /* can't delete if builtin */
8384
8385 if (get_a_builtin_ntform_by_string(form_name,&tmpForm)) {
8386 status = WERR_INVALID_PARAM;
8387 goto done;
8388 }
8389
8390 count = get_ntforms(&list);
8391
8392 become_root();
8393 ret = delete_a_form(&list, form_name, &count, &status);
8394 unbecome_root();
8395 if (ret == false) {
8396 goto done;
8397 }
8398
8399 /*
8400 * ChangeID must always be set if this is a printer
8401 */
8402
8403 if ( Printer->printer_type == SPLHND_PRINTER )
8404 status = mod_a_printer(printer, 2);
8405
8406 done:
8407 if ( printer )
8408 free_a_printer(&printer, 2);
8409 SAFE_FREE(list);
8410
8411 return status;
8412 }
8413
8414 /****************************************************************
8415 _spoolss_SetForm
8416 ****************************************************************/
8417
8418 WERROR _spoolss_SetForm(pipes_struct *p,
/* [<][>][^][v][top][bottom][index][help] */
8419 struct spoolss_SetForm *r)
8420 {
8421 struct spoolss_AddFormInfo1 *form = r->in.info.info1;
8422 nt_forms_struct tmpForm;
8423 int snum = -1;
8424 WERROR status = WERR_OK;
8425 NT_PRINTER_INFO_LEVEL *printer = NULL;
8426 SE_PRIV se_printop = SE_PRINT_OPERATOR;
8427
8428 int count=0;
8429 nt_forms_struct *list=NULL;
8430 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
8431
8432 DEBUG(5,("_spoolss_SetForm\n"));
8433
8434 if (!Printer) {
8435 DEBUG(2,("_spoolss_SetForm: Invalid handle (%s:%u:%u).\n",
8436 OUR_HANDLE(r->in.handle)));
8437 return WERR_BADFID;
8438 }
8439
8440 /* forms can be modified on printer of on the print server handle */
8441
8442 if ( Printer->printer_type == SPLHND_PRINTER )
8443 {
8444 if (!get_printer_snum(p, r->in.handle, &snum, NULL))
8445 return WERR_BADFID;
8446
8447 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8448 if (!W_ERROR_IS_OK(status))
8449 goto done;
8450 }
8451
8452 /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
8453 and not a printer admin, then fail */
8454
8455 if ((p->server_info->utok.uid != sec_initial_uid()) &&
8456 !user_has_privileges(p->server_info->ptok, &se_printop) &&
8457 !token_contains_name_in_list(uidtoname(p->server_info->utok.uid),
8458 NULL, NULL,
8459 p->server_info->ptok,
8460 lp_printer_admin(snum))) {
8461 DEBUG(2,("_spoolss_Setform: denied by insufficient permissions.\n"));
8462 return WERR_ACCESS_DENIED;
8463 }
8464
8465 /* can't set if builtin */
8466 if (get_a_builtin_ntform_by_string(form->form_name, &tmpForm)) {
8467 status = WERR_INVALID_PARAM;
8468 goto done;
8469 }
8470
8471 count = get_ntforms(&list);
8472 update_a_form(&list, form, count);
8473 become_root();
8474 write_ntforms(&list, count);
8475 unbecome_root();
8476
8477 /*
8478 * ChangeID must always be set if this is a printer
8479 */
8480
8481 if ( Printer->printer_type == SPLHND_PRINTER )
8482 status = mod_a_printer(printer, 2);
8483
8484
8485 done:
8486 if ( printer )
8487 free_a_printer(&printer, 2);
8488 SAFE_FREE(list);
8489
8490 return status;
8491 }
8492
8493 /****************************************************************************
8494 fill_print_processor1
8495 ****************************************************************************/
8496
8497 static WERROR fill_print_processor1(TALLOC_CTX *mem_ctx,
/* [<][>][^][v][top][bottom][index][help] */
8498 struct spoolss_PrintProcessorInfo1 *r,
8499 const char *print_processor_name)
8500 {
8501 r->print_processor_name = talloc_strdup(mem_ctx, print_processor_name);
8502 W_ERROR_HAVE_NO_MEMORY(r->print_processor_name);
8503
8504 return WERR_OK;
8505 }
8506
8507 /****************************************************************************
8508 enumprintprocessors level 1.
8509 ****************************************************************************/
8510
8511 static WERROR enumprintprocessors_level_1(TALLOC_CTX *mem_ctx,
/* [<][>][^][v][top][bottom][index][help] */
8512 union spoolss_PrintProcessorInfo **info_p,
8513 uint32_t *count)
8514 {
8515 union spoolss_PrintProcessorInfo *info;
8516 WERROR result;
8517
8518 info = TALLOC_ARRAY(mem_ctx, union spoolss_PrintProcessorInfo, 1);
8519 W_ERROR_HAVE_NO_MEMORY(info);
8520
8521 *count = 1;
8522
8523 result = fill_print_processor1(info, &info[0].info1, "winprint");
8524 if (!W_ERROR_IS_OK(result)) {
8525 goto out;
8526 }
8527
8528 out:
8529 if (!W_ERROR_IS_OK(result)) {
8530 TALLOC_FREE(info);
8531 *count = 0;
8532 return result;
8533 }
8534
8535 *info_p = info;
8536
8537 return WERR_OK;
8538 }
8539
8540 /****************************************************************
8541 _spoolss_EnumPrintProcessors
8542 ****************************************************************/
8543
8544 WERROR _spoolss_EnumPrintProcessors(pipes_struct *p,
/* [<][>][^][v][top][bottom][index][help] */
8545 struct spoolss_EnumPrintProcessors *r)
8546 {
8547 WERROR result;
8548
8549 /* that's an [in out] buffer */
8550
8551 if (!r->in.buffer && (r->in.offered != 0)) {
8552 return WERR_INVALID_PARAM;
8553 }
8554
8555 DEBUG(5,("_spoolss_EnumPrintProcessors\n"));
8556
8557 /*
8558 * Enumerate the print processors ...
8559 *
8560 * Just reply with "winprint", to keep NT happy
8561 * and I can use my nice printer checker.
8562 */
8563
8564 *r->out.count = 0;
8565 *r->out.needed = 0;
8566 *r->out.info = NULL;
8567
8568 switch (r->in.level) {
8569 case 1:
8570 result = enumprintprocessors_level_1(p->mem_ctx, r->out.info,
8571 r->out.count);
8572 break;
8573 default:
8574 return WERR_UNKNOWN_LEVEL;
8575 }
8576
8577 if (!W_ERROR_IS_OK(result)) {
8578 return result;
8579 }
8580
8581 *r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
8582 spoolss_EnumPrintProcessors, NULL,
8583 *r->out.info, r->in.level,
8584 *r->out.count);
8585 *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
8586 *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, 0);
8587
8588 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
8589 }
8590
8591 /****************************************************************************
8592 fill_printprocdatatype1
8593 ****************************************************************************/
8594
8595 static WERROR fill_printprocdatatype1(TALLOC_CTX *mem_ctx,
/* [<][>][^][v][top][bottom][index][help] */
8596 struct spoolss_PrintProcDataTypesInfo1 *r,
8597 const char *name_array)
8598 {
8599 r->name_array = talloc_strdup(mem_ctx, name_array);
8600 W_ERROR_HAVE_NO_MEMORY(r->name_array);
8601
8602 return WERR_OK;
8603 }
8604
8605 /****************************************************************************
8606 enumprintprocdatatypes level 1.
8607 ****************************************************************************/
8608
8609 static WERROR enumprintprocdatatypes_level_1(TALLOC_CTX *mem_ctx,
/* [<][>][^][v][top][bottom][index][help] */
8610 union spoolss_PrintProcDataTypesInfo **info_p,
8611 uint32_t *count)
8612 {
8613 WERROR result;
8614 union spoolss_PrintProcDataTypesInfo *info;
8615
8616 info = TALLOC_ARRAY(mem_ctx, union spoolss_PrintProcDataTypesInfo, 1);
8617 W_ERROR_HAVE_NO_MEMORY(info);
8618
8619 *count = 1;
8620
8621 result = fill_printprocdatatype1(info, &info[0].info1, "RAW");
8622 if (!W_ERROR_IS_OK(result)) {
8623 goto out;
8624 }
8625
8626 out:
8627 if (!W_ERROR_IS_OK(result)) {
8628 TALLOC_FREE(info);
8629 *count = 0;
8630 return result;
8631 }
8632
8633 *info_p = info;
8634
8635 return WERR_OK;
8636 }
8637
8638 /****************************************************************
8639 _spoolss_EnumPrintProcDataTypes
8640 ****************************************************************/
8641
8642 WERROR _spoolss_EnumPrintProcDataTypes(pipes_struct *p,
/* [<][>][^][v][top][bottom][index][help] */
8643 struct spoolss_EnumPrintProcDataTypes *r)
8644 {
8645 WERROR result;
8646
8647 /* that's an [in out] buffer */
8648
8649 if (!r->in.buffer && (r->in.offered != 0)) {
8650 return WERR_INVALID_PARAM;
8651 }
8652
8653 DEBUG(5,("_spoolss_EnumPrintProcDataTypes\n"));
8654
8655 *r->out.count = 0;
8656 *r->out.needed = 0;
8657 *r->out.info = NULL;
8658
8659 switch (r->in.level) {
8660 case 1:
8661 result = enumprintprocdatatypes_level_1(p->mem_ctx, r->out.info,
8662 r->out.count);
8663 break;
8664 default:
8665 return WERR_UNKNOWN_LEVEL;
8666 }
8667
8668 *r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
8669 spoolss_EnumPrintProcDataTypes, NULL,
8670 *r->out.info, r->in.level,
8671 *r->out.count);
8672 *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
8673 *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, 0);
8674
8675 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
8676 }
8677
8678 /****************************************************************************
8679 fill_monitor_1
8680 ****************************************************************************/
8681
8682 static WERROR fill_monitor_1(TALLOC_CTX *mem_ctx,
/* [<][>][^][v][top][bottom][index][help] */
8683 struct spoolss_MonitorInfo1 *r,
8684 const char *monitor_name)
8685 {
8686 r->monitor_name = talloc_strdup(mem_ctx, monitor_name);
8687 W_ERROR_HAVE_NO_MEMORY(r->monitor_name);
8688
8689 return WERR_OK;
8690 }
8691
8692 /****************************************************************************
8693 fill_monitor_2
8694 ****************************************************************************/
8695
8696 static WERROR fill_monitor_2(TALLOC_CTX *mem_ctx,
/* [<][>][^][v][top][bottom][index][help] */
8697 struct spoolss_MonitorInfo2 *r,
8698 const char *monitor_name,
8699 const char *environment,
8700 const char *dll_name)
8701 {
8702 r->monitor_name = talloc_strdup(mem_ctx, monitor_name);
8703 W_ERROR_HAVE_NO_MEMORY(r->monitor_name);
8704 r->environment = talloc_strdup(mem_ctx, environment);
8705 W_ERROR_HAVE_NO_MEMORY(r->environment);
8706 r->dll_name = talloc_strdup(mem_ctx, dll_name);
8707 W_ERROR_HAVE_NO_MEMORY(r->dll_name);
8708
8709 return WERR_OK;
8710 }
8711
8712 /****************************************************************************
8713 enumprintmonitors level 1.
8714 ****************************************************************************/
8715
8716 static WERROR enumprintmonitors_level_1(TALLOC_CTX *mem_ctx,
/* [<][>][^][v][top][bottom][index][help] */
8717 union spoolss_MonitorInfo **info_p,
8718 uint32_t *count)
8719 {
8720 union spoolss_MonitorInfo *info;
8721 WERROR result = WERR_OK;
8722
8723 info = TALLOC_ARRAY(mem_ctx, union spoolss_MonitorInfo, 2);
8724 W_ERROR_HAVE_NO_MEMORY(info);
8725
8726 *count = 2;
8727
8728 result = fill_monitor_1(info, &info[0].info1,
8729 SPL_LOCAL_PORT);
8730 if (!W_ERROR_IS_OK(result)) {
8731 goto out;
8732 }
8733
8734 result = fill_monitor_1(info, &info[1].info1,
8735 SPL_TCPIP_PORT);
8736 if (!W_ERROR_IS_OK(result)) {
8737 goto out;
8738 }
8739
8740 out:
8741 if (!W_ERROR_IS_OK(result)) {
8742 TALLOC_FREE(info);
8743 *count = 0;
8744 return result;
8745 }
8746
8747 *info_p = info;
8748
8749 return WERR_OK;
8750 }
8751
8752 /****************************************************************************
8753 enumprintmonitors level 2.
8754 ****************************************************************************/
8755
8756 static WERROR enumprintmonitors_level_2(TALLOC_CTX *mem_ctx,
/* [<][>][^][v][top][bottom][index][help] */
8757 union spoolss_MonitorInfo **info_p,
8758 uint32_t *count)
8759 {
8760 union spoolss_MonitorInfo *info;
8761 WERROR result = WERR_OK;
8762
8763 info = TALLOC_ARRAY(mem_ctx, union spoolss_MonitorInfo, 2);
8764 W_ERROR_HAVE_NO_MEMORY(info);
8765
8766 *count = 2;
8767
8768 result = fill_monitor_2(info, &info[0].info2,
8769 SPL_LOCAL_PORT,
8770 "Windows NT X86", /* FIXME */
8771 "localmon.dll");
8772 if (!W_ERROR_IS_OK(result)) {
8773 goto out;
8774 }
8775
8776 result = fill_monitor_2(info, &info[1].info2,
8777 SPL_TCPIP_PORT,
8778 "Windows NT X86", /* FIXME */
8779 "tcpmon.dll");
8780 if (!W_ERROR_IS_OK(result)) {
8781 goto out;
8782 }
8783
8784 out:
8785 if (!W_ERROR_IS_OK(result)) {
8786 TALLOC_FREE(info);
8787 *count = 0;
8788 return result;
8789 }
8790
8791 *info_p = info;
8792
8793 return WERR_OK;
8794 }
8795
8796 /****************************************************************
8797 _spoolss_EnumMonitors
8798 ****************************************************************/
8799
8800 WERROR _spoolss_EnumMonitors(pipes_struct *p,
/* [<][>][^][v][top][bottom][index][help] */
8801 struct spoolss_EnumMonitors *r)
8802 {
8803 WERROR result;
8804
8805 /* that's an [in out] buffer */
8806
8807 if (!r->in.buffer && (r->in.offered != 0)) {
8808 return WERR_INVALID_PARAM;
8809 }
8810
8811 DEBUG(5,("_spoolss_EnumMonitors\n"));
8812
8813 /*
8814 * Enumerate the print monitors ...
8815 *
8816 * Just reply with "Local Port", to keep NT happy
8817 * and I can use my nice printer checker.
8818 */
8819
8820 *r->out.count = 0;
8821 *r->out.needed = 0;
8822 *r->out.info = NULL;
8823
8824 switch (r->in.level) {
8825 case 1:
8826 result = enumprintmonitors_level_1(p->mem_ctx, r->out.info,
8827 r->out.count);
8828 break;
8829 case 2:
8830 result = enumprintmonitors_level_2(p->mem_ctx, r->out.info,
8831 r->out.count);
8832 break;
8833 default:
8834 return WERR_UNKNOWN_LEVEL;
8835 }
8836
8837 if (!W_ERROR_IS_OK(result)) {
8838 return result;
8839 }
8840
8841 *r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
8842 spoolss_EnumMonitors, NULL,
8843 *r->out.info, r->in.level,
8844 *r->out.count);
8845 *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
8846 *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, 0);
8847
8848 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
8849 }
8850
8851 /****************************************************************************
8852 ****************************************************************************/
8853
8854 static WERROR getjob_level_1(TALLOC_CTX *mem_ctx,
/* [<][>][^][v][top][bottom][index][help] */
8855 const print_queue_struct *queue,
8856 int count, int snum,
8857 const NT_PRINTER_INFO_LEVEL *ntprinter,
8858 uint32_t jobid,
8859 struct spoolss_JobInfo1 *r)
8860 {
8861 int i = 0;
8862 bool found = false;
8863
8864 for (i=0; i<count && found == false; i++) {
8865 if (queue[i].job == (int)jobid) {
8866 found = true;
8867 }
8868 }
8869
8870 if (found == false) {
8871 /* NT treats not found as bad param... yet another bad choice */
8872 return WERR_INVALID_PARAM;
8873 }
8874
8875 return fill_job_info1(mem_ctx,
8876 r,
8877 &queue[i-1],
8878 i,
8879 snum,
8880 ntprinter);
8881 }
8882
8883 /****************************************************************************
8884 ****************************************************************************/
8885
8886 static WERROR getjob_level_2(TALLOC_CTX *mem_ctx,
/* [<][>][^][v][top][bottom][index][help] */
8887 const print_queue_struct *queue,
8888 int count, int snum,
8889 const NT_PRINTER_INFO_LEVEL *ntprinter,
8890 uint32_t jobid,
8891 struct spoolss_JobInfo2 *r)
8892 {
8893 int i = 0;
8894 bool found = false;
8895 struct spoolss_DeviceMode *devmode;
8896 NT_DEVICEMODE *nt_devmode;
8897 WERROR result;
8898
8899 for (i=0; i<count && found == false; i++) {
8900 if (queue[i].job == (int)jobid) {
8901 found = true;
8902 }
8903 }
8904
8905 if (found == false) {
8906 /* NT treats not found as bad param... yet another bad
8907 choice */
8908 return WERR_INVALID_PARAM;
8909 }
8910
8911 /*
8912 * if the print job does not have a DEVMODE associated with it,
8913 * just use the one for the printer. A NULL devicemode is not
8914 * a failure condition
8915 */
8916
8917 nt_devmode = print_job_devmode(lp_const_servicename(snum), jobid);
8918 if (nt_devmode) {
8919 devmode = TALLOC_ZERO_P(mem_ctx, struct spoolss_DeviceMode);
8920 W_ERROR_HAVE_NO_MEMORY(devmode);
8921 result = convert_nt_devicemode(devmode, devmode, nt_devmode);
8922 if (!W_ERROR_IS_OK(result)) {
8923 return result;
8924 }
8925 } else {
8926 devmode = construct_dev_mode(mem_ctx, lp_const_servicename(snum));
8927 W_ERROR_HAVE_NO_MEMORY(devmode);
8928 }
8929
8930 return fill_job_info2(mem_ctx,
8931 r,
8932 &queue[i-1],
8933 i,
8934 snum,
8935 ntprinter,
8936 devmode);
8937 }
8938
8939 /****************************************************************
8940 _spoolss_GetJob
8941 ****************************************************************/
8942
8943 WERROR _spoolss_GetJob(pipes_struct *p,
/* [<][>][^][v][top][bottom][index][help] */
8944 struct spoolss_GetJob *r)
8945 {
8946 WERROR result = WERR_OK;
8947 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
8948 int snum;
8949 int count;
8950 print_queue_struct *queue = NULL;
8951 print_status_struct prt_status;
8952
8953 /* that's an [in out] buffer */
8954
8955 if (!r->in.buffer && (r->in.offered != 0)) {
8956 return WERR_INVALID_PARAM;
8957 }
8958
8959 DEBUG(5,("_spoolss_GetJob\n"));
8960
8961 *r->out.needed = 0;
8962
8963 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
8964 return WERR_BADFID;
8965 }
8966
8967 result = get_a_printer(NULL, &ntprinter, 2, lp_servicename(snum));
8968 if (!W_ERROR_IS_OK(result)) {
8969 return result;
8970 }
8971
8972 count = print_queue_status(snum, &queue, &prt_status);
8973
8974 DEBUGADD(4,("count:[%d], prt_status:[%d], [%s]\n",
8975 count, prt_status.status, prt_status.message));
8976
8977 switch (r->in.level) {
8978 case 1:
8979 result = getjob_level_1(p->mem_ctx,
8980 queue, count, snum, ntprinter,
8981 r->in.job_id, &r->out.info->info1);
8982 break;
8983 case 2:
8984 result = getjob_level_2(p->mem_ctx,
8985 queue, count, snum, ntprinter,
8986 r->in.job_id, &r->out.info->info2);
8987 break;
8988 default:
8989 result = WERR_UNKNOWN_LEVEL;
8990 break;
8991 }
8992
8993 SAFE_FREE(queue);
8994 free_a_printer(&ntprinter, 2);
8995
8996 if (!W_ERROR_IS_OK(result)) {
8997 TALLOC_FREE(r->out.info);
8998 return result;
8999 }
9000
9001 *r->out.needed = SPOOLSS_BUFFER_UNION(spoolss_JobInfo, NULL,
9002 r->out.info, r->in.level);
9003 r->out.info = SPOOLSS_BUFFER_OK(r->out.info, NULL);
9004
9005 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
9006 }
9007
9008 /****************************************************************
9009 _spoolss_GetPrinterDataEx
9010
9011 From MSDN documentation of GetPrinterDataEx: pass request
9012 to GetPrinterData if key is "PrinterDriverData".
9013 ****************************************************************/
9014
9015 WERROR _spoolss_GetPrinterDataEx(pipes_struct *p,
/* [<][>][^][v][top][bottom][index][help] */
9016 struct spoolss_GetPrinterDataEx *r)
9017 {
9018
9019 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
9020 REGISTRY_VALUE *val = NULL;
9021 NT_PRINTER_INFO_LEVEL *printer = NULL;
9022 int snum = 0;
9023 WERROR result = WERR_OK;
9024
9025 DEBUG(4,("_spoolss_GetPrinterDataEx\n"));
9026
9027 DEBUG(10, ("_spoolss_GetPrinterDataEx: key => [%s], value => [%s]\n",
9028 r->in.key_name, r->in.value_name));
9029
9030 /* in case of problem, return some default values */
9031
9032 *r->out.needed = 0;
9033 *r->out.type = REG_NONE;
9034
9035 if (!Printer) {
9036 DEBUG(2,("_spoolss_GetPrinterDataEx: Invalid handle (%s:%u:%u).\n",
9037 OUR_HANDLE(r->in.handle)));
9038 result = WERR_BADFID;
9039 goto done;
9040 }
9041
9042 /* Is the handle to a printer or to the server? */
9043
9044 if (Printer->printer_type == SPLHND_SERVER) {
9045 DEBUG(10,("_spoolss_GetPrinterDataEx: "
9046 "Not implemented for server handles yet\n"));
9047 result = WERR_INVALID_PARAM;
9048 goto done;
9049 }
9050
9051 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9052 return WERR_BADFID;
9053 }
9054
9055 result = get_a_printer(Printer, &printer, 2, lp_servicename(snum));
9056 if (!W_ERROR_IS_OK(result)) {
9057 goto done;
9058 }
9059
9060 /* check to see if the keyname is valid */
9061 if (!strlen(r->in.key_name)) {
9062 result = WERR_INVALID_PARAM;
9063 goto done;
9064 }
9065
9066 if (lookup_printerkey(printer->info_2->data, r->in.key_name) == -1) {
9067 DEBUG(4,("_spoolss_GetPrinterDataEx: "
9068 "Invalid keyname [%s]\n", r->in.key_name ));
9069 result = WERR_BADFILE;
9070 goto done;
9071 }
9072
9073 /* When given a new keyname, we should just create it */
9074
9075 val = get_printer_data(printer->info_2,
9076 r->in.key_name, r->in.value_name);
9077 if (!val) {
9078 result = WERR_BADFILE;
9079 goto done;
9080 }
9081
9082 *r->out.needed = regval_size(val);
9083
9084 if (*r->out.needed > r->in.offered) {
9085 result = WERR_MORE_DATA;
9086 goto done;
9087 }
9088
9089 *r->out.type = regval_type(val);
9090
9091 memcpy(r->out.buffer, regval_data_p(val), regval_size(val));
9092
9093 done:
9094 if (printer) {
9095 free_a_printer(&printer, 2);
9096 }
9097
9098 return result;
9099 }
9100
9101 /****************************************************************
9102 _spoolss_SetPrinterDataEx
9103 ****************************************************************/
9104
9105 WERROR _spoolss_SetPrinterDataEx(pipes_struct *p,
/* [<][>][^][v][top][bottom][index][help] */
9106 struct spoolss_SetPrinterDataEx *r)
9107 {
9108 NT_PRINTER_INFO_LEVEL *printer = NULL;
9109 int snum = 0;
9110 WERROR result = WERR_OK;
9111 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
9112 char *oid_string;
9113
9114 DEBUG(4,("_spoolss_SetPrinterDataEx\n"));
9115
9116 /* From MSDN documentation of SetPrinterDataEx: pass request to
9117 SetPrinterData if key is "PrinterDriverData" */
9118
9119 if (!Printer) {
9120 DEBUG(2,("_spoolss_SetPrinterDataEx: Invalid handle (%s:%u:%u).\n",
9121 OUR_HANDLE(r->in.handle)));
9122 return WERR_BADFID;
9123 }
9124
9125 if (Printer->printer_type == SPLHND_SERVER) {
9126 DEBUG(10,("_spoolss_SetPrinterDataEx: "
9127 "Not implemented for server handles yet\n"));
9128 return WERR_INVALID_PARAM;
9129 }
9130
9131 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9132 return WERR_BADFID;
9133 }
9134
9135 /*
9136 * Access check : NT returns "access denied" if you make a
9137 * SetPrinterData call without the necessary privildge.
9138 * we were originally returning OK if nothing changed
9139 * which made Win2k issue **a lot** of SetPrinterData
9140 * when connecting to a printer --jerry
9141 */
9142
9143 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
9144 DEBUG(3, ("_spoolss_SetPrinterDataEx: "
9145 "change denied by handle access permissions\n"));
9146 return WERR_ACCESS_DENIED;
9147 }
9148
9149 result = get_a_printer(Printer, &printer, 2, lp_servicename(snum));
9150 if (!W_ERROR_IS_OK(result)) {
9151 return result;
9152 }
9153
9154 /* check for OID in valuename */
9155
9156 oid_string = strchr(r->in.value_name, ',');
9157 if (oid_string) {
9158 *oid_string = '\0';
9159 oid_string++;
9160 }
9161
9162 /* save the registry data */
9163
9164 result = set_printer_dataex(printer, r->in.key_name, r->in.value_name,
9165 r->in.type, r->in.buffer, r->in.offered);
9166
9167 if (W_ERROR_IS_OK(result)) {
9168 /* save the OID if one was specified */
9169 if (oid_string) {
9170 char *str = talloc_asprintf(p->mem_ctx, "%s\\%s",
9171 r->in.key_name, SPOOL_OID_KEY);
9172 if (!str) {
9173 result = WERR_NOMEM;
9174 goto done;
9175 }
9176
9177 /*
9178 * I'm not checking the status here on purpose. Don't know
9179 * if this is right, but I'm returning the status from the
9180 * previous set_printer_dataex() call. I have no idea if
9181 * this is right. --jerry
9182 */
9183
9184 set_printer_dataex(printer, str, r->in.value_name,
9185 REG_SZ, (uint8_t *)oid_string,
9186 strlen(oid_string)+1);
9187 }
9188
9189 result = mod_a_printer(printer, 2);
9190 }
9191
9192 done:
9193 free_a_printer(&printer, 2);
9194
9195 return result;
9196 }
9197
9198 /****************************************************************
9199 _spoolss_DeletePrinterDataEx
9200 ****************************************************************/
9201
9202 WERROR _spoolss_DeletePrinterDataEx(pipes_struct *p,
/* [<][>][^][v][top][bottom][index][help] */
9203 struct spoolss_DeletePrinterDataEx *r)
9204 {
9205 NT_PRINTER_INFO_LEVEL *printer = NULL;
9206 int snum=0;
9207 WERROR status = WERR_OK;
9208 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
9209
9210 DEBUG(5,("_spoolss_DeletePrinterDataEx\n"));
9211
9212 if (!Printer) {
9213 DEBUG(2,("_spoolss_DeletePrinterDataEx: "
9214 "Invalid handle (%s:%u:%u).\n",
9215 OUR_HANDLE(r->in.handle)));
9216 return WERR_BADFID;
9217 }
9218
9219 if (!get_printer_snum(p, r->in.handle, &snum, NULL))
9220 return WERR_BADFID;
9221
9222 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
9223 DEBUG(3, ("_spoolss_DeletePrinterDataEx: "
9224 "printer properties change denied by handle\n"));
9225 return WERR_ACCESS_DENIED;
9226 }
9227
9228 if (!r->in.value_name || !r->in.key_name) {
9229 return WERR_NOMEM;
9230 }
9231
9232 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
9233 if (!W_ERROR_IS_OK(status))
9234 return status;
9235
9236 status = delete_printer_dataex( printer, r->in.key_name, r->in.value_name );
9237
9238 if ( W_ERROR_IS_OK(status) )
9239 mod_a_printer( printer, 2 );
9240
9241 free_a_printer(&printer, 2);
9242
9243 return status;
9244 }
9245
9246 /****************************************************************
9247 _spoolss_EnumPrinterKey
9248 ****************************************************************/
9249
9250 WERROR _spoolss_EnumPrinterKey(pipes_struct *p,
/* [<][>][^][v][top][bottom][index][help] */
9251 struct spoolss_EnumPrinterKey *r)
9252 {
9253 fstring *keynames = NULL;
9254 int num_keys;
9255 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
9256 NT_PRINTER_DATA *data;
9257 NT_PRINTER_INFO_LEVEL *printer = NULL;
9258 int snum = 0;
9259 WERROR result = WERR_BADFILE;
9260 int i;
9261 const char **array = NULL;
9262
9263
9264 DEBUG(4,("_spoolss_EnumPrinterKey\n"));
9265
9266 if (!Printer) {
9267 DEBUG(2,("_spoolss_EnumPrinterKey: Invalid handle (%s:%u:%u).\n",
9268 OUR_HANDLE(r->in.handle)));
9269 return WERR_BADFID;
9270 }
9271
9272 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9273 return WERR_BADFID;
9274 }
9275
9276 result = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
9277 if (!W_ERROR_IS_OK(result)) {
9278 return result;
9279 }
9280
9281 /* get the list of subkey names */
9282
9283 data = printer->info_2->data;
9284
9285 num_keys = get_printer_subkeys(data, r->in.key_name, &keynames);
9286 if (num_keys == -1) {
9287 result = WERR_BADFILE;
9288 goto done;
9289 }
9290
9291 *r->out.needed = 4;
9292
9293 array = talloc_zero_array(r->out.key_buffer, const char *, num_keys + 1);
9294 if (!array) {
9295 result = WERR_NOMEM;
9296 goto done;
9297 }
9298
9299 for (i=0; i < num_keys; i++) {
9300 array[i] = talloc_strdup(array, keynames[i]);
9301 if (!array[i]) {
9302 result = WERR_NOMEM;
9303 goto done;
9304 }
9305
9306 *r->out.needed += strlen_m_term(keynames[i]) * 2;
9307 }
9308
9309 if (r->in.offered < *r->out.needed) {
9310 result = WERR_MORE_DATA;
9311 goto done;
9312 }
9313
9314 result = WERR_OK;
9315
9316 *r->out.key_buffer = array;
9317
9318 done:
9319 if (!W_ERROR_IS_OK(result)) {
9320 TALLOC_FREE(array);
9321 ZERO_STRUCTP(r->out.key_buffer);
9322 }
9323
9324 free_a_printer(&printer, 2);
9325 SAFE_FREE(keynames);
9326
9327 return result;
9328 }
9329
9330 /****************************************************************
9331 _spoolss_DeletePrinterKey
9332 ****************************************************************/
9333
9334 WERROR _spoolss_DeletePrinterKey(pipes_struct *p,
/* [<][>][^][v][top][bottom][index][help] */
9335 struct spoolss_DeletePrinterKey *r)
9336 {
9337 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
9338 NT_PRINTER_INFO_LEVEL *printer = NULL;
9339 int snum=0;
9340 WERROR status;
9341
9342 DEBUG(5,("_spoolss_DeletePrinterKey\n"));
9343
9344 if (!Printer) {
9345 DEBUG(2,("_spoolss_DeletePrinterKey: Invalid handle (%s:%u:%u).\n",
9346 OUR_HANDLE(r->in.handle)));
9347 return WERR_BADFID;
9348 }
9349
9350 /* if keyname == NULL, return error */
9351
9352 if ( !r->in.key_name )
9353 return WERR_INVALID_PARAM;
9354
9355 if (!get_printer_snum(p, r->in.handle, &snum, NULL))
9356 return WERR_BADFID;
9357
9358 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
9359 DEBUG(3, ("_spoolss_DeletePrinterKey: "
9360 "printer properties change denied by handle\n"));
9361 return WERR_ACCESS_DENIED;
9362 }
9363
9364 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
9365 if (!W_ERROR_IS_OK(status))
9366 return status;
9367
9368 /* delete the key and all subneys */
9369
9370 status = delete_all_printer_data( printer->info_2, r->in.key_name );
9371
9372 if ( W_ERROR_IS_OK(status) )
9373 status = mod_a_printer(printer, 2);
9374
9375 free_a_printer( &printer, 2 );
9376
9377 return status;
9378 }
9379
9380 /****************************************************************
9381 ****************************************************************/
9382
9383 static WERROR registry_value_to_printer_enum_value(TALLOC_CTX *mem_ctx,
/* [<][>][^][v][top][bottom][index][help] */
9384 REGISTRY_VALUE *v,
9385 struct spoolss_PrinterEnumValues *r)
9386 {
9387 WERROR result;
9388
9389 r->data = TALLOC_ZERO_P(mem_ctx, union spoolss_PrinterData);
9390 W_ERROR_HAVE_NO_MEMORY(r->data);
9391
9392 r->value_name = talloc_strdup(mem_ctx, regval_name(v));
9393 W_ERROR_HAVE_NO_MEMORY(r->value_name);
9394
9395 r->type = regval_type(v);
9396 r->data_length = regval_size(v);
9397
9398 if (r->data_length) {
9399 DATA_BLOB blob = data_blob_const(regval_data_p(v),
9400 regval_size(v));
9401 result = pull_spoolss_PrinterData(mem_ctx, &blob,
9402 r->data,
9403 r->type);
9404 if (!W_ERROR_IS_OK(result)) {
9405 return result;
9406 }
9407 }
9408
9409 return WERR_OK;
9410 }
9411
9412 /****************************************************************
9413 _spoolss_EnumPrinterDataEx
9414 ****************************************************************/
9415
9416 WERROR _spoolss_EnumPrinterDataEx(pipes_struct *p,
/* [<][>][^][v][top][bottom][index][help] */
9417 struct spoolss_EnumPrinterDataEx *r)
9418 {
9419 uint32_t count = 0;
9420 NT_PRINTER_INFO_LEVEL *printer = NULL;
9421 struct spoolss_PrinterEnumValues *info = NULL;
9422 NT_PRINTER_DATA *p_data;
9423 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
9424 int snum;
9425 WERROR result;
9426 int key_index;
9427 int i;
9428
9429 DEBUG(4,("_spoolss_EnumPrinterDataEx\n"));
9430
9431 *r->out.count = 0;
9432 *r->out.needed = 0;
9433 *r->out.info = NULL;
9434
9435 if (!Printer) {
9436 DEBUG(2,("_spoolss_EnumPrinterDataEx: Invalid handle (%s:%u:%u1<).\n",
9437 OUR_HANDLE(r->in.handle)));
9438 return WERR_BADFID;
9439 }
9440
9441 /*
9442 * first check for a keyname of NULL or "". Win2k seems to send
9443 * this a lot and we should send back WERR_INVALID_PARAM
9444 * no need to spend time looking up the printer in this case.
9445 * --jerry
9446 */
9447
9448 if (!strlen(r->in.key_name)) {
9449 result = WERR_INVALID_PARAM;
9450 goto done;
9451 }
9452
9453 /* get the printer off of disk */
9454
9455 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9456 return WERR_BADFID;
9457 }
9458
9459 ZERO_STRUCT(printer);
9460 result = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
9461 if (!W_ERROR_IS_OK(result)) {
9462 return result;
9463 }
9464
9465 /* now look for a match on the key name */
9466
9467 p_data = printer->info_2->data;
9468
9469 key_index = lookup_printerkey(p_data, r->in.key_name);
9470 if (key_index == -1) {
9471 DEBUG(10,("_spoolss_EnumPrinterDataEx: Unknown keyname [%s]\n",
9472 r->in.key_name));
9473 result = WERR_INVALID_PARAM;
9474 goto done;
9475 }
9476
9477 /* allocate the memory for the array of pointers -- if necessary */
9478
9479 count = regval_ctr_numvals(p_data->keys[key_index].values);
9480 if (!count) {
9481 result = WERR_OK; /* ??? */
9482 goto done;
9483 }
9484
9485 info = TALLOC_ZERO_ARRAY(p->mem_ctx,
9486 struct spoolss_PrinterEnumValues,
9487 count);
9488 if (!info) {
9489 DEBUG(0,("_spoolss_EnumPrinterDataEx: talloc() failed\n"));
9490 result = WERR_NOMEM;
9491 goto done;
9492 }
9493
9494 /*
9495 * loop through all params and build the array to pass
9496 * back to the client
9497 */
9498
9499 for (i=0; i < count; i++) {
9500
9501 REGISTRY_VALUE *val;
9502
9503 /* lookup the registry value */
9504
9505 val = regval_ctr_specific_value(p_data->keys[key_index].values, i);
9506
9507 DEBUG(10,("retrieved value number [%d] [%s]\n", i, regval_name(val)));
9508
9509 /* copy the data */
9510
9511 result = registry_value_to_printer_enum_value(info, val, &info[i]);
9512 if (!W_ERROR_IS_OK(result)) {
9513 goto done;
9514 }
9515 }
9516
9517 #if 0 /* FIXME - gd */
9518 /* housekeeping information in the reply */
9519
9520 /* Fix from Martin Zielinski <mz@seh.de> - ensure
9521 * the hand marshalled container size is a multiple
9522 * of 4 bytes for RPC alignment.
9523 */
9524
9525 if (needed % 4) {
9526 needed += 4-(needed % 4);
9527 }
9528 #endif
9529 *r->out.count = count;
9530 *r->out.info = info;
9531
9532 done:
9533
9534 if (printer) {
9535 free_a_printer(&printer, 2);
9536 }
9537
9538 if (!W_ERROR_IS_OK(result)) {
9539 return result;
9540 }
9541
9542 *r->out.needed = SPOOLSS_BUFFER_ARRAY(p->mem_ctx,
9543 spoolss_EnumPrinterDataEx, NULL,
9544 *r->out.info,
9545 *r->out.count);
9546 *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
9547 *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, *r->out.count);
9548
9549 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_MORE_DATA);
9550 }
9551
9552 /****************************************************************************
9553 ****************************************************************************/
9554
9555 static WERROR getprintprocessordirectory_level_1(TALLOC_CTX *mem_ctx,
/* [<][>][^][v][top][bottom][index][help] */
9556 const char *servername,
9557 const char *environment,
9558 struct spoolss_PrintProcessorDirectoryInfo1 *r)
9559 {
9560 WERROR werr;
9561 char *path = NULL;
9562
9563 werr = compose_spoolss_server_path(mem_ctx,
9564 servername,
9565 environment,
9566 SPOOLSS_PRTPROCS_PATH,
9567 &path);
9568 if (!W_ERROR_IS_OK(werr)) {
9569 return werr;
9570 }
9571
9572 DEBUG(4,("print processor directory: [%s]\n", path));
9573
9574 r->directory_name = path;
9575
9576 return WERR_OK;
9577 }
9578
9579 /****************************************************************
9580 _spoolss_GetPrintProcessorDirectory
9581 ****************************************************************/
9582
9583 WERROR _spoolss_GetPrintProcessorDirectory(pipes_struct *p,
/* [<][>][^][v][top][bottom][index][help] */
9584 struct spoolss_GetPrintProcessorDirectory *r)
9585 {
9586 WERROR result;
9587
9588 /* that's an [in out] buffer */
9589
9590 if (!r->in.buffer && (r->in.offered != 0)) {
9591 return WERR_INVALID_PARAM;
9592 }
9593
9594 DEBUG(5,("_spoolss_GetPrintProcessorDirectory: level %d\n",
9595 r->in.level));
9596
9597 *r->out.needed = 0;
9598
9599 /* r->in.level is ignored */
9600
9601 /* We always should reply with a local print processor directory so that
9602 * users are not forced to have a [prnproc$] share on the Samba spoolss
9603 * server - Guenther */
9604
9605 result = getprintprocessordirectory_level_1(p->mem_ctx,
9606 NULL, /* r->in.server */
9607 r->in.environment,
9608 &r->out.info->info1);
9609 if (!W_ERROR_IS_OK(result)) {
9610 TALLOC_FREE(r->out.info);
9611 return result;
9612 }
9613
9614 *r->out.needed = SPOOLSS_BUFFER_UNION(spoolss_PrintProcessorDirectoryInfo, NULL,
9615 r->out.info, r->in.level);
9616 r->out.info = SPOOLSS_BUFFER_OK(r->out.info, NULL);
9617
9618 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
9619 }
9620
9621 /*******************************************************************
9622 ********************************************************************/
9623
9624 static bool push_monitorui_buf(TALLOC_CTX *mem_ctx, DATA_BLOB *buf,
/* [<][>][^][v][top][bottom][index][help] */
9625 const char *dllname)
9626 {
9627 enum ndr_err_code ndr_err;
9628 struct spoolss_MonitorUi ui;
9629
9630 ui.dll_name = dllname;
9631
9632 ndr_err = ndr_push_struct_blob(buf, mem_ctx, NULL, &ui,
9633 (ndr_push_flags_fn_t)ndr_push_spoolss_MonitorUi);
9634 if (NDR_ERR_CODE_IS_SUCCESS(ndr_err) && (DEBUGLEVEL >= 10)) {
9635 NDR_PRINT_DEBUG(spoolss_MonitorUi, &ui);
9636 }
9637 return NDR_ERR_CODE_IS_SUCCESS(ndr_err);
9638 }
9639
9640 /*******************************************************************
9641 Streams the monitor UI DLL name in UNICODE
9642 *******************************************************************/
9643
9644 static WERROR xcvtcp_monitorui(TALLOC_CTX *mem_ctx,
/* [<][>][^][v][top][bottom][index][help] */
9645 NT_USER_TOKEN *token, DATA_BLOB *in,
9646 DATA_BLOB *out, uint32_t *needed)
9647 {
9648 const char *dllname = "tcpmonui.dll";
9649
9650 *needed = (strlen(dllname)+1) * 2;
9651
9652 if (out->length < *needed) {
9653 return WERR_INSUFFICIENT_BUFFER;
9654 }
9655
9656 if (!push_monitorui_buf(mem_ctx, out, dllname)) {
9657 return WERR_NOMEM;
9658 }
9659
9660 return WERR_OK;
9661 }
9662
9663 /*******************************************************************
9664 ********************************************************************/
9665
9666 static bool pull_port_data_1(TALLOC_CTX *mem_ctx,
/* [<][>][^][v][top][bottom][index][help] */
9667 struct spoolss_PortData1 *port1,
9668 const DATA_BLOB *buf)
9669 {
9670 enum ndr_err_code ndr_err;
9671 ndr_err = ndr_pull_struct_blob(buf, mem_ctx, NULL, port1,
9672 (ndr_pull_flags_fn_t)ndr_pull_spoolss_PortData1);
9673 if (NDR_ERR_CODE_IS_SUCCESS(ndr_err) && (DEBUGLEVEL >= 10)) {
9674 NDR_PRINT_DEBUG(spoolss_PortData1, port1);
9675 }
9676 return NDR_ERR_CODE_IS_SUCCESS(ndr_err);
9677 }
9678
9679 /*******************************************************************
9680 ********************************************************************/
9681
9682 static bool pull_port_data_2(TALLOC_CTX *mem_ctx,
/* [<][>][^][v][top][bottom][index][help] */
9683 struct spoolss_PortData2 *port2,
9684 const DATA_BLOB *buf)
9685 {
9686 enum ndr_err_code ndr_err;
9687 ndr_err = ndr_pull_struct_blob(buf, mem_ctx, NULL, port2,
9688 (ndr_pull_flags_fn_t)ndr_pull_spoolss_PortData2);
9689 if (NDR_ERR_CODE_IS_SUCCESS(ndr_err) && (DEBUGLEVEL >= 10)) {
9690 NDR_PRINT_DEBUG(spoolss_PortData2, port2);
9691 }
9692 return NDR_ERR_CODE_IS_SUCCESS(ndr_err);
9693 }
9694
9695 /*******************************************************************
9696 Create a new TCP/IP port
9697 *******************************************************************/
9698
9699 static WERROR xcvtcp_addport(TALLOC_CTX *mem_ctx,
/* [<][>][^][v][top][bottom][index][help] */
9700 NT_USER_TOKEN *token, DATA_BLOB *in,
9701 DATA_BLOB *out, uint32_t *needed)
9702 {
9703 struct spoolss_PortData1 port1;
9704 struct spoolss_PortData2 port2;
9705 char *device_uri = NULL;
9706 uint32_t version;
9707
9708 const char *portname;
9709 const char *hostaddress;
9710 const char *queue;
9711 uint32_t port_number;
9712 uint32_t protocol;
9713
9714 /* peek for spoolss_PortData version */
9715
9716 if (!in || (in->length < (128 + 4))) {
9717 return WERR_GENERAL_FAILURE;
9718 }
9719
9720 version = IVAL(in->data, 128);
9721
9722 switch (version) {
9723 case 1:
9724 ZERO_STRUCT(port1);
9725
9726 if (!pull_port_data_1(mem_ctx, &port1, in)) {
9727 return WERR_NOMEM;
9728 }
9729
9730 portname = port1.portname;
9731 hostaddress = port1.hostaddress;
9732 queue = port1.queue;
9733 protocol = port1.protocol;
9734 port_number = port1.port_number;
9735
9736 break;
9737 case 2:
9738 ZERO_STRUCT(port2);
9739
9740 if (!pull_port_data_2(mem_ctx, &port2, in)) {
9741 return WERR_NOMEM;
9742 }
9743
9744 portname = port2.portname;
9745 hostaddress = port2.hostaddress;
9746 queue = port2.queue;
9747 protocol = port2.protocol;
9748 port_number = port2.port_number;
9749
9750 break;
9751 default:
9752 DEBUG(1,("xcvtcp_addport: "
9753 "unknown version of port_data: %d\n", version));
9754 return WERR_UNKNOWN_PORT;
9755 }
9756
9757 /* create the device URI and call the add_port_hook() */
9758
9759 switch (protocol) {
9760 case PROTOCOL_RAWTCP_TYPE:
9761 device_uri = talloc_asprintf(mem_ctx,
9762 "socket://%s:%d/", hostaddress,
9763 port_number);
9764 break;
9765
9766 case PROTOCOL_LPR_TYPE:
9767 device_uri = talloc_asprintf(mem_ctx,
9768 "lpr://%s/%s", hostaddress, queue );
9769 break;
9770
9771 default:
9772 return WERR_UNKNOWN_PORT;
9773 }
9774
9775 if (!device_uri) {
9776 return WERR_NOMEM;
9777 }
9778
9779 return add_port_hook(mem_ctx, token, portname, device_uri);
9780 }
9781
9782 /*******************************************************************
9783 *******************************************************************/
9784
9785 struct xcv_api_table xcvtcp_cmds[] = {
9786 { "MonitorUI", xcvtcp_monitorui },
9787 { "AddPort", xcvtcp_addport},
9788 { NULL, NULL }
9789 };
9790
9791 static WERROR process_xcvtcp_command(TALLOC_CTX *mem_ctx,
/* [<][>][^][v][top][bottom][index][help] */
9792 NT_USER_TOKEN *token, const char *command,
9793 DATA_BLOB *inbuf,
9794 DATA_BLOB *outbuf,
9795 uint32_t *needed )
9796 {
9797 int i;
9798
9799 DEBUG(10,("process_xcvtcp_command: Received command \"%s\"\n", command));
9800
9801 for ( i=0; xcvtcp_cmds[i].name; i++ ) {
9802 if ( strcmp( command, xcvtcp_cmds[i].name ) == 0 )
9803 return xcvtcp_cmds[i].fn(mem_ctx, token, inbuf, outbuf, needed);
9804 }
9805
9806 return WERR_BADFUNC;
9807 }
9808
9809 /*******************************************************************
9810 *******************************************************************/
9811 #if 0 /* don't support management using the "Local Port" monitor */
9812
9813 static WERROR xcvlocal_monitorui(TALLOC_CTX *mem_ctx,
/* [<][>][^][v][top][bottom][index][help] */
9814 NT_USER_TOKEN *token, DATA_BLOB *in,
9815 DATA_BLOB *out, uint32_t *needed)
9816 {
9817 const char *dllname = "localui.dll";
9818
9819 *needed = (strlen(dllname)+1) * 2;
9820
9821 if (out->length < *needed) {
9822 return WERR_INSUFFICIENT_BUFFER;
9823 }
9824
9825 if (!push_monitorui_buf(mem_ctx, out, dllname)) {
9826 return WERR_NOMEM;
9827 }
9828
9829 return WERR_OK;
9830 }
9831
9832 /*******************************************************************
9833 *******************************************************************/
9834
9835 struct xcv_api_table xcvlocal_cmds[] = {
9836 { "MonitorUI", xcvlocal_monitorui },
9837 { NULL, NULL }
9838 };
9839 #else
9840 struct xcv_api_table xcvlocal_cmds[] = {
9841 { NULL, NULL }
9842 };
9843 #endif
9844
9845
9846
9847 /*******************************************************************
9848 *******************************************************************/
9849
9850 static WERROR process_xcvlocal_command(TALLOC_CTX *mem_ctx,
/* [<][>][^][v][top][bottom][index][help] */
9851 NT_USER_TOKEN *token, const char *command,
9852 DATA_BLOB *inbuf, DATA_BLOB *outbuf,
9853 uint32_t *needed)
9854 {
9855 int i;
9856
9857 DEBUG(10,("process_xcvlocal_command: Received command \"%s\"\n", command));
9858
9859 for ( i=0; xcvlocal_cmds[i].name; i++ ) {
9860 if ( strcmp( command, xcvlocal_cmds[i].name ) == 0 )
9861 return xcvlocal_cmds[i].fn(mem_ctx, token, inbuf, outbuf, needed);
9862 }
9863 return WERR_BADFUNC;
9864 }
9865
9866 /****************************************************************
9867 _spoolss_XcvData
9868 ****************************************************************/
9869
9870 WERROR _spoolss_XcvData(pipes_struct *p,
/* [<][>][^][v][top][bottom][index][help] */
9871 struct spoolss_XcvData *r)
9872 {
9873 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
9874 DATA_BLOB out_data = data_blob_null;
9875 WERROR werror;
9876
9877 if (!Printer) {
9878 DEBUG(2,("_spoolss_XcvData: Invalid handle (%s:%u:%u).\n",
9879 OUR_HANDLE(r->in.handle)));
9880 return WERR_BADFID;
9881 }
9882
9883 /* Has to be a handle to the TCP/IP port monitor */
9884
9885 if ( !(Printer->printer_type & (SPLHND_PORTMON_LOCAL|SPLHND_PORTMON_TCP)) ) {
9886 DEBUG(2,("_spoolss_XcvData: Call only valid for Port Monitors\n"));
9887 return WERR_BADFID;
9888 }
9889
9890 /* requires administrative access to the server */
9891
9892 if ( !(Printer->access_granted & SERVER_ACCESS_ADMINISTER) ) {
9893 DEBUG(2,("_spoolss_XcvData: denied by handle permissions.\n"));
9894 return WERR_ACCESS_DENIED;
9895 }
9896
9897 /* Allocate the outgoing buffer */
9898
9899 if (r->in.out_data_size) {
9900 out_data = data_blob_talloc_zero(p->mem_ctx, r->in.out_data_size);
9901 if (out_data.data == NULL) {
9902 return WERR_NOMEM;
9903 }
9904 }
9905
9906 switch ( Printer->printer_type ) {
9907 case SPLHND_PORTMON_TCP:
9908 werror = process_xcvtcp_command(p->mem_ctx,
9909 p->server_info->ptok,
9910 r->in.function_name,
9911 &r->in.in_data, &out_data,
9912 r->out.needed);
9913 break;
9914 case SPLHND_PORTMON_LOCAL:
9915 werror = process_xcvlocal_command(p->mem_ctx,
9916 p->server_info->ptok,
9917 r->in.function_name,
9918 &r->in.in_data, &out_data,
9919 r->out.needed);
9920 break;
9921 default:
9922 werror = WERR_INVALID_PRINT_MONITOR;
9923 }
9924
9925 if (!W_ERROR_IS_OK(werror)) {
9926 return werror;
9927 }
9928
9929 *r->out.status_code = 0;
9930
9931 memcpy(r->out.out_data, out_data.data, out_data.length);
9932
9933 return WERR_OK;
9934 }
9935
9936 /****************************************************************
9937 _spoolss_AddPrintProcessor
9938 ****************************************************************/
9939
9940 WERROR _spoolss_AddPrintProcessor(pipes_struct *p,
/* [<][>][^][v][top][bottom][index][help] */
9941 struct spoolss_AddPrintProcessor *r)
9942 {
9943 /* for now, just indicate success and ignore the add. We'll
9944 automatically set the winprint processor for printer
9945 entries later. Used to debug the LexMark Optra S 1855 PCL
9946 driver --jerry */
9947
9948 return WERR_OK;
9949 }
9950
9951 /****************************************************************
9952 _spoolss_AddPort
9953 ****************************************************************/
9954
9955 WERROR _spoolss_AddPort(pipes_struct *p,
/* [<][>][^][v][top][bottom][index][help] */
9956 struct spoolss_AddPort *r)
9957 {
9958 /* do what w2k3 does */
9959
9960 return WERR_NOT_SUPPORTED;
9961 }
9962
9963 /****************************************************************
9964 _spoolss_AddPrinter
9965 ****************************************************************/
9966
9967 WERROR _spoolss_AddPrinter(pipes_struct *p,
/* [<][>][^][v][top][bottom][index][help] */
9968 struct spoolss_AddPrinter *r)
9969 {
9970 p->rng_fault_state = true;
9971 return WERR_NOT_SUPPORTED;
9972 }
9973
9974 /****************************************************************
9975 _spoolss_GetPrinterDriver
9976 ****************************************************************/
9977
9978 WERROR _spoolss_GetPrinterDriver(pipes_struct *p,
/* [<][>][^][v][top][bottom][index][help] */
9979 struct spoolss_GetPrinterDriver *r)
9980 {
9981 p->rng_fault_state = true;
9982 return WERR_NOT_SUPPORTED;
9983 }
9984
9985 /****************************************************************
9986 _spoolss_ReadPrinter
9987 ****************************************************************/
9988
9989 WERROR _spoolss_ReadPrinter(pipes_struct *p,
/* [<][>][^][v][top][bottom][index][help] */
9990 struct spoolss_ReadPrinter *r)
9991 {
9992 p->rng_fault_state = true;
9993 return WERR_NOT_SUPPORTED;
9994 }
9995
9996 /****************************************************************
9997 _spoolss_WaitForPrinterChange
9998 ****************************************************************/
9999
10000 WERROR _spoolss_WaitForPrinterChange(pipes_struct *p,
/* [<][>][^][v][top][bottom][index][help] */
10001 struct spoolss_WaitForPrinterChange *r)
10002 {
10003 p->rng_fault_state = true;
10004 return WERR_NOT_SUPPORTED;
10005 }
10006
10007 /****************************************************************
10008 _spoolss_ConfigurePort
10009 ****************************************************************/
10010
10011 WERROR _spoolss_ConfigurePort(pipes_struct *p,
/* [<][>][^][v][top][bottom][index][help] */
10012 struct spoolss_ConfigurePort *r)
10013 {
10014 p->rng_fault_state = true;
10015 return WERR_NOT_SUPPORTED;
10016 }
10017
10018 /****************************************************************
10019 _spoolss_DeletePort
10020 ****************************************************************/
10021
10022 WERROR _spoolss_DeletePort(pipes_struct *p,
/* [<][>][^][v][top][bottom][index][help] */
10023 struct spoolss_DeletePort *r)
10024 {
10025 p->rng_fault_state = true;
10026 return WERR_NOT_SUPPORTED;
10027 }
10028
10029 /****************************************************************
10030 _spoolss_CreatePrinterIC
10031 ****************************************************************/
10032
10033 WERROR _spoolss_CreatePrinterIC(pipes_struct *p,
/* [<][>][^][v][top][bottom][index][help] */
10034 struct spoolss_CreatePrinterIC *r)
10035 {
10036 p->rng_fault_state = true;
10037 return WERR_NOT_SUPPORTED;
10038 }
10039
10040 /****************************************************************
10041 _spoolss_PlayGDIScriptOnPrinterIC
10042 ****************************************************************/
10043
10044 WERROR _spoolss_PlayGDIScriptOnPrinterIC(pipes_struct *p,
/* [<][>][^][v][top][bottom][index][help] */
10045 struct spoolss_PlayGDIScriptOnPrinterIC *r)
10046 {
10047 p->rng_fault_state = true;
10048 return WERR_NOT_SUPPORTED;
10049 }
10050
10051 /****************************************************************
10052 _spoolss_DeletePrinterIC
10053 ****************************************************************/
10054
10055 WERROR _spoolss_DeletePrinterIC(pipes_struct *p,
/* [<][>][^][v][top][bottom][index][help] */
10056 struct spoolss_DeletePrinterIC *r)
10057 {
10058 p->rng_fault_state = true;
10059 return WERR_NOT_SUPPORTED;
10060 }
10061
10062 /****************************************************************
10063 _spoolss_AddPrinterConnection
10064 ****************************************************************/
10065
10066 WERROR _spoolss_AddPrinterConnection(pipes_struct *p,
/* [<][>][^][v][top][bottom][index][help] */
10067 struct spoolss_AddPrinterConnection *r)
10068 {
10069 p->rng_fault_state = true;
10070 return WERR_NOT_SUPPORTED;
10071 }
10072
10073 /****************************************************************
10074 _spoolss_DeletePrinterConnection
10075 ****************************************************************/
10076
10077 WERROR _spoolss_DeletePrinterConnection(pipes_struct *p,
/* [<][>][^][v][top][bottom][index][help] */
10078 struct spoolss_DeletePrinterConnection *r)
10079 {
10080 p->rng_fault_state = true;
10081 return WERR_NOT_SUPPORTED;
10082 }
10083
10084 /****************************************************************
10085 _spoolss_PrinterMessageBox
10086 ****************************************************************/
10087
10088 WERROR _spoolss_PrinterMessageBox(pipes_struct *p,
/* [<][>][^][v][top][bottom][index][help] */
10089 struct spoolss_PrinterMessageBox *r)
10090 {
10091 p->rng_fault_state = true;
10092 return WERR_NOT_SUPPORTED;
10093 }
10094
10095 /****************************************************************
10096 _spoolss_AddMonitor
10097 ****************************************************************/
10098
10099 WERROR _spoolss_AddMonitor(pipes_struct *p,
/* [<][>][^][v][top][bottom][index][help] */
10100 struct spoolss_AddMonitor *r)
10101 {
10102 p->rng_fault_state = true;
10103 return WERR_NOT_SUPPORTED;
10104 }
10105
10106 /****************************************************************
10107 _spoolss_DeleteMonitor
10108 ****************************************************************/
10109
10110 WERROR _spoolss_DeleteMonitor(pipes_struct *p,
/* [<][>][^][v][top][bottom][index][help] */
10111 struct spoolss_DeleteMonitor *r)
10112 {
10113 p->rng_fault_state = true;
10114 return WERR_NOT_SUPPORTED;
10115 }
10116
10117 /****************************************************************
10118 _spoolss_DeletePrintProcessor
10119 ****************************************************************/
10120
10121 WERROR _spoolss_DeletePrintProcessor(pipes_struct *p,
/* [<][>][^][v][top][bottom][index][help] */
10122 struct spoolss_DeletePrintProcessor *r)
10123 {
10124 p->rng_fault_state = true;
10125 return WERR_NOT_SUPPORTED;
10126 }
10127
10128 /****************************************************************
10129 _spoolss_AddPrintProvidor
10130 ****************************************************************/
10131
10132 WERROR _spoolss_AddPrintProvidor(pipes_struct *p,
/* [<][>][^][v][top][bottom][index][help] */
10133 struct spoolss_AddPrintProvidor *r)
10134 {
10135 p->rng_fault_state = true;
10136 return WERR_NOT_SUPPORTED;
10137 }
10138
10139 /****************************************************************
10140 _spoolss_DeletePrintProvidor
10141 ****************************************************************/
10142
10143 WERROR _spoolss_DeletePrintProvidor(pipes_struct *p,
/* [<][>][^][v][top][bottom][index][help] */
10144 struct spoolss_DeletePrintProvidor *r)
10145 {
10146 p->rng_fault_state = true;
10147 return WERR_NOT_SUPPORTED;
10148 }
10149
10150 /****************************************************************
10151 _spoolss_FindFirstPrinterChangeNotification
10152 ****************************************************************/
10153
10154 WERROR _spoolss_FindFirstPrinterChangeNotification(pipes_struct *p,
/* [<][>][^][v][top][bottom][index][help] */
10155 struct spoolss_FindFirstPrinterChangeNotification *r)
10156 {
10157 p->rng_fault_state = true;
10158 return WERR_NOT_SUPPORTED;
10159 }
10160
10161 /****************************************************************
10162 _spoolss_FindNextPrinterChangeNotification
10163 ****************************************************************/
10164
10165 WERROR _spoolss_FindNextPrinterChangeNotification(pipes_struct *p,
/* [<][>][^][v][top][bottom][index][help] */
10166 struct spoolss_FindNextPrinterChangeNotification *r)
10167 {
10168 p->rng_fault_state = true;
10169 return WERR_NOT_SUPPORTED;
10170 }
10171
10172 /****************************************************************
10173 _spoolss_RouterFindFirstPrinterChangeNotificationOld
10174 ****************************************************************/
10175
10176 WERROR _spoolss_RouterFindFirstPrinterChangeNotificationOld(pipes_struct *p,
/* [<][>][^][v][top][bottom][index][help] */
10177 struct spoolss_RouterFindFirstPrinterChangeNotificationOld *r)
10178 {
10179 p->rng_fault_state = true;
10180 return WERR_NOT_SUPPORTED;
10181 }
10182
10183 /****************************************************************
10184 _spoolss_ReplyOpenPrinter
10185 ****************************************************************/
10186
10187 WERROR _spoolss_ReplyOpenPrinter(pipes_struct *p,
/* [<][>][^][v][top][bottom][index][help] */
10188 struct spoolss_ReplyOpenPrinter *r)
10189 {
10190 p->rng_fault_state = true;
10191 return WERR_NOT_SUPPORTED;
10192 }
10193
10194 /****************************************************************
10195 _spoolss_RouterReplyPrinter
10196 ****************************************************************/
10197
10198 WERROR _spoolss_RouterReplyPrinter(pipes_struct *p,
/* [<][>][^][v][top][bottom][index][help] */
10199 struct spoolss_RouterReplyPrinter *r)
10200 {
10201 p->rng_fault_state = true;
10202 return WERR_NOT_SUPPORTED;
10203 }
10204
10205 /****************************************************************
10206 _spoolss_ReplyClosePrinter
10207 ****************************************************************/
10208
10209 WERROR _spoolss_ReplyClosePrinter(pipes_struct *p,
/* [<][>][^][v][top][bottom][index][help] */
10210 struct spoolss_ReplyClosePrinter *r)
10211 {
10212 p->rng_fault_state = true;
10213 return WERR_NOT_SUPPORTED;
10214 }
10215
10216 /****************************************************************
10217 _spoolss_AddPortEx
10218 ****************************************************************/
10219
10220 WERROR _spoolss_AddPortEx(pipes_struct *p,
/* [<][>][^][v][top][bottom][index][help] */
10221 struct spoolss_AddPortEx *r)
10222 {
10223 p->rng_fault_state = true;
10224 return WERR_NOT_SUPPORTED;
10225 }
10226
10227 /****************************************************************
10228 _spoolss_RouterFindFirstPrinterChangeNotification
10229 ****************************************************************/
10230
10231 WERROR _spoolss_RouterFindFirstPrinterChangeNotification(pipes_struct *p,
/* [<][>][^][v][top][bottom][index][help] */
10232 struct spoolss_RouterFindFirstPrinterChangeNotification *r)
10233 {
10234 p->rng_fault_state = true;
10235 return WERR_NOT_SUPPORTED;
10236 }
10237
10238 /****************************************************************
10239 _spoolss_SpoolerInit
10240 ****************************************************************/
10241
10242 WERROR _spoolss_SpoolerInit(pipes_struct *p,
/* [<][>][^][v][top][bottom][index][help] */
10243 struct spoolss_SpoolerInit *r)
10244 {
10245 p->rng_fault_state = true;
10246 return WERR_NOT_SUPPORTED;
10247 }
10248
10249 /****************************************************************
10250 _spoolss_ResetPrinterEx
10251 ****************************************************************/
10252
10253 WERROR _spoolss_ResetPrinterEx(pipes_struct *p,
/* [<][>][^][v][top][bottom][index][help] */
10254 struct spoolss_ResetPrinterEx *r)
10255 {
10256 p->rng_fault_state = true;
10257 return WERR_NOT_SUPPORTED;
10258 }
10259
10260 /****************************************************************
10261 _spoolss_RouterReplyPrinterEx
10262 ****************************************************************/
10263
10264 WERROR _spoolss_RouterReplyPrinterEx(pipes_struct *p,
/* [<][>][^][v][top][bottom][index][help] */
10265 struct spoolss_RouterReplyPrinterEx *r)
10266 {
10267 p->rng_fault_state = true;
10268 return WERR_NOT_SUPPORTED;
10269 }
10270
10271 /****************************************************************
10272 _spoolss_44
10273 ****************************************************************/
10274
10275 WERROR _spoolss_44(pipes_struct *p,
/* [<][>][^][v][top][bottom][index][help] */
10276 struct spoolss_44 *r)
10277 {
10278 p->rng_fault_state = true;
10279 return WERR_NOT_SUPPORTED;
10280 }
10281
10282 /****************************************************************
10283 _spoolss_47
10284 ****************************************************************/
10285
10286 WERROR _spoolss_47(pipes_struct *p,
/* [<][>][^][v][top][bottom][index][help] */
10287 struct spoolss_47 *r)
10288 {
10289 p->rng_fault_state = true;
10290 return WERR_NOT_SUPPORTED;
10291 }
10292
10293 /****************************************************************
10294 _spoolss_4a
10295 ****************************************************************/
10296
10297 WERROR _spoolss_4a(pipes_struct *p,
/* [<][>][^][v][top][bottom][index][help] */
10298 struct spoolss_4a *r)
10299 {
10300 p->rng_fault_state = true;
10301 return WERR_NOT_SUPPORTED;
10302 }
10303
10304 /****************************************************************
10305 _spoolss_4b
10306 ****************************************************************/
10307
10308 WERROR _spoolss_4b(pipes_struct *p,
/* [<][>][^][v][top][bottom][index][help] */
10309 struct spoolss_4b *r)
10310 {
10311 p->rng_fault_state = true;
10312 return WERR_NOT_SUPPORTED;
10313 }
10314
10315 /****************************************************************
10316 _spoolss_4c
10317 ****************************************************************/
10318
10319 WERROR _spoolss_4c(pipes_struct *p,
/* [<][>][^][v][top][bottom][index][help] */
10320 struct spoolss_4c *r)
10321 {
10322 p->rng_fault_state = true;
10323 return WERR_NOT_SUPPORTED;
10324 }
10325
10326 /****************************************************************
10327 _spoolss_53
10328 ****************************************************************/
10329
10330 WERROR _spoolss_53(pipes_struct *p,
/* [<][>][^][v][top][bottom][index][help] */
10331 struct spoolss_53 *r)
10332 {
10333 p->rng_fault_state = true;
10334 return WERR_NOT_SUPPORTED;
10335 }
10336
10337 /****************************************************************
10338 _spoolss_55
10339 ****************************************************************/
10340
10341 WERROR _spoolss_55(pipes_struct *p,
/* [<][>][^][v][top][bottom][index][help] */
10342 struct spoolss_55 *r)
10343 {
10344 p->rng_fault_state = true;
10345 return WERR_NOT_SUPPORTED;
10346 }
10347
10348 /****************************************************************
10349 _spoolss_56
10350 ****************************************************************/
10351
10352 WERROR _spoolss_56(pipes_struct *p,
/* [<][>][^][v][top][bottom][index][help] */
10353 struct spoolss_56 *r)
10354 {
10355 p->rng_fault_state = true;
10356 return WERR_NOT_SUPPORTED;
10357 }
10358
10359 /****************************************************************
10360 _spoolss_57
10361 ****************************************************************/
10362
10363 WERROR _spoolss_57(pipes_struct *p,
/* [<][>][^][v][top][bottom][index][help] */
10364 struct spoolss_57 *r)
10365 {
10366 p->rng_fault_state = true;
10367 return WERR_NOT_SUPPORTED;
10368 }
10369
10370 /****************************************************************
10371 _spoolss_5a
10372 ****************************************************************/
10373
10374 WERROR _spoolss_5a(pipes_struct *p,
/* [<][>][^][v][top][bottom][index][help] */
10375 struct spoolss_5a *r)
10376 {
10377 p->rng_fault_state = true;
10378 return WERR_NOT_SUPPORTED;
10379 }
10380
10381 /****************************************************************
10382 _spoolss_5b
10383 ****************************************************************/
10384
10385 WERROR _spoolss_5b(pipes_struct *p,
/* [<][>][^][v][top][bottom][index][help] */
10386 struct spoolss_5b *r)
10387 {
10388 p->rng_fault_state = true;
10389 return WERR_NOT_SUPPORTED;
10390 }
10391
10392 /****************************************************************
10393 _spoolss_5c
10394 ****************************************************************/
10395
10396 WERROR _spoolss_5c(pipes_struct *p,
/* [<][>][^][v][top][bottom][index][help] */
10397 struct spoolss_5c *r)
10398 {
10399 p->rng_fault_state = true;
10400 return WERR_NOT_SUPPORTED;
10401 }
10402
10403 /****************************************************************
10404 _spoolss_5d
10405 ****************************************************************/
10406
10407 WERROR _spoolss_5d(pipes_struct *p,
/* [<][>][^][v][top][bottom][index][help] */
10408 struct spoolss_5d *r)
10409 {
10410 p->rng_fault_state = true;
10411 return WERR_NOT_SUPPORTED;
10412 }
10413
10414 /****************************************************************
10415 _spoolss_5e
10416 ****************************************************************/
10417
10418 WERROR _spoolss_5e(pipes_struct *p,
/* [<][>][^][v][top][bottom][index][help] */
10419 struct spoolss_5e *r)
10420 {
10421 p->rng_fault_state = true;
10422 return WERR_NOT_SUPPORTED;
10423 }
10424
10425 /****************************************************************
10426 _spoolss_5f
10427 ****************************************************************/
10428
10429 WERROR _spoolss_5f(pipes_struct *p,
/* [<][>][^][v][top][bottom][index][help] */
10430 struct spoolss_5f *r)
10431 {
10432 p->rng_fault_state = true;
10433 return WERR_NOT_SUPPORTED;
10434 }
10435