~zulcss/samba/server-dailies-3.4

« back to all changes in this revision

Viewing changes to docs/htmldocs/Samba3-Developers-Guide/devprinting.html

  • Committer: Chuck Short
  • Date: 2010-09-28 20:38:39 UTC
  • Revision ID: zulcss@ubuntu.com-20100928203839-pgjulytsi9ue63x1
Initial version

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
<html><head><meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1"><title>Chapter�15.�Samba Printing Internals</title><link rel="stylesheet" href="../samba.css" type="text/css"><meta name="generator" content="DocBook XSL Stylesheets V1.74.0"><link rel="home" href="index.html" title="SAMBA Developers Guide"><link rel="up" href="pt04.html" title="Part�IV.�Debugging and tracing"><link rel="prev" href="tracing.html" title="Chapter�14.�Tracing samba system calls"><link rel="next" href="pt05.html" title="Part�V.�Appendices"></head><body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF"><div class="navheader"><table width="100%" summary="Navigation header"><tr><th colspan="3" align="center">Chapter�15.�Samba Printing Internals</th></tr><tr><td width="20%" align="left"><a accesskey="p" href="tracing.html">Prev</a>�</td><th width="60%" align="center">Part�IV.�Debugging and tracing</th><td width="20%" align="right">�<a accesskey="n" href="pt05.html">Next</a></td></tr></table><hr></div><div class="chapter" lang="en"><div class="titlepage"><div><div><h2 class="title"><a name="devprinting"></a>Chapter�15.�Samba Printing Internals</h2></div><div><div class="author"><h3 class="author"><span class="firstname">Gerald</span> <span class="surname">Carter</span></h3></div></div><div><p class="pubdate">October 2002</p></div></div></div><div class="toc"><p><b>Table of Contents</b></p><dl><dt><span class="sect1"><a href="devprinting.html#id2561382">Abstract</a></span></dt><dt><span class="sect1"><a href="devprinting.html#id2561395">
 
2
Printing Interface to Various Back ends
 
3
</a></span></dt><dt><span class="sect1"><a href="devprinting.html#id2561471">
 
4
Print Queue TDB's
 
5
</a></span></dt><dt><span class="sect1"><a href="devprinting.html#id2561645">
 
6
ChangeID and Client Caching of Printer Information
 
7
</a></span></dt><dt><span class="sect1"><a href="devprinting.html#id2561655">
 
8
Windows NT/2K Printer Change Notify
 
9
</a></span></dt></dl></div><div class="sect1" lang="en"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="id2561382"></a>Abstract</h2></div></div></div><p>
 
10
The purpose of this document is to provide some insight into
 
11
Samba's printing functionality and also to describe the semantics
 
12
of certain features of Windows client printing.
 
13
</p></div><div class="sect1" lang="en"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="id2561395"></a>
 
14
Printing Interface to Various Back ends
 
15
</h2></div></div></div><p>
 
16
Samba uses a table of function pointers to seven functions.  The
 
17
function prototypes are defined in the <code class="varname">printif</code> structure declared
 
18
in <code class="filename">printing.h</code>.
 
19
</p><div class="itemizedlist"><ul type="disc"><li><p>retrieve the contents of a print queue</p></li><li><p>pause the print queue</p></li><li><p>resume a paused print queue</p></li><li><p>delete a job from the queue</p></li><li><p>pause a job in the print queue</p></li><li><p>result a paused print job in the queue</p></li><li><p>submit a job to the print queue</p></li></ul></div><p>
 
20
Currently there are only two printing back end implementations
 
21
defined.
 
22
</p><div class="itemizedlist"><ul type="disc"><li><p>a generic set of functions for working with standard UNIX
 
23
        printing subsystems</p></li><li><p>a set of CUPS specific functions (this is only enabled if
 
24
        the CUPS libraries were located at compile time).</p></li></ul></div></div><div class="sect1" lang="en"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="id2561471"></a>
 
25
Print Queue TDB's
 
26
</h2></div></div></div><p>
 
27
Samba provides periodic caching of the output from the "lpq command"
 
28
for performance reasons.  This cache time is configurable in seconds.
 
