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