WHATSNEW: Update changes.
[Samba/gbeck.git] / docs-xml / Samba3-Developers-Guide / printing.xml
blobbbdbb85ef70107a8495fc844f71f5d625234f55e
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>
12 <title>Samba Printing Internals</title>
15 <sect1>
16 <title>Abstract</title>
17 <para>
18 The purpose of this document is to provide some insight into
19 Samba's printing functionality and also to describe the semantics
20 of certain features of Windows client printing.
21 </para>
22 </sect1>
26 <sect1>
27 <title>
28 Printing Interface to Various Back ends
29 </title>
31 <para>
32 Samba uses a table of function pointers to seven functions.  The
33 function prototypes are defined in the <varname>printif</varname> structure declared
34 in <filename>printing.h</filename>.
35 </para>
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>
47 <para>
48 Currently there are only two printing back end implementations
49 defined.
50 </para>
52 <itemizedlist>
53         <listitem><para>a generic set of functions for working with standard UNIX
54         printing subsystems</para></listitem>
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>
60 </sect1>
65 <sect1>
66 <title>
67 Print Queue TDB's
68 </title>
71 <para>
72 Samba provides periodic caching of the output from the "lpq command"
73 for performance reasons.  This cache time is configurable in seconds.
74 Obviously the longer the cache time the less often smbd will be
75 required to exec a copy of lpq.  However, the accuracy of the print
76 queue contents displayed to clients will be diminished as well.
77 </para>
79 <para>
80 The list of currently opened print queue TDB's can be found
81 be examining the list of tdb_print_db structures ( see print_db_head
82 in printing.c ). A queue TDB is opened using the wrapper function
83 printing.c:get_print_db_byname().  The function ensures that smbd
84 does not open more than MAX_PRINT_DBS_OPEN in an effort to prevent
85 a large print server from exhausting all available file descriptors.
86 If the number of open queue TDB's exceeds the MAX_PRINT_DBS_OPEN
87 limit, smbd falls back to a most recently used algorithm for maintaining
88 a list of open TDB's.
89 </para>
91 <para>
92 There are two ways in which a a print job can be entered into
93 a print queue's TDB.  The first is to submit the job from a Windows
94 client which will insert the job information directly into the TDB.
95 The second method is to have the print job picked up by executing the
96 "lpq command".
97 </para>
99 <para><programlisting>
100 /* included from printing.h */
101 struct 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;
117 </programlisting></para>
119 <para>
120 The current manifestation of the printjob structure contains a field
121 for the UNIX job id returned from the "lpq command" and a Windows job
122 ID (32-bit bounded by PRINT_MAX_JOBID).  When a print job is returned
123 by the "lpq command" that does not match an existing job in the queue's
124 TDB, 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
125 the id reported by lpq.
126 </para>
128 <para>
129 In order to match a 32-bit Windows jobid onto a 16-bit lanman print job
130 id, smbd uses an in memory TDB to match the former to a number appropriate
131 for old lanman clients.
132 </para>
134 <para>
135 When updating a print queue, smbd will perform the following
136 steps ( refer to <filename>print.c:print_queue_update()</filename> ):
137 </para>
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>
148         <listitem><para>Store the updated time stamp for the new cache
149         listing</para></listitem>
151         <listitem><para>Retrieve the queue listing via "lpq command"</para></listitem>
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>
167         <listitem><para>Delete any jobs in the TDB that are not
168         in the in the lpq listing</para></listitem>
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>
176 <para>
177 Note that it is the contents of this TDB that is returned to Windows
178 clients and not the actual listing from the "lpq command".
179 </para>
181 <para>
182 The NT_DEVICEMODE stored as part of the printjob structure is used to
183 store a pointer to a non-default DeviceMode associated with the print
184 job.  The pointer will be non-null when the client included a Device
185 Mode in the OpenPrinterEx() call and subsequently submitted a job for
186 printing on that same handle.  If the client did not include a Device
187 Mode in the OpenPrinterEx() request, the nt_devmode field is NULL
188 and the job has the printer's device mode associated with it by default.
189 </para>
191 <para>
192 Only non-default Device Mode are stored with print jobs in the print
193 queue TDB.  Otherwise, the Device Mode is obtained from the printer
194 object when the client issues a GetJob(level == 2) request.
195 </para>
197 </sect1>
202 <sect1>
203 <title>
204 ChangeID and Client Caching of Printer Information
205 </title>
207 <para>
208 [To be filled in later]
209 </para>
210 </sect1>
214 <sect1>
215 <title>
216 Windows NT/2K Printer Change Notify
217 </title>
219 <para>
220 When working with Windows NT+ clients, it is possible for a
221 print server to use RPC to send asynchronous change notification
222 events to clients for certain printer and print job attributes.
223 This can be useful when the client needs to know that a new
224 job has been added to the queue for a given printer or that the
225 driver for a printer has been changed.  Note that this is done
226 entirely orthogonal to cache updates based on a new ChangeID for
227 a printer object.
228 </para>
230 <para>
231 The basic set of RPC's used to implement change notification are
232 </para>
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>
243 <para>
244 One additional RPC is available to a server, but is never used by the
245 Windows spooler service:
246 </para>
248 <itemizedlist>
249         <listitem><para>RouteReplyPrinter()</para></listitem>
250 </itemizedlist>
252 <para>
253 The opnum for all of these RPC's are defined in include/rpc_spoolss.h
254 </para>
256 <para>
257 Windows NT print servers use a bizarre method of sending print
258 notification event to clients.  The process of registering a new change
259 notification handle is as follows.  The 'C' is for client and the
260 'S' is for server.  All error conditions have been eliminated.
261 </para>
263 <para><programlisting>
264 C:      Obtain handle to printer or to the printer
265         server via the standard OpenPrinterEx() call.
266 S:      Respond with a valid handle to object
268 C:      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).
273 S:      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.
276 C:      The client responds with a printer handle that can be used to
277         send event notification messages.
278 S:      The server replies success to the RFFPCN request.
280 C:      The windows spooler follows the RFFPCN with a RFNPCN
281         request to fetch the current values of all monitored
282         attributes.
283 S:      The server replies with an array SPOOL_NOTIFY_INFO_DATA
284         structures (contained in a SPOOL_NOTIFY_INFO structure).
286 C:      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.
292 S:      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>
297 <para>
298 The current list of notification events supported by Samba can be
299 found by examining the internal tables in srv_spoolss_nt.c
300 </para>
302 <itemizedlist>
303         <listitem><para>printer_notify_table[]</para></listitem>
304         <listitem><para>job_notify_table[]</para></listitem>
305 </itemizedlist>
307 <para>
308 When an event occurs that could be monitored, smbd sends a message
309 to itself about the change.  The list of events to be transmitted
310 are queued by the smbd process sending the message to prevent an
311 overload of TDB usage and the internal message is sent during smbd's
312 idle loop (refer to printing/notify.c and the functions
313 send_spoolss_notify2_msg() and print_notify_send_messages() ).
314 </para>
316 <para>
317 The decision of whether or not the change is to be sent to connected
318 clients is made by the routine which actually sends the notification.
319 ( refer to srv_spoolss_nt.c:recieve_notify2_message() ).
320 </para>
322 <para>
323 Because it possible to receive a listing of multiple changes for
324 multiple printers, the notification events must be split into
325 categories by the printer name.  This makes it possible to group
326 multiple change events to be sent in a single RPC according to the
327 printer handle obtained via a ReplyOpenPrinter().
328 </para>
330 <para>
331 The actual change notification is performed using the RRPCN request
332 RPC.  This packet contains
333 </para>
336 <itemizedlist>
337         
338 <listitem><para>the printer handle registered with the
339 client's spooler on which the change occurred</para></listitem>
341 <listitem><para>The change_low value which was sent as part
342 of the last RFNPCN request from the client</para></listitem>
344 <listitem><para>The SPOOL_NOTIFY_INFO container with the event
345 information</para></listitem>
347 </itemizedlist>
349 <para>
350 A <varname>SPOOL_NOTIFY_INFO</varname> contains:
351 </para>
353 <itemizedlist>
355 <listitem><para>the version and flags field are predefined
356 and should not be changed</para></listitem>
358 <listitem><para>The count field is the number of entries
359 in the SPOOL_NOTIFY_INFO_DATA array</para></listitem>
361 </itemizedlist>
363 <para>
364 The <varname>SPOOL_NOTIFY_INFO_DATA</varname> entries contain:
365 </para>
367 <itemizedlist>
369 <listitem><para>The type defines whether or not this event
370 is for a printer or a print job</para></listitem>
372 <listitem><para>The field is the flag identifying the event</para></listitem>
374 <listitem><para>the notify_data union contains the new valuie of the
375 attribute</para></listitem>
377 <listitem><para>The enc_type defines the size of the structure for marshalling
378 and unmarshalling</para></listitem>
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
383 in the response packet to the RFNPCN when using a print server
384 handle for notification.  Samba currently uses the snum of
385 the printer for this which can break if the list of services
386 has been modified since the notification handle was registered.</para></listitem>
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
390 data values.</para></listitem>
392 </itemizedlist>
394 </sect1>
395 </chapter>