29
Obviously the longer the cache time the less often smbd will be
 
30
required to exec a copy of lpq.  However, the accuracy of the print
 
31
queue contents displayed to clients will be diminished as well.
 
32
</p><p>
 
33
The list of currently opened print queue TDB's can be found
 
34
be examining the list of tdb_print_db structures ( see print_db_head
 
35
in printing.c ). A queue TDB is opened using the wrapper function
 
36
printing.c:get_print_db_byname().  The function ensures that smbd
 
37
does not open more than MAX_PRINT_DBS_OPEN in an effort to prevent
 
38
a large print server from exhausting all available file descriptors.
 
39
If the number of open queue TDB's exceeds the MAX_PRINT_DBS_OPEN
 
40
limit, smbd falls back to a most recently used algorithm for maintaining
 
41
a list of open TDB's.
 
42
</p><p>
 
43
There are two ways in which a a print job can be entered into
 
44
a print queue's TDB.  The first is to submit the job from a Windows
 
45
client which will insert the job information directly into the TDB.
 
46
The second method is to have the print job picked up by executing the
 
47
"lpq command".
 
48
</p><pre class="programlisting">
 
49
/* included from printing.h */
 
50
struct printjob {
 
51
        pid_t pid; /* which process launched the job */
 
52
        int sysjob; /* the system (lp) job number */
 
53
        int fd; /* file descriptor of open file if open */
 
54
        time_t starttime; /* when the job started spooling */
 
55
        int status; /* the status of this job */
 
56
        size_t size; /* the size of the job so far */
 
57
        int page_count; /* then number of pages so far */
 
58
        BOOL spooled; /* has it been sent to the spooler yet? */
 
59
        BOOL smbjob; /* set if the job is a SMB job */
 
60
        fstring filename; /* the filename used to spool the file */
 
61
        fstring jobname; /* the job name given to us by the client */
 
62
        fstring user; /* the user who started the job */
 
63
        fstring queuename; /* service number of printer for this job */
 
64
        NT_DEVICEMODE *nt_devmode;
 
65
};
 
66
</pre><p>
 
67
The current manifestation of the printjob structure contains a field
 
68
for the UNIX job id returned from the "lpq command" and a Windows job
 
69
ID (32-bit bounded by PRINT_MAX_JOBID).  When a print job is returned
 
70
by the "lpq command" that does not match an existing job in the queue's
 
71
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
 
72
the id reported by lpq.
 
73
</p><p>
 
74
In order to match a 32-bit Windows jobid onto a 16-bit lanman print job
 
75
id, smbd uses an in memory TDB to match the former to a number appropriate
 
76
for old lanman clients.
 
77
</p><p>
 
78
When updating a print queue, smbd will perform the following
 
79
steps ( refer to <code class="filename">print.c:print_queue_update()</code> ):
 
80
</p><div class="orderedlist"><ol type="1"><li><p>Check to see if another smbd is currently in 
 
81
        the process of updating the queue contents by checking the pid 
 
82
        stored in <code class="constant">LOCK/<em class="replaceable"><code>printer_name</code></em></code>.  
 
83
        If so, then do not update the TDB.</p></li><li><p>Lock the mutex entry in the TDB and store our own pid.
 
84
        Check that this succeeded, else fail.</p></li><li><p>Store the updated time stamp for the new cache
 
85
        listing</p></li><li><p>Retrieve the queue listing via "lpq command"</p></li><li><pre class="programlisting">
 
86
        foreach job in the queue
 
87
        {
 
88
                if the job is a UNIX job, create a new entry;
 
89
                if the job has a Windows based jobid, then
 
90
                {
 
91
                        Lookup the record by the jobid;
 
92
                        if the lookup failed, then
 
93
                                treat it as a UNIX job;
 
94
                        else
 
95
                                update the job status only
 
96
                }
 
97
        }</pre></li><li><p>Delete any jobs in the TDB that are not
 
98
        in the in the lpq listing</p></li><li><p>Store the print queue status in the TDB</p></li><li><p>update the cache time stamp again</p></li></ol></div><p>
 
99
Note that it is the contents of this TDB that is returned to Windows
 
100
clients and not the actual listing from the "lpq command".
 
