08737f87e4222a55bc68fea26c79ea125f1c02bc
[samba.git] / source / libsmb / cliprint.c
1 /* 
2    Unix SMB/CIFS implementation.
3    client print routines
4    Copyright (C) Andrew Tridgell 1994-1998
5    
6    This program is free software; you can redistribute it and/or modify
7    it under the terms of the GNU General Public License as published by
8    the Free Software Foundation; either version 3 of the License, or
9    (at your option) any later version.
10    
11    This program is distributed in the hope that it will be useful,
12    but WITHOUT ANY WARRANTY; without even the implied warranty of
13    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14    GNU General Public License for more details.
15    
16    You should have received a copy of the GNU General Public License
17    along with this program.  If not, see <http://www.gnu.org/licenses/>.
18 */
19
20 #include "includes.h"
21
22 /*****************************************************************************
23  Convert a character pointer in a cli_call_api() response to a form we can use.
24  This function contains code to prevent core dumps if the server returns 
25  invalid data.
26 *****************************************************************************/
27 static const char *fix_char_ptr(unsigned int datap, unsigned int converter, 
28                           char *rdata, int rdrcnt)
29 {
30         if (datap == 0) {       /* turn NULL pointers into zero length strings */
31                 return "";
32         } else {
33                 unsigned int offset = datap - converter;
34
35                 if (offset >= rdrcnt) {
36                         DEBUG(1,("bad char ptr: datap=%u, converter=%u rdrcnt=%d>",
37                                  datap, converter, rdrcnt));
38                         return "<ERROR>";
39                 } else {
40                         return &rdata[offset];
41                 }
42         }
43 }
44
45
46 /****************************************************************************
47 call fn() on each entry in a print queue
48 ****************************************************************************/
49 int cli_print_queue(struct cli_state *cli, 
50                     void (*fn)(struct print_job_info *))
51 {
52         char *rparam = NULL;
53         char *rdata = NULL;
54         char *p;
55         unsigned int rdrcnt, rprcnt;
56         pstring param;
57         int result_code=0;
58         int i = -1;
59         
60         memset(param,'\0',sizeof(param));
61
62         p = param;
63         SSVAL(p,0,76);         /* API function number 76 (DosPrintJobEnum) */
64         p += 2;
65         pstrcpy_base(p,"zWrLeh", param);   /* parameter description? */
66         p = skip_string(param,sizeof(param),p);
67         pstrcpy_base(p,"WWzWWDDzz", param);  /* returned data format */
68         p = skip_string(param,sizeof(param),p);
69         pstrcpy_base(p,cli->share, param);    /* name of queue */
70         p = skip_string(param,sizeof(param),p);
71         SSVAL(p,0,2);   /* API function level 2, PRJINFO_2 data structure */
72         SSVAL(p,2,1000); /* size of bytes of returned data buffer */
73         p += 4;
74         pstrcpy_base(p,"", param);   /* subformat */
75         p = skip_string(param,sizeof(param),p);
76
77         DEBUG(4,("doing cli_print_queue for %s\n", cli->share));
78
79         if (cli_api(cli, 
80                     param, PTR_DIFF(p,param), 1024,  /* Param, length, maxlen */
81                     NULL, 0, CLI_BUFFER_SIZE,            /* data, length, maxlen */
82                     &rparam, &rprcnt,                /* return params, length */
83                     &rdata, &rdrcnt)) {               /* return data, length */
84                 int converter;
85                 result_code = SVAL(rparam,0);
86                 converter = SVAL(rparam,2);       /* conversion factor */
87
88                 if (result_code == 0) {
89                         struct print_job_info job;
90                         
91                         p = rdata; 
92
93                         for (i = 0; i < SVAL(rparam,4); ++i) {
94                                 job.id = SVAL(p,0);
95                                 job.priority = SVAL(p,2);
96                                 fstrcpy(job.user,
97                                         fix_char_ptr(SVAL(p,4), converter, 
98                                                      rdata, rdrcnt));
99                                 job.t = cli_make_unix_date3(cli, p + 12);
100                                 job.size = IVAL(p,16);
101                                 fstrcpy(job.name,fix_char_ptr(SVAL(p,24), 
102                                                               converter, 
103                                                               rdata, rdrcnt));
104                                 fn(&job);                               
105                                 p += 28;
106                         }
107                 }
108         }
109
110         /* If any parameters or data were returned, free the storage. */
111         SAFE_FREE(rparam);
112         SAFE_FREE(rdata);
113
114         return i;
115 }
116
117 /****************************************************************************
118   cancel a print job
119   ****************************************************************************/
120 int cli_printjob_del(struct cli_state *cli, int job)
121 {
122         char *rparam = NULL;
123         char *rdata = NULL;
124         char *p;
125         unsigned int rdrcnt,rprcnt;
126         int ret = -1;
127         pstring param;
128
129         memset(param,'\0',sizeof(param));
130
131         p = param;
132         SSVAL(p,0,81);          /* DosPrintJobDel() */
133         p += 2;
134         pstrcpy_base(p,"W", param);
135         p = skip_string(param,sizeof(param),p);
136         pstrcpy_base(p,"", param);
137         p = skip_string(param,sizeof(param),p);
138         SSVAL(p,0,job);     
139         p += 2;
140         
141         if (cli_api(cli, 
142                     param, PTR_DIFF(p,param), 1024,  /* Param, length, maxlen */
143                     NULL, 0, CLI_BUFFER_SIZE,            /* data, length, maxlen */
144                     &rparam, &rprcnt,                /* return params, length */
145                     &rdata, &rdrcnt)) {               /* return data, length */
146                 ret = SVAL(rparam,0);
147         }
148
149         SAFE_FREE(rparam);
150         SAFE_FREE(rdata);
151
152         return ret;
153 }
154
155
156 /****************************************************************************
157  Open a spool file
158 ****************************************************************************/
159
160 int cli_spl_open(struct cli_state *cli, const char *fname, int flags, int share_mode)
161 {
162         char *p;
163         unsigned openfn=0;
164         unsigned accessmode=0;
165
166         if (flags & O_CREAT)
167                 openfn |= (1<<4);
168         if (!(flags & O_EXCL)) {
169                 if (flags & O_TRUNC)
170                         openfn |= (1<<1);
171                 else
172                         openfn |= (1<<0);
173         }
174
175         accessmode = (share_mode<<4);
176
177         if ((flags & O_ACCMODE) == O_RDWR) {
178                 accessmode |= 2;
179         } else if ((flags & O_ACCMODE) == O_WRONLY) {
180                 accessmode |= 1;
181         } 
182
183 #if defined(O_SYNC)
184         if ((flags & O_SYNC) == O_SYNC) {
185                 accessmode |= (1<<14);
186         }
187 #endif /* O_SYNC */
188
189         if (share_mode == DENY_FCB) {
190                 accessmode = 0xFF;
191         }
192
193         memset(cli->outbuf,'\0',smb_size);
194         memset(cli->inbuf,'\0',smb_size);
195
196         set_message(NULL,cli->outbuf,15,0,True);
197
198         SCVAL(cli->outbuf,smb_com,SMBsplopen);
199         SSVAL(cli->outbuf,smb_tid,cli->cnum);
200         cli_setup_packet(cli);
201
202         SSVAL(cli->outbuf,smb_vwv0,0xFF);
203         SSVAL(cli->outbuf,smb_vwv2,0);  /* no additional info */
204         SSVAL(cli->outbuf,smb_vwv3,accessmode);
205         SSVAL(cli->outbuf,smb_vwv4,aSYSTEM | aHIDDEN);
206         SSVAL(cli->outbuf,smb_vwv5,0);
207         SSVAL(cli->outbuf,smb_vwv8,openfn);
208
209         if (cli->use_oplocks) {
210                 /* if using oplocks then ask for a batch oplock via
211                    core and extended methods */
212                 SCVAL(cli->outbuf,smb_flg, CVAL(cli->outbuf,smb_flg)|
213                         FLAG_REQUEST_OPLOCK|FLAG_REQUEST_BATCH_OPLOCK);
214                 SSVAL(cli->outbuf,smb_vwv2,SVAL(cli->outbuf,smb_vwv2) | 6);
215         }
216   
217         p = smb_buf(cli->outbuf);
218         p += clistr_push(cli, p, fname, -1, STR_TERMINATE);
219
220         cli_setup_bcc(cli, p);
221
222         cli_send_smb(cli);
223         if (!cli_receive_smb(cli)) {
224                 return -1;
225         }
226
227         if (cli_is_error(cli)) {
228                 return -1;
229         }
230
231         return SVAL(cli->inbuf,smb_vwv2);
232 }
233
234 /****************************************************************************
235  Close a file.
236 ****************************************************************************/
237
238 BOOL cli_spl_close(struct cli_state *cli, int fnum)
239 {
240         memset(cli->outbuf,'\0',smb_size);
241         memset(cli->inbuf,'\0',smb_size);
242
243         set_message(NULL,cli->outbuf,3,0,True);
244
245         SCVAL(cli->outbuf,smb_com,SMBsplclose);
246         SSVAL(cli->outbuf,smb_tid,cli->cnum);
247         cli_setup_packet(cli);
248
249         SSVAL(cli->outbuf,smb_vwv0,fnum);
250         SIVALS(cli->outbuf,smb_vwv1,-1);
251
252         cli_send_smb(cli);
253         if (!cli_receive_smb(cli)) {
254                 return False;
255         }
256
257         return !cli_is_error(cli);
258 }
259
260