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