1da6c28aaSamw /* 2da6c28aaSamw * CDDL HEADER START 3da6c28aaSamw * 4da6c28aaSamw * The contents of this file are subject to the terms of the 5da6c28aaSamw * Common Development and Distribution License (the "License"). 6da6c28aaSamw * You may not use this file except in compliance with the License. 7da6c28aaSamw * 8da6c28aaSamw * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9da6c28aaSamw * or http://www.opensolaris.org/os/licensing. 10da6c28aaSamw * See the License for the specific language governing permissions 11da6c28aaSamw * and limitations under the License. 12da6c28aaSamw * 13da6c28aaSamw * When distributing Covered Code, include this CDDL HEADER in each 14da6c28aaSamw * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15da6c28aaSamw * If applicable, add the following below this CDDL HEADER, with the 16da6c28aaSamw * fields enclosed by brackets "[]" replaced with your own identifying 17da6c28aaSamw * information: Portions Copyright [yyyy] [name of copyright owner] 18da6c28aaSamw * 19da6c28aaSamw * CDDL HEADER END 20da6c28aaSamw */ 21da6c28aaSamw /* 22*148c5f43SAlan Wright * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved. 23da6c28aaSamw */ 24da6c28aaSamw 25da6c28aaSamw /* 26da6c28aaSamw * SMB print interface. 27da6c28aaSamw */ 28da6c28aaSamw 29bbf6f00cSJordan Brown #include <smbsrv/smb_kproto.h> 30da6c28aaSamw 31da6c28aaSamw /* 32f96bd5c8SAlan Wright * Create a new printer file, which should be deleted automatically once 33f96bd5c8SAlan Wright * it has been closed and printed. 34da6c28aaSamw * 35da6c28aaSamw * SetupLength is the number of bytes in the first part of the resulting 36da6c28aaSamw * print spool file which contains printer-specific control strings. 37da6c28aaSamw * 38da6c28aaSamw * Mode can have the following values: 39da6c28aaSamw * 0 Text mode. The server may optionally 40da6c28aaSamw * expand tabs to a series of spaces. 41da6c28aaSamw * 1 Graphics mode. No conversion of data 42da6c28aaSamw * should be done by the server. 43da6c28aaSamw * 44f96bd5c8SAlan Wright * IdentifierString can be used by the server to provide some sort of 45f96bd5c8SAlan Wright * per-client identifying component to the print file. 46da6c28aaSamw * 47f96bd5c8SAlan Wright * When the file is closed, it will be sent to the spooler and printed. 48da6c28aaSamw */ 49faa1795aSjb150015 smb_sdrc_t 50faa1795aSjb150015 smb_pre_open_print_file(smb_request_t *sr) 51da6c28aaSamw { 52f96bd5c8SAlan Wright static uint32_t tmp_id = 10000; 53f96bd5c8SAlan Wright struct open_param *op = &sr->arg.open; 54f96bd5c8SAlan Wright char *path; 55f96bd5c8SAlan Wright char *identifier; 56*148c5f43SAlan Wright uint32_t new_id; 57f96bd5c8SAlan Wright uint16_t setup; 58f96bd5c8SAlan Wright uint16_t mode; 59f96bd5c8SAlan Wright int rc; 60f96bd5c8SAlan Wright 61f96bd5c8SAlan Wright bzero(op, sizeof (sr->arg.open)); 62f96bd5c8SAlan Wright 63f96bd5c8SAlan Wright rc = smbsr_decode_vwv(sr, "ww", &setup, &mode); 64f96bd5c8SAlan Wright if (rc == 0) 65f96bd5c8SAlan Wright rc = smbsr_decode_data(sr, "%S", sr, &identifier); 66f96bd5c8SAlan Wright 67*148c5f43SAlan Wright if (rc == 0) { 689fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States path = smb_srm_zalloc(sr, MAXPATHLEN); 69f96bd5c8SAlan Wright op->fqi.fq_path.pn_path = path; 70*148c5f43SAlan Wright new_id = atomic_inc_32_nv(&tmp_id); 71*148c5f43SAlan Wright (void) snprintf(path, MAXPATHLEN, "%s%05u", identifier, new_id); 72*148c5f43SAlan Wright } 73f96bd5c8SAlan Wright 74f96bd5c8SAlan Wright op->create_disposition = FILE_OVERWRITE_IF; 75f96bd5c8SAlan Wright op->create_options = FILE_NON_DIRECTORY_FILE; 76f96bd5c8SAlan Wright 77f96bd5c8SAlan Wright DTRACE_SMB_2(op__OpenPrintFile__start, smb_request_t *, sr, 78f96bd5c8SAlan Wright struct open_param *, op); 79f96bd5c8SAlan Wright 80f96bd5c8SAlan Wright return ((rc == 0) ? SDRC_SUCCESS : SDRC_ERROR); 81faa1795aSjb150015 } 82faa1795aSjb150015 83faa1795aSjb150015 void 84faa1795aSjb150015 smb_post_open_print_file(smb_request_t *sr) 85faa1795aSjb150015 { 86faa1795aSjb150015 DTRACE_SMB_1(op__OpenPrintFile__done, smb_request_t *, sr); 87faa1795aSjb150015 } 88faa1795aSjb150015 89f96bd5c8SAlan Wright smb_sdrc_t 90faa1795aSjb150015 smb_com_open_print_file(smb_request_t *sr) 91faa1795aSjb150015 { 92f96bd5c8SAlan Wright int rc; 93f96bd5c8SAlan Wright 94f96bd5c8SAlan Wright if (!STYPE_ISPRN(sr->tid_tree->t_res_type)) { 95f96bd5c8SAlan Wright smbsr_error(sr, NT_STATUS_BAD_DEVICE_TYPE, 96f96bd5c8SAlan Wright ERRDOS, ERROR_BAD_DEV_TYPE); 97f96bd5c8SAlan Wright return (SDRC_ERROR); 98da6c28aaSamw } 99da6c28aaSamw 100f96bd5c8SAlan Wright if (smb_common_create(sr) != NT_STATUS_SUCCESS) 101f96bd5c8SAlan Wright return (SDRC_ERROR); 102f96bd5c8SAlan Wright 103f96bd5c8SAlan Wright rc = smbsr_encode_result(sr, 1, 0, "bww", 1, sr->smb_fid, 0); 104f96bd5c8SAlan Wright return ((rc == 0) ? SDRC_SUCCESS : SDRC_ERROR); 105f96bd5c8SAlan Wright } 106da6c28aaSamw 107da6c28aaSamw /* 108f96bd5c8SAlan Wright * Close the specified file handle and queue the file for printing. 109f96bd5c8SAlan Wright * The fid refers to a file previously created as a print spool file. 110da6c28aaSamw * On successful completion of this request, the file is queued for 111da6c28aaSamw * printing by the server. 112da6c28aaSamw * 113f96bd5c8SAlan Wright * Servers that negotiate LANMAN1.0 or later allow all the the fid 114f96bd5c8SAlan Wright * to be closed and printed via any close request. 115da6c28aaSamw */ 116faa1795aSjb150015 smb_sdrc_t 117faa1795aSjb150015 smb_pre_close_print_file(smb_request_t *sr) 118da6c28aaSamw { 119f96bd5c8SAlan Wright int rc; 120f96bd5c8SAlan Wright 121f96bd5c8SAlan Wright rc = smbsr_decode_vwv(sr, "w", &sr->smb_fid); 122f96bd5c8SAlan Wright 123faa1795aSjb150015 DTRACE_SMB_1(op__ClosePrintFile__start, smb_request_t *, sr); 124f96bd5c8SAlan Wright return ((rc == 0) ? SDRC_SUCCESS : SDRC_ERROR); 125faa1795aSjb150015 } 126faa1795aSjb150015 127faa1795aSjb150015 void 128faa1795aSjb150015 smb_post_close_print_file(smb_request_t *sr) 129faa1795aSjb150015 { 130faa1795aSjb150015 DTRACE_SMB_1(op__ClosePrintFile__done, smb_request_t *, sr); 131faa1795aSjb150015 } 132faa1795aSjb150015 133f96bd5c8SAlan Wright smb_sdrc_t 134faa1795aSjb150015 smb_com_close_print_file(smb_request_t *sr) 135faa1795aSjb150015 { 136f96bd5c8SAlan Wright if (!STYPE_ISPRN(sr->tid_tree->t_res_type)) { 137f96bd5c8SAlan Wright smbsr_error(sr, NT_STATUS_BAD_DEVICE_TYPE, 138f96bd5c8SAlan Wright ERRDOS, ERROR_BAD_DEV_TYPE); 139f96bd5c8SAlan Wright return (SDRC_ERROR); 140da6c28aaSamw } 141da6c28aaSamw 142f96bd5c8SAlan Wright return (smb_com_close(sr)); 143f96bd5c8SAlan Wright } 144da6c28aaSamw 145da6c28aaSamw /* 146f96bd5c8SAlan Wright * Get a list of print queue entries on the server. Support for 147f96bd5c8SAlan Wright * this request is optional (not required for Windows clients). 148da6c28aaSamw */ 1497b59d02dSjb150015 smb_sdrc_t 150faa1795aSjb150015 smb_pre_get_print_queue(smb_request_t *sr) 151faa1795aSjb150015 { 152faa1795aSjb150015 DTRACE_SMB_1(op__GetPrintQueue__start, smb_request_t *, sr); 153faa1795aSjb150015 return (SDRC_SUCCESS); 154faa1795aSjb150015 } 155faa1795aSjb150015 156faa1795aSjb150015 void 157faa1795aSjb150015 smb_post_get_print_queue(smb_request_t *sr) 158faa1795aSjb150015 { 159faa1795aSjb150015 DTRACE_SMB_1(op__GetPrintQueue__done, smb_request_t *, sr); 160faa1795aSjb150015 } 161faa1795aSjb150015 162faa1795aSjb150015 smb_sdrc_t 163faa1795aSjb150015 smb_com_get_print_queue(smb_request_t *sr) 164da6c28aaSamw { 165da6c28aaSamw unsigned short max_count, start_ix; 166da6c28aaSamw 1677b59d02dSjb150015 if (smbsr_decode_vwv(sr, "ww", &max_count, &start_ix) != 0) 168faa1795aSjb150015 return (SDRC_ERROR); 169da6c28aaSamw 1707b59d02dSjb150015 if (smbsr_encode_result(sr, 2, 3, "bwwwbw", 2, 0, 0, 3, 1, 0)) 171faa1795aSjb150015 return (SDRC_ERROR); 1727b59d02dSjb150015 173faa1795aSjb150015 return (SDRC_SUCCESS); 174da6c28aaSamw } 175da6c28aaSamw 176da6c28aaSamw /* 177f96bd5c8SAlan Wright * Write (append) data to a print spool file. The fid must refer to 178f96bd5c8SAlan Wright * a print spool file. 179da6c28aaSamw * 180f96bd5c8SAlan Wright * The first SetupLength bytes (see SMB_COM_OPEN_PRINT_FILE) in the 181f96bd5c8SAlan Wright * print spool file contain printer setup data. 182da6c28aaSamw * 183f96bd5c8SAlan Wright * Servers that negotiate LANMAN1.0 or later also support the use of 184f96bd5c8SAlan Wright * normal write requests with print spool files. 185da6c28aaSamw */ 186faa1795aSjb150015 smb_sdrc_t 187faa1795aSjb150015 smb_pre_write_print_file(smb_request_t *sr) 188da6c28aaSamw { 189f96bd5c8SAlan Wright smb_rw_param_t *param; 190f96bd5c8SAlan Wright int rc; 191f96bd5c8SAlan Wright 192f96bd5c8SAlan Wright param = kmem_zalloc(sizeof (smb_rw_param_t), KM_SLEEP); 193f96bd5c8SAlan Wright sr->arg.rw = param; 194f96bd5c8SAlan Wright param->rw_magic = SMB_RW_MAGIC; 195f96bd5c8SAlan Wright 196f96bd5c8SAlan Wright rc = smbsr_decode_vwv(sr, "w", &sr->smb_fid); 197f96bd5c8SAlan Wright 198faa1795aSjb150015 DTRACE_SMB_1(op__WritePrintFile__start, smb_request_t *, sr); 199f96bd5c8SAlan Wright return ((rc == 0) ? SDRC_SUCCESS : SDRC_ERROR); 200faa1795aSjb150015 } 201faa1795aSjb150015 202faa1795aSjb150015 void 203faa1795aSjb150015 smb_post_write_print_file(smb_request_t *sr) 204faa1795aSjb150015 { 205faa1795aSjb150015 DTRACE_SMB_1(op__WritePrintFile__done, smb_request_t *, sr); 206f96bd5c8SAlan Wright 207f96bd5c8SAlan Wright kmem_free(sr->arg.rw, sizeof (smb_rw_param_t)); 208faa1795aSjb150015 } 209faa1795aSjb150015 210f96bd5c8SAlan Wright smb_sdrc_t 211faa1795aSjb150015 smb_com_write_print_file(smb_request_t *sr) 212faa1795aSjb150015 { 213f96bd5c8SAlan Wright smb_rw_param_t *param = sr->arg.rw; 214f96bd5c8SAlan Wright smb_node_t *node; 215f96bd5c8SAlan Wright smb_attr_t attr; 216f96bd5c8SAlan Wright int rc; 217f96bd5c8SAlan Wright 218f96bd5c8SAlan Wright if (!STYPE_ISPRN(sr->tid_tree->t_res_type)) { 219f96bd5c8SAlan Wright smbsr_error(sr, NT_STATUS_BAD_DEVICE_TYPE, 220f96bd5c8SAlan Wright ERRDOS, ERROR_BAD_DEV_TYPE); 221f96bd5c8SAlan Wright return (SDRC_ERROR); 222f96bd5c8SAlan Wright } 223f96bd5c8SAlan Wright 224f96bd5c8SAlan Wright smbsr_lookup_file(sr); 225f96bd5c8SAlan Wright if (sr->fid_ofile == NULL) { 226f96bd5c8SAlan Wright smbsr_error(sr, NT_STATUS_INVALID_HANDLE, ERRDOS, ERRbadfid); 227f96bd5c8SAlan Wright return (SDRC_ERROR); 228f96bd5c8SAlan Wright } 229f96bd5c8SAlan Wright 230f96bd5c8SAlan Wright node = sr->fid_ofile->f_node; 231f96bd5c8SAlan Wright sr->user_cr = smb_ofile_getcred(sr->fid_ofile); 232f96bd5c8SAlan Wright 233f96bd5c8SAlan Wright if (smb_node_getattr(sr, node, &attr) != 0) { 234f96bd5c8SAlan Wright smbsr_error(sr, NT_STATUS_INTERNAL_ERROR, 235f96bd5c8SAlan Wright ERRDOS, ERROR_INTERNAL_ERROR); 236f96bd5c8SAlan Wright return (SDRC_ERROR); 237f96bd5c8SAlan Wright } 238f96bd5c8SAlan Wright 239f96bd5c8SAlan Wright if ((smbsr_decode_data(sr, "D", ¶m->rw_vdb)) != 0) { 240f96bd5c8SAlan Wright smbsr_error(sr, NT_STATUS_INVALID_PARAMETER, 241f96bd5c8SAlan Wright ERRDOS, ERROR_INVALID_PARAMETER); 242f96bd5c8SAlan Wright return (SDRC_ERROR); 243f96bd5c8SAlan Wright } 244f96bd5c8SAlan Wright 245f96bd5c8SAlan Wright param->rw_count = param->rw_vdb.vdb_len; 246f96bd5c8SAlan Wright param->rw_offset = attr.sa_vattr.va_size; 247f96bd5c8SAlan Wright param->rw_vdb.vdb_uio.uio_loffset = (offset_t)param->rw_offset; 248f96bd5c8SAlan Wright 249f96bd5c8SAlan Wright if ((rc = smb_common_write(sr, param)) != 0) { 250f96bd5c8SAlan Wright if (sr->smb_error.status != NT_STATUS_FILE_LOCK_CONFLICT) 251f96bd5c8SAlan Wright smbsr_errno(sr, rc); 252f96bd5c8SAlan Wright return (SDRC_ERROR); 253f96bd5c8SAlan Wright } 254f96bd5c8SAlan Wright 255f96bd5c8SAlan Wright rc = smbsr_encode_empty_result(sr); 256f96bd5c8SAlan Wright return ((rc == 0) ? SDRC_SUCCESS : SDRC_ERROR); 257da6c28aaSamw } 258