source: vendor/3.6.23/docs-xml/Samba3-Developers-Guide/printing.xml

Last change on this file was 414, checked in by Herwig Bauernfeind, 15 years ago

Samba 3.5.0: Initial import

File size: 12.9 KB
Line 
1<?xml version="1.0" encoding="iso-8859-1"?>
2<!DOCTYPE chapter PUBLIC "-//Samba-Team//DTD DocBook V4.2-Based Variant V1.0//EN" "http://www.samba.org/samba/DTD/samba-doc">
3<chapter id="devprinting">
4<chapterinfo>
5 <author>
6 <firstname>Gerald</firstname><surname>Carter</surname>
7 </author>
8 <pubdate>October 2002</pubdate>
9</chapterinfo>
10
11
12<title>Samba Printing Internals</title>
13
14
15<sect1>
16<title>Abstract</title>
17<para>
18The purpose of this document is to provide some insight into
19Samba's printing functionality and also to describe the semantics
20of certain features of Windows client printing.
21</para>
22</sect1>
23
24
25
26<sect1>
27<title>
28Printing Interface to Various Back ends
29</title>
30
31<para>
32Samba uses a table of function pointers to seven functions. The
33function prototypes are defined in the <varname>printif</varname> structure declared
34in <filename>printing.h</filename>.
35</para>
36
37<itemizedlist>
38 <listitem><para>retrieve the contents of a print queue</para></listitem>
39 <listitem><para>pause the print queue</para></listitem>
40 <listitem><para>resume a paused print queue</para></listitem>
41 <listitem><para>delete a job from the queue</para></listitem>
42 <listitem><para>pause a job in the print queue</para></listitem>
43 <listitem><para>result a paused print job in the queue</para></listitem>
44 <listitem><para>submit a job to the print queue</para></listitem>
45</itemizedlist>
46
47<para>
48Currently there are only two printing back end implementations
49defined.
50</para>
51
52<itemizedlist>
53 <listitem><para>a generic set of functions for working with standard UNIX
54 printing subsystems</para></listitem>
55
56 <listitem><para>a set of CUPS specific functions (this is only enabled if
57 the CUPS libraries were located at compile time).</para></listitem>
58</itemizedlist>
59
60</sect1>
61
62
63
64
65<sect1>
66<title>
67Print Queue TDB's
68</title>
69
70
71<para>
72Samba provides periodic caching of the output from the "lpq command"
73for performance reasons. This cache time is configurable in seconds.
74Obviously the longer the cache time the less often smbd will be
75required to exec a copy of lpq. However, the accuracy of the print
76queue contents displayed to clients will be diminished as well.
77</para>
78
79<para>
80The list of currently opened print queue TDB's can be found
81be examining the list of tdb_print_db structures ( see print_db_head
82in printing.c ). A queue TDB is opened using the wrapper function
83printing.c:get_print_db_byname(). The function ensures that smbd
84does not open more than MAX_PRINT_DBS_OPEN in an effort to prevent
85a large print server from exhausting all available file descriptors.
86If the number of open queue TDB's exceeds the MAX_PRINT_DBS_OPEN
87limit, smbd falls back to a most recently used algorithm for maintaining
88a list of open TDB's.
89</para>
90
91<para>
92There are two ways in which a a print job can be entered into
93a print queue's TDB. The first is to submit the job from a Windows
94client which will insert the job information directly into the TDB.
95The second method is to have the print job picked up by executing the
96"lpq command".
97</para>
98
99<para><programlisting>
100/* included from printing.h */
101struct printjob {
102 pid_t pid; /* which process launched the job */
103 int sysjob; /* the system (lp) job number */
104 int fd; /* file descriptor of open file if open */
105 time_t starttime; /* when the job started spooling */
106 int status; /* the status of this job */
107 size_t size; /* the size of the job so far */
108 int page_count; /* then number of pages so far */
109 BOOL spooled; /* has it been sent to the spooler yet? */
110 BOOL smbjob; /* set if the job is a SMB job */
111 fstring filename; /* the filename used to spool the file */
112 fstring jobname; /* the job name given to us by the client */
113 fstring user; /* the user who started the job */
114 fstring queuename; /* service number of printer for this job */
115 NT_DEVICEMODE *nt_devmode;
116};
117</programlisting></para>
118
119<para>
120The current manifestation of the printjob structure contains a field
121for the UNIX job id returned from the "lpq command" and a Windows job
122ID (32-bit bounded by PRINT_MAX_JOBID). When a print job is returned
123by the "lpq command" that does not match an existing job in the queue's
124TDB, a 32-bit job ID above the &lt;*vance doesn't know what word is missing here*&gt; is generating by adding UNIX_JOB_START to
125the id reported by lpq.
126</para>
127
128<para>
129In order to match a 32-bit Windows jobid onto a 16-bit lanman print job
130id, smbd uses an in memory TDB to match the former to a number appropriate
131for old lanman clients.
132</para>
133
134<para>
135When updating a print queue, smbd will perform the following
136steps ( refer to <filename>print.c:print_queue_update()</filename> ):
137</para>
138
139<orderedlist>
140 <listitem><para>Check to see if another smbd is currently in
141 the process of updating the queue contents by checking the pid
142 stored in <constant>LOCK/<replaceable>printer_name</replaceable></constant>.
143 If so, then do not update the TDB.</para></listitem>
144
145 <listitem><para>Lock the mutex entry in the TDB and store our own pid.
146 Check that this succeeded, else fail.</para></listitem>
147
148 <listitem><para>Store the updated time stamp for the new cache
149 listing</para></listitem>
150
151 <listitem><para>Retrieve the queue listing via "lpq command"</para></listitem>
152
153 <listitem><para><programlisting>
154 foreach job in the queue
155 {
156 if the job is a UNIX job, create a new entry;
157 if the job has a Windows based jobid, then
158 {
159 Lookup the record by the jobid;
160 if the lookup failed, then
161 treat it as a UNIX job;
162 else
163 update the job status only
164 }
165 }</programlisting></para></listitem>
166
167 <listitem><para>Delete any jobs in the TDB that are not
168 in the in the lpq listing</para></listitem>
169
170 <listitem><para>Store the print queue status in the TDB</para></listitem>
171
172 <listitem><para>update the cache time stamp again</para></listitem>
173
174</orderedlist>
175
176<para>
177Note that it is the contents of this TDB that is returned to Windows
178clients and not the actual listing from the "lpq command".
179</para>
180
181<para>
182The NT_DEVICEMODE stored as part of the printjob structure is used to
183store a pointer to a non-default DeviceMode associated with the print
184job. The pointer will be non-null when the client included a Device
185Mode in the OpenPrinterEx() call and subsequently submitted a job for
186printing on that same handle. If the client did not include a Device
187Mode in the OpenPrinterEx() request, the nt_devmode field is NULL
188and the job has the printer's device mode associated with it by default.
189</para>
190
191<para>
192Only non-default Device Mode are stored with print jobs in the print
193queue TDB. Otherwise, the Device Mode is obtained from the printer
194object when the client issues a GetJob(level == 2) request.
195</para>
196
197</sect1>
198
199
200
201
202<sect1>
203<title>
204ChangeID and Client Caching of Printer Information
205</title>
206
207<para>
208[To be filled in later]
209</para>
210</sect1>
211
212
213
214<sect1>
215<title>
216Windows NT/2K Printer Change Notify
217</title>
218
219<para>
220When working with Windows NT+ clients, it is possible for a
221print server to use RPC to send asynchronous change notification
222events to clients for certain printer and print job attributes.
223This can be useful when the client needs to know that a new
224job has been added to the queue for a given printer or that the
225driver for a printer has been changed. Note that this is done
226entirely orthogonal to cache updates based on a new ChangeID for
227a printer object.
228</para>
229
230<para>
231The basic set of RPC's used to implement change notification are
232</para>
233
234<itemizedlist>
235 <listitem><para>RemoteFindFirstPrinterChangeNotifyEx ( RFFPCN )</para></listitem>
236 <listitem><para>RemoteFindNextPrinterChangeNotifyEx ( RFNPCN )</para></listitem>
237 <listitem><para>FindClosePrinterChangeNotify( FCPCN )</para></listitem>
238 <listitem><para>ReplyOpenPrinter</para></listitem>
239 <listitem><para>ReplyClosePrinter</para></listitem>
240 <listitem><para>RouteRefreshPrinterChangeNotify ( RRPCN )</para></listitem>
241</itemizedlist>
242
243<para>
244One additional RPC is available to a server, but is never used by the
245Windows spooler service:
246</para>
247
248<itemizedlist>
249 <listitem><para>RouteReplyPrinter()</para></listitem>
250</itemizedlist>
251
252<para>
253The opnum for all of these RPC's are defined in include/rpc_spoolss.h
254</para>
255
256<para>
257Windows NT print servers use a bizarre method of sending print
258notification event to clients. The process of registering a new change
259notification handle is as follows. The 'C' is for client and the
260'S' is for server. All error conditions have been eliminated.
261</para>
262
263<para><programlisting>
264C: Obtain handle to printer or to the printer
265 server via the standard OpenPrinterEx() call.
266S: Respond with a valid handle to object
267
268C: Send a RFFPCN request with the previously obtained
269 handle with either (a) set of flags for change events
270 to monitor, or (b) a PRINTER_NOTIFY_OPTIONS structure
271 containing the event information to monitor. The windows
272 spooler has only been observed to use (b).
273S: The &lt;* another missing word*&gt; opens a new TCP session to the client (thus requiring
274 all print clients to be CIFS servers as well) and sends
275 a ReplyOpenPrinter() request to the client.
276C: The client responds with a printer handle that can be used to
277 send event notification messages.
278S: The server replies success to the RFFPCN request.
279
280C: The windows spooler follows the RFFPCN with a RFNPCN
281 request to fetch the current values of all monitored
282 attributes.
283S: The server replies with an array SPOOL_NOTIFY_INFO_DATA
284 structures (contained in a SPOOL_NOTIFY_INFO structure).
285
286C: If the change notification handle is ever released by the
287 client via a FCPCN request, the server sends a ReplyClosePrinter()
288 request back to the client first. However a request of this
289 nature from the client is often an indication that the previous
290 notification event was not marshalled correctly by the server
291 or a piece of data was wrong.
292S: The server closes the internal change notification handle
293 (POLICY_HND) and does not send any further change notification
294 events to the client for that printer or job.
295</programlisting></para>
296
297<para>
298The current list of notification events supported by Samba can be
299found by examining the internal tables in srv_spoolss_nt.c
300</para>
301
302<itemizedlist>
303 <listitem><para>printer_notify_table[]</para></listitem>
304 <listitem><para>job_notify_table[]</para></listitem>
305</itemizedlist>
306
307<para>
308When an event occurs that could be monitored, smbd sends a message
309to itself about the change. The list of events to be transmitted
310are queued by the smbd process sending the message to prevent an
311overload of TDB usage and the internal message is sent during smbd's
312idle loop (refer to printing/notify.c and the functions
313send_spoolss_notify2_msg() and print_notify_send_messages() ).
314</para>
315
316<para>
317The decision of whether or not the change is to be sent to connected
318clients is made by the routine which actually sends the notification.
319( refer to srv_spoolss_nt.c:recieve_notify2_message() ).
320</para>
321
322<para>
323Because it possible to receive a listing of multiple changes for
324multiple printers, the notification events must be split into
325categories by the printer name. This makes it possible to group
326multiple change events to be sent in a single RPC according to the
327printer handle obtained via a ReplyOpenPrinter().
328</para>
329
330<para>
331The actual change notification is performed using the RRPCN request
332RPC. This packet contains
333</para>
334
335
336<itemizedlist>
337
338<listitem><para>the printer handle registered with the
339client's spooler on which the change occurred</para></listitem>
340
341<listitem><para>The change_low value which was sent as part
342of the last RFNPCN request from the client</para></listitem>
343
344<listitem><para>The SPOOL_NOTIFY_INFO container with the event
345information</para></listitem>
346
347</itemizedlist>
348
349<para>
350A <varname>SPOOL_NOTIFY_INFO</varname> contains:
351</para>
352
353<itemizedlist>
354
355<listitem><para>the version and flags field are predefined
356and should not be changed</para></listitem>
357
358<listitem><para>The count field is the number of entries
359in the SPOOL_NOTIFY_INFO_DATA array</para></listitem>
360
361</itemizedlist>
362
363<para>
364The <varname>SPOOL_NOTIFY_INFO_DATA</varname> entries contain:
365</para>
366
367<itemizedlist>
368
369<listitem><para>The type defines whether or not this event
370is for a printer or a print job</para></listitem>
371
372<listitem><para>The field is the flag identifying the event</para></listitem>
373
374<listitem><para>the notify_data union contains the new valuie of the
375attribute</para></listitem>
376
377<listitem><para>The enc_type defines the size of the structure for marshalling
378and unmarshalling</para></listitem>
379
380<listitem><para>(a) the id must be 0 for a printer event on a printer handle.
381(b) the id must be the job id for an event on a printer job
382(c) the id must be the matching number of the printer index used
383in the response packet to the RFNPCN when using a print server
384handle for notification. Samba currently uses the snum of
385the printer for this which can break if the list of services
386has been modified since the notification handle was registered.</para></listitem>
387
388<listitem><para>The size is either (a) the string length in UNICODE for strings,
389(b) the size in bytes of the security descriptor, or (c) 0 for
390data values.</para></listitem>
391
392</itemizedlist>
393
394</sect1>
395</chapter>
Note: See TracBrowser for help on using the repository browser.