101
</p><p>
 
102
The NT_DEVICEMODE stored as part of the printjob structure is used to
 
103
store a pointer to a non-default DeviceMode associated with the print
 
104
job.  The pointer will be non-null when the client included a Device
 
105
Mode in the OpenPrinterEx() call and subsequently submitted a job for
 
106
printing on that same handle.  If the client did not include a Device
 
107
Mode in the OpenPrinterEx() request, the nt_devmode field is NULL
 
108
and the job has the printer's device mode associated with it by default.
 
109
</p><p>
 
110
Only non-default Device Mode are stored with print jobs in the print
 
111
queue TDB.  Otherwise, the Device Mode is obtained from the printer
 
112
object when the client issues a GetJob(level == 2) request.
 
113
</p></div><div class="sect1" lang="en"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="id2561645"></a>
 
114
ChangeID and Client Caching of Printer Information
 
115
</h2></div></div></div><p>
 
116
[To be filled in later]
 
117
</p></div><div class="sect1" lang="en"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="id2561655"></a>
 
118
Windows NT/2K Printer Change Notify
 
119
</h2></div></div></div><p>
 
120
When working with Windows NT+ clients, it is possible for a
 
121
print server to use RPC to send asynchronous change notification
 
122
events to clients for certain printer and print job attributes.
 
123
This can be useful when the client needs to know that a new
 
124
job has been added to the queue for a given printer or that the
 
125
driver for a printer has been changed.  Note that this is done
 
126
entirely orthogonal to cache updates based on a new ChangeID for
 
127
a printer object.
 
128
</p><p>
 
129
The basic set of RPC's used to implement change notification are
 
130
</p><div class="itemizedlist"><ul type="disc"><li><p>RemoteFindFirstPrinterChangeNotifyEx ( RFFPCN )</p></li><li><p>RemoteFindNextPrinterChangeNotifyEx ( RFNPCN )</p></li><li><p>FindClosePrinterChangeNotify( FCPCN )</p></li><li><p>ReplyOpenPrinter</p></li><li><p>ReplyClosePrinter</p></li><li><p>RouteRefreshPrinterChangeNotify ( RRPCN )</p></li></ul></div><p>
 
131
One additional RPC is available to a server, but is never used by the
 
132
Windows spooler service:
 
133
</p><div class="itemizedlist"><ul type="disc"><li><p>RouteReplyPrinter()</p></li></ul></div><p>
 
134
The opnum for all of these RPC's are defined in include/rpc_spoolss.h
 
135
</p><p>
 
136
Windows NT print servers use a bizarre method of sending print
 
137
notification event to clients.  The process of registering a new change
 
138
notification handle is as follows.  The 'C' is for client and the
 
139
'S' is for server.  All error conditions have been eliminated.
 
140
</p><pre class="programlisting">
 
141
C:      Obtain handle to printer or to the printer
 
142
        server via the standard OpenPrinterEx() call.
 
143
S:      Respond with a valid handle to object
 
144
 
 
145
C:      Send a RFFPCN request with the previously obtained
 
146
        handle with either (a) set of flags for change events
 
147
        to monitor, or (b) a PRINTER_NOTIFY_OPTIONS structure
 
148
        containing the event information to monitor.  The windows
 
149
        spooler has only been observed to use (b).
 
150
S:      The &lt;* another missing word*&gt; opens a new TCP session to the client (thus requiring
 
151
        all print clients to be CIFS servers as well) and sends
 
152
        a ReplyOpenPrinter() request to the client.
 
153
C:      The client responds with a printer handle that can be used to
 
154
        send event notification messages.
 
155
S:      The server replies success to the RFFPCN request.
 
156
 
 
157
C:      The windows spooler follows the RFFPCN with a RFNPCN
 
158
        request to fetch the current values of all monitored
 
159
        attributes.
 
160
S:      The server replies with an array SPOOL_NOTIFY_INFO_DATA
 
161
        structures (contained in a SPOOL_NOTIFY_INFO structure).
 
162
 
 
163
C:      If the change notification handle is ever released by the
 
164
        client via a FCPCN request, the server sends a ReplyClosePrinter()
 
165
        request back to the client first.  However a request of this
 
166
        nature from the client is often an indication that the previous
 
167
        notification event was not marshalled correctly by the server
 
168
        or a piece of data was wrong.
 
169
S:      The server closes the internal change notification handle
 
170
        (POLICY_HND) and does not send any further change notification
 
171
        events to the client for that printer or job.
 
172
</pre><p>
 
173
The current list of notification events supported by Samba can be
 
174
found by examining the internal tables in srv_spoolss_nt.c
 
175
</p><div class="itemizedlist"><ul type="disc"><li><p>printer_notify_table[]</p></li><li><p>job_notify_table[]</p></li></ul></div><p>
 
176
When an event occurs that could be monitored, smbd sends a message
 
177
to itself about the change.  The list of events to be transmitted
 
178
are queued by the smbd process sending the message to prevent an
 
179
overload of TDB usage and the internal message is sent during smbd's
 
180
idle loop (refer to printing/notify.c and the functions
 
181
send_spoolss_notify2_msg() and print_notify_send_messages() ).
 
182
</p><p>
 
183
The decision of whether or not the change is to be sent to connected
 
184
clients is made by the routine which actually sends the notification.
 
185
( refer to srv_spoolss_nt.c:recieve_notify2_message() ).
 
186
</p><p>
 
187
Because it possible to receive a listing of multiple changes for
 
188
multiple printers, the notification events must be split into
 
189
categories by the printer name.  This makes it possible to group
 
190
multiple change events to be sent in a single RPC according to the
 
191
printer handle obtained via a ReplyOpenPrinter().
 
192
</p><p>
 
193
The actual change notification is performed using the RRPCN request
 
194
RPC.  This packet contains
 
195
</p><div class="itemizedlist"><ul type="disc"><li><p>the printer handle registered with the
 
196
client's spooler on which the change occurred</p></li><li><p>The change_low value which was sent as part
 
197
of the last RFNPCN request from the client</p></li><li><p>The SPOOL_NOTIFY_INFO container with the event
 
198
information</p></li></ul></div><p>
 
199
A <code class="varname">SPOOL_NOTIFY_INFO</code> contains:
 
200
</p><div class="itemizedlist"><ul type="disc"><li><p>the version and flags field are predefined
 
201
and should not be changed</p></li><li><p>The count field is the number of entries
 
202
in the SPOOL_NOTIFY_INFO_DATA array</p></li></ul></div><p>
 
203
The <code class="varname">SPOOL_NOTIFY_INFO_DATA</code> entries contain:
 
204
</p><div class="itemizedlist"><ul type="disc"><li><p>The type defines whether or not this event
 
205
is for a printer or a print job</p></li><li><p>The field is the flag identifying the event</p></li><li><p>the notify_data union contains the new valuie of the
 
206
attribute</p></li><li><p>The enc_type defines the size of the structure for marshalling
 
207
and unmarshalling</p></li><li><p>(a) the id must be 0 for a printer event on a printer handle.
 
208
(b) the id must be the job id for an event on a printer job
 
209
(c) the id must be the matching number of the printer index used
 
210
in the response packet to the RFNPCN when using a print server
 
211
handle for notification.  Samba currently uses the snum of
 
212
the printer for this which can break if the list of services
 
213
has been modified since the notification handle was registered.</p></li><li><p>The size is either (a) the string length in UNICODE for strings,
 
214
(b) the size in bytes of the security descriptor, or (c) 0 for
 
215
data values.</p></li></ul></div></div></div><div class="navfooter"><hr><table width="100%" summary="Navigation footer"><tr><td width="40%" align="left"><a accesskey="p" href="tracing.html">Prev</a>�</td><td width="20%" align="center"><a accesskey="u" href="pt04.html">Up</a></td><td width="40%" align="right">�<a accesskey="n" href="pt05.html">Next</a></td></tr><tr><td width="40%" align="left" valign="top">Chapter�14.�Tracing samba system calls�</td><td width="20%" align="center"><a accesskey="h" href="index.html">Home</a></td><td width="40%" align="right" valign="top">�Part�V.�Appendices</td></tr></table></div></body></html>