| 1 | /*
|
|---|
| 2 | * Unix SMB/CIFS implementation.
|
|---|
| 3 | * RPC Pipe client / server routines
|
|---|
| 4 | * Copyright (C) Andrew Tridgell 1992-2000,
|
|---|
| 5 | * Copyright (C) Jean François Micouleau 1998-2000.
|
|---|
| 6 | * Copyright (C) Gerald Carter 2002-2005.
|
|---|
| 7 | *
|
|---|
| 8 | * This program is free software; you can redistribute it and/or modify
|
|---|
| 9 | * it under the terms of the GNU General Public License as published by
|
|---|
| 10 | * the Free Software Foundation; either version 3 of the License, or
|
|---|
| 11 | * (at your option) any later version.
|
|---|
| 12 | *
|
|---|
| 13 | * This program is distributed in the hope that it will be useful,
|
|---|
| 14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|---|
| 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|---|
| 16 | * GNU General Public License for more details.
|
|---|
| 17 | *
|
|---|
| 18 | * You should have received a copy of the GNU General Public License
|
|---|
| 19 | * along with this program; if not, see <http://www.gnu.org/licenses/>.
|
|---|
| 20 | */
|
|---|
| 21 |
|
|---|
| 22 | #include "includes.h"
|
|---|
| 23 |
|
|---|
| 24 | static TDB_CONTEXT *tdb_forms; /* used for forms files */
|
|---|
| 25 | static TDB_CONTEXT *tdb_drivers; /* used for driver files */
|
|---|
| 26 | static TDB_CONTEXT *tdb_printers; /* used for printers files */
|
|---|
| 27 |
|
|---|
| 28 | #define FORMS_PREFIX "FORMS/"
|
|---|
| 29 | #define DRIVERS_PREFIX "DRIVERS/"
|
|---|
| 30 | #define DRIVER_INIT_PREFIX "DRIVER_INIT/"
|
|---|
| 31 | #define PRINTERS_PREFIX "PRINTERS/"
|
|---|
| 32 | #define SECDESC_PREFIX "SECDESC/"
|
|---|
| 33 | #define GLOBAL_C_SETPRINTER "GLOBALS/c_setprinter"
|
|---|
| 34 |
|
|---|
| 35 | #define NTDRIVERS_DATABASE_VERSION_1 1
|
|---|
| 36 | #define NTDRIVERS_DATABASE_VERSION_2 2
|
|---|
| 37 | #define NTDRIVERS_DATABASE_VERSION_3 3 /* little endian version of v2 */
|
|---|
| 38 | #define NTDRIVERS_DATABASE_VERSION_4 4 /* fix generic bits in security descriptors */
|
|---|
| 39 | #define NTDRIVERS_DATABASE_VERSION_5 5 /* normalize keys in ntprinters.tdb */
|
|---|
| 40 |
|
|---|
| 41 | /* Map generic permissions to printer object specific permissions */
|
|---|
| 42 |
|
|---|
| 43 | const struct generic_mapping printer_generic_mapping = {
|
|---|
| 44 | PRINTER_READ,
|
|---|
| 45 | PRINTER_WRITE,
|
|---|
| 46 | PRINTER_EXECUTE,
|
|---|
| 47 | PRINTER_ALL_ACCESS
|
|---|
| 48 | };
|
|---|
| 49 |
|
|---|
| 50 | const struct standard_mapping printer_std_mapping = {
|
|---|
| 51 | PRINTER_READ,
|
|---|
| 52 | PRINTER_WRITE,
|
|---|
| 53 | PRINTER_EXECUTE,
|
|---|
| 54 | PRINTER_ALL_ACCESS
|
|---|
| 55 | };
|
|---|
| 56 |
|
|---|
| 57 | /* Map generic permissions to print server object specific permissions */
|
|---|
| 58 |
|
|---|
| 59 | const struct generic_mapping printserver_generic_mapping = {
|
|---|
| 60 | SERVER_READ,
|
|---|
| 61 | SERVER_WRITE,
|
|---|
| 62 | SERVER_EXECUTE,
|
|---|
| 63 | SERVER_ALL_ACCESS
|
|---|
| 64 | };
|
|---|
| 65 |
|
|---|
| 66 | const struct generic_mapping printserver_std_mapping = {
|
|---|
| 67 | SERVER_READ,
|
|---|
| 68 | SERVER_WRITE,
|
|---|
| 69 | SERVER_EXECUTE,
|
|---|
| 70 | SERVER_ALL_ACCESS
|
|---|
| 71 | };
|
|---|
| 72 |
|
|---|
| 73 | /* Map generic permissions to job object specific permissions */
|
|---|
| 74 |
|
|---|
| 75 | const struct generic_mapping job_generic_mapping = {
|
|---|
| 76 | JOB_READ,
|
|---|
| 77 | JOB_WRITE,
|
|---|
| 78 | JOB_EXECUTE,
|
|---|
| 79 | JOB_ALL_ACCESS
|
|---|
| 80 | };
|
|---|
| 81 |
|
|---|
| 82 | /* We need one default form to support our default printer. Msoft adds the
|
|---|
| 83 | forms it wants and in the ORDER it wants them (note: DEVMODE papersize is an
|
|---|
| 84 | array index). Letter is always first, so (for the current code) additions
|
|---|
| 85 | always put things in the correct order. */
|
|---|
| 86 | static const nt_forms_struct default_forms[] = {
|
|---|
| 87 | {"Letter",0x1,0x34b5c,0x44368,0x0,0x0,0x34b5c,0x44368},
|
|---|
| 88 | {"Letter Small",0x1,0x34b5c,0x44368,0x0,0x0,0x34b5c,0x44368},
|
|---|
| 89 | {"Tabloid",0x1,0x44368,0x696b8,0x0,0x0,0x44368,0x696b8},
|
|---|
| 90 | {"Ledger",0x1,0x696b8,0x44368,0x0,0x0,0x696b8,0x44368},
|
|---|
| 91 | {"Legal",0x1,0x34b5c,0x56d10,0x0,0x0,0x34b5c,0x56d10},
|
|---|
| 92 | {"Statement",0x1,0x221b4,0x34b5c,0x0,0x0,0x221b4,0x34b5c},
|
|---|
| 93 | {"Executive",0x1,0x2cf56,0x411cc,0x0,0x0,0x2cf56,0x411cc},
|
|---|
| 94 | {"A3",0x1,0x48828,0x668a0,0x0,0x0,0x48828,0x668a0},
|
|---|
| 95 | {"A4",0x1,0x33450,0x48828,0x0,0x0,0x33450,0x48828},
|
|---|
| 96 | {"A4 Small",0x1,0x33450,0x48828,0x0,0x0,0x33450,0x48828},
|
|---|
| 97 | {"A5",0x1,0x24220,0x33450,0x0,0x0,0x24220,0x33450},
|
|---|
| 98 | {"B4 (JIS)",0x1,0x3ebe8,0x58de0,0x0,0x0,0x3ebe8,0x58de0},
|
|---|
| 99 | {"B5 (JIS)",0x1,0x2c6f0,0x3ebe8,0x0,0x0,0x2c6f0,0x3ebe8},
|
|---|
| 100 | {"Folio",0x1,0x34b5c,0x509d8,0x0,0x0,0x34b5c,0x509d8},
|
|---|
| 101 | {"Quarto",0x1,0x347d8,0x43238,0x0,0x0,0x347d8,0x43238},
|
|---|
| 102 | {"10x14",0x1,0x3e030,0x56d10,0x0,0x0,0x3e030,0x56d10},
|
|---|
| 103 | {"11x17",0x1,0x44368,0x696b8,0x0,0x0,0x44368,0x696b8},
|
|---|
| 104 | {"Note",0x1,0x34b5c,0x44368,0x0,0x0,0x34b5c,0x44368},
|
|---|
| 105 | {"Envelope #9",0x1,0x18079,0x37091,0x0,0x0,0x18079,0x37091},
|
|---|
| 106 | {"Envelope #10",0x1,0x19947,0x3ae94,0x0,0x0,0x19947,0x3ae94},
|
|---|
| 107 | {"Envelope #11",0x1,0x1be7c,0x40565,0x0,0x0,0x1be7c,0x40565},
|
|---|
| 108 | {"Envelope #12",0x1,0x1d74a,0x44368,0x0,0x0,0x1d74a,0x44368},
|
|---|
| 109 | {"Envelope #14",0x1,0x1f018,0x47504,0x0,0x0,0x1f018,0x47504},
|
|---|
| 110 | {"C size sheet",0x1,0x696b8,0x886d0,0x0,0x0,0x696b8,0x886d0},
|
|---|
| 111 | {"D size sheet",0x1,0x886d0,0xd2d70,0x0,0x0,0x886d0,0xd2d70},
|
|---|
| 112 | {"E size sheet",0x1,0xd2d70,0x110da0,0x0,0x0,0xd2d70,0x110da0},
|
|---|
| 113 | {"Envelope DL",0x1,0x1adb0,0x35b60,0x0,0x0,0x1adb0,0x35b60},
|
|---|
| 114 | {"Envelope C5",0x1,0x278d0,0x37e88,0x0,0x0,0x278d0,0x37e88},
|
|---|
| 115 | {"Envelope C3",0x1,0x4f1a0,0x6fd10,0x0,0x0,0x4f1a0,0x6fd10},
|
|---|
| 116 | {"Envelope C4",0x1,0x37e88,0x4f1a0,0x0,0x0,0x37e88,0x4f1a0},
|
|---|
| 117 | {"Envelope C6",0x1,0x1bd50,0x278d0,0x0,0x0,0x1bd50,0x278d0},
|
|---|
| 118 | {"Envelope C65",0x1,0x1bd50,0x37e88,0x0,0x0,0x1bd50,0x37e88},
|
|---|
| 119 | {"Envelope B4",0x1,0x3d090,0x562e8,0x0,0x0,0x3d090,0x562e8},
|
|---|
| 120 | {"Envelope B5",0x1,0x2af80,0x3d090,0x0,0x0,0x2af80,0x3d090},
|
|---|
| 121 | {"Envelope B6",0x1,0x2af80,0x1e848,0x0,0x0,0x2af80,0x1e848},
|
|---|
| 122 | {"Envelope",0x1,0x1adb0,0x38270,0x0,0x0,0x1adb0,0x38270},
|
|---|
| 123 | {"Envelope Monarch",0x1,0x18079,0x2e824,0x0,0x0,0x18079,0x2e824},
|
|---|
| 124 | {"6 3/4 Envelope",0x1,0x167ab,0x284ec,0x0,0x0,0x167ab,0x284ec},
|
|---|
| 125 | {"US Std Fanfold",0x1,0x5c3e1,0x44368,0x0,0x0,0x5c3e1,0x44368},
|
|---|
| 126 | {"German Std Fanfold",0x1,0x34b5c,0x4a6a0,0x0,0x0,0x34b5c,0x4a6a0},
|
|---|
| 127 | {"German Legal Fanfold",0x1,0x34b5c,0x509d8,0x0,0x0,0x34b5c,0x509d8},
|
|---|
| 128 | {"B4 (ISO)",0x1,0x3d090,0x562e8,0x0,0x0,0x3d090,0x562e8},
|
|---|
| 129 | {"Japanese Postcard",0x1,0x186a0,0x24220,0x0,0x0,0x186a0,0x24220},
|
|---|
| 130 | {"9x11",0x1,0x37cf8,0x44368,0x0,0x0,0x37cf8,0x44368},
|
|---|
| 131 | {"10x11",0x1,0x3e030,0x44368,0x0,0x0,0x3e030,0x44368},
|
|---|
| 132 | {"15x11",0x1,0x5d048,0x44368,0x0,0x0,0x5d048,0x44368},
|
|---|
| 133 | {"Envelope Invite",0x1,0x35b60,0x35b60,0x0,0x0,0x35b60,0x35b60},
|
|---|
| 134 | {"Reserved48",0x1,0x1,0x1,0x0,0x0,0x1,0x1},
|
|---|
| 135 | {"Reserved49",0x1,0x1,0x1,0x0,0x0,0x1,0x1},
|
|---|
| 136 | {"Letter Extra",0x1,0x3ae94,0x4a6a0,0x0,0x0,0x3ae94,0x4a6a0},
|
|---|
| 137 | {"Legal Extra",0x1,0x3ae94,0x5d048,0x0,0x0,0x3ae94,0x5d048},
|
|---|
| 138 | {"Tabloid Extra",0x1,0x4a6a0,0x6f9f0,0x0,0x0,0x4a6a0,0x6f9f0},
|
|---|
| 139 | {"A4 Extra",0x1,0x397c2,0x4eb16,0x0,0x0,0x397c2,0x4eb16},
|
|---|
| 140 | {"Letter Transverse",0x1,0x34b5c,0x44368,0x0,0x0,0x34b5c,0x44368},
|
|---|
| 141 | {"A4 Transverse",0x1,0x33450,0x48828,0x0,0x0,0x33450,0x48828},
|
|---|
| 142 | {"Letter Extra Transverse",0x1,0x3ae94,0x4a6a0,0x0,0x0,0x3ae94,0x4a6a0},
|
|---|
| 143 | {"Super A",0x1,0x376b8,0x56ea0,0x0,0x0,0x376b8,0x56ea0},
|
|---|
| 144 | {"Super B",0x1,0x4a768,0x76e58,0x0,0x0,0x4a768,0x76e58},
|
|---|
| 145 | {"Letter Plus",0x1,0x34b5c,0x4eb16,0x0,0x0,0x34b5c,0x4eb16},
|
|---|
| 146 | {"A4 Plus",0x1,0x33450,0x50910,0x0,0x0,0x33450,0x50910},
|
|---|
| 147 | {"A5 Transverse",0x1,0x24220,0x33450,0x0,0x0,0x24220,0x33450},
|
|---|
| 148 | {"B5 (JIS) Transverse",0x1,0x2c6f0,0x3ebe8,0x0,0x0,0x2c6f0,0x3ebe8},
|
|---|
| 149 | {"A3 Extra",0x1,0x4e9d0,0x6ca48,0x0,0x0,0x4e9d0,0x6ca48},
|
|---|
| 150 | {"A5 Extra",0x1,0x2a7b0,0x395f8,0x0,0x0,0x2a7b0,0x395f8},
|
|---|
| 151 | {"B5 (ISO) Extra",0x1,0x31128,0x43620,0x0,0x0,0x31128,0x43620},
|
|---|
| 152 | {"A2",0x1,0x668a0,0x91050,0x0,0x0,0x668a0,0x91050},
|
|---|
| 153 | {"A3 Transverse",0x1,0x48828,0x668a0,0x0,0x0,0x48828,0x668a0},
|
|---|
| 154 | {"A3 Extra Transverse",0x1,0x4e9d0,0x6ca48,0x0,0x0,0x4e9d0,0x6ca48},
|
|---|
| 155 | {"Japanese Double Postcard",0x1,0x30d40,0x24220,0x0,0x0,0x30d40,0x24220},
|
|---|
| 156 | {"A6",0x1,0x19a28,0x24220,0x0,0x0,0x19a28,0x24220},
|
|---|
| 157 | {"Japanese Envelope Kaku #2",0x1,0x3a980,0x510e0,0x0,0x0,0x3a980,0x510e0},
|
|---|
| 158 | {"Japanese Envelope Kaku #3",0x1,0x34bc0,0x43a08,0x0,0x0,0x34bc0,0x43a08},
|
|---|
| 159 | {"Japanese Envelope Chou #3",0x1,0x1d4c0,0x395f8,0x0,0x0,0x1d4c0,0x395f8},
|
|---|
| 160 | {"Japanese Envelope Chou #4",0x1,0x15f90,0x320c8,0x0,0x0,0x15f90,0x320c8},
|
|---|
| 161 | {"Letter Rotated",0x1,0x44368,0x34b5c,0x0,0x0,0x44368,0x34b5c},
|
|---|
| 162 | {"A3 Rotated",0x1,0x668a0,0x48828,0x0,0x0,0x668a0,0x48828},
|
|---|
| 163 | {"A4 Rotated",0x1,0x48828,0x33450,0x0,0x0,0x48828,0x33450},
|
|---|
| 164 | {"A5 Rotated",0x1,0x33450,0x24220,0x0,0x0,0x33450,0x24220},
|
|---|
| 165 | {"B4 (JIS) Rotated",0x1,0x58de0,0x3ebe8,0x0,0x0,0x58de0,0x3ebe8},
|
|---|
| 166 | {"B5 (JIS) Rotated",0x1,0x3ebe8,0x2c6f0,0x0,0x0,0x3ebe8,0x2c6f0},
|
|---|
| 167 | {"Japanese Postcard Rotated",0x1,0x24220,0x186a0,0x0,0x0,0x24220,0x186a0},
|
|---|
| 168 | {"Double Japan Postcard Rotated",0x1,0x24220,0x30d40,0x0,0x0,0x24220,0x30d40},
|
|---|
| 169 | {"A6 Rotated",0x1,0x24220,0x19a28,0x0,0x0,0x24220,0x19a28},
|
|---|
| 170 | {"Japan Envelope Kaku #2 Rotated",0x1,0x510e0,0x3a980,0x0,0x0,0x510e0,0x3a980},
|
|---|
| 171 | {"Japan Envelope Kaku #3 Rotated",0x1,0x43a08,0x34bc0,0x0,0x0,0x43a08, 0x34bc0},
|
|---|
| 172 | {"Japan Envelope Chou #3 Rotated",0x1,0x395f8,0x1d4c0,0x0,0x0,0x395f8,0x1d4c0},
|
|---|
| 173 | {"Japan Envelope Chou #4 Rotated",0x1,0x320c8,0x15f90,0x0,0x0,0x320c8,0x15f90},
|
|---|
| 174 | {"B6 (JIS)",0x1,0x1f400,0x2c6f0,0x0,0x0,0x1f400,0x2c6f0},
|
|---|
| 175 | {"B6 (JIS) Rotated",0x1,0x2c6f0,0x1f400,0x0,0x0,0x2c6f0,0x1f400},
|
|---|
| 176 | {"12x11",0x1,0x4a724,0x443e1,0x0,0x0,0x4a724,0x443e1},
|
|---|
| 177 | {"Japan Envelope You #4",0x1,0x19a28,0x395f8,0x0,0x0,0x19a28,0x395f8},
|
|---|
| 178 | {"Japan Envelope You #4 Rotated",0x1,0x395f8,0x19a28,0x0,0x0,0x395f8,0x19a28},
|
|---|
| 179 | {"PRC 16K",0x1,0x2de60,0x3f7a0,0x0,0x0,0x2de60,0x3f7a0},
|
|---|
| 180 | {"PRC 32K",0x1,0x1fbd0,0x2cec0,0x0,0x0,0x1fbd0,0x2cec0},
|
|---|
| 181 | {"PRC 32K(Big)",0x1,0x222e0,0x318f8,0x0,0x0,0x222e0,0x318f8},
|
|---|
| 182 | {"PRC Envelope #1",0x1,0x18e70,0x28488,0x0,0x0,0x18e70,0x28488},
|
|---|
| 183 | {"PRC Envelope #2",0x1,0x18e70,0x2af80,0x0,0x0,0x18e70,0x2af80},
|
|---|
| 184 | {"PRC Envelope #3",0x1,0x1e848,0x2af80,0x0,0x0,0x1e848,0x2af80},
|
|---|
| 185 | {"PRC Envelope #4",0x1,0x1adb0,0x32c80,0x0,0x0,0x1adb0,0x32c80},
|
|---|
| 186 | {"PRC Envelope #5",0x1,0x1adb0,0x35b60,0x0,0x0,0x1adb0,0x35b60},
|
|---|
| 187 | {"PRC Envelope #6",0x1,0x1d4c0,0x38270,0x0,0x0,0x1d4c0,0x38270},
|
|---|
| 188 | {"PRC Envelope #7",0x1,0x27100,0x38270,0x0,0x0,0x27100,0x38270},
|
|---|
| 189 | {"PRC Envelope #8",0x1,0x1d4c0,0x4b708,0x0,0x0,0x1d4c0,0x4b708},
|
|---|
| 190 | {"PRC Envelope #9",0x1,0x37e88,0x4f1a0,0x0,0x0,0x37e88,0x4f1a0},
|
|---|
| 191 | {"PRC Envelope #10",0x1,0x4f1a0,0x6fd10,0x0,0x0,0x4f1a0,0x6fd10},
|
|---|
| 192 | {"PRC 16K Rotated",0x1,0x3f7a0,0x2de60,0x0,0x0,0x3f7a0,0x2de60},
|
|---|
| 193 | {"PRC 32K Rotated",0x1,0x2cec0,0x1fbd0,0x0,0x0,0x2cec0,0x1fbd0},
|
|---|
| 194 | {"PRC 32K(Big) Rotated",0x1,0x318f8,0x222e0,0x0,0x0,0x318f8,0x222e0},
|
|---|
| 195 | {"PRC Envelope #1 Rotated",0x1,0x28488,0x18e70,0x0,0x0,0x28488,0x18e70},
|
|---|
| 196 | {"PRC Envelope #2 Rotated",0x1,0x2af80,0x18e70,0x0,0x0,0x2af80,0x18e70},
|
|---|
| 197 | {"PRC Envelope #3 Rotated",0x1,0x2af80,0x1e848,0x0,0x0,0x2af80,0x1e848},
|
|---|
| 198 | {"PRC Envelope #4 Rotated",0x1,0x32c80,0x1adb0,0x0,0x0,0x32c80,0x1adb0},
|
|---|
| 199 | {"PRC Envelope #5 Rotated",0x1,0x35b60,0x1adb0,0x0,0x0,0x35b60,0x1adb0},
|
|---|
| 200 | {"PRC Envelope #6 Rotated",0x1,0x38270,0x1d4c0,0x0,0x0,0x38270,0x1d4c0},
|
|---|
| 201 | {"PRC Envelope #7 Rotated",0x1,0x38270,0x27100,0x0,0x0,0x38270,0x27100},
|
|---|
| 202 | {"PRC Envelope #8 Rotated",0x1,0x4b708,0x1d4c0,0x0,0x0,0x4b708,0x1d4c0},
|
|---|
| 203 | {"PRC Envelope #9 Rotated",0x1,0x4f1a0,0x37e88,0x0,0x0,0x4f1a0,0x37e88},
|
|---|
| 204 | {"PRC Envelope #10 Rotated",0x1,0x6fd10,0x4f1a0,0x0,0x0,0x6fd10,0x4f1a0}
|
|---|
| 205 | };
|
|---|
| 206 |
|
|---|
| 207 | static const struct print_architecture_table_node archi_table[]= {
|
|---|
| 208 |
|
|---|
| 209 | {"Windows 4.0", SPL_ARCH_WIN40, 0 },
|
|---|
| 210 | {"Windows NT x86", SPL_ARCH_W32X86, 2 },
|
|---|
| 211 | {"Windows NT R4000", SPL_ARCH_W32MIPS, 2 },
|
|---|
| 212 | {"Windows NT Alpha_AXP", SPL_ARCH_W32ALPHA, 2 },
|
|---|
| 213 | {"Windows NT PowerPC", SPL_ARCH_W32PPC, 2 },
|
|---|
| 214 | {"Windows IA64", SPL_ARCH_IA64, 3 },
|
|---|
| 215 | {"Windows x64", SPL_ARCH_X64, 3 },
|
|---|
| 216 | {NULL, "", -1 }
|
|---|
| 217 | };
|
|---|
| 218 |
|
|---|
| 219 |
|
|---|
| 220 | /****************************************************************************
|
|---|
| 221 | generate a new TDB_DATA key for storing a printer
|
|---|
| 222 | ****************************************************************************/
|
|---|
| 223 |
|
|---|
| 224 | static TDB_DATA make_printer_tdbkey(TALLOC_CTX *ctx, const char *sharename )
|
|---|
| 225 | {
|
|---|
| 226 | fstring share;
|
|---|
| 227 | char *keystr = NULL;
|
|---|
| 228 | TDB_DATA key;
|
|---|
| 229 |
|
|---|
| 230 | fstrcpy(share, sharename);
|
|---|
| 231 | strlower_m(share);
|
|---|
| 232 |
|
|---|
| 233 | keystr = talloc_asprintf(ctx, "%s%s", PRINTERS_PREFIX, share);
|
|---|
| 234 | key = string_term_tdb_data(keystr ? keystr : "");
|
|---|
| 235 |
|
|---|
| 236 | return key;
|
|---|
| 237 | }
|
|---|
| 238 |
|
|---|
| 239 | /****************************************************************************
|
|---|
| 240 | generate a new TDB_DATA key for storing a printer security descriptor
|
|---|
| 241 | ****************************************************************************/
|
|---|
| 242 |
|
|---|
| 243 | static TDB_DATA make_printers_secdesc_tdbkey(TALLOC_CTX *ctx,
|
|---|
| 244 | const char* sharename )
|
|---|
| 245 | {
|
|---|
| 246 | fstring share;
|
|---|
| 247 | char *keystr = NULL;
|
|---|
| 248 | TDB_DATA key;
|
|---|
| 249 |
|
|---|
| 250 | fstrcpy(share, sharename );
|
|---|
| 251 | strlower_m(share);
|
|---|
| 252 |
|
|---|
| 253 | keystr = talloc_asprintf(ctx, "%s%s", SECDESC_PREFIX, share);
|
|---|
| 254 | key = string_term_tdb_data(keystr ? keystr : "");
|
|---|
| 255 |
|
|---|
| 256 | return key;
|
|---|
| 257 | }
|
|---|
| 258 |
|
|---|
| 259 | /****************************************************************************
|
|---|
| 260 | ****************************************************************************/
|
|---|
| 261 |
|
|---|
| 262 | static bool upgrade_to_version_3(void)
|
|---|
| 263 | {
|
|---|
| 264 | TDB_DATA kbuf, newkey, dbuf;
|
|---|
| 265 |
|
|---|
| 266 | DEBUG(0,("upgrade_to_version_3: upgrading print tdb's to version 3\n"));
|
|---|
| 267 |
|
|---|
| 268 | for (kbuf = tdb_firstkey(tdb_drivers); kbuf.dptr;
|
|---|
| 269 | newkey = tdb_nextkey(tdb_drivers, kbuf), free(kbuf.dptr), kbuf=newkey) {
|
|---|
| 270 |
|
|---|
| 271 | dbuf = tdb_fetch(tdb_drivers, kbuf);
|
|---|
| 272 |
|
|---|
| 273 | if (strncmp((const char *)kbuf.dptr, FORMS_PREFIX, strlen(FORMS_PREFIX)) == 0) {
|
|---|
| 274 | DEBUG(0,("upgrade_to_version_3:moving form\n"));
|
|---|
| 275 | if (tdb_store(tdb_forms, kbuf, dbuf, TDB_REPLACE) != 0) {
|
|---|
| 276 | SAFE_FREE(dbuf.dptr);
|
|---|
| 277 | DEBUG(0,("upgrade_to_version_3: failed to move form. Error (%s).\n", tdb_errorstr(tdb_forms)));
|
|---|
| 278 | return False;
|
|---|
| 279 | }
|
|---|
| 280 | if (tdb_delete(tdb_drivers, kbuf) != 0) {
|
|---|
| 281 | SAFE_FREE(dbuf.dptr);
|
|---|
| 282 | DEBUG(0,("upgrade_to_version_3: failed to delete form. Error (%s)\n", tdb_errorstr(tdb_drivers)));
|
|---|
| 283 | return False;
|
|---|
| 284 | }
|
|---|
| 285 | }
|
|---|
| 286 |
|
|---|
| 287 | if (strncmp((const char *)kbuf.dptr, PRINTERS_PREFIX, strlen(PRINTERS_PREFIX)) == 0) {
|
|---|
| 288 | DEBUG(0,("upgrade_to_version_3:moving printer\n"));
|
|---|
| 289 | if (tdb_store(tdb_printers, kbuf, dbuf, TDB_REPLACE) != 0) {
|
|---|
| 290 | SAFE_FREE(dbuf.dptr);
|
|---|
| 291 | DEBUG(0,("upgrade_to_version_3: failed to move printer. Error (%s)\n", tdb_errorstr(tdb_printers)));
|
|---|
| 292 | return False;
|
|---|
| 293 | }
|
|---|
| 294 | if (tdb_delete(tdb_drivers, kbuf) != 0) {
|
|---|
| 295 | SAFE_FREE(dbuf.dptr);
|
|---|
| 296 | DEBUG(0,("upgrade_to_version_3: failed to delete printer. Error (%s)\n", tdb_errorstr(tdb_drivers)));
|
|---|
| 297 | return False;
|
|---|
| 298 | }
|
|---|
| 299 | }
|
|---|
| 300 |
|
|---|
| 301 | if (strncmp((const char *)kbuf.dptr, SECDESC_PREFIX, strlen(SECDESC_PREFIX)) == 0) {
|
|---|
| 302 | DEBUG(0,("upgrade_to_version_3:moving secdesc\n"));
|
|---|
| 303 | if (tdb_store(tdb_printers, kbuf, dbuf, TDB_REPLACE) != 0) {
|
|---|
| 304 | SAFE_FREE(dbuf.dptr);
|
|---|
| 305 | DEBUG(0,("upgrade_to_version_3: failed to move secdesc. Error (%s)\n", tdb_errorstr(tdb_printers)));
|
|---|
| 306 | return False;
|
|---|
| 307 | }
|
|---|
| 308 | if (tdb_delete(tdb_drivers, kbuf) != 0) {
|
|---|
| 309 | SAFE_FREE(dbuf.dptr);
|
|---|
| 310 | DEBUG(0,("upgrade_to_version_3: failed to delete secdesc. Error (%s)\n", tdb_errorstr(tdb_drivers)));
|
|---|
| 311 | return False;
|
|---|
| 312 | }
|
|---|
| 313 | }
|
|---|
| 314 |
|
|---|
| 315 | SAFE_FREE(dbuf.dptr);
|
|---|
| 316 | }
|
|---|
| 317 |
|
|---|
| 318 | return True;
|
|---|
| 319 | }
|
|---|
| 320 |
|
|---|
| 321 | /*******************************************************************
|
|---|
| 322 | Fix an issue with security descriptors. Printer sec_desc must
|
|---|
| 323 | use more than the generic bits that were previously used
|
|---|
| 324 | in <= 3.0.14a. They must also have a owner and group SID assigned.
|
|---|
| 325 | Otherwise, any printers than have been migrated to a Windows
|
|---|
| 326 | host using printmig.exe will not be accessible.
|
|---|
| 327 | *******************************************************************/
|
|---|
| 328 |
|
|---|
| 329 | static int sec_desc_upg_fn( TDB_CONTEXT *the_tdb, TDB_DATA key,
|
|---|
| 330 | TDB_DATA data, void *state )
|
|---|
| 331 | {
|
|---|
| 332 | NTSTATUS status;
|
|---|
| 333 | SEC_DESC_BUF *sd_orig = NULL;
|
|---|
| 334 | SEC_DESC_BUF *sd_new, *sd_store;
|
|---|
| 335 | SEC_DESC *sec, *new_sec;
|
|---|
| 336 | TALLOC_CTX *ctx = state;
|
|---|
| 337 | int result, i;
|
|---|
| 338 | uint32 sd_size;
|
|---|
| 339 | size_t size_new_sec;
|
|---|
| 340 |
|
|---|
| 341 | if (!data.dptr || data.dsize == 0) {
|
|---|
| 342 | return 0;
|
|---|
| 343 | }
|
|---|
| 344 |
|
|---|
| 345 | if ( strncmp((const char *) key.dptr, SECDESC_PREFIX, strlen(SECDESC_PREFIX) ) != 0 ) {
|
|---|
| 346 | return 0;
|
|---|
| 347 | }
|
|---|
| 348 |
|
|---|
| 349 | /* upgrade the security descriptor */
|
|---|
| 350 |
|
|---|
| 351 | status = unmarshall_sec_desc_buf(ctx, data.dptr, data.dsize, &sd_orig);
|
|---|
| 352 | if (!NT_STATUS_IS_OK(status)) {
|
|---|
| 353 | /* delete bad entries */
|
|---|
| 354 | DEBUG(0,("sec_desc_upg_fn: Failed to parse original sec_desc for %si. Deleting....\n",
|
|---|
| 355 | (const char *)key.dptr ));
|
|---|
| 356 | tdb_delete( tdb_printers, key );
|
|---|
| 357 | return 0;
|
|---|
| 358 | }
|
|---|
| 359 |
|
|---|
| 360 | if (!sd_orig) {
|
|---|
| 361 | return 0;
|
|---|
| 362 | }
|
|---|
| 363 | sec = sd_orig->sd;
|
|---|
| 364 |
|
|---|
| 365 | /* is this even valid? */
|
|---|
| 366 |
|
|---|
| 367 | if ( !sec->dacl ) {
|
|---|
| 368 | return 0;
|
|---|
| 369 | }
|
|---|
| 370 |
|
|---|
| 371 | /* update access masks */
|
|---|
| 372 |
|
|---|
| 373 | for ( i=0; i<sec->dacl->num_aces; i++ ) {
|
|---|
| 374 | switch ( sec->dacl->aces[i].access_mask ) {
|
|---|
| 375 | case (GENERIC_READ_ACCESS | GENERIC_WRITE_ACCESS | GENERIC_EXECUTE_ACCESS):
|
|---|
| 376 | sec->dacl->aces[i].access_mask = PRINTER_ACE_PRINT;
|
|---|
| 377 | break;
|
|---|
| 378 |
|
|---|
| 379 | case GENERIC_ALL_ACCESS:
|
|---|
| 380 | sec->dacl->aces[i].access_mask = PRINTER_ACE_FULL_CONTROL;
|
|---|
| 381 | break;
|
|---|
| 382 |
|
|---|
| 383 | case READ_CONTROL_ACCESS:
|
|---|
| 384 | sec->dacl->aces[i].access_mask = PRINTER_ACE_MANAGE_DOCUMENTS;
|
|---|
| 385 |
|
|---|
| 386 | default: /* no change */
|
|---|
| 387 | break;
|
|---|
| 388 | }
|
|---|
| 389 | }
|
|---|
| 390 |
|
|---|
| 391 | /* create a new SEC_DESC with the appropriate owner and group SIDs */
|
|---|
| 392 |
|
|---|
| 393 | new_sec = make_sec_desc( ctx, SEC_DESC_REVISION, SEC_DESC_SELF_RELATIVE,
|
|---|
| 394 | &global_sid_Builtin_Administrators,
|
|---|
| 395 | &global_sid_Builtin_Administrators,
|
|---|
| 396 | NULL, NULL, &size_new_sec );
|
|---|
| 397 | if (!new_sec) {
|
|---|
| 398 | return 0;
|
|---|
| 399 | }
|
|---|
| 400 | sd_new = make_sec_desc_buf( ctx, size_new_sec, new_sec );
|
|---|
| 401 | if (!sd_new) {
|
|---|
| 402 | return 0;
|
|---|
| 403 | }
|
|---|
| 404 |
|
|---|
| 405 | if ( !(sd_store = sec_desc_merge( ctx, sd_new, sd_orig )) ) {
|
|---|
| 406 | DEBUG(0,("sec_desc_upg_fn: Failed to update sec_desc for %s\n", key.dptr ));
|
|---|
| 407 | return 0;
|
|---|
| 408 | }
|
|---|
| 409 |
|
|---|
| 410 | /* store it back */
|
|---|
| 411 |
|
|---|
| 412 | sd_size = ndr_size_security_descriptor(sd_store->sd, NULL, 0)
|
|---|
| 413 | + sizeof(SEC_DESC_BUF);
|
|---|
| 414 |
|
|---|
| 415 | status = marshall_sec_desc_buf(ctx, sd_store, &data.dptr, &data.dsize);
|
|---|
| 416 | if (!NT_STATUS_IS_OK(status)) {
|
|---|
| 417 | DEBUG(0,("sec_desc_upg_fn: Failed to parse new sec_desc for %s\n", key.dptr ));
|
|---|
| 418 | return 0;
|
|---|
| 419 | }
|
|---|
| 420 |
|
|---|
| 421 | result = tdb_store( tdb_printers, key, data, TDB_REPLACE );
|
|---|
| 422 |
|
|---|
| 423 | /* 0 to continue and non-zero to stop traversal */
|
|---|
| 424 |
|
|---|
| 425 | return (result == -1);
|
|---|
| 426 | }
|
|---|
| 427 |
|
|---|
| 428 | /*******************************************************************
|
|---|
| 429 | *******************************************************************/
|
|---|
| 430 |
|
|---|
| 431 | static bool upgrade_to_version_4(void)
|
|---|
| 432 | {
|
|---|
| 433 | TALLOC_CTX *ctx;
|
|---|
| 434 | int result;
|
|---|
| 435 |
|
|---|
| 436 | DEBUG(0,("upgrade_to_version_4: upgrading printer security descriptors\n"));
|
|---|
| 437 |
|
|---|
| 438 | if ( !(ctx = talloc_init( "upgrade_to_version_4" )) )
|
|---|
| 439 | return False;
|
|---|
| 440 |
|
|---|
| 441 | result = tdb_traverse( tdb_printers, sec_desc_upg_fn, ctx );
|
|---|
| 442 |
|
|---|
| 443 | talloc_destroy( ctx );
|
|---|
| 444 |
|
|---|
| 445 | return ( result != -1 );
|
|---|
| 446 | }
|
|---|
| 447 |
|
|---|
| 448 | /*******************************************************************
|
|---|
| 449 | Fix an issue with security descriptors. Printer sec_desc must
|
|---|
| 450 | use more than the generic bits that were previously used
|
|---|
| 451 | in <= 3.0.14a. They must also have a owner and group SID assigned.
|
|---|
| 452 | Otherwise, any printers than have been migrated to a Windows
|
|---|
| 453 | host using printmig.exe will not be accessible.
|
|---|
| 454 | *******************************************************************/
|
|---|
| 455 |
|
|---|
| 456 | static int normalize_printers_fn( TDB_CONTEXT *the_tdb, TDB_DATA key,
|
|---|
| 457 | TDB_DATA data, void *state )
|
|---|
| 458 | {
|
|---|
| 459 | TALLOC_CTX *ctx = talloc_tos();
|
|---|
| 460 | TDB_DATA new_key;
|
|---|
| 461 |
|
|---|
| 462 | if (!data.dptr || data.dsize == 0)
|
|---|
| 463 | return 0;
|
|---|
| 464 |
|
|---|
| 465 | /* upgrade printer records and security descriptors */
|
|---|
| 466 |
|
|---|
| 467 | if ( strncmp((const char *) key.dptr, PRINTERS_PREFIX, strlen(PRINTERS_PREFIX) ) == 0 ) {
|
|---|
| 468 | new_key = make_printer_tdbkey(ctx, (const char *)key.dptr+strlen(PRINTERS_PREFIX) );
|
|---|
| 469 | }
|
|---|
| 470 | else if ( strncmp((const char *) key.dptr, SECDESC_PREFIX, strlen(SECDESC_PREFIX) ) == 0 ) {
|
|---|
| 471 | new_key = make_printers_secdesc_tdbkey(ctx, (const char *)key.dptr+strlen(SECDESC_PREFIX) );
|
|---|
| 472 | }
|
|---|
| 473 | else {
|
|---|
| 474 | /* ignore this record */
|
|---|
| 475 | return 0;
|
|---|
| 476 | }
|
|---|
| 477 |
|
|---|
| 478 | /* delete the original record and store under the normalized key */
|
|---|
| 479 |
|
|---|
| 480 | if ( tdb_delete( the_tdb, key ) != 0 ) {
|
|---|
| 481 | DEBUG(0,("normalize_printers_fn: tdb_delete for [%s] failed!\n",
|
|---|
| 482 | key.dptr));
|
|---|
| 483 | return 1;
|
|---|
| 484 | }
|
|---|
| 485 |
|
|---|
| 486 | if ( tdb_store( the_tdb, new_key, data, TDB_REPLACE) != 0 ) {
|
|---|
| 487 | DEBUG(0,("normalize_printers_fn: failed to store new record for [%s]!\n",
|
|---|
| 488 | key.dptr));
|
|---|
| 489 | return 1;
|
|---|
| 490 | }
|
|---|
| 491 |
|
|---|
| 492 | return 0;
|
|---|
| 493 | }
|
|---|
| 494 |
|
|---|
| 495 | /*******************************************************************
|
|---|
| 496 | *******************************************************************/
|
|---|
| 497 |
|
|---|
| 498 | static bool upgrade_to_version_5(void)
|
|---|
| 499 | {
|
|---|
| 500 | TALLOC_CTX *ctx;
|
|---|
| 501 | int result;
|
|---|
| 502 |
|
|---|
| 503 | DEBUG(0,("upgrade_to_version_5: normalizing printer keys\n"));
|
|---|
| 504 |
|
|---|
| 505 | if ( !(ctx = talloc_init( "upgrade_to_version_5" )) )
|
|---|
| 506 | return False;
|
|---|
| 507 |
|
|---|
| 508 | result = tdb_traverse( tdb_printers, normalize_printers_fn, NULL );
|
|---|
| 509 |
|
|---|
| 510 | talloc_destroy( ctx );
|
|---|
| 511 |
|
|---|
| 512 | return ( result != -1 );
|
|---|
| 513 | }
|
|---|
| 514 |
|
|---|
| 515 | /****************************************************************************
|
|---|
| 516 | Open the NT printing tdbs. Done once before fork().
|
|---|
| 517 | ****************************************************************************/
|
|---|
| 518 |
|
|---|
| 519 | bool nt_printing_init(struct messaging_context *msg_ctx)
|
|---|
| 520 | {
|
|---|
| 521 | const char *vstring = "INFO/version";
|
|---|
| 522 | WERROR win_rc;
|
|---|
| 523 | int32 vers_id;
|
|---|
| 524 |
|
|---|
| 525 | if ( tdb_drivers && tdb_printers && tdb_forms )
|
|---|
| 526 | return True;
|
|---|
| 527 |
|
|---|
| 528 | if (tdb_drivers)
|
|---|
| 529 | tdb_close(tdb_drivers);
|
|---|
| 530 | tdb_drivers = tdb_open_log(state_path("ntdrivers.tdb"), 0, TDB_DEFAULT, O_RDWR|O_CREAT, 0600);
|
|---|
| 531 | if (!tdb_drivers) {
|
|---|
| 532 | DEBUG(0,("nt_printing_init: Failed to open nt drivers database %s (%s)\n",
|
|---|
| 533 | state_path("ntdrivers.tdb"), strerror(errno) ));
|
|---|
| 534 | return False;
|
|---|
| 535 | }
|
|---|
| 536 |
|
|---|
| 537 | if (tdb_printers)
|
|---|
| 538 | tdb_close(tdb_printers);
|
|---|
| 539 | tdb_printers = tdb_open_log(state_path("ntprinters.tdb"), 0, TDB_DEFAULT, O_RDWR|O_CREAT, 0600);
|
|---|
| 540 | if (!tdb_printers) {
|
|---|
| 541 | DEBUG(0,("nt_printing_init: Failed to open nt printers database %s (%s)\n",
|
|---|
| 542 | state_path("ntprinters.tdb"), strerror(errno) ));
|
|---|
| 543 | return False;
|
|---|
| 544 | }
|
|---|
| 545 |
|
|---|
| 546 | if (tdb_forms)
|
|---|
| 547 | tdb_close(tdb_forms);
|
|---|
| 548 | tdb_forms = tdb_open_log(state_path("ntforms.tdb"), 0, TDB_DEFAULT, O_RDWR|O_CREAT, 0600);
|
|---|
| 549 | if (!tdb_forms) {
|
|---|
| 550 | DEBUG(0,("nt_printing_init: Failed to open nt forms database %s (%s)\n",
|
|---|
| 551 | state_path("ntforms.tdb"), strerror(errno) ));
|
|---|
| 552 | return False;
|
|---|
| 553 | }
|
|---|
| 554 |
|
|---|
| 555 | /* handle a Samba upgrade */
|
|---|
| 556 |
|
|---|
| 557 | vers_id = tdb_fetch_int32(tdb_drivers, vstring);
|
|---|
| 558 | if (vers_id == -1) {
|
|---|
| 559 | DEBUG(10, ("Fresh database\n"));
|
|---|
| 560 | tdb_store_int32( tdb_drivers, vstring, NTDRIVERS_DATABASE_VERSION_5 );
|
|---|
| 561 | vers_id = NTDRIVERS_DATABASE_VERSION_5;
|
|---|
| 562 | }
|
|---|
| 563 |
|
|---|
| 564 | if ( vers_id != NTDRIVERS_DATABASE_VERSION_5 ) {
|
|---|
| 565 |
|
|---|
| 566 | if ((vers_id == NTDRIVERS_DATABASE_VERSION_1) || (IREV(vers_id) == NTDRIVERS_DATABASE_VERSION_1)) {
|
|---|
| 567 | if (!upgrade_to_version_3())
|
|---|
| 568 | return False;
|
|---|
| 569 | tdb_store_int32(tdb_drivers, vstring, NTDRIVERS_DATABASE_VERSION_3);
|
|---|
| 570 | vers_id = NTDRIVERS_DATABASE_VERSION_3;
|
|---|
| 571 | }
|
|---|
| 572 |
|
|---|
| 573 | if ((vers_id == NTDRIVERS_DATABASE_VERSION_2) || (IREV(vers_id) == NTDRIVERS_DATABASE_VERSION_2)) {
|
|---|
| 574 | /* Written on a bigendian machine with old fetch_int code. Save as le. */
|
|---|
| 575 | /* The only upgrade between V2 and V3 is to save the version in little-endian. */
|
|---|
| 576 | tdb_store_int32(tdb_drivers, vstring, NTDRIVERS_DATABASE_VERSION_3);
|
|---|
| 577 | vers_id = NTDRIVERS_DATABASE_VERSION_3;
|
|---|
| 578 | }
|
|---|
| 579 |
|
|---|
| 580 | if (vers_id == NTDRIVERS_DATABASE_VERSION_3 ) {
|
|---|
| 581 | if ( !upgrade_to_version_4() )
|
|---|
| 582 | return False;
|
|---|
| 583 | tdb_store_int32(tdb_drivers, vstring, NTDRIVERS_DATABASE_VERSION_4);
|
|---|
| 584 | vers_id = NTDRIVERS_DATABASE_VERSION_4;
|
|---|
| 585 | }
|
|---|
| 586 |
|
|---|
| 587 | if (vers_id == NTDRIVERS_DATABASE_VERSION_4 ) {
|
|---|
| 588 | if ( !upgrade_to_version_5() )
|
|---|
| 589 | return False;
|
|---|
| 590 | tdb_store_int32(tdb_drivers, vstring, NTDRIVERS_DATABASE_VERSION_5);
|
|---|
| 591 | vers_id = NTDRIVERS_DATABASE_VERSION_5;
|
|---|
| 592 | }
|
|---|
| 593 |
|
|---|
| 594 |
|
|---|
| 595 | if ( vers_id != NTDRIVERS_DATABASE_VERSION_5 ) {
|
|---|
| 596 | DEBUG(0,("nt_printing_init: Unknown printer database version [%d]\n", vers_id));
|
|---|
| 597 | return False;
|
|---|
| 598 | }
|
|---|
| 599 | }
|
|---|
| 600 |
|
|---|
| 601 | update_c_setprinter(True);
|
|---|
| 602 |
|
|---|
| 603 | /*
|
|---|
| 604 | * register callback to handle updating printers as new
|
|---|
| 605 | * drivers are installed
|
|---|
| 606 | */
|
|---|
| 607 |
|
|---|
| 608 | messaging_register(msg_ctx, NULL, MSG_PRINTER_DRVUPGRADE,
|
|---|
| 609 | do_drv_upgrade_printer);
|
|---|
| 610 |
|
|---|
| 611 | /*
|
|---|
| 612 | * register callback to handle updating printer data
|
|---|
| 613 | * when a driver is initialized
|
|---|
| 614 | */
|
|---|
| 615 |
|
|---|
| 616 | messaging_register(msg_ctx, NULL, MSG_PRINTERDATA_INIT_RESET,
|
|---|
| 617 | reset_all_printerdata);
|
|---|
| 618 |
|
|---|
| 619 | /* of course, none of the message callbacks matter if you don't
|
|---|
| 620 | tell messages.c that you interested in receiving PRINT_GENERAL
|
|---|
| 621 | msgs. This is done in claim_connection() */
|
|---|
| 622 |
|
|---|
| 623 |
|
|---|
| 624 | if ( lp_security() == SEC_ADS ) {
|
|---|
| 625 | win_rc = check_published_printers();
|
|---|
| 626 | if (!W_ERROR_IS_OK(win_rc))
|
|---|
| 627 | DEBUG(0, ("nt_printing_init: error checking published printers: %s\n", win_errstr(win_rc)));
|
|---|
| 628 | }
|
|---|
| 629 |
|
|---|
| 630 | return True;
|
|---|
| 631 | }
|
|---|
| 632 |
|
|---|
| 633 | /*******************************************************************
|
|---|
| 634 | Function to allow filename parsing "the old way".
|
|---|
| 635 | ********************************************************************/
|
|---|
| 636 |
|
|---|
| 637 | static NTSTATUS driver_unix_convert(connection_struct *conn,
|
|---|
| 638 | const char *old_name,
|
|---|
| 639 | struct smb_filename **smb_fname)
|
|---|
| 640 | {
|
|---|
| 641 | NTSTATUS status;
|
|---|
| 642 | TALLOC_CTX *ctx = talloc_tos();
|
|---|
| 643 | char *name = talloc_strdup(ctx, old_name);
|
|---|
| 644 |
|
|---|
| 645 | if (!name) {
|
|---|
| 646 | return NT_STATUS_NO_MEMORY;
|
|---|
| 647 | }
|
|---|
| 648 | unix_format(name);
|
|---|
| 649 | name = unix_clean_name(ctx, name);
|
|---|
| 650 | if (!name) {
|
|---|
| 651 | return NT_STATUS_NO_MEMORY;
|
|---|
| 652 | }
|
|---|
| 653 | trim_string(name,"/","/");
|
|---|
| 654 |
|
|---|
| 655 | status = unix_convert(ctx, conn, name, smb_fname, 0);
|
|---|
| 656 | if (!NT_STATUS_IS_OK(status)) {
|
|---|
| 657 | return NT_STATUS_NO_MEMORY;
|
|---|
| 658 | }
|
|---|
| 659 |
|
|---|
| 660 | return NT_STATUS_OK;
|
|---|
| 661 | }
|
|---|
| 662 |
|
|---|
| 663 | /*******************************************************************
|
|---|
| 664 | tdb traversal function for counting printers.
|
|---|
| 665 | ********************************************************************/
|
|---|
| 666 |
|
|---|
| 667 | static int traverse_counting_printers(TDB_CONTEXT *t, TDB_DATA key,
|
|---|
| 668 | TDB_DATA data, void *context)
|
|---|
| 669 | {
|
|---|
| 670 | int *printer_count = (int*)context;
|
|---|
| 671 |
|
|---|
| 672 | if (memcmp(PRINTERS_PREFIX, key.dptr, sizeof(PRINTERS_PREFIX)-1) == 0) {
|
|---|
| 673 | (*printer_count)++;
|
|---|
| 674 | DEBUG(10,("traverse_counting_printers: printer = [%s] printer_count = %d\n", key.dptr, *printer_count));
|
|---|
| 675 | }
|
|---|
| 676 |
|
|---|
| 677 | return 0;
|
|---|
| 678 | }
|
|---|
| 679 |
|
|---|
| 680 | /*******************************************************************
|
|---|
| 681 | Update the spooler global c_setprinter. This variable is initialized
|
|---|
| 682 | when the parent smbd starts with the number of existing printers. It
|
|---|
| 683 | is monotonically increased by the current number of printers *after*
|
|---|
| 684 | each add or delete printer RPC. Only Microsoft knows why... JRR020119
|
|---|
| 685 | ********************************************************************/
|
|---|
| 686 |
|
|---|
| 687 | uint32 update_c_setprinter(bool initialize)
|
|---|
| 688 | {
|
|---|
| 689 | int32 c_setprinter;
|
|---|
| 690 | int32 printer_count = 0;
|
|---|
| 691 |
|
|---|
| 692 | tdb_lock_bystring(tdb_printers, GLOBAL_C_SETPRINTER);
|
|---|
| 693 |
|
|---|
| 694 | /* Traverse the tdb, counting the printers */
|
|---|
| 695 | tdb_traverse(tdb_printers, traverse_counting_printers, (void *)&printer_count);
|
|---|
| 696 |
|
|---|
| 697 | /* If initializing, set c_setprinter to current printers count
|
|---|
| 698 | * otherwise, bump it by the current printer count
|
|---|
| 699 | */
|
|---|
| 700 | if (!initialize)
|
|---|
| 701 | c_setprinter = tdb_fetch_int32(tdb_printers, GLOBAL_C_SETPRINTER) + printer_count;
|
|---|
| 702 | else
|
|---|
| 703 | c_setprinter = printer_count;
|
|---|
| 704 |
|
|---|
| 705 | DEBUG(10,("update_c_setprinter: c_setprinter = %u\n", (unsigned int)c_setprinter));
|
|---|
| 706 | tdb_store_int32(tdb_printers, GLOBAL_C_SETPRINTER, c_setprinter);
|
|---|
| 707 |
|
|---|
| 708 | tdb_unlock_bystring(tdb_printers, GLOBAL_C_SETPRINTER);
|
|---|
| 709 |
|
|---|
| 710 | return (uint32)c_setprinter;
|
|---|
| 711 | }
|
|---|
| 712 |
|
|---|
| 713 | /*******************************************************************
|
|---|
| 714 | Get the spooler global c_setprinter, accounting for initialization.
|
|---|
| 715 | ********************************************************************/
|
|---|
| 716 |
|
|---|
| 717 | uint32 get_c_setprinter(void)
|
|---|
| 718 | {
|
|---|
| 719 | int32 c_setprinter = tdb_fetch_int32(tdb_printers, GLOBAL_C_SETPRINTER);
|
|---|
| 720 |
|
|---|
| 721 | if (c_setprinter == (int32)-1)
|
|---|
| 722 | c_setprinter = update_c_setprinter(True);
|
|---|
| 723 |
|
|---|
| 724 | DEBUG(10,("get_c_setprinter: c_setprinter = %d\n", c_setprinter));
|
|---|
| 725 |
|
|---|
| 726 | return (uint32)c_setprinter;
|
|---|
| 727 | }
|
|---|
| 728 |
|
|---|
| 729 | /****************************************************************************
|
|---|
| 730 | Get builtin form struct list.
|
|---|
| 731 | ****************************************************************************/
|
|---|
| 732 |
|
|---|
| 733 | int get_builtin_ntforms(nt_forms_struct **list)
|
|---|
| 734 | {
|
|---|
| 735 | *list = (nt_forms_struct *)memdup(&default_forms[0], sizeof(default_forms));
|
|---|
| 736 | if (!*list) {
|
|---|
| 737 | return 0;
|
|---|
| 738 | }
|
|---|
| 739 | return ARRAY_SIZE(default_forms);
|
|---|
| 740 | }
|
|---|
| 741 |
|
|---|
| 742 | /****************************************************************************
|
|---|
| 743 | get a builtin form struct
|
|---|
| 744 | ****************************************************************************/
|
|---|
| 745 |
|
|---|
| 746 | bool get_a_builtin_ntform_by_string(const char *form_name, nt_forms_struct *form)
|
|---|
| 747 | {
|
|---|
| 748 | int i;
|
|---|
| 749 | DEBUGADD(6,("Looking for builtin form %s \n", form_name));
|
|---|
| 750 | for (i=0; i<ARRAY_SIZE(default_forms); i++) {
|
|---|
| 751 | if (strequal(form_name,default_forms[i].name)) {
|
|---|
| 752 | DEBUGADD(6,("Found builtin form %s \n", form_name));
|
|---|
| 753 | memcpy(form,&default_forms[i],sizeof(*form));
|
|---|
| 754 | return true;
|
|---|
| 755 | }
|
|---|
| 756 | }
|
|---|
| 757 |
|
|---|
| 758 | return false;
|
|---|
| 759 | }
|
|---|
| 760 |
|
|---|
| 761 | /****************************************************************************
|
|---|
| 762 | get a form struct list.
|
|---|
| 763 | ****************************************************************************/
|
|---|
| 764 |
|
|---|
| 765 | int get_ntforms(nt_forms_struct **list)
|
|---|
| 766 | {
|
|---|
| 767 | TDB_DATA kbuf, newkey, dbuf;
|
|---|
| 768 | nt_forms_struct form;
|
|---|
| 769 | int ret;
|
|---|
| 770 | int i;
|
|---|
| 771 | int n = 0;
|
|---|
| 772 |
|
|---|
| 773 | *list = NULL;
|
|---|
| 774 |
|
|---|
| 775 | for (kbuf = tdb_firstkey(tdb_forms);
|
|---|
| 776 | kbuf.dptr;
|
|---|
| 777 | newkey = tdb_nextkey(tdb_forms, kbuf), free(kbuf.dptr), kbuf=newkey)
|
|---|
| 778 | {
|
|---|
| 779 | if (strncmp((const char *)kbuf.dptr, FORMS_PREFIX, strlen(FORMS_PREFIX)) != 0)
|
|---|
| 780 | continue;
|
|---|
| 781 |
|
|---|
| 782 | dbuf = tdb_fetch(tdb_forms, kbuf);
|
|---|
| 783 | if (!dbuf.dptr)
|
|---|
| 784 | continue;
|
|---|
| 785 |
|
|---|
| 786 | fstrcpy(form.name, (const char *)kbuf.dptr+strlen(FORMS_PREFIX));
|
|---|
| 787 | ret = tdb_unpack(dbuf.dptr, dbuf.dsize, "dddddddd",
|
|---|
| 788 | &i, &form.flag, &form.width, &form.length, &form.left,
|
|---|
| 789 | &form.top, &form.right, &form.bottom);
|
|---|
| 790 | SAFE_FREE(dbuf.dptr);
|
|---|
| 791 | if (ret != dbuf.dsize)
|
|---|
| 792 | continue;
|
|---|
| 793 |
|
|---|
| 794 | *list = SMB_REALLOC_ARRAY(*list, nt_forms_struct, n+1);
|
|---|
| 795 | if (!*list) {
|
|---|
| 796 | DEBUG(0,("get_ntforms: Realloc fail.\n"));
|
|---|
| 797 | return 0;
|
|---|
| 798 | }
|
|---|
| 799 | (*list)[n] = form;
|
|---|
| 800 | n++;
|
|---|
| 801 | }
|
|---|
| 802 |
|
|---|
| 803 |
|
|---|
| 804 | return n;
|
|---|
| 805 | }
|
|---|
| 806 |
|
|---|
| 807 | /****************************************************************************
|
|---|
| 808 | write a form struct list
|
|---|
| 809 | ****************************************************************************/
|
|---|
| 810 |
|
|---|
| 811 | int write_ntforms(nt_forms_struct **list, int number)
|
|---|
| 812 | {
|
|---|
| 813 | TALLOC_CTX *ctx = talloc_tos();
|
|---|
| 814 | char *buf = NULL;
|
|---|
| 815 | char *key = NULL;
|
|---|
| 816 | int len;
|
|---|
| 817 | TDB_DATA dbuf;
|
|---|
| 818 | int i;
|
|---|
| 819 |
|
|---|
| 820 | for (i=0;i<number;i++) {
|
|---|
| 821 | /* save index, so list is rebuilt in correct order */
|
|---|
| 822 | len = tdb_pack(NULL, 0, "dddddddd",
|
|---|
| 823 | i, (*list)[i].flag, (*list)[i].width, (*list)[i].length,
|
|---|
| 824 | (*list)[i].left, (*list)[i].top, (*list)[i].right,
|
|---|
| 825 | (*list)[i].bottom);
|
|---|
| 826 | if (!len) {
|
|---|
| 827 | continue;
|
|---|
| 828 | }
|
|---|
| 829 | buf = TALLOC_ARRAY(ctx, char, len);
|
|---|
| 830 | if (!buf) {
|
|---|
| 831 | return 0;
|
|---|
| 832 | }
|
|---|
| 833 | len = tdb_pack((uint8 *)buf, len, "dddddddd",
|
|---|
| 834 | i, (*list)[i].flag, (*list)[i].width, (*list)[i].length,
|
|---|
| 835 | (*list)[i].left, (*list)[i].top, (*list)[i].right,
|
|---|
| 836 | (*list)[i].bottom);
|
|---|
| 837 | key = talloc_asprintf(ctx, "%s%s", FORMS_PREFIX, (*list)[i].name);
|
|---|
| 838 | if (!key) {
|
|---|
| 839 | return 0;
|
|---|
| 840 | }
|
|---|
| 841 | dbuf.dsize = len;
|
|---|
| 842 | dbuf.dptr = (uint8 *)buf;
|
|---|
| 843 | if (tdb_store_bystring(tdb_forms, key, dbuf, TDB_REPLACE) != 0) {
|
|---|
| 844 | TALLOC_FREE(key);
|
|---|
| 845 | TALLOC_FREE(buf);
|
|---|
| 846 | break;
|
|---|
| 847 | }
|
|---|
| 848 | TALLOC_FREE(key);
|
|---|
| 849 | TALLOC_FREE(buf);
|
|---|
| 850 | }
|
|---|
| 851 |
|
|---|
| 852 | return i;
|
|---|
| 853 | }
|
|---|
| 854 |
|
|---|
| 855 | /****************************************************************************
|
|---|
| 856 | add a form struct at the end of the list
|
|---|
| 857 | ****************************************************************************/
|
|---|
| 858 | bool add_a_form(nt_forms_struct **list, struct spoolss_AddFormInfo1 *form, int *count)
|
|---|
| 859 | {
|
|---|
| 860 | int n=0;
|
|---|
| 861 | bool update;
|
|---|
| 862 |
|
|---|
| 863 | /*
|
|---|
| 864 | * NT tries to add forms even when
|
|---|
| 865 | * they are already in the base
|
|---|
| 866 | * only update the values if already present
|
|---|
| 867 | */
|
|---|
| 868 |
|
|---|
| 869 | update=False;
|
|---|
| 870 |
|
|---|
| 871 | for (n=0; n<*count; n++) {
|
|---|
| 872 | if ( strequal((*list)[n].name, form->form_name) ) {
|
|---|
| 873 | update=True;
|
|---|
| 874 | break;
|
|---|
| 875 | }
|
|---|
| 876 | }
|
|---|
| 877 |
|
|---|
| 878 | if (update==False) {
|
|---|
| 879 | if((*list=SMB_REALLOC_ARRAY(*list, nt_forms_struct, n+1)) == NULL) {
|
|---|
| 880 | DEBUG(0,("add_a_form: failed to enlarge forms list!\n"));
|
|---|
| 881 | return False;
|
|---|
| 882 | }
|
|---|
| 883 | fstrcpy((*list)[n].name, form->form_name);
|
|---|
| 884 | (*count)++;
|
|---|
| 885 | }
|
|---|
| 886 |
|
|---|
| 887 | (*list)[n].flag = form->flags;
|
|---|
| 888 | (*list)[n].width = form->size.width;
|
|---|
| 889 | (*list)[n].length = form->size.height;
|
|---|
| 890 | (*list)[n].left = form->area.left;
|
|---|
| 891 | (*list)[n].top = form->area.top;
|
|---|
| 892 | (*list)[n].right = form->area.right;
|
|---|
| 893 | (*list)[n].bottom = form->area.bottom;
|
|---|
| 894 |
|
|---|
| 895 | DEBUG(6,("add_a_form: Successfully %s form [%s]\n",
|
|---|
| 896 | update ? "updated" : "added", form->form_name));
|
|---|
| 897 |
|
|---|
| 898 | return True;
|
|---|
| 899 | }
|
|---|
| 900 |
|
|---|
| 901 | /****************************************************************************
|
|---|
| 902 | Delete a named form struct.
|
|---|
| 903 | ****************************************************************************/
|
|---|
| 904 |
|
|---|
| 905 | bool delete_a_form(nt_forms_struct **list, const char *del_name, int *count, WERROR *ret)
|
|---|
| 906 | {
|
|---|
| 907 | char *key = NULL;
|
|---|
| 908 | int n=0;
|
|---|
| 909 |
|
|---|
| 910 | *ret = WERR_OK;
|
|---|
| 911 |
|
|---|
| 912 | for (n=0; n<*count; n++) {
|
|---|
| 913 | if (!strncmp((*list)[n].name, del_name, strlen(del_name))) {
|
|---|
| 914 | DEBUG(103, ("delete_a_form, [%s] in list\n", del_name));
|
|---|
| 915 | break;
|
|---|
| 916 | }
|
|---|
| 917 | }
|
|---|
| 918 |
|
|---|
| 919 | if (n == *count) {
|
|---|
| 920 | DEBUG(10,("delete_a_form, [%s] not found\n", del_name));
|
|---|
| 921 | *ret = WERR_INVALID_PARAM;
|
|---|
| 922 | return False;
|
|---|
| 923 | }
|
|---|
| 924 |
|
|---|
| 925 | if (asprintf(&key, "%s%s", FORMS_PREFIX, (*list)[n].name) < 0) {
|
|---|
| 926 | *ret = WERR_NOMEM;
|
|---|
| 927 | return false;
|
|---|
| 928 | }
|
|---|
| 929 | if (tdb_delete_bystring(tdb_forms, key) != 0) {
|
|---|
| 930 | SAFE_FREE(key);
|
|---|
| 931 | *ret = WERR_NOMEM;
|
|---|
| 932 | return False;
|
|---|
| 933 | }
|
|---|
| 934 | SAFE_FREE(key);
|
|---|
| 935 | return true;
|
|---|
| 936 | }
|
|---|
| 937 |
|
|---|
| 938 | /****************************************************************************
|
|---|
| 939 | Update a form struct.
|
|---|
| 940 | ****************************************************************************/
|
|---|
| 941 |
|
|---|
| 942 | void update_a_form(nt_forms_struct **list, struct spoolss_AddFormInfo1 *form, int count)
|
|---|
| 943 | {
|
|---|
| 944 | int n=0;
|
|---|
| 945 |
|
|---|
| 946 | DEBUG(106, ("[%s]\n", form->form_name));
|
|---|
| 947 | for (n=0; n<count; n++) {
|
|---|
| 948 | DEBUGADD(106, ("n [%d]:[%s]\n", n, (*list)[n].name));
|
|---|
| 949 | if (!strncmp((*list)[n].name, form->form_name, strlen(form->form_name)))
|
|---|
| 950 | break;
|
|---|
| 951 | }
|
|---|
| 952 |
|
|---|
| 953 | if (n==count) return;
|
|---|
| 954 |
|
|---|
| 955 | (*list)[n].flag = form->flags;
|
|---|
| 956 | (*list)[n].width = form->size.width;
|
|---|
| 957 | (*list)[n].length = form->size.height;
|
|---|
| 958 | (*list)[n].left = form->area.left;
|
|---|
| 959 | (*list)[n].top = form->area.top;
|
|---|
| 960 | (*list)[n].right = form->area.right;
|
|---|
| 961 | (*list)[n].bottom = form->area.bottom;
|
|---|
| 962 | }
|
|---|
| 963 |
|
|---|
| 964 | /****************************************************************************
|
|---|
| 965 | Get the nt drivers list.
|
|---|
| 966 | Traverse the database and look-up the matching names.
|
|---|
| 967 | ****************************************************************************/
|
|---|
| 968 | int get_ntdrivers(fstring **list, const char *architecture, uint32 version)
|
|---|
| 969 | {
|
|---|
| 970 | int total=0;
|
|---|
| 971 | const char *short_archi;
|
|---|
| 972 | char *key = NULL;
|
|---|
| 973 | TDB_DATA kbuf, newkey;
|
|---|
| 974 |
|
|---|
| 975 | short_archi = get_short_archi(architecture);
|
|---|
| 976 | if (!short_archi) {
|
|---|
| 977 | return 0;
|
|---|
| 978 | }
|
|---|
| 979 |
|
|---|
| 980 | if (asprintf(&key, "%s%s/%d/", DRIVERS_PREFIX,
|
|---|
| 981 | short_archi, version) < 0) {
|
|---|
| 982 | return 0;
|
|---|
| 983 | }
|
|---|
| 984 |
|
|---|
| 985 | for (kbuf = tdb_firstkey(tdb_drivers);
|
|---|
| 986 | kbuf.dptr;
|
|---|
| 987 | newkey = tdb_nextkey(tdb_drivers, kbuf), free(kbuf.dptr), kbuf=newkey) {
|
|---|
| 988 |
|
|---|
| 989 | if (strncmp((const char *)kbuf.dptr, key, strlen(key)) != 0)
|
|---|
| 990 | continue;
|
|---|
| 991 |
|
|---|
| 992 | if((*list = SMB_REALLOC_ARRAY(*list, fstring, total+1)) == NULL) {
|
|---|
| 993 | DEBUG(0,("get_ntdrivers: failed to enlarge list!\n"));
|
|---|
| 994 | SAFE_FREE(key);
|
|---|
| 995 | return -1;
|
|---|
| 996 | }
|
|---|
| 997 |
|
|---|
| 998 | fstrcpy((*list)[total], (const char *)kbuf.dptr+strlen(key));
|
|---|
| 999 | total++;
|
|---|
| 1000 | }
|
|---|
| 1001 |
|
|---|
| 1002 | SAFE_FREE(key);
|
|---|
| 1003 | return(total);
|
|---|
| 1004 | }
|
|---|
| 1005 |
|
|---|
| 1006 | /****************************************************************************
|
|---|
| 1007 | Function to do the mapping between the long architecture name and
|
|---|
| 1008 | the short one.
|
|---|
| 1009 | ****************************************************************************/
|
|---|
| 1010 |
|
|---|
| 1011 | const char *get_short_archi(const char *long_archi)
|
|---|
| 1012 | {
|
|---|
| 1013 | int i=-1;
|
|---|
| 1014 |
|
|---|
| 1015 | DEBUG(107,("Getting architecture dependant directory\n"));
|
|---|
| 1016 | do {
|
|---|
| 1017 | i++;
|
|---|
| 1018 | } while ( (archi_table[i].long_archi!=NULL ) &&
|
|---|
| 1019 | StrCaseCmp(long_archi, archi_table[i].long_archi) );
|
|---|
| 1020 |
|
|---|
| 1021 | if (archi_table[i].long_archi==NULL) {
|
|---|
| 1022 | DEBUGADD(10,("Unknown architecture [%s] !\n", long_archi));
|
|---|
| 1023 | return NULL;
|
|---|
| 1024 | }
|
|---|
| 1025 |
|
|---|
| 1026 | /* this might be client code - but shouldn't this be an fstrcpy etc? */
|
|---|
| 1027 |
|
|---|
| 1028 | DEBUGADD(108,("index: [%d]\n", i));
|
|---|
| 1029 | DEBUGADD(108,("long architecture: [%s]\n", archi_table[i].long_archi));
|
|---|
| 1030 | DEBUGADD(108,("short architecture: [%s]\n", archi_table[i].short_archi));
|
|---|
| 1031 |
|
|---|
| 1032 | return archi_table[i].short_archi;
|
|---|
| 1033 | }
|
|---|
| 1034 |
|
|---|
| 1035 | /****************************************************************************
|
|---|
| 1036 | Version information in Microsoft files is held in a VS_VERSION_INFO structure.
|
|---|
| 1037 | There are two case to be covered here: PE (Portable Executable) and NE (New
|
|---|
| 1038 | Executable) files. Both files support the same INFO structure, but PE files
|
|---|
| 1039 | store the signature in unicode, and NE files store it as !unicode.
|
|---|
| 1040 | returns -1 on error, 1 on version info found, and 0 on no version info found.
|
|---|
| 1041 | ****************************************************************************/
|
|---|
| 1042 |
|
|---|
| 1043 | static int get_file_version(files_struct *fsp, char *fname,uint32 *major, uint32 *minor)
|
|---|
| 1044 | {
|
|---|
| 1045 | int i;
|
|---|
| 1046 | char *buf = NULL;
|
|---|
| 1047 | ssize_t byte_count;
|
|---|
| 1048 |
|
|---|
| 1049 | if ((buf=(char *)SMB_MALLOC(DOS_HEADER_SIZE)) == NULL) {
|
|---|
| 1050 | DEBUG(0,("get_file_version: PE file [%s] DOS Header malloc failed bytes = %d\n",
|
|---|
| 1051 | fname, DOS_HEADER_SIZE));
|
|---|
| 1052 | goto error_exit;
|
|---|
| 1053 | }
|
|---|
| 1054 |
|
|---|
| 1055 | if ((byte_count = vfs_read_data(fsp, buf, DOS_HEADER_SIZE)) < DOS_HEADER_SIZE) {
|
|---|
| 1056 | DEBUG(3,("get_file_version: File [%s] DOS header too short, bytes read = %lu\n",
|
|---|
| 1057 | fname, (unsigned long)byte_count));
|
|---|
| 1058 | goto no_version_info;
|
|---|
| 1059 | }
|
|---|
| 1060 |
|
|---|
| 1061 | /* Is this really a DOS header? */
|
|---|
| 1062 | if (SVAL(buf,DOS_HEADER_MAGIC_OFFSET) != DOS_HEADER_MAGIC) {
|
|---|
| 1063 | DEBUG(6,("get_file_version: File [%s] bad DOS magic = 0x%x\n",
|
|---|
| 1064 | fname, SVAL(buf,DOS_HEADER_MAGIC_OFFSET)));
|
|---|
| 1065 | goto no_version_info;
|
|---|
| 1066 | }
|
|---|
| 1067 |
|
|---|
| 1068 | /* Skip OEM header (if any) and the DOS stub to start of Windows header */
|
|---|
| 1069 | if (SMB_VFS_LSEEK(fsp, SVAL(buf,DOS_HEADER_LFANEW_OFFSET), SEEK_SET) == (SMB_OFF_T)-1) {
|
|---|
| 1070 | DEBUG(3,("get_file_version: File [%s] too short, errno = %d\n",
|
|---|
| 1071 | fname, errno));
|
|---|
| 1072 | /* Assume this isn't an error... the file just looks sort of like a PE/NE file */
|
|---|
| 1073 | goto no_version_info;
|
|---|
| 1074 | }
|
|---|
| 1075 |
|
|---|
| 1076 | /* Note: DOS_HEADER_SIZE and NE_HEADER_SIZE are incidentally same */
|
|---|
| 1077 | if ((byte_count = vfs_read_data(fsp, buf, NE_HEADER_SIZE)) < NE_HEADER_SIZE) {
|
|---|
| 1078 | DEBUG(3,("get_file_version: File [%s] Windows header too short, bytes read = %lu\n",
|
|---|
| 1079 | fname, (unsigned long)byte_count));
|
|---|
| 1080 | /* Assume this isn't an error... the file just looks sort of like a PE/NE file */
|
|---|
| 1081 | goto no_version_info;
|
|---|
| 1082 | }
|
|---|
| 1083 |
|
|---|
| 1084 | /* The header may be a PE (Portable Executable) or an NE (New Executable) */
|
|---|
| 1085 | if (IVAL(buf,PE_HEADER_SIGNATURE_OFFSET) == PE_HEADER_SIGNATURE) {
|
|---|
| 1086 | unsigned int num_sections;
|
|---|
| 1087 | unsigned int section_table_bytes;
|
|---|
| 1088 |
|
|---|
| 1089 | /* Just skip over optional header to get to section table */
|
|---|
| 1090 | if (SMB_VFS_LSEEK(fsp,
|
|---|
| 1091 | SVAL(buf,PE_HEADER_OPTIONAL_HEADER_SIZE)-(NE_HEADER_SIZE-PE_HEADER_SIZE),
|
|---|
| 1092 | SEEK_CUR) == (SMB_OFF_T)-1) {
|
|---|
| 1093 | DEBUG(3,("get_file_version: File [%s] Windows optional header too short, errno = %d\n",
|
|---|
| 1094 | fname, errno));
|
|---|
| 1095 | goto error_exit;
|
|---|
| 1096 | }
|
|---|
| 1097 |
|
|---|
| 1098 | /* get the section table */
|
|---|
| 1099 | num_sections = SVAL(buf,PE_HEADER_NUMBER_OF_SECTIONS);
|
|---|
| 1100 | section_table_bytes = num_sections * PE_HEADER_SECT_HEADER_SIZE;
|
|---|
| 1101 | if (section_table_bytes == 0)
|
|---|
| 1102 | goto error_exit;
|
|---|
| 1103 |
|
|---|
| 1104 | SAFE_FREE(buf);
|
|---|
| 1105 | if ((buf=(char *)SMB_MALLOC(section_table_bytes)) == NULL) {
|
|---|
| 1106 | DEBUG(0,("get_file_version: PE file [%s] section table malloc failed bytes = %d\n",
|
|---|
| 1107 | fname, section_table_bytes));
|
|---|
| 1108 | goto error_exit;
|
|---|
| 1109 | }
|
|---|
| 1110 |
|
|---|
| 1111 | if ((byte_count = vfs_read_data(fsp, buf, section_table_bytes)) < section_table_bytes) {
|
|---|
| 1112 | DEBUG(3,("get_file_version: PE file [%s] Section header too short, bytes read = %lu\n",
|
|---|
| 1113 | fname, (unsigned long)byte_count));
|
|---|
| 1114 | goto error_exit;
|
|---|
| 1115 | }
|
|---|
| 1116 |
|
|---|
| 1117 | /* Iterate the section table looking for the resource section ".rsrc" */
|
|---|
| 1118 | for (i = 0; i < num_sections; i++) {
|
|---|
| 1119 | int sec_offset = i * PE_HEADER_SECT_HEADER_SIZE;
|
|---|
| 1120 |
|
|---|
| 1121 | if (strcmp(".rsrc", &buf[sec_offset+PE_HEADER_SECT_NAME_OFFSET]) == 0) {
|
|---|
| 1122 | unsigned int section_pos = IVAL(buf,sec_offset+PE_HEADER_SECT_PTR_DATA_OFFSET);
|
|---|
| 1123 | unsigned int section_bytes = IVAL(buf,sec_offset+PE_HEADER_SECT_SIZE_DATA_OFFSET);
|
|---|
| 1124 |
|
|---|
| 1125 | if (section_bytes == 0)
|
|---|
| 1126 | goto error_exit;
|
|---|
| 1127 |
|
|---|
| 1128 | SAFE_FREE(buf);
|
|---|
| 1129 | if ((buf=(char *)SMB_MALLOC(section_bytes)) == NULL) {
|
|---|
| 1130 | DEBUG(0,("get_file_version: PE file [%s] version malloc failed bytes = %d\n",
|
|---|
| 1131 | fname, section_bytes));
|
|---|
| 1132 | goto error_exit;
|
|---|
| 1133 | }
|
|---|
| 1134 |
|
|---|
| 1135 | /* Seek to the start of the .rsrc section info */
|
|---|
| 1136 | if (SMB_VFS_LSEEK(fsp, section_pos, SEEK_SET) == (SMB_OFF_T)-1) {
|
|---|
| 1137 | DEBUG(3,("get_file_version: PE file [%s] too short for section info, errno = %d\n",
|
|---|
| 1138 | fname, errno));
|
|---|
| 1139 | goto error_exit;
|
|---|
| 1140 | }
|
|---|
| 1141 |
|
|---|
| 1142 | if ((byte_count = vfs_read_data(fsp, buf, section_bytes)) < section_bytes) {
|
|---|
| 1143 | DEBUG(3,("get_file_version: PE file [%s] .rsrc section too short, bytes read = %lu\n",
|
|---|
| 1144 | fname, (unsigned long)byte_count));
|
|---|
| 1145 | goto error_exit;
|
|---|
| 1146 | }
|
|---|
| 1147 |
|
|---|
| 1148 | if (section_bytes < VS_VERSION_INFO_UNICODE_SIZE)
|
|---|
| 1149 | goto error_exit;
|
|---|
| 1150 |
|
|---|
| 1151 | for (i=0; i<section_bytes-VS_VERSION_INFO_UNICODE_SIZE; i++) {
|
|---|
| 1152 | /* Scan for 1st 3 unicoded bytes followed by word aligned magic value */
|
|---|
| 1153 | if (buf[i] == 'V' && buf[i+1] == '\0' && buf[i+2] == 'S') {
|
|---|
| 1154 | /* Align to next long address */
|
|---|
| 1155 | int pos = (i + sizeof(VS_SIGNATURE)*2 + 3) & 0xfffffffc;
|
|---|
| 1156 |
|
|---|
| 1157 | if (IVAL(buf,pos) == VS_MAGIC_VALUE) {
|
|---|
| 1158 | *major = IVAL(buf,pos+VS_MAJOR_OFFSET);
|
|---|
| 1159 | *minor = IVAL(buf,pos+VS_MINOR_OFFSET);
|
|---|
| 1160 |
|
|---|
| 1161 | DEBUG(6,("get_file_version: PE file [%s] Version = %08x:%08x (%d.%d.%d.%d)\n",
|
|---|
| 1162 | fname, *major, *minor,
|
|---|
| 1163 | (*major>>16)&0xffff, *major&0xffff,
|
|---|
| 1164 | (*minor>>16)&0xffff, *minor&0xffff));
|
|---|
| 1165 | SAFE_FREE(buf);
|
|---|
| 1166 | return 1;
|
|---|
| 1167 | }
|
|---|
| 1168 | }
|
|---|
| 1169 | }
|
|---|
| 1170 | }
|
|---|
| 1171 | }
|
|---|
| 1172 |
|
|---|
| 1173 | /* Version info not found, fall back to origin date/time */
|
|---|
| 1174 | DEBUG(10,("get_file_version: PE file [%s] has no version info\n", fname));
|
|---|
| 1175 | SAFE_FREE(buf);
|
|---|
| 1176 | return 0;
|
|---|
| 1177 |
|
|---|
| 1178 | } else if (SVAL(buf,NE_HEADER_SIGNATURE_OFFSET) == NE_HEADER_SIGNATURE) {
|
|---|
| 1179 | if (CVAL(buf,NE_HEADER_TARGET_OS_OFFSET) != NE_HEADER_TARGOS_WIN ) {
|
|---|
| 1180 | DEBUG(3,("get_file_version: NE file [%s] wrong target OS = 0x%x\n",
|
|---|
| 1181 | fname, CVAL(buf,NE_HEADER_TARGET_OS_OFFSET)));
|
|---|
| 1182 | /* At this point, we assume the file is in error. It still could be somthing
|
|---|
| 1183 | * else besides a NE file, but it unlikely at this point. */
|
|---|
| 1184 | goto error_exit;
|
|---|
| 1185 | }
|
|---|
| 1186 |
|
|---|
| 1187 | /* Allocate a bit more space to speed up things */
|
|---|
| 1188 | SAFE_FREE(buf);
|
|---|
| 1189 | if ((buf=(char *)SMB_MALLOC(VS_NE_BUF_SIZE)) == NULL) {
|
|---|
| 1190 | DEBUG(0,("get_file_version: NE file [%s] malloc failed bytes = %d\n",
|
|---|
| 1191 | fname, PE_HEADER_SIZE));
|
|---|
| 1192 | goto error_exit;
|
|---|
| 1193 | }
|
|---|
| 1194 |
|
|---|
| 1195 | /* This is a HACK! I got tired of trying to sort through the messy
|
|---|
| 1196 | * 'NE' file format. If anyone wants to clean this up please have at
|
|---|
| 1197 | * it, but this works. 'NE' files will eventually fade away. JRR */
|
|---|
| 1198 | while((byte_count = vfs_read_data(fsp, buf, VS_NE_BUF_SIZE)) > 0) {
|
|---|
| 1199 | /* Cover case that should not occur in a well formed 'NE' .dll file */
|
|---|
| 1200 | if (byte_count-VS_VERSION_INFO_SIZE <= 0) break;
|
|---|
| 1201 |
|
|---|
| 1202 | for(i=0; i<byte_count; i++) {
|
|---|
| 1203 | /* Fast skip past data that can't possibly match */
|
|---|
| 1204 | if (buf[i] != 'V') continue;
|
|---|
| 1205 |
|
|---|
| 1206 | /* Potential match data crosses buf boundry, move it to beginning
|
|---|
| 1207 | * of buf, and fill the buf with as much as it will hold. */
|
|---|
| 1208 | if (i>byte_count-VS_VERSION_INFO_SIZE) {
|
|---|
| 1209 | int bc;
|
|---|
| 1210 |
|
|---|
| 1211 | memcpy(buf, &buf[i], byte_count-i);
|
|---|
| 1212 | if ((bc = vfs_read_data(fsp, &buf[byte_count-i], VS_NE_BUF_SIZE-
|
|---|
| 1213 | (byte_count-i))) < 0) {
|
|---|
| 1214 |
|
|---|
| 1215 | DEBUG(0,("get_file_version: NE file [%s] Read error, errno=%d\n",
|
|---|
| 1216 | fname, errno));
|
|---|
| 1217 | goto error_exit;
|
|---|
| 1218 | }
|
|---|
| 1219 |
|
|---|
| 1220 | byte_count = bc + (byte_count - i);
|
|---|
| 1221 | if (byte_count<VS_VERSION_INFO_SIZE) break;
|
|---|
| 1222 |
|
|---|
| 1223 | i = 0;
|
|---|
| 1224 | }
|
|---|
| 1225 |
|
|---|
| 1226 | /* Check that the full signature string and the magic number that
|
|---|
| 1227 | * follows exist (not a perfect solution, but the chances that this
|
|---|
| 1228 | * occurs in code is, well, remote. Yes I know I'm comparing the 'V'
|
|---|
| 1229 | * twice, as it is simpler to read the code. */
|
|---|
| 1230 | if (strcmp(&buf[i], VS_SIGNATURE) == 0) {
|
|---|
| 1231 | /* Compute skip alignment to next long address */
|
|---|
| 1232 | int skip = -(SMB_VFS_LSEEK(fsp, 0, SEEK_CUR) - (byte_count - i) +
|
|---|
| 1233 | sizeof(VS_SIGNATURE)) & 3;
|
|---|
| 1234 | if (IVAL(buf,i+sizeof(VS_SIGNATURE)+skip) != 0xfeef04bd) continue;
|
|---|
| 1235 |
|
|---|
| 1236 | *major = IVAL(buf,i+sizeof(VS_SIGNATURE)+skip+VS_MAJOR_OFFSET);
|
|---|
| 1237 | *minor = IVAL(buf,i+sizeof(VS_SIGNATURE)+skip+VS_MINOR_OFFSET);
|
|---|
| 1238 | DEBUG(6,("get_file_version: NE file [%s] Version = %08x:%08x (%d.%d.%d.%d)\n",
|
|---|
| 1239 | fname, *major, *minor,
|
|---|
| 1240 | (*major>>16)&0xffff, *major&0xffff,
|
|---|
| 1241 | (*minor>>16)&0xffff, *minor&0xffff));
|
|---|
| 1242 | SAFE_FREE(buf);
|
|---|
| 1243 | return 1;
|
|---|
| 1244 | }
|
|---|
| 1245 | }
|
|---|
| 1246 | }
|
|---|
| 1247 |
|
|---|
| 1248 | /* Version info not found, fall back to origin date/time */
|
|---|
| 1249 | DEBUG(0,("get_file_version: NE file [%s] Version info not found\n", fname));
|
|---|
| 1250 | SAFE_FREE(buf);
|
|---|
| 1251 | return 0;
|
|---|
| 1252 |
|
|---|
| 1253 | } else
|
|---|
| 1254 | /* Assume this isn't an error... the file just looks sort of like a PE/NE file */
|
|---|
| 1255 | DEBUG(3,("get_file_version: File [%s] unknown file format, signature = 0x%x\n",
|
|---|
| 1256 | fname, IVAL(buf,PE_HEADER_SIGNATURE_OFFSET)));
|
|---|
| 1257 |
|
|---|
| 1258 | no_version_info:
|
|---|
| 1259 | SAFE_FREE(buf);
|
|---|
| 1260 | return 0;
|
|---|
| 1261 |
|
|---|
| 1262 | error_exit:
|
|---|
| 1263 | SAFE_FREE(buf);
|
|---|
| 1264 | return -1;
|
|---|
| 1265 | }
|
|---|
| 1266 |
|
|---|
| 1267 | /****************************************************************************
|
|---|
| 1268 | Drivers for Microsoft systems contain multiple files. Often, multiple drivers
|
|---|
| 1269 | share one or more files. During the MS installation process files are checked
|
|---|
| 1270 | to insure that only a newer version of a shared file is installed over an
|
|---|
| 1271 | older version. There are several possibilities for this comparison. If there
|
|---|
| 1272 | is no previous version, the new one is newer (obviously). If either file is
|
|---|
| 1273 | missing the version info structure, compare the creation date (on Unix use
|
|---|
| 1274 | the modification date). Otherwise chose the numerically larger version number.
|
|---|
| 1275 | ****************************************************************************/
|
|---|
| 1276 |
|
|---|
| 1277 | static int file_version_is_newer(connection_struct *conn, fstring new_file, fstring old_file)
|
|---|
| 1278 | {
|
|---|
| 1279 | bool use_version = true;
|
|---|
| 1280 |
|
|---|
| 1281 | uint32 new_major;
|
|---|
| 1282 | uint32 new_minor;
|
|---|
| 1283 | time_t new_create_time;
|
|---|
| 1284 |
|
|---|
| 1285 | uint32 old_major;
|
|---|
| 1286 | uint32 old_minor;
|
|---|
| 1287 | time_t old_create_time;
|
|---|
| 1288 |
|
|---|
| 1289 | struct smb_filename *smb_fname = NULL;
|
|---|
| 1290 | files_struct *fsp = NULL;
|
|---|
| 1291 | SMB_STRUCT_STAT st;
|
|---|
| 1292 |
|
|---|
| 1293 | NTSTATUS status;
|
|---|
| 1294 | int ret;
|
|---|
| 1295 |
|
|---|
| 1296 | SET_STAT_INVALID(st);
|
|---|
| 1297 | new_create_time = (time_t)0;
|
|---|
| 1298 | old_create_time = (time_t)0;
|
|---|
| 1299 |
|
|---|
| 1300 | /* Get file version info (if available) for previous file (if it exists) */
|
|---|
| 1301 | status = driver_unix_convert(conn, old_file, &smb_fname);
|
|---|
| 1302 | if (!NT_STATUS_IS_OK(status)) {
|
|---|
| 1303 | goto error_exit;
|
|---|
| 1304 | }
|
|---|
| 1305 |
|
|---|
| 1306 | status = SMB_VFS_CREATE_FILE(
|
|---|
| 1307 | conn, /* conn */
|
|---|
| 1308 | NULL, /* req */
|
|---|
| 1309 | 0, /* root_dir_fid */
|
|---|
| 1310 | smb_fname, /* fname */
|
|---|
| 1311 | FILE_GENERIC_READ, /* access_mask */
|
|---|
| 1312 | FILE_SHARE_READ | FILE_SHARE_WRITE, /* share_access */
|
|---|
| 1313 | FILE_OPEN, /* create_disposition*/
|
|---|
| 1314 | 0, /* create_options */
|
|---|
| 1315 | FILE_ATTRIBUTE_NORMAL, /* file_attributes */
|
|---|
| 1316 | INTERNAL_OPEN_ONLY, /* oplock_request */
|
|---|
| 1317 | 0, /* allocation_size */
|
|---|
| 1318 | NULL, /* sd */
|
|---|
| 1319 | NULL, /* ea_list */
|
|---|
| 1320 | &fsp, /* result */
|
|---|
| 1321 | NULL); /* pinfo */
|
|---|
| 1322 |
|
|---|
| 1323 | if (!NT_STATUS_IS_OK(status)) {
|
|---|
| 1324 | /* Old file not found, so by definition new file is in fact newer */
|
|---|
| 1325 | DEBUG(10,("file_version_is_newer: Can't open old file [%s], "
|
|---|
| 1326 | "errno = %d\n", smb_fname_str_dbg(smb_fname),
|
|---|
| 1327 | errno));
|
|---|
| 1328 | ret = 1;
|
|---|
| 1329 | goto done;
|
|---|
| 1330 |
|
|---|
| 1331 | } else {
|
|---|
| 1332 | ret = get_file_version(fsp, old_file, &old_major, &old_minor);
|
|---|
| 1333 | if (ret == -1) {
|
|---|
| 1334 | goto error_exit;
|
|---|
| 1335 | }
|
|---|
| 1336 |
|
|---|
| 1337 | if (!ret) {
|
|---|
| 1338 | DEBUG(6,("file_version_is_newer: Version info not found [%s], use mod time\n",
|
|---|
| 1339 | old_file));
|
|---|
| 1340 | use_version = false;
|
|---|
| 1341 | if (SMB_VFS_FSTAT(fsp, &st) == -1) {
|
|---|
| 1342 | goto error_exit;
|
|---|
| 1343 | }
|
|---|
| 1344 | old_create_time = convert_timespec_to_time_t(st.st_ex_mtime);
|
|---|
| 1345 | DEBUGADD(6,("file_version_is_newer: mod time = %ld sec\n",
|
|---|
| 1346 | (long)old_create_time));
|
|---|
| 1347 | }
|
|---|
| 1348 | }
|
|---|
| 1349 | close_file(NULL, fsp, NORMAL_CLOSE);
|
|---|
| 1350 | fsp = NULL;
|
|---|
| 1351 |
|
|---|
| 1352 | /* Get file version info (if available) for new file */
|
|---|
| 1353 | status = driver_unix_convert(conn, new_file, &smb_fname);
|
|---|
| 1354 | if (!NT_STATUS_IS_OK(status)) {
|
|---|
| 1355 | goto error_exit;
|
|---|
| 1356 | }
|
|---|
| 1357 |
|
|---|
| 1358 | status = SMB_VFS_CREATE_FILE(
|
|---|
| 1359 | conn, /* conn */
|
|---|
| 1360 | NULL, /* req */
|
|---|
| 1361 | 0, /* root_dir_fid */
|
|---|
| 1362 | smb_fname, /* fname */
|
|---|
| 1363 | FILE_GENERIC_READ, /* access_mask */
|
|---|
| 1364 | FILE_SHARE_READ | FILE_SHARE_WRITE, /* share_access */
|
|---|
| 1365 | FILE_OPEN, /* create_disposition*/
|
|---|
| 1366 | 0, /* create_options */
|
|---|
| 1367 | FILE_ATTRIBUTE_NORMAL, /* file_attributes */
|
|---|
| 1368 | INTERNAL_OPEN_ONLY, /* oplock_request */
|
|---|
| 1369 | 0, /* allocation_size */
|
|---|
| 1370 | NULL, /* sd */
|
|---|
| 1371 | NULL, /* ea_list */
|
|---|
| 1372 | &fsp, /* result */
|
|---|
| 1373 | NULL); /* pinfo */
|
|---|
| 1374 |
|
|---|
| 1375 | if (!NT_STATUS_IS_OK(status)) {
|
|---|
| 1376 | /* New file not found, this shouldn't occur if the caller did its job */
|
|---|
| 1377 | DEBUG(3,("file_version_is_newer: Can't open new file [%s], "
|
|---|
| 1378 | "errno = %d\n", smb_fname_str_dbg(smb_fname), errno));
|
|---|
| 1379 | goto error_exit;
|
|---|
| 1380 |
|
|---|
| 1381 | } else {
|
|---|
| 1382 | ret = get_file_version(fsp, new_file, &new_major, &new_minor);
|
|---|
| 1383 | if (ret == -1) {
|
|---|
| 1384 | goto error_exit;
|
|---|
| 1385 | }
|
|---|
| 1386 |
|
|---|
| 1387 | if (!ret) {
|
|---|
| 1388 | DEBUG(6,("file_version_is_newer: Version info not found [%s], use mod time\n",
|
|---|
| 1389 | new_file));
|
|---|
| 1390 | use_version = false;
|
|---|
| 1391 | if (SMB_VFS_FSTAT(fsp, &st) == -1) {
|
|---|
| 1392 | goto error_exit;
|
|---|
| 1393 | }
|
|---|
| 1394 | new_create_time = convert_timespec_to_time_t(st.st_ex_mtime);
|
|---|
| 1395 | DEBUGADD(6,("file_version_is_newer: mod time = %ld sec\n",
|
|---|
| 1396 | (long)new_create_time));
|
|---|
| 1397 | }
|
|---|
| 1398 | }
|
|---|
| 1399 | close_file(NULL, fsp, NORMAL_CLOSE);
|
|---|
| 1400 | fsp = NULL;
|
|---|
| 1401 |
|
|---|
| 1402 | if (use_version && (new_major != old_major || new_minor != old_minor)) {
|
|---|
| 1403 | /* Compare versions and choose the larger version number */
|
|---|
| 1404 | if (new_major > old_major ||
|
|---|
| 1405 | (new_major == old_major && new_minor > old_minor)) {
|
|---|
| 1406 |
|
|---|
| 1407 | DEBUG(6,("file_version_is_newer: Replacing [%s] with [%s]\n", old_file, new_file));
|
|---|
| 1408 | ret = 1;
|
|---|
| 1409 | goto done;
|
|---|
| 1410 | }
|
|---|
| 1411 | else {
|
|---|
| 1412 | DEBUG(6,("file_version_is_newer: Leaving [%s] unchanged\n", old_file));
|
|---|
| 1413 | ret = 0;
|
|---|
| 1414 | goto done;
|
|---|
| 1415 | }
|
|---|
| 1416 |
|
|---|
| 1417 | } else {
|
|---|
| 1418 | /* Compare modification time/dates and choose the newest time/date */
|
|---|
| 1419 | if (new_create_time > old_create_time) {
|
|---|
| 1420 | DEBUG(6,("file_version_is_newer: Replacing [%s] with [%s]\n", old_file, new_file));
|
|---|
| 1421 | ret = 1;
|
|---|
| 1422 | goto done;
|
|---|
| 1423 | }
|
|---|
| 1424 | else {
|
|---|
| 1425 | DEBUG(6,("file_version_is_newer: Leaving [%s] unchanged\n", old_file));
|
|---|
| 1426 | ret = 0;
|
|---|
| 1427 | goto done;
|
|---|
| 1428 | }
|
|---|
| 1429 | }
|
|---|
| 1430 |
|
|---|
| 1431 | error_exit:
|
|---|
| 1432 | if(fsp)
|
|---|
| 1433 | close_file(NULL, fsp, NORMAL_CLOSE);
|
|---|
| 1434 | ret = -1;
|
|---|
| 1435 | done:
|
|---|
| 1436 | TALLOC_FREE(smb_fname);
|
|---|
| 1437 | return ret;
|
|---|
| 1438 | }
|
|---|
| 1439 |
|
|---|
| 1440 | /****************************************************************************
|
|---|
| 1441 | Determine the correct cVersion associated with an architecture and driver
|
|---|
| 1442 | ****************************************************************************/
|
|---|
| 1443 | static uint32 get_correct_cversion(struct pipes_struct *p,
|
|---|
| 1444 | const char *architecture,
|
|---|
| 1445 | const char *driverpath_in,
|
|---|
| 1446 | WERROR *perr)
|
|---|
| 1447 | {
|
|---|
| 1448 | int cversion;
|
|---|
| 1449 | NTSTATUS nt_status;
|
|---|
| 1450 | struct smb_filename *smb_fname = NULL;
|
|---|
| 1451 | char *driverpath = NULL;
|
|---|
| 1452 | files_struct *fsp = NULL;
|
|---|
| 1453 | connection_struct *conn = NULL;
|
|---|
| 1454 | NTSTATUS status;
|
|---|
| 1455 | char *oldcwd;
|
|---|
| 1456 | fstring printdollar;
|
|---|
| 1457 | int printdollar_snum;
|
|---|
| 1458 |
|
|---|
| 1459 | *perr = WERR_INVALID_PARAM;
|
|---|
| 1460 |
|
|---|
| 1461 | /* If architecture is Windows 95/98/ME, the version is always 0. */
|
|---|
| 1462 | if (strcmp(architecture, SPL_ARCH_WIN40) == 0) {
|
|---|
| 1463 | DEBUG(10,("get_correct_cversion: Driver is Win9x, cversion = 0\n"));
|
|---|
| 1464 | *perr = WERR_OK;
|
|---|
| 1465 | return 0;
|
|---|
| 1466 | }
|
|---|
| 1467 |
|
|---|
| 1468 | /* If architecture is Windows x64, the version is always 3. */
|
|---|
| 1469 | if (strcmp(architecture, SPL_ARCH_X64) == 0) {
|
|---|
| 1470 | DEBUG(10,("get_correct_cversion: Driver is x64, cversion = 3\n"));
|
|---|
| 1471 | *perr = WERR_OK;
|
|---|
| 1472 | return 3;
|
|---|
| 1473 | }
|
|---|
| 1474 |
|
|---|
| 1475 | fstrcpy(printdollar, "print$");
|
|---|
| 1476 |
|
|---|
| 1477 | printdollar_snum = find_service(printdollar);
|
|---|
| 1478 | if (printdollar_snum == -1) {
|
|---|
| 1479 | *perr = WERR_NO_SUCH_SHARE;
|
|---|
| 1480 | return -1;
|
|---|
| 1481 | }
|
|---|
| 1482 |
|
|---|
| 1483 | nt_status = create_conn_struct(talloc_tos(), &conn, printdollar_snum,
|
|---|
| 1484 | lp_pathname(printdollar_snum),
|
|---|
| 1485 | p->server_info, &oldcwd);
|
|---|
| 1486 | if (!NT_STATUS_IS_OK(nt_status)) {
|
|---|
| 1487 | DEBUG(0,("get_correct_cversion: create_conn_struct "
|
|---|
| 1488 | "returned %s\n", nt_errstr(nt_status)));
|
|---|
| 1489 | *perr = ntstatus_to_werror(nt_status);
|
|---|
| 1490 | return -1;
|
|---|
| 1491 | }
|
|---|
| 1492 |
|
|---|
| 1493 | /* Open the driver file (Portable Executable format) and determine the
|
|---|
| 1494 | * deriver the cversion. */
|
|---|
| 1495 | driverpath = talloc_asprintf(talloc_tos(),
|
|---|
| 1496 | "%s/%s",
|
|---|
| 1497 | architecture,
|
|---|
| 1498 | driverpath_in);
|
|---|
| 1499 | if (!driverpath) {
|
|---|
| 1500 | *perr = WERR_NOMEM;
|
|---|
| 1501 | goto error_exit;
|
|---|
| 1502 | }
|
|---|
| 1503 |
|
|---|
| 1504 | nt_status = driver_unix_convert(conn, driverpath, &smb_fname);
|
|---|
| 1505 | if (!NT_STATUS_IS_OK(nt_status)) {
|
|---|
| 1506 | *perr = ntstatus_to_werror(nt_status);
|
|---|
| 1507 | goto error_exit;
|
|---|
| 1508 | }
|
|---|
| 1509 |
|
|---|
| 1510 | nt_status = vfs_file_exist(conn, smb_fname);
|
|---|
| 1511 | if (!NT_STATUS_IS_OK(nt_status)) {
|
|---|
| 1512 | *perr = WERR_BADFILE;
|
|---|
| 1513 | goto error_exit;
|
|---|
| 1514 | }
|
|---|
| 1515 |
|
|---|
| 1516 | status = SMB_VFS_CREATE_FILE(
|
|---|
| 1517 | conn, /* conn */
|
|---|
| 1518 | NULL, /* req */
|
|---|
| 1519 | 0, /* root_dir_fid */
|
|---|
| 1520 | smb_fname, /* fname */
|
|---|
| 1521 | FILE_GENERIC_READ, /* access_mask */
|
|---|
| 1522 | FILE_SHARE_READ | FILE_SHARE_WRITE, /* share_access */
|
|---|
| 1523 | FILE_OPEN, /* create_disposition*/
|
|---|
| 1524 | 0, /* create_options */
|
|---|
| 1525 | FILE_ATTRIBUTE_NORMAL, /* file_attributes */
|
|---|
| 1526 | INTERNAL_OPEN_ONLY, /* oplock_request */
|
|---|
| 1527 | 0, /* allocation_size */
|
|---|
| 1528 | NULL, /* sd */
|
|---|
| 1529 | NULL, /* ea_list */
|
|---|
| 1530 | &fsp, /* result */
|
|---|
| 1531 | NULL); /* pinfo */
|
|---|
| 1532 |
|
|---|
| 1533 | if (!NT_STATUS_IS_OK(status)) {
|
|---|
| 1534 | DEBUG(3,("get_correct_cversion: Can't open file [%s], errno = "
|
|---|
| 1535 | "%d\n", smb_fname_str_dbg(smb_fname), errno));
|
|---|
| 1536 | *perr = WERR_ACCESS_DENIED;
|
|---|
| 1537 | goto error_exit;
|
|---|
| 1538 | } else {
|
|---|
| 1539 | uint32 major;
|
|---|
| 1540 | uint32 minor;
|
|---|
| 1541 | int ret;
|
|---|
| 1542 |
|
|---|
| 1543 | ret = get_file_version(fsp, smb_fname->base_name, &major, &minor);
|
|---|
| 1544 | if (ret == -1) goto error_exit;
|
|---|
| 1545 |
|
|---|
| 1546 | if (!ret) {
|
|---|
| 1547 | DEBUG(6,("get_correct_cversion: Version info not "
|
|---|
| 1548 | "found [%s]\n",
|
|---|
| 1549 | smb_fname_str_dbg(smb_fname)));
|
|---|
| 1550 | goto error_exit;
|
|---|
| 1551 | }
|
|---|
| 1552 |
|
|---|
| 1553 | /*
|
|---|
| 1554 | * This is a Microsoft'ism. See references in MSDN to VER_FILEVERSION
|
|---|
| 1555 | * for more details. Version in this case is not just the version of the
|
|---|
| 1556 | * file, but the version in the sense of kernal mode (2) vs. user mode
|
|---|
| 1557 | * (3) drivers. Other bits of the version fields are the version info.
|
|---|
| 1558 | * JRR 010716
|
|---|
| 1559 | */
|
|---|
| 1560 | cversion = major & 0x0000ffff;
|
|---|
| 1561 | switch (cversion) {
|
|---|
| 1562 | case 2: /* WinNT drivers */
|
|---|
| 1563 | case 3: /* Win2K drivers */
|
|---|
| 1564 | break;
|
|---|
| 1565 |
|
|---|
| 1566 | default:
|
|---|
| 1567 | DEBUG(6,("get_correct_cversion: cversion "
|
|---|
| 1568 | "invalid [%s] cversion = %d\n",
|
|---|
| 1569 | smb_fname_str_dbg(smb_fname),
|
|---|
| 1570 | cversion));
|
|---|
| 1571 | goto error_exit;
|
|---|
| 1572 | }
|
|---|
| 1573 |
|
|---|
| 1574 | DEBUG(10,("get_correct_cversion: Version info found [%s] major"
|
|---|
| 1575 | " = 0x%x minor = 0x%x\n",
|
|---|
| 1576 | smb_fname_str_dbg(smb_fname), major, minor));
|
|---|
| 1577 | }
|
|---|
| 1578 |
|
|---|
| 1579 | DEBUG(10,("get_correct_cversion: Driver file [%s] cversion = %d\n",
|
|---|
| 1580 | smb_fname_str_dbg(smb_fname), cversion));
|
|---|
| 1581 |
|
|---|
| 1582 | goto done;
|
|---|
| 1583 |
|
|---|
| 1584 | error_exit:
|
|---|
| 1585 | cversion = -1;
|
|---|
| 1586 | done:
|
|---|
| 1587 | TALLOC_FREE(smb_fname);
|
|---|
| 1588 | if (fsp != NULL) {
|
|---|
| 1589 | close_file(NULL, fsp, NORMAL_CLOSE);
|
|---|
| 1590 | }
|
|---|
| 1591 | if (conn != NULL) {
|
|---|
| 1592 | vfs_ChDir(conn, oldcwd);
|
|---|
| 1593 | conn_free(conn);
|
|---|
| 1594 | }
|
|---|
| 1595 | if (cversion != -1) {
|
|---|
| 1596 | *perr = WERR_OK;
|
|---|
| 1597 | }
|
|---|
| 1598 | return cversion;
|
|---|
| 1599 | }
|
|---|
| 1600 |
|
|---|
| 1601 | /****************************************************************************
|
|---|
| 1602 | ****************************************************************************/
|
|---|
| 1603 |
|
|---|
| 1604 | #define strip_driver_path(_mem_ctx, _element) do { \
|
|---|
| 1605 | if (_element && ((_p = strrchr((_element), '\\')) != NULL)) { \
|
|---|
| 1606 | (_element) = talloc_asprintf((_mem_ctx), "%s", _p+1); \
|
|---|
| 1607 | W_ERROR_HAVE_NO_MEMORY((_element)); \
|
|---|
| 1608 | } \
|
|---|
| 1609 | } while (0);
|
|---|
| 1610 |
|
|---|
| 1611 | static WERROR clean_up_driver_struct_level(TALLOC_CTX *mem_ctx,
|
|---|
| 1612 | struct pipes_struct *rpc_pipe,
|
|---|
| 1613 | const char *architecture,
|
|---|
| 1614 | const char **driver_path,
|
|---|
| 1615 | const char **data_file,
|
|---|
| 1616 | const char **config_file,
|
|---|
| 1617 | const char **help_file,
|
|---|
| 1618 | struct spoolss_StringArray *dependent_files,
|
|---|
| 1619 | uint32_t *version)
|
|---|
| 1620 | {
|
|---|
| 1621 | const char *short_architecture;
|
|---|
| 1622 | int i;
|
|---|
| 1623 | WERROR err;
|
|---|
| 1624 | char *_p;
|
|---|
| 1625 |
|
|---|
| 1626 | if (!*driver_path || !*data_file) {
|
|---|
| 1627 | return WERR_INVALID_PARAM;
|
|---|
| 1628 | }
|
|---|
| 1629 |
|
|---|
| 1630 | if (!strequal(architecture, SPOOLSS_ARCHITECTURE_4_0) && !*config_file) {
|
|---|
| 1631 | return WERR_INVALID_PARAM;
|
|---|
| 1632 | }
|
|---|
| 1633 |
|
|---|
| 1634 | /* clean up the driver name.
|
|---|
| 1635 | * we can get .\driver.dll
|
|---|
| 1636 | * or worse c:\windows\system\driver.dll !
|
|---|
| 1637 | */
|
|---|
| 1638 | /* using an intermediate string to not have overlaping memcpy()'s */
|
|---|
| 1639 |
|
|---|
| 1640 | strip_driver_path(mem_ctx, *driver_path);
|
|---|
| 1641 | strip_driver_path(mem_ctx, *data_file);
|
|---|
| 1642 | if (*config_file) {
|
|---|
| 1643 | strip_driver_path(mem_ctx, *config_file);
|
|---|
| 1644 | }
|
|---|
| 1645 | if (help_file) {
|
|---|
| 1646 | strip_driver_path(mem_ctx, *help_file);
|
|---|
| 1647 | }
|
|---|
| 1648 |
|
|---|
| 1649 | if (dependent_files && dependent_files->string) {
|
|---|
| 1650 | for (i=0; dependent_files->string[i]; i++) {
|
|---|
| 1651 | strip_driver_path(mem_ctx, dependent_files->string[i]);
|
|---|
| 1652 | }
|
|---|
| 1653 | }
|
|---|
| 1654 |
|
|---|
| 1655 | short_architecture = get_short_archi(architecture);
|
|---|
| 1656 | if (!short_architecture) {
|
|---|
| 1657 | return WERR_UNKNOWN_PRINTER_DRIVER;
|
|---|
| 1658 | }
|
|---|
| 1659 |
|
|---|
| 1660 | /* jfm:7/16/2000 the client always sends the cversion=0.
|
|---|
| 1661 | * The server should check which version the driver is by reading
|
|---|
| 1662 | * the PE header of driver->driverpath.
|
|---|
| 1663 | *
|
|---|
| 1664 | * For Windows 95/98 the version is 0 (so the value sent is correct)
|
|---|
| 1665 | * For Windows NT (the architecture doesn't matter)
|
|---|
| 1666 | * NT 3.1: cversion=0
|
|---|
| 1667 | * NT 3.5/3.51: cversion=1
|
|---|
| 1668 | * NT 4: cversion=2
|
|---|
| 1669 | * NT2K: cversion=3
|
|---|
| 1670 | */
|
|---|
| 1671 |
|
|---|
| 1672 | *version = get_correct_cversion(rpc_pipe, short_architecture,
|
|---|
| 1673 | *driver_path, &err);
|
|---|
| 1674 | if (*version == -1) {
|
|---|
| 1675 | return err;
|
|---|
| 1676 | }
|
|---|
| 1677 |
|
|---|
| 1678 | return WERR_OK;
|
|---|
| 1679 | }
|
|---|
| 1680 |
|
|---|
| 1681 | /****************************************************************************
|
|---|
| 1682 | ****************************************************************************/
|
|---|
| 1683 |
|
|---|
| 1684 | WERROR clean_up_driver_struct(struct pipes_struct *rpc_pipe,
|
|---|
| 1685 | struct spoolss_AddDriverInfoCtr *r)
|
|---|
| 1686 | {
|
|---|
| 1687 | switch (r->level) {
|
|---|
| 1688 | case 3:
|
|---|
| 1689 | return clean_up_driver_struct_level(r, rpc_pipe,
|
|---|
| 1690 | r->info.info3->architecture,
|
|---|
| 1691 | &r->info.info3->driver_path,
|
|---|
| 1692 | &r->info.info3->data_file,
|
|---|
| 1693 | &r->info.info3->config_file,
|
|---|
| 1694 | &r->info.info3->help_file,
|
|---|
| 1695 | r->info.info3->dependent_files,
|
|---|
| 1696 | &r->info.info3->version);
|
|---|
| 1697 | case 6:
|
|---|
| 1698 | return clean_up_driver_struct_level(r, rpc_pipe,
|
|---|
| 1699 | r->info.info6->architecture,
|
|---|
| 1700 | &r->info.info6->driver_path,
|
|---|
| 1701 | &r->info.info6->data_file,
|
|---|
| 1702 | &r->info.info6->config_file,
|
|---|
| 1703 | &r->info.info6->help_file,
|
|---|
| 1704 | r->info.info6->dependent_files,
|
|---|
| 1705 | &r->info.info6->version);
|
|---|
| 1706 | default:
|
|---|
| 1707 | return WERR_NOT_SUPPORTED;
|
|---|
| 1708 | }
|
|---|
| 1709 | }
|
|---|
| 1710 |
|
|---|
| 1711 | /****************************************************************************
|
|---|
| 1712 | This function sucks and should be replaced. JRA.
|
|---|
| 1713 | ****************************************************************************/
|
|---|
| 1714 |
|
|---|
| 1715 | static void convert_level_6_to_level3(struct spoolss_AddDriverInfo3 *dst,
|
|---|
| 1716 | const struct spoolss_AddDriverInfo6 *src)
|
|---|
| 1717 | {
|
|---|
| 1718 | dst->version = src->version;
|
|---|
| 1719 |
|
|---|
| 1720 | dst->driver_name = src->driver_name;
|
|---|
| 1721 | dst->architecture = src->architecture;
|
|---|
| 1722 | dst->driver_path = src->driver_path;
|
|---|
| 1723 | dst->data_file = src->data_file;
|
|---|
| 1724 | dst->config_file = src->config_file;
|
|---|
| 1725 | dst->help_file = src->help_file;
|
|---|
| 1726 | dst->monitor_name = src->monitor_name;
|
|---|
| 1727 | dst->default_datatype = src->default_datatype;
|
|---|
| 1728 | dst->_ndr_size_dependent_files = src->_ndr_size_dependent_files;
|
|---|
| 1729 | dst->dependent_files = src->dependent_files;
|
|---|
| 1730 | }
|
|---|
| 1731 |
|
|---|
| 1732 | /****************************************************************************
|
|---|
| 1733 | This function sucks and should be replaced. JRA.
|
|---|
| 1734 | ****************************************************************************/
|
|---|
| 1735 |
|
|---|
| 1736 | static void convert_level_8_to_level3(TALLOC_CTX *mem_ctx,
|
|---|
| 1737 | struct spoolss_AddDriverInfo3 *dst,
|
|---|
| 1738 | const struct spoolss_DriverInfo8 *src)
|
|---|
| 1739 | {
|
|---|
| 1740 | dst->version = src->version;
|
|---|
| 1741 | dst->driver_name = src->driver_name;
|
|---|
| 1742 | dst->architecture = src->architecture;
|
|---|
| 1743 | dst->driver_path = src->driver_path;
|
|---|
| 1744 | dst->data_file = src->data_file;
|
|---|
| 1745 | dst->config_file = src->config_file;
|
|---|
| 1746 | dst->help_file = src->help_file;
|
|---|
| 1747 | dst->monitor_name = src->monitor_name;
|
|---|
| 1748 | dst->default_datatype = src->default_datatype;
|
|---|
| 1749 | if (src->dependent_files) {
|
|---|
| 1750 | dst->dependent_files = talloc_zero(mem_ctx, struct spoolss_StringArray);
|
|---|
| 1751 | if (!dst->dependent_files) return;
|
|---|
| 1752 | dst->dependent_files->string = src->dependent_files;
|
|---|
| 1753 | } else {
|
|---|
| 1754 | dst->dependent_files = NULL;
|
|---|
| 1755 | }
|
|---|
| 1756 | }
|
|---|
| 1757 |
|
|---|
| 1758 | /****************************************************************************
|
|---|
| 1759 | ****************************************************************************/
|
|---|
| 1760 |
|
|---|
| 1761 | static WERROR move_driver_file_to_download_area(TALLOC_CTX *mem_ctx,
|
|---|
| 1762 | connection_struct *conn,
|
|---|
| 1763 | const char *driver_file,
|
|---|
| 1764 | const char *short_architecture,
|
|---|
| 1765 | uint32_t driver_version,
|
|---|
| 1766 | uint32_t version)
|
|---|
| 1767 | {
|
|---|
| 1768 | struct smb_filename *smb_fname_old = NULL;
|
|---|
| 1769 | struct smb_filename *smb_fname_new = NULL;
|
|---|
| 1770 | char *old_name = NULL;
|
|---|
| 1771 | char *new_name = NULL;
|
|---|
| 1772 | NTSTATUS status;
|
|---|
| 1773 | WERROR ret;
|
|---|
| 1774 |
|
|---|
| 1775 | old_name = talloc_asprintf(mem_ctx, "%s/%s",
|
|---|
| 1776 | short_architecture, driver_file);
|
|---|
| 1777 | W_ERROR_HAVE_NO_MEMORY(old_name);
|
|---|
| 1778 |
|
|---|
| 1779 | new_name = talloc_asprintf(mem_ctx, "%s/%d/%s",
|
|---|
| 1780 | short_architecture, driver_version, driver_file);
|
|---|
| 1781 | if (new_name == NULL) {
|
|---|
| 1782 | TALLOC_FREE(old_name);
|
|---|
| 1783 | return WERR_NOMEM;
|
|---|
| 1784 | }
|
|---|
| 1785 |
|
|---|
| 1786 | if (version != -1 && (version = file_version_is_newer(conn, old_name, new_name)) > 0) {
|
|---|
| 1787 |
|
|---|
| 1788 | status = driver_unix_convert(conn, old_name, &smb_fname_old);
|
|---|
| 1789 | if (!NT_STATUS_IS_OK(status)) {
|
|---|
| 1790 | ret = WERR_NOMEM;
|
|---|
| 1791 | goto out;
|
|---|
| 1792 | }
|
|---|
| 1793 |
|
|---|
| 1794 | /* Setup a synthetic smb_filename struct */
|
|---|
| 1795 | smb_fname_new = TALLOC_ZERO_P(mem_ctx, struct smb_filename);
|
|---|
| 1796 | if (!smb_fname_new) {
|
|---|
| 1797 | ret = WERR_NOMEM;
|
|---|
| 1798 | goto out;
|
|---|
| 1799 | }
|
|---|
| 1800 |
|
|---|
| 1801 | smb_fname_new->base_name = new_name;
|
|---|
| 1802 |
|
|---|
| 1803 | DEBUG(10,("move_driver_file_to_download_area: copying '%s' to "
|
|---|
| 1804 | "'%s'\n", smb_fname_old->base_name,
|
|---|
| 1805 | smb_fname_new->base_name));
|
|---|
| 1806 |
|
|---|
| 1807 | status = copy_file(mem_ctx, conn, smb_fname_old, smb_fname_new,
|
|---|
| 1808 | OPENX_FILE_EXISTS_TRUNCATE |
|
|---|
| 1809 | OPENX_FILE_CREATE_IF_NOT_EXIST,
|
|---|
| 1810 | 0, false);
|
|---|
| 1811 |
|
|---|
| 1812 | if (!NT_STATUS_IS_OK(status)) {
|
|---|
| 1813 | DEBUG(0,("move_driver_file_to_download_area: Unable "
|
|---|
| 1814 | "to rename [%s] to [%s]: %s\n",
|
|---|
| 1815 | smb_fname_old->base_name, new_name,
|
|---|
| 1816 | nt_errstr(status)));
|
|---|
| 1817 | ret = WERR_ACCESS_DENIED;
|
|---|
| 1818 | goto out;
|
|---|
| 1819 | }
|
|---|
| 1820 | }
|
|---|
| 1821 |
|
|---|
| 1822 | ret = WERR_OK;
|
|---|
| 1823 | out:
|
|---|
| 1824 | TALLOC_FREE(smb_fname_old);
|
|---|
| 1825 | TALLOC_FREE(smb_fname_new);
|
|---|
| 1826 | return ret;
|
|---|
| 1827 | }
|
|---|
| 1828 |
|
|---|
| 1829 | WERROR move_driver_to_download_area(struct pipes_struct *p,
|
|---|
| 1830 | struct spoolss_AddDriverInfoCtr *r,
|
|---|
| 1831 | WERROR *perr)
|
|---|
| 1832 | {
|
|---|
| 1833 | struct spoolss_AddDriverInfo3 *driver;
|
|---|
| 1834 | struct spoolss_AddDriverInfo3 converted_driver;
|
|---|
| 1835 | const char *short_architecture;
|
|---|
| 1836 | struct smb_filename *smb_dname = NULL;
|
|---|
| 1837 | char *new_dir = NULL;
|
|---|
| 1838 | connection_struct *conn = NULL;
|
|---|
| 1839 | NTSTATUS nt_status;
|
|---|
| 1840 | int i;
|
|---|
| 1841 | TALLOC_CTX *ctx = talloc_tos();
|
|---|
| 1842 | int ver = 0;
|
|---|
| 1843 | char *oldcwd;
|
|---|
| 1844 | fstring printdollar;
|
|---|
| 1845 | int printdollar_snum;
|
|---|
| 1846 |
|
|---|
| 1847 | *perr = WERR_OK;
|
|---|
| 1848 |
|
|---|
| 1849 | switch (r->level) {
|
|---|
| 1850 | case 3:
|
|---|
| 1851 | driver = r->info.info3;
|
|---|
| 1852 | break;
|
|---|
| 1853 | case 6:
|
|---|
| 1854 | convert_level_6_to_level3(&converted_driver, r->info.info6);
|
|---|
| 1855 | driver = &converted_driver;
|
|---|
| 1856 | break;
|
|---|
| 1857 | default:
|
|---|
| 1858 | DEBUG(0,("move_driver_to_download_area: Unknown info level (%u)\n", (unsigned int)r->level));
|
|---|
| 1859 | return WERR_UNKNOWN_LEVEL;
|
|---|
| 1860 | }
|
|---|
| 1861 |
|
|---|
| 1862 | short_architecture = get_short_archi(driver->architecture);
|
|---|
| 1863 | if (!short_architecture) {
|
|---|
| 1864 | return WERR_UNKNOWN_PRINTER_DRIVER;
|
|---|
| 1865 | }
|
|---|
| 1866 |
|
|---|
| 1867 | fstrcpy(printdollar, "print$");
|
|---|
| 1868 |
|
|---|
| 1869 | printdollar_snum = find_service(printdollar);
|
|---|
| 1870 | if (printdollar_snum == -1) {
|
|---|
| 1871 | *perr = WERR_NO_SUCH_SHARE;
|
|---|
| 1872 | return WERR_NO_SUCH_SHARE;
|
|---|
| 1873 | }
|
|---|
| 1874 |
|
|---|
| 1875 | nt_status = create_conn_struct(talloc_tos(), &conn, printdollar_snum,
|
|---|
| 1876 | lp_pathname(printdollar_snum),
|
|---|
| 1877 | p->server_info, &oldcwd);
|
|---|
| 1878 | if (!NT_STATUS_IS_OK(nt_status)) {
|
|---|
| 1879 | DEBUG(0,("move_driver_to_download_area: create_conn_struct "
|
|---|
| 1880 | "returned %s\n", nt_errstr(nt_status)));
|
|---|
| 1881 | *perr = ntstatus_to_werror(nt_status);
|
|---|
| 1882 | return *perr;
|
|---|
| 1883 | }
|
|---|
| 1884 |
|
|---|
| 1885 | new_dir = talloc_asprintf(ctx,
|
|---|
| 1886 | "%s/%d",
|
|---|
| 1887 | short_architecture,
|
|---|
| 1888 | driver->version);
|
|---|
| 1889 | if (!new_dir) {
|
|---|
| 1890 | *perr = WERR_NOMEM;
|
|---|
| 1891 | goto err_exit;
|
|---|
| 1892 | }
|
|---|
| 1893 | nt_status = driver_unix_convert(conn, new_dir, &smb_dname);
|
|---|
| 1894 | if (!NT_STATUS_IS_OK(nt_status)) {
|
|---|
| 1895 | *perr = WERR_NOMEM;
|
|---|
| 1896 | goto err_exit;
|
|---|
| 1897 | }
|
|---|
| 1898 |
|
|---|
| 1899 | DEBUG(5,("Creating first directory: %s\n", smb_dname->base_name));
|
|---|
| 1900 |
|
|---|
| 1901 | create_directory(conn, NULL, smb_dname);
|
|---|
| 1902 |
|
|---|
| 1903 | /* For each driver file, archi\filexxx.yyy, if there is a duplicate file
|
|---|
| 1904 | * listed for this driver which has already been moved, skip it (note:
|
|---|
| 1905 | * drivers may list the same file name several times. Then check if the
|
|---|
| 1906 | * file already exists in archi\version\, if so, check that the version
|
|---|
| 1907 | * info (or time stamps if version info is unavailable) is newer (or the
|
|---|
| 1908 | * date is later). If it is, move it to archi\version\filexxx.yyy.
|
|---|
| 1909 | * Otherwise, delete the file.
|
|---|
| 1910 | *
|
|---|
| 1911 | * If a file is not moved to archi\version\ because of an error, all the
|
|---|
| 1912 | * rest of the 'unmoved' driver files are removed from archi\. If one or
|
|---|
| 1913 | * more of the driver's files was already moved to archi\version\, it
|
|---|
| 1914 | * potentially leaves the driver in a partially updated state. Version
|
|---|
| 1915 | * trauma will most likely occur if an client attempts to use any printer
|
|---|
| 1916 | * bound to the driver. Perhaps a rewrite to make sure the moves can be
|
|---|
| 1917 | * done is appropriate... later JRR
|
|---|
| 1918 | */
|
|---|
| 1919 |
|
|---|
| 1920 | DEBUG(5,("Moving files now !\n"));
|
|---|
| 1921 |
|
|---|
| 1922 | if (driver->driver_path && strlen(driver->driver_path)) {
|
|---|
| 1923 |
|
|---|
| 1924 | *perr = move_driver_file_to_download_area(ctx,
|
|---|
| 1925 | conn,
|
|---|
| 1926 | driver->driver_path,
|
|---|
| 1927 | short_architecture,
|
|---|
| 1928 | driver->version,
|
|---|
| 1929 | ver);
|
|---|
| 1930 | if (!W_ERROR_IS_OK(*perr)) {
|
|---|
| 1931 | if (W_ERROR_EQUAL(*perr, WERR_ACCESS_DENIED)) {
|
|---|
| 1932 | ver = -1;
|
|---|
| 1933 | }
|
|---|
| 1934 | goto err_exit;
|
|---|
| 1935 | }
|
|---|
| 1936 | }
|
|---|
| 1937 |
|
|---|
| 1938 | if (driver->data_file && strlen(driver->data_file)) {
|
|---|
| 1939 | if (!strequal(driver->data_file, driver->driver_path)) {
|
|---|
| 1940 |
|
|---|
| 1941 | *perr = move_driver_file_to_download_area(ctx,
|
|---|
| 1942 | conn,
|
|---|
| 1943 | driver->data_file,
|
|---|
| 1944 | short_architecture,
|
|---|
| 1945 | driver->version,
|
|---|
| 1946 | ver);
|
|---|
| 1947 | if (!W_ERROR_IS_OK(*perr)) {
|
|---|
| 1948 | if (W_ERROR_EQUAL(*perr, WERR_ACCESS_DENIED)) {
|
|---|
| 1949 | ver = -1;
|
|---|
| 1950 | }
|
|---|
| 1951 | goto err_exit;
|
|---|
| 1952 | }
|
|---|
| 1953 | }
|
|---|
| 1954 | }
|
|---|
| 1955 |
|
|---|
| 1956 | if (driver->config_file && strlen(driver->config_file)) {
|
|---|
| 1957 | if (!strequal(driver->config_file, driver->driver_path) &&
|
|---|
| 1958 | !strequal(driver->config_file, driver->data_file)) {
|
|---|
| 1959 |
|
|---|
| 1960 | *perr = move_driver_file_to_download_area(ctx,
|
|---|
| 1961 | conn,
|
|---|
| 1962 | driver->config_file,
|
|---|
| 1963 | short_architecture,
|
|---|
| 1964 | driver->version,
|
|---|
| 1965 | ver);
|
|---|
| 1966 | if (!W_ERROR_IS_OK(*perr)) {
|
|---|
| 1967 | if (W_ERROR_EQUAL(*perr, WERR_ACCESS_DENIED)) {
|
|---|
| 1968 | ver = -1;
|
|---|
| 1969 | }
|
|---|
| 1970 | goto err_exit;
|
|---|
| 1971 | }
|
|---|
| 1972 | }
|
|---|
| 1973 | }
|
|---|
| 1974 |
|
|---|
| 1975 | if (driver->help_file && strlen(driver->help_file)) {
|
|---|
| 1976 | if (!strequal(driver->help_file, driver->driver_path) &&
|
|---|
| 1977 | !strequal(driver->help_file, driver->data_file) &&
|
|---|
| 1978 | !strequal(driver->help_file, driver->config_file)) {
|
|---|
| 1979 |
|
|---|
| 1980 | *perr = move_driver_file_to_download_area(ctx,
|
|---|
| 1981 | conn,
|
|---|
| 1982 | driver->help_file,
|
|---|
| 1983 | short_architecture,
|
|---|
| 1984 | driver->version,
|
|---|
| 1985 | ver);
|
|---|
| 1986 | if (!W_ERROR_IS_OK(*perr)) {
|
|---|
| 1987 | if (W_ERROR_EQUAL(*perr, WERR_ACCESS_DENIED)) {
|
|---|
| 1988 | ver = -1;
|
|---|
| 1989 | }
|
|---|
| 1990 | goto err_exit;
|
|---|
| 1991 | }
|
|---|
| 1992 | }
|
|---|
| 1993 | }
|
|---|
| 1994 |
|
|---|
| 1995 | if (driver->dependent_files && driver->dependent_files->string) {
|
|---|
| 1996 | for (i=0; driver->dependent_files->string[i]; i++) {
|
|---|
| 1997 | if (!strequal(driver->dependent_files->string[i], driver->driver_path) &&
|
|---|
| 1998 | !strequal(driver->dependent_files->string[i], driver->data_file) &&
|
|---|
| 1999 | !strequal(driver->dependent_files->string[i], driver->config_file) &&
|
|---|
| 2000 | !strequal(driver->dependent_files->string[i], driver->help_file)) {
|
|---|
| 2001 | int j;
|
|---|
| 2002 | for (j=0; j < i; j++) {
|
|---|
| 2003 | if (strequal(driver->dependent_files->string[i], driver->dependent_files->string[j])) {
|
|---|
| 2004 | goto NextDriver;
|
|---|
| 2005 | }
|
|---|
| 2006 | }
|
|---|
| 2007 |
|
|---|
| 2008 | *perr = move_driver_file_to_download_area(ctx,
|
|---|
| 2009 | conn,
|
|---|
| 2010 | driver->dependent_files->string[i],
|
|---|
| 2011 | short_architecture,
|
|---|
| 2012 | driver->version,
|
|---|
| 2013 | ver);
|
|---|
| 2014 | if (!W_ERROR_IS_OK(*perr)) {
|
|---|
| 2015 | if (W_ERROR_EQUAL(*perr, WERR_ACCESS_DENIED)) {
|
|---|
| 2016 | ver = -1;
|
|---|
| 2017 | }
|
|---|
| 2018 | goto err_exit;
|
|---|
| 2019 | }
|
|---|
| 2020 | }
|
|---|
| 2021 | NextDriver: ;
|
|---|
| 2022 | }
|
|---|
| 2023 | }
|
|---|
| 2024 |
|
|---|
| 2025 | err_exit:
|
|---|
| 2026 | TALLOC_FREE(smb_dname);
|
|---|
| 2027 |
|
|---|
| 2028 | if (conn != NULL) {
|
|---|
| 2029 | vfs_ChDir(conn, oldcwd);
|
|---|
| 2030 | conn_free(conn);
|
|---|
| 2031 | }
|
|---|
| 2032 |
|
|---|
| 2033 | if (W_ERROR_EQUAL(*perr, WERR_OK)) {
|
|---|
| 2034 | return WERR_OK;
|
|---|
| 2035 | }
|
|---|
| 2036 | if (ver == -1) {
|
|---|
| 2037 | return WERR_UNKNOWN_PRINTER_DRIVER;
|
|---|
| 2038 | }
|
|---|
| 2039 | return (*perr);
|
|---|
| 2040 | }
|
|---|
| 2041 |
|
|---|
| 2042 | /****************************************************************************
|
|---|
| 2043 | ****************************************************************************/
|
|---|
| 2044 |
|
|---|
| 2045 | static uint32 add_a_printer_driver_3(struct spoolss_AddDriverInfo3 *driver)
|
|---|
| 2046 | {
|
|---|
| 2047 | TALLOC_CTX *ctx = talloc_tos();
|
|---|
| 2048 | int len, buflen;
|
|---|
| 2049 | const char *architecture;
|
|---|
| 2050 | char *directory = NULL;
|
|---|
| 2051 | char *key = NULL;
|
|---|
| 2052 | uint8 *buf;
|
|---|
| 2053 | int i, ret;
|
|---|
| 2054 | TDB_DATA dbuf;
|
|---|
| 2055 |
|
|---|
| 2056 | architecture = get_short_archi(driver->architecture);
|
|---|
| 2057 | if (!architecture) {
|
|---|
| 2058 | return (uint32)-1;
|
|---|
| 2059 | }
|
|---|
| 2060 |
|
|---|
| 2061 | /* The names are relative. We store them in the form: \print$\arch\version\driver.xxx
|
|---|
| 2062 | * \\server is added in the rpc server layer.
|
|---|
| 2063 | * It does make sense to NOT store the server's name in the printer TDB.
|
|---|
| 2064 | */
|
|---|
| 2065 |
|
|---|
| 2066 | directory = talloc_asprintf(ctx, "\\print$\\%s\\%d\\",
|
|---|
| 2067 | architecture, driver->version);
|
|---|
| 2068 | if (!directory) {
|
|---|
| 2069 | return (uint32)-1;
|
|---|
| 2070 | }
|
|---|
| 2071 |
|
|---|
| 2072 | #define gen_full_driver_unc_path(ctx, directory, file) \
|
|---|
| 2073 | do { \
|
|---|
| 2074 | if (file && strlen(file)) { \
|
|---|
| 2075 | file = talloc_asprintf(ctx, "%s%s", directory, file); \
|
|---|
| 2076 | } else { \
|
|---|
| 2077 | file = talloc_strdup(ctx, ""); \
|
|---|
| 2078 | } \
|
|---|
| 2079 | if (!file) { \
|
|---|
| 2080 | return (uint32_t)-1; \
|
|---|
| 2081 | } \
|
|---|
| 2082 | } while (0);
|
|---|
| 2083 |
|
|---|
| 2084 | /* .inf files do not always list a file for each of the four standard files.
|
|---|
| 2085 | * Don't prepend a path to a null filename, or client claims:
|
|---|
| 2086 | * "The server on which the printer resides does not have a suitable
|
|---|
| 2087 | * <printer driver name> printer driver installed. Click OK if you
|
|---|
| 2088 | * wish to install the driver on your local machine."
|
|---|
| 2089 | */
|
|---|
| 2090 |
|
|---|
| 2091 | gen_full_driver_unc_path(ctx, directory, driver->driver_path);
|
|---|
| 2092 | gen_full_driver_unc_path(ctx, directory, driver->data_file);
|
|---|
| 2093 | gen_full_driver_unc_path(ctx, directory, driver->config_file);
|
|---|
| 2094 | gen_full_driver_unc_path(ctx, directory, driver->help_file);
|
|---|
| 2095 |
|
|---|
| 2096 | if (driver->dependent_files && driver->dependent_files->string) {
|
|---|
| 2097 | for (i=0; driver->dependent_files->string[i]; i++) {
|
|---|
| 2098 | gen_full_driver_unc_path(ctx, directory,
|
|---|
| 2099 | driver->dependent_files->string[i]);
|
|---|
| 2100 | }
|
|---|
| 2101 | }
|
|---|
| 2102 |
|
|---|
| 2103 | key = talloc_asprintf(ctx, "%s%s/%d/%s", DRIVERS_PREFIX,
|
|---|
| 2104 | architecture, driver->version, driver->driver_name);
|
|---|
| 2105 | if (!key) {
|
|---|
| 2106 | return (uint32)-1;
|
|---|
| 2107 | }
|
|---|
| 2108 |
|
|---|
| 2109 | DEBUG(5,("add_a_printer_driver_3: Adding driver with key %s\n", key ));
|
|---|
| 2110 |
|
|---|
| 2111 | buf = NULL;
|
|---|
| 2112 | len = buflen = 0;
|
|---|
| 2113 |
|
|---|
| 2114 | again:
|
|---|
| 2115 | len = 0;
|
|---|
| 2116 | len += tdb_pack(buf+len, buflen-len, "dffffffff",
|
|---|
| 2117 | driver->version,
|
|---|
| 2118 | driver->driver_name,
|
|---|
| 2119 | driver->architecture,
|
|---|
| 2120 | driver->driver_path,
|
|---|
| 2121 | driver->data_file,
|
|---|
| 2122 | driver->config_file,
|
|---|
| 2123 | driver->help_file,
|
|---|
| 2124 | driver->monitor_name ? driver->monitor_name : "",
|
|---|
| 2125 | driver->default_datatype ? driver->default_datatype : "");
|
|---|
| 2126 |
|
|---|
| 2127 | if (driver->dependent_files && driver->dependent_files->string) {
|
|---|
| 2128 | for (i=0; driver->dependent_files->string[i]; i++) {
|
|---|
| 2129 | len += tdb_pack(buf+len, buflen-len, "f",
|
|---|
| 2130 | driver->dependent_files->string[i]);
|
|---|
| 2131 | }
|
|---|
| 2132 | }
|
|---|
| 2133 |
|
|---|
| 2134 | if (len != buflen) {
|
|---|
| 2135 | buf = (uint8 *)SMB_REALLOC(buf, len);
|
|---|
| 2136 | if (!buf) {
|
|---|
| 2137 | DEBUG(0,("add_a_printer_driver_3: failed to enlarge buffer\n!"));
|
|---|
| 2138 | ret = -1;
|
|---|
| 2139 | goto done;
|
|---|
| 2140 | }
|
|---|
| 2141 | buflen = len;
|
|---|
| 2142 | goto again;
|
|---|
| 2143 | }
|
|---|
| 2144 |
|
|---|
| 2145 | dbuf.dptr = buf;
|
|---|
| 2146 | dbuf.dsize = len;
|
|---|
| 2147 |
|
|---|
| 2148 | ret = tdb_store_bystring(tdb_drivers, key, dbuf, TDB_REPLACE);
|
|---|
| 2149 |
|
|---|
| 2150 | done:
|
|---|
| 2151 | if (ret)
|
|---|
| 2152 | DEBUG(0,("add_a_printer_driver_3: Adding driver with key %s failed.\n", key ));
|
|---|
| 2153 |
|
|---|
| 2154 | SAFE_FREE(buf);
|
|---|
| 2155 | return ret;
|
|---|
| 2156 | }
|
|---|
| 2157 |
|
|---|
| 2158 | /****************************************************************************
|
|---|
| 2159 | ****************************************************************************/
|
|---|
| 2160 |
|
|---|
| 2161 | static uint32_t add_a_printer_driver_8(struct spoolss_DriverInfo8 *driver)
|
|---|
| 2162 | {
|
|---|
| 2163 | TALLOC_CTX *mem_ctx = talloc_new(talloc_tos());
|
|---|
| 2164 | struct spoolss_AddDriverInfo3 info3;
|
|---|
| 2165 | uint32_t ret;
|
|---|
| 2166 |
|
|---|
| 2167 | convert_level_8_to_level3(mem_ctx, &info3, driver);
|
|---|
| 2168 |
|
|---|
| 2169 | ret = add_a_printer_driver_3(&info3);
|
|---|
| 2170 | talloc_free(mem_ctx);
|
|---|
| 2171 |
|
|---|
| 2172 | return ret;
|
|---|
| 2173 | }
|
|---|
| 2174 |
|
|---|
| 2175 | /****************************************************************************
|
|---|
| 2176 | ****************************************************************************/
|
|---|
| 2177 |
|
|---|
| 2178 | static WERROR get_a_printer_driver_3_default(TALLOC_CTX *mem_ctx,
|
|---|
| 2179 | struct spoolss_DriverInfo3 *info,
|
|---|
| 2180 | const char *driver, const char *arch)
|
|---|
| 2181 | {
|
|---|
| 2182 | info->driver_name = talloc_strdup(mem_ctx, driver);
|
|---|
| 2183 | if (!info->driver_name) {
|
|---|
| 2184 | return WERR_NOMEM;
|
|---|
| 2185 | }
|
|---|
| 2186 |
|
|---|
| 2187 | info->default_datatype = talloc_strdup(mem_ctx, "RAW");
|
|---|
| 2188 | if (!info->default_datatype) {
|
|---|
| 2189 | return WERR_NOMEM;
|
|---|
| 2190 | }
|
|---|
| 2191 |
|
|---|
| 2192 | info->driver_path = talloc_strdup(mem_ctx, "");
|
|---|
| 2193 | info->data_file = talloc_strdup(mem_ctx, "");
|
|---|
| 2194 | info->config_file = talloc_strdup(mem_ctx, "");
|
|---|
| 2195 | info->help_file = talloc_strdup(mem_ctx, "");
|
|---|
| 2196 | if (!info->driver_path || !info->data_file || !info->config_file || !info->help_file) {
|
|---|
| 2197 | return WERR_NOMEM;
|
|---|
| 2198 | }
|
|---|
| 2199 |
|
|---|
| 2200 | return WERR_OK;
|
|---|
| 2201 | }
|
|---|
| 2202 |
|
|---|
| 2203 | /****************************************************************************
|
|---|
| 2204 | ****************************************************************************/
|
|---|
| 2205 |
|
|---|
| 2206 | static WERROR get_a_printer_driver_3(TALLOC_CTX *mem_ctx,
|
|---|
| 2207 | struct spoolss_DriverInfo3 *driver,
|
|---|
| 2208 | const char *drivername, const char *arch,
|
|---|
| 2209 | uint32_t version)
|
|---|
| 2210 | {
|
|---|
| 2211 | TDB_DATA dbuf;
|
|---|
| 2212 | const char *architecture;
|
|---|
| 2213 | int len = 0;
|
|---|
| 2214 | int i;
|
|---|
| 2215 | char *key = NULL;
|
|---|
| 2216 | fstring name, driverpath, environment, datafile, configfile, helpfile, monitorname, defaultdatatype;
|
|---|
| 2217 |
|
|---|
| 2218 | architecture = get_short_archi(arch);
|
|---|
| 2219 | if ( !architecture ) {
|
|---|
| 2220 | return WERR_UNKNOWN_PRINTER_DRIVER;
|
|---|
| 2221 | }
|
|---|
| 2222 |
|
|---|
| 2223 | /* Windows 4.0 (i.e. win9x) should always use a version of 0 */
|
|---|
| 2224 |
|
|---|
| 2225 | if ( strcmp( architecture, SPL_ARCH_WIN40 ) == 0 )
|
|---|
| 2226 | version = 0;
|
|---|
| 2227 |
|
|---|
| 2228 | DEBUG(8,("get_a_printer_driver_3: [%s%s/%d/%s]\n", DRIVERS_PREFIX, architecture, version, drivername));
|
|---|
| 2229 |
|
|---|
| 2230 | if (asprintf(&key, "%s%s/%d/%s", DRIVERS_PREFIX,
|
|---|
| 2231 | architecture, version, drivername) < 0) {
|
|---|
| 2232 | return WERR_NOMEM;
|
|---|
| 2233 | }
|
|---|
| 2234 |
|
|---|
| 2235 | dbuf = tdb_fetch_bystring(tdb_drivers, key);
|
|---|
| 2236 | if (!dbuf.dptr) {
|
|---|
| 2237 | SAFE_FREE(key);
|
|---|
| 2238 | return WERR_UNKNOWN_PRINTER_DRIVER;
|
|---|
| 2239 | }
|
|---|
| 2240 |
|
|---|
| 2241 | len += tdb_unpack(dbuf.dptr, dbuf.dsize, "dffffffff",
|
|---|
| 2242 | &driver->version,
|
|---|
| 2243 | name,
|
|---|
| 2244 | environment,
|
|---|
| 2245 | driverpath,
|
|---|
| 2246 | datafile,
|
|---|
| 2247 | configfile,
|
|---|
| 2248 | helpfile,
|
|---|
| 2249 | monitorname,
|
|---|
| 2250 | defaultdatatype);
|
|---|
| 2251 |
|
|---|
| 2252 | driver->driver_name = talloc_strdup(mem_ctx, name);
|
|---|
| 2253 | driver->architecture = talloc_strdup(mem_ctx, environment);
|
|---|
| 2254 | driver->driver_path = talloc_strdup(mem_ctx, driverpath);
|
|---|
| 2255 | driver->data_file = talloc_strdup(mem_ctx, datafile);
|
|---|
| 2256 | driver->config_file = talloc_strdup(mem_ctx, configfile);
|
|---|
| 2257 | driver->help_file = talloc_strdup(mem_ctx, helpfile);
|
|---|
| 2258 | driver->monitor_name = talloc_strdup(mem_ctx, monitorname);
|
|---|
| 2259 | driver->default_datatype = talloc_strdup(mem_ctx, defaultdatatype);
|
|---|
| 2260 |
|
|---|
| 2261 | i=0;
|
|---|
| 2262 |
|
|---|
| 2263 | while (len < dbuf.dsize) {
|
|---|
| 2264 |
|
|---|
| 2265 | fstring file;
|
|---|
| 2266 |
|
|---|
| 2267 | driver->dependent_files = talloc_realloc(mem_ctx, driver->dependent_files, const char *, i+2);
|
|---|
| 2268 | if (!driver->dependent_files ) {
|
|---|
| 2269 | DEBUG(0,("get_a_printer_driver_3: failed to enlarge buffer!\n"));
|
|---|
| 2270 | break;
|
|---|
| 2271 | }
|
|---|
| 2272 |
|
|---|
| 2273 | len += tdb_unpack(dbuf.dptr+len, dbuf.dsize-len, "f",
|
|---|
| 2274 | &file);
|
|---|
| 2275 |
|
|---|
| 2276 | driver->dependent_files[i] = talloc_strdup(mem_ctx, file);
|
|---|
| 2277 |
|
|---|
| 2278 | i++;
|
|---|
| 2279 | }
|
|---|
| 2280 |
|
|---|
| 2281 | if (driver->dependent_files)
|
|---|
| 2282 | driver->dependent_files[i] = NULL;
|
|---|
| 2283 |
|
|---|
| 2284 | SAFE_FREE(dbuf.dptr);
|
|---|
| 2285 | SAFE_FREE(key);
|
|---|
| 2286 |
|
|---|
| 2287 | if (len != dbuf.dsize) {
|
|---|
| 2288 | return get_a_printer_driver_3_default(mem_ctx, driver, drivername, arch);
|
|---|
| 2289 | }
|
|---|
| 2290 |
|
|---|
| 2291 | return WERR_OK;
|
|---|
| 2292 | }
|
|---|
| 2293 |
|
|---|
| 2294 | /****************************************************************************
|
|---|
| 2295 | ****************************************************************************/
|
|---|
| 2296 | int pack_devicemode(NT_DEVICEMODE *nt_devmode, uint8 *buf, int buflen)
|
|---|
| 2297 | {
|
|---|
| 2298 | int len = 0;
|
|---|
| 2299 |
|
|---|
| 2300 | len += tdb_pack(buf+len, buflen-len, "p", nt_devmode);
|
|---|
| 2301 |
|
|---|
| 2302 | if (!nt_devmode)
|
|---|
| 2303 | return len;
|
|---|
| 2304 |
|
|---|
| 2305 | len += tdb_pack(buf+len, buflen-len, "ffwwwwwwwwwwwwwwwwwwddddddddddddddp",
|
|---|
| 2306 | nt_devmode->devicename,
|
|---|
| 2307 | nt_devmode->formname,
|
|---|
| 2308 |
|
|---|
| 2309 | nt_devmode->specversion,
|
|---|
| 2310 | nt_devmode->driverversion,
|
|---|
| 2311 | nt_devmode->size,
|
|---|
| 2312 | nt_devmode->driverextra,
|
|---|
| 2313 | nt_devmode->orientation,
|
|---|
| 2314 | nt_devmode->papersize,
|
|---|
| 2315 | nt_devmode->paperlength,
|
|---|
| 2316 | nt_devmode->paperwidth,
|
|---|
| 2317 | nt_devmode->scale,
|
|---|
| 2318 | nt_devmode->copies,
|
|---|
| 2319 | nt_devmode->defaultsource,
|
|---|
| 2320 | nt_devmode->printquality,
|
|---|
| 2321 | nt_devmode->color,
|
|---|
| 2322 | nt_devmode->duplex,
|
|---|
| 2323 | nt_devmode->yresolution,
|
|---|
| 2324 | nt_devmode->ttoption,
|
|---|
| 2325 | nt_devmode->collate,
|
|---|
| 2326 | nt_devmode->logpixels,
|
|---|
| 2327 |
|
|---|
| 2328 | nt_devmode->fields,
|
|---|
| 2329 | nt_devmode->bitsperpel,
|
|---|
| 2330 | nt_devmode->pelswidth,
|
|---|
| 2331 | nt_devmode->pelsheight,
|
|---|
| 2332 | nt_devmode->displayflags,
|
|---|
| 2333 | nt_devmode->displayfrequency,
|
|---|
| 2334 | nt_devmode->icmmethod,
|
|---|
| 2335 | nt_devmode->icmintent,
|
|---|
| 2336 | nt_devmode->mediatype,
|
|---|
| 2337 | nt_devmode->dithertype,
|
|---|
| 2338 | nt_devmode->reserved1,
|
|---|
| 2339 | nt_devmode->reserved2,
|
|---|
| 2340 | nt_devmode->panningwidth,
|
|---|
| 2341 | nt_devmode->panningheight,
|
|---|
| 2342 | nt_devmode->nt_dev_private);
|
|---|
| 2343 |
|
|---|
| 2344 | if (nt_devmode->nt_dev_private) {
|
|---|
| 2345 | len += tdb_pack(buf+len, buflen-len, "B",
|
|---|
| 2346 | nt_devmode->driverextra,
|
|---|
| 2347 | nt_devmode->nt_dev_private);
|
|---|
| 2348 | }
|
|---|
| 2349 |
|
|---|
| 2350 | DEBUG(8,("Packed devicemode [%s]\n", nt_devmode->formname));
|
|---|
| 2351 |
|
|---|
| 2352 | return len;
|
|---|
| 2353 | }
|
|---|
| 2354 |
|
|---|
| 2355 | /****************************************************************************
|
|---|
| 2356 | Pack all values in all printer keys
|
|---|
| 2357 | ***************************************************************************/
|
|---|
| 2358 |
|
|---|
| 2359 | static int pack_values(NT_PRINTER_DATA *data, uint8 *buf, int buflen)
|
|---|
| 2360 | {
|
|---|
| 2361 | int len = 0;
|
|---|
| 2362 | int i, j;
|
|---|
| 2363 | struct regval_blob *val;
|
|---|
| 2364 | struct regval_ctr *val_ctr;
|
|---|
| 2365 | char *path = NULL;
|
|---|
| 2366 | int num_values;
|
|---|
| 2367 |
|
|---|
| 2368 | if ( !data )
|
|---|
| 2369 | return 0;
|
|---|
| 2370 |
|
|---|
| 2371 | /* loop over all keys */
|
|---|
| 2372 |
|
|---|
| 2373 | for ( i=0; i<data->num_keys; i++ ) {
|
|---|
| 2374 | val_ctr = data->keys[i].values;
|
|---|
| 2375 | num_values = regval_ctr_numvals( val_ctr );
|
|---|
| 2376 |
|
|---|
| 2377 | /* pack the keyname followed by a empty value */
|
|---|
| 2378 |
|
|---|
| 2379 | len += tdb_pack(buf+len, buflen-len, "pPdB",
|
|---|
| 2380 | &data->keys[i].name,
|
|---|
| 2381 | data->keys[i].name,
|
|---|
| 2382 | REG_NONE,
|
|---|
| 2383 | 0,
|
|---|
| 2384 | NULL);
|
|---|
| 2385 |
|
|---|
| 2386 | /* now loop over all values */
|
|---|
| 2387 |
|
|---|
| 2388 | for ( j=0; j<num_values; j++ ) {
|
|---|
| 2389 | /* pathname should be stored as <key>\<value> */
|
|---|
| 2390 |
|
|---|
| 2391 | val = regval_ctr_specific_value( val_ctr, j );
|
|---|
| 2392 | if (asprintf(&path, "%s\\%s",
|
|---|
| 2393 | data->keys[i].name,
|
|---|
| 2394 | regval_name(val)) < 0) {
|
|---|
| 2395 | return -1;
|
|---|
| 2396 | }
|
|---|
| 2397 |
|
|---|
| 2398 | len += tdb_pack(buf+len, buflen-len, "pPdB",
|
|---|
| 2399 | val,
|
|---|
| 2400 | path,
|
|---|
| 2401 | regval_type(val),
|
|---|
| 2402 | regval_size(val),
|
|---|
| 2403 | regval_data_p(val) );
|
|---|
| 2404 |
|
|---|
| 2405 | DEBUG(8,("specific: [%s], len: %d\n", regval_name(val), regval_size(val)));
|
|---|
| 2406 | SAFE_FREE(path);
|
|---|
| 2407 | }
|
|---|
| 2408 |
|
|---|
| 2409 | }
|
|---|
| 2410 |
|
|---|
| 2411 | /* terminator */
|
|---|
| 2412 |
|
|---|
| 2413 | len += tdb_pack(buf+len, buflen-len, "p", NULL);
|
|---|
| 2414 |
|
|---|
| 2415 | return len;
|
|---|
| 2416 | }
|
|---|
| 2417 |
|
|---|
| 2418 |
|
|---|
| 2419 | /****************************************************************************
|
|---|
| 2420 | Delete a printer - this just deletes the printer info file, any open
|
|---|
| 2421 | handles are not affected.
|
|---|
| 2422 | ****************************************************************************/
|
|---|
| 2423 |
|
|---|
| 2424 | uint32 del_a_printer(const char *sharename)
|
|---|
| 2425 | {
|
|---|
| 2426 | TDB_DATA kbuf;
|
|---|
| 2427 | char *printdb_path = NULL;
|
|---|
| 2428 | TALLOC_CTX *ctx = talloc_tos();
|
|---|
| 2429 |
|
|---|
| 2430 | kbuf = make_printer_tdbkey(ctx, sharename);
|
|---|
| 2431 | tdb_delete(tdb_printers, kbuf);
|
|---|
| 2432 |
|
|---|
| 2433 | kbuf= make_printers_secdesc_tdbkey(ctx, sharename);
|
|---|
| 2434 | tdb_delete(tdb_printers, kbuf);
|
|---|
| 2435 |
|
|---|
| 2436 | close_all_print_db();
|
|---|
| 2437 |
|
|---|
| 2438 | if (geteuid() == sec_initial_uid()) {
|
|---|
| 2439 | if (asprintf(&printdb_path, "%s%s.tdb",
|
|---|
| 2440 | cache_path("printing/"),
|
|---|
| 2441 | sharename) < 0) {
|
|---|
| 2442 | return (uint32)-1;
|
|---|
| 2443 | }
|
|---|
| 2444 | unlink(printdb_path);
|
|---|
| 2445 | SAFE_FREE(printdb_path);
|
|---|
| 2446 | }
|
|---|
| 2447 |
|
|---|
| 2448 | return 0;
|
|---|
| 2449 | }
|
|---|
| 2450 |
|
|---|
| 2451 | /****************************************************************************
|
|---|
| 2452 | ****************************************************************************/
|
|---|
| 2453 | static WERROR update_a_printer_2(NT_PRINTER_INFO_LEVEL_2 *info)
|
|---|
| 2454 | {
|
|---|
| 2455 | uint8 *buf;
|
|---|
| 2456 | int buflen, len;
|
|---|
| 2457 | int retlen;
|
|---|
| 2458 | WERROR ret;
|
|---|
| 2459 | TDB_DATA kbuf, dbuf;
|
|---|
| 2460 |
|
|---|
| 2461 | /*
|
|---|
| 2462 | * in addprinter: no servername and the printer is the name
|
|---|
| 2463 | * in setprinter: servername is \\server
|
|---|
| 2464 | * and printer is \\server\\printer
|
|---|
| 2465 | *
|
|---|
| 2466 | * Samba manages only local printers.
|
|---|
| 2467 | * we currently don't support things like i
|
|---|
| 2468 | * path=\\other_server\printer
|
|---|
| 2469 | *
|
|---|
| 2470 | * We only store the printername, not \\server\printername
|
|---|
| 2471 | */
|
|---|
| 2472 |
|
|---|
| 2473 | if ( info->servername[0] != '\0' ) {
|
|---|
| 2474 | trim_string(info->printername, info->servername, NULL);
|
|---|
| 2475 | trim_char(info->printername, '\\', '\0');
|
|---|
| 2476 | info->servername[0]='\0';
|
|---|
| 2477 | }
|
|---|
| 2478 |
|
|---|
| 2479 | /*
|
|---|
| 2480 | * JFM: one day I'll forget.
|
|---|
| 2481 | * below that's info->portname because that's the SAMBA sharename
|
|---|
| 2482 | * and I made NT 'thinks' it's the portname
|
|---|
| 2483 | * the info->sharename is the thing you can name when you add a printer
|
|---|
| 2484 | * that's the short-name when you create shared printer for 95/98
|
|---|
| 2485 | * So I've made a limitation in SAMBA: you can only have 1 printer model
|
|---|
| 2486 | * behind a SAMBA share.
|
|---|
| 2487 | */
|
|---|
| 2488 |
|
|---|
| 2489 | buf = NULL;
|
|---|
| 2490 | buflen = 0;
|
|---|
| 2491 |
|
|---|
| 2492 | again:
|
|---|
| 2493 | len = 0;
|
|---|
| 2494 | len += tdb_pack(buf+len, buflen-len, "dddddddddddfffffPfffff",
|
|---|
| 2495 | info->attributes,
|
|---|
| 2496 | info->priority,
|
|---|
| 2497 | info->default_priority,
|
|---|
| 2498 | info->starttime,
|
|---|
| 2499 | info->untiltime,
|
|---|
| 2500 | info->status,
|
|---|
| 2501 | info->cjobs,
|
|---|
| 2502 | info->averageppm,
|
|---|
| 2503 | info->changeid,
|
|---|
| 2504 | info->c_setprinter,
|
|---|
| 2505 | info->setuptime,
|
|---|
| 2506 | info->servername,
|
|---|
| 2507 | info->printername,
|
|---|
| 2508 | info->sharename,
|
|---|
| 2509 | info->portname,
|
|---|
| 2510 | info->drivername,
|
|---|
| 2511 | info->comment,
|
|---|
| 2512 | info->location,
|
|---|
| 2513 | info->sepfile,
|
|---|
| 2514 | info->printprocessor,
|
|---|
| 2515 | info->datatype,
|
|---|
| 2516 | info->parameters);
|
|---|
| 2517 |
|
|---|
| 2518 | len += pack_devicemode(info->devmode, buf+len, buflen-len);
|
|---|
| 2519 | retlen = pack_values( info->data, buf+len, buflen-len );
|
|---|
| 2520 | if (retlen == -1) {
|
|---|
| 2521 | ret = WERR_NOMEM;
|
|---|
| 2522 | goto done;
|
|---|
| 2523 | }
|
|---|
| 2524 | len += retlen;
|
|---|
| 2525 |
|
|---|
| 2526 | if (buflen != len) {
|
|---|
| 2527 | buf = (uint8 *)SMB_REALLOC(buf, len);
|
|---|
| 2528 | if (!buf) {
|
|---|
| 2529 | DEBUG(0,("update_a_printer_2: failed to enlarge buffer!\n"));
|
|---|
| 2530 | ret = WERR_NOMEM;
|
|---|
| 2531 | goto done;
|
|---|
| 2532 | }
|
|---|
| 2533 | buflen = len;
|
|---|
| 2534 | goto again;
|
|---|
| 2535 | }
|
|---|
| 2536 |
|
|---|
| 2537 | kbuf = make_printer_tdbkey(talloc_tos(), info->sharename );
|
|---|
| 2538 |
|
|---|
| 2539 | dbuf.dptr = buf;
|
|---|
| 2540 | dbuf.dsize = len;
|
|---|
| 2541 |
|
|---|
| 2542 | ret = (tdb_store(tdb_printers, kbuf, dbuf, TDB_REPLACE) == 0? WERR_OK : WERR_NOMEM);
|
|---|
| 2543 |
|
|---|
| 2544 | done:
|
|---|
| 2545 | if (!W_ERROR_IS_OK(ret))
|
|---|
| 2546 | DEBUG(8, ("error updating printer to tdb on disk\n"));
|
|---|
| 2547 |
|
|---|
| 2548 | SAFE_FREE(buf);
|
|---|
| 2549 |
|
|---|
| 2550 | DEBUG(8,("packed printer [%s] with driver [%s] portname=[%s] len=%d\n",
|
|---|
| 2551 | info->sharename, info->drivername, info->portname, len));
|
|---|
| 2552 |
|
|---|
| 2553 | return ret;
|
|---|
| 2554 | }
|
|---|
| 2555 |
|
|---|
| 2556 |
|
|---|
| 2557 | /****************************************************************************
|
|---|
| 2558 | Malloc and return an NT devicemode.
|
|---|
| 2559 | ****************************************************************************/
|
|---|
| 2560 |
|
|---|
| 2561 | NT_DEVICEMODE *construct_nt_devicemode(const fstring default_devicename)
|
|---|
| 2562 | {
|
|---|
| 2563 |
|
|---|
| 2564 | char adevice[MAXDEVICENAME];
|
|---|
| 2565 | NT_DEVICEMODE *nt_devmode = SMB_MALLOC_P(NT_DEVICEMODE);
|
|---|
| 2566 |
|
|---|
| 2567 | if (nt_devmode == NULL) {
|
|---|
| 2568 | DEBUG(0,("construct_nt_devicemode: malloc fail.\n"));
|
|---|
| 2569 | return NULL;
|
|---|
| 2570 | }
|
|---|
| 2571 |
|
|---|
| 2572 | ZERO_STRUCTP(nt_devmode);
|
|---|
| 2573 |
|
|---|
| 2574 | slprintf(adevice, sizeof(adevice), "%s", default_devicename);
|
|---|
| 2575 | fstrcpy(nt_devmode->devicename, adevice);
|
|---|
| 2576 |
|
|---|
| 2577 | fstrcpy(nt_devmode->formname, "Letter");
|
|---|
| 2578 |
|
|---|
| 2579 | nt_devmode->specversion = DMSPEC_NT4_AND_ABOVE;
|
|---|
| 2580 | nt_devmode->driverversion = 0x0400;
|
|---|
| 2581 | nt_devmode->size = 0x00DC;
|
|---|
| 2582 | nt_devmode->driverextra = 0x0000;
|
|---|
| 2583 | nt_devmode->fields = DEVMODE_FORMNAME |
|
|---|
| 2584 | DEVMODE_TTOPTION |
|
|---|
| 2585 | DEVMODE_PRINTQUALITY |
|
|---|
| 2586 | DEVMODE_DEFAULTSOURCE |
|
|---|
| 2587 | DEVMODE_COPIES |
|
|---|
| 2588 | DEVMODE_SCALE |
|
|---|
| 2589 | DEVMODE_PAPERSIZE |
|
|---|
| 2590 | DEVMODE_ORIENTATION;
|
|---|
| 2591 | nt_devmode->orientation = DMORIENT_PORTRAIT;
|
|---|
| 2592 | nt_devmode->papersize = DMPAPER_LETTER;
|
|---|
| 2593 | nt_devmode->paperlength = 0;
|
|---|
| 2594 | nt_devmode->paperwidth = 0;
|
|---|
| 2595 | nt_devmode->scale = 0x64;
|
|---|
| 2596 | nt_devmode->copies = 1;
|
|---|
| 2597 | nt_devmode->defaultsource = DMBIN_FORMSOURCE;
|
|---|
| 2598 | nt_devmode->printquality = DMRES_HIGH; /* 0x0258 */
|
|---|
| 2599 | nt_devmode->color = DMRES_MONOCHROME;
|
|---|
| 2600 | nt_devmode->duplex = DMDUP_SIMPLEX;
|
|---|
| 2601 | nt_devmode->yresolution = 0;
|
|---|
| 2602 | nt_devmode->ttoption = DMTT_SUBDEV;
|
|---|
| 2603 | nt_devmode->collate = DMCOLLATE_FALSE;
|
|---|
| 2604 | nt_devmode->icmmethod = 0;
|
|---|
| 2605 | nt_devmode->icmintent = 0;
|
|---|
| 2606 | nt_devmode->mediatype = 0;
|
|---|
| 2607 | nt_devmode->dithertype = 0;
|
|---|
| 2608 |
|
|---|
| 2609 | /* non utilisés par un driver d'imprimante */
|
|---|
| 2610 | nt_devmode->logpixels = 0;
|
|---|
| 2611 | nt_devmode->bitsperpel = 0;
|
|---|
| 2612 | nt_devmode->pelswidth = 0;
|
|---|
| 2613 | nt_devmode->pelsheight = 0;
|
|---|
| 2614 | nt_devmode->displayflags = 0;
|
|---|
| 2615 | nt_devmode->displayfrequency = 0;
|
|---|
| 2616 | nt_devmode->reserved1 = 0;
|
|---|
| 2617 | nt_devmode->reserved2 = 0;
|
|---|
| 2618 | nt_devmode->panningwidth = 0;
|
|---|
| 2619 | nt_devmode->panningheight = 0;
|
|---|
| 2620 |
|
|---|
| 2621 | nt_devmode->nt_dev_private = NULL;
|
|---|
| 2622 | return nt_devmode;
|
|---|
| 2623 | }
|
|---|
| 2624 |
|
|---|
| 2625 | /****************************************************************************
|
|---|
| 2626 | Clean up and deallocate a (maybe partially) allocated NT_DEVICEMODE.
|
|---|
| 2627 | ****************************************************************************/
|
|---|
| 2628 |
|
|---|
| 2629 | void free_nt_devicemode(NT_DEVICEMODE **devmode_ptr)
|
|---|
| 2630 | {
|
|---|
| 2631 | NT_DEVICEMODE *nt_devmode = *devmode_ptr;
|
|---|
| 2632 |
|
|---|
| 2633 | if(nt_devmode == NULL)
|
|---|
| 2634 | return;
|
|---|
| 2635 |
|
|---|
| 2636 | DEBUG(106,("free_nt_devicemode: deleting DEVMODE\n"));
|
|---|
| 2637 |
|
|---|
| 2638 | SAFE_FREE(nt_devmode->nt_dev_private);
|
|---|
| 2639 | SAFE_FREE(*devmode_ptr);
|
|---|
| 2640 | }
|
|---|
| 2641 |
|
|---|
| 2642 | /****************************************************************************
|
|---|
| 2643 | Clean up and deallocate a (maybe partially) allocated NT_PRINTER_INFO_LEVEL_2.
|
|---|
| 2644 | ****************************************************************************/
|
|---|
| 2645 |
|
|---|
| 2646 | static void free_nt_printer_info_level_2(NT_PRINTER_INFO_LEVEL_2 **info_ptr)
|
|---|
| 2647 | {
|
|---|
| 2648 | NT_PRINTER_INFO_LEVEL_2 *info = *info_ptr;
|
|---|
| 2649 |
|
|---|
| 2650 | if ( !info )
|
|---|
| 2651 | return;
|
|---|
| 2652 |
|
|---|
| 2653 | free_nt_devicemode(&info->devmode);
|
|---|
| 2654 |
|
|---|
| 2655 | TALLOC_FREE( *info_ptr );
|
|---|
| 2656 | }
|
|---|
| 2657 |
|
|---|
| 2658 |
|
|---|
| 2659 | /****************************************************************************
|
|---|
| 2660 | ****************************************************************************/
|
|---|
| 2661 | int unpack_devicemode(NT_DEVICEMODE **nt_devmode, const uint8 *buf, int buflen)
|
|---|
| 2662 | {
|
|---|
| 2663 | int len = 0;
|
|---|
| 2664 | int extra_len = 0;
|
|---|
| 2665 | NT_DEVICEMODE devmode;
|
|---|
| 2666 |
|
|---|
| 2667 | ZERO_STRUCT(devmode);
|
|---|
| 2668 |
|
|---|
| 2669 | len += tdb_unpack(buf+len, buflen-len, "p", nt_devmode);
|
|---|
| 2670 |
|
|---|
| 2671 | if (!*nt_devmode) return len;
|
|---|
| 2672 |
|
|---|
| 2673 | len += tdb_unpack(buf+len, buflen-len, "ffwwwwwwwwwwwwwwwwwwddddddddddddddp",
|
|---|
| 2674 | devmode.devicename,
|
|---|
| 2675 | devmode.formname,
|
|---|
| 2676 |
|
|---|
| 2677 | &devmode.specversion,
|
|---|
| 2678 | &devmode.driverversion,
|
|---|
| 2679 | &devmode.size,
|
|---|
| 2680 | &devmode.driverextra,
|
|---|
| 2681 | &devmode.orientation,
|
|---|
| 2682 | &devmode.papersize,
|
|---|
| 2683 | &devmode.paperlength,
|
|---|
| 2684 | &devmode.paperwidth,
|
|---|
| 2685 | &devmode.scale,
|
|---|
| 2686 | &devmode.copies,
|
|---|
| 2687 | &devmode.defaultsource,
|
|---|
| 2688 | &devmode.printquality,
|
|---|
| 2689 | &devmode.color,
|
|---|
| 2690 | &devmode.duplex,
|
|---|
| 2691 | &devmode.yresolution,
|
|---|
| 2692 | &devmode.ttoption,
|
|---|
| 2693 | &devmode.collate,
|
|---|
| 2694 | &devmode.logpixels,
|
|---|
| 2695 |
|
|---|
| 2696 | &devmode.fields,
|
|---|
| 2697 | &devmode.bitsperpel,
|
|---|
| 2698 | &devmode.pelswidth,
|
|---|
| 2699 | &devmode.pelsheight,
|
|---|
| 2700 | &devmode.displayflags,
|
|---|
| 2701 | &devmode.displayfrequency,
|
|---|
| 2702 | &devmode.icmmethod,
|
|---|
| 2703 | &devmode.icmintent,
|
|---|
| 2704 | &devmode.mediatype,
|
|---|
| 2705 | &devmode.dithertype,
|
|---|
| 2706 | &devmode.reserved1,
|
|---|
| 2707 | &devmode.reserved2,
|
|---|
| 2708 | &devmode.panningwidth,
|
|---|
| 2709 | &devmode.panningheight,
|
|---|
| 2710 | &devmode.nt_dev_private);
|
|---|
| 2711 |
|
|---|
| 2712 | if (devmode.nt_dev_private) {
|
|---|
| 2713 | /* the len in tdb_unpack is an int value and
|
|---|
| 2714 | * devmode.driverextra is only a short
|
|---|
| 2715 | */
|
|---|
| 2716 | len += tdb_unpack(buf+len, buflen-len, "B", &extra_len, &devmode.nt_dev_private);
|
|---|
| 2717 | devmode.driverextra=(uint16)extra_len;
|
|---|
| 2718 |
|
|---|
| 2719 | /* check to catch an invalid TDB entry so we don't segfault */
|
|---|
| 2720 | if (devmode.driverextra == 0) {
|
|---|
| 2721 | devmode.nt_dev_private = NULL;
|
|---|
| 2722 | }
|
|---|
| 2723 | }
|
|---|
| 2724 |
|
|---|
| 2725 | *nt_devmode = (NT_DEVICEMODE *)memdup(&devmode, sizeof(devmode));
|
|---|
| 2726 | if (!*nt_devmode) {
|
|---|
| 2727 | SAFE_FREE(devmode.nt_dev_private);
|
|---|
| 2728 | return -1;
|
|---|
| 2729 | }
|
|---|
| 2730 |
|
|---|
| 2731 | DEBUG(8,("Unpacked devicemode [%s](%s)\n", devmode.devicename, devmode.formname));
|
|---|
| 2732 | if (devmode.nt_dev_private)
|
|---|
| 2733 | DEBUG(8,("with a private section of %d bytes\n", devmode.driverextra));
|
|---|
| 2734 |
|
|---|
| 2735 | return len;
|
|---|
| 2736 | }
|
|---|
| 2737 |
|
|---|
| 2738 | /****************************************************************************
|
|---|
| 2739 | Allocate and initialize a new slot.
|
|---|
| 2740 | ***************************************************************************/
|
|---|
| 2741 |
|
|---|
| 2742 | int add_new_printer_key( NT_PRINTER_DATA *data, const char *name )
|
|---|
| 2743 | {
|
|---|
| 2744 | NT_PRINTER_KEY *d;
|
|---|
| 2745 | int key_index;
|
|---|
| 2746 |
|
|---|
| 2747 | if ( !name || !data )
|
|---|
| 2748 | return -1;
|
|---|
| 2749 |
|
|---|
| 2750 | /* allocate another slot in the NT_PRINTER_KEY array */
|
|---|
| 2751 |
|
|---|
| 2752 | if ( !(d = TALLOC_REALLOC_ARRAY( data, data->keys, NT_PRINTER_KEY, data->num_keys+1)) ) {
|
|---|
| 2753 | DEBUG(0,("add_new_printer_key: Realloc() failed!\n"));
|
|---|
| 2754 | return -1;
|
|---|
| 2755 | }
|
|---|
| 2756 |
|
|---|
| 2757 | data->keys = d;
|
|---|
| 2758 |
|
|---|
| 2759 | key_index = data->num_keys;
|
|---|
| 2760 |
|
|---|
| 2761 | /* initialze new key */
|
|---|
| 2762 |
|
|---|
| 2763 | data->keys[key_index].name = talloc_strdup( data, name );
|
|---|
| 2764 |
|
|---|
| 2765 | if ( !(data->keys[key_index].values = TALLOC_ZERO_P( data, struct regval_ctr )) )
|
|---|
| 2766 | return -1;
|
|---|
| 2767 |
|
|---|
| 2768 | data->num_keys++;
|
|---|
| 2769 |
|
|---|
| 2770 | DEBUG(10,("add_new_printer_key: Inserted new data key [%s]\n", name ));
|
|---|
| 2771 |
|
|---|
| 2772 | return key_index;
|
|---|
| 2773 | }
|
|---|
| 2774 |
|
|---|
| 2775 | /****************************************************************************
|
|---|
| 2776 | search for a registry key name in the existing printer data
|
|---|
| 2777 | ***************************************************************************/
|
|---|
| 2778 |
|
|---|
| 2779 | int delete_printer_key( NT_PRINTER_DATA *data, const char *name )
|
|---|
| 2780 | {
|
|---|
| 2781 | int i;
|
|---|
| 2782 |
|
|---|
| 2783 | for ( i=0; i<data->num_keys; i++ ) {
|
|---|
| 2784 | if ( strequal( data->keys[i].name, name ) ) {
|
|---|
| 2785 |
|
|---|
| 2786 | /* cleanup memory */
|
|---|
| 2787 |
|
|---|
| 2788 | TALLOC_FREE( data->keys[i].name );
|
|---|
| 2789 | TALLOC_FREE( data->keys[i].values );
|
|---|
| 2790 |
|
|---|
| 2791 | /* if not the end of the array, move remaining elements down one slot */
|
|---|
| 2792 |
|
|---|
| 2793 | data->num_keys--;
|
|---|
| 2794 | if ( data->num_keys && (i < data->num_keys) )
|
|---|
| 2795 | memmove( &data->keys[i], &data->keys[i+1], sizeof(NT_PRINTER_KEY)*(data->num_keys-i) );
|
|---|
| 2796 |
|
|---|
| 2797 | break;
|
|---|
| 2798 | }
|
|---|
| 2799 | }
|
|---|
| 2800 |
|
|---|
| 2801 |
|
|---|
| 2802 | return data->num_keys;
|
|---|
| 2803 | }
|
|---|
| 2804 |
|
|---|
| 2805 | /****************************************************************************
|
|---|
| 2806 | search for a registry key name in the existing printer data
|
|---|
| 2807 | ***************************************************************************/
|
|---|
| 2808 |
|
|---|
| 2809 | int lookup_printerkey( NT_PRINTER_DATA *data, const char *name )
|
|---|
| 2810 | {
|
|---|
| 2811 | int key_index = -1;
|
|---|
| 2812 | int i;
|
|---|
| 2813 |
|
|---|
| 2814 | if ( !data || !name )
|
|---|
| 2815 | return -1;
|
|---|
| 2816 |
|
|---|
| 2817 | DEBUG(12,("lookup_printerkey: Looking for [%s]\n", name));
|
|---|
| 2818 |
|
|---|
| 2819 | /* loop over all existing keys */
|
|---|
| 2820 |
|
|---|
| 2821 | for ( i=0; i<data->num_keys; i++ ) {
|
|---|
| 2822 | if ( strequal(data->keys[i].name, name) ) {
|
|---|
| 2823 | DEBUG(12,("lookup_printerkey: Found [%s]!\n", name));
|
|---|
| 2824 | key_index = i;
|
|---|
| 2825 | break;
|
|---|
| 2826 |
|
|---|
| 2827 | }
|
|---|
| 2828 | }
|
|---|
| 2829 |
|
|---|
| 2830 | return key_index;
|
|---|
| 2831 | }
|
|---|
| 2832 |
|
|---|
| 2833 | /****************************************************************************
|
|---|
| 2834 | ***************************************************************************/
|
|---|
| 2835 |
|
|---|
| 2836 | int get_printer_subkeys( NT_PRINTER_DATA *data, const char* key, fstring **subkeys )
|
|---|
| 2837 | {
|
|---|
| 2838 | int i, j;
|
|---|
| 2839 | int key_len;
|
|---|
| 2840 | int num_subkeys = 0;
|
|---|
| 2841 | char *p;
|
|---|
| 2842 | fstring *subkeys_ptr = NULL;
|
|---|
| 2843 | fstring subkeyname;
|
|---|
| 2844 |
|
|---|
| 2845 | *subkeys = NULL;
|
|---|
| 2846 |
|
|---|
| 2847 | if ( !data )
|
|---|
| 2848 | return 0;
|
|---|
| 2849 |
|
|---|
| 2850 | if ( !key )
|
|---|
| 2851 | return -1;
|
|---|
| 2852 |
|
|---|
| 2853 | /* special case of asking for the top level printer data registry key names */
|
|---|
| 2854 |
|
|---|
| 2855 | if ( strlen(key) == 0 ) {
|
|---|
| 2856 | for ( i=0; i<data->num_keys; i++ ) {
|
|---|
| 2857 |
|
|---|
| 2858 | /* found a match, so allocate space and copy the name */
|
|---|
| 2859 |
|
|---|
| 2860 | if ( !(subkeys_ptr = SMB_REALLOC_ARRAY( subkeys_ptr, fstring, num_subkeys+2)) ) {
|
|---|
| 2861 | DEBUG(0,("get_printer_subkeys: Realloc failed for [%d] entries!\n",
|
|---|
| 2862 | num_subkeys+1));
|
|---|
| 2863 | return -1;
|
|---|
| 2864 | }
|
|---|
| 2865 |
|
|---|
| 2866 | fstrcpy( subkeys_ptr[num_subkeys], data->keys[i].name );
|
|---|
| 2867 | num_subkeys++;
|
|---|
| 2868 | }
|
|---|
| 2869 |
|
|---|
| 2870 | goto done;
|
|---|
| 2871 | }
|
|---|
| 2872 |
|
|---|
| 2873 | /* asking for the subkeys of some key */
|
|---|
| 2874 | /* subkey paths are stored in the key name using '\' as the delimiter */
|
|---|
| 2875 |
|
|---|
| 2876 | for ( i=0; i<data->num_keys; i++ ) {
|
|---|
| 2877 | if ( StrnCaseCmp(data->keys[i].name, key, strlen(key)) == 0 ) {
|
|---|
| 2878 |
|
|---|
| 2879 | /* if we found the exact key, then break */
|
|---|
| 2880 | key_len = strlen( key );
|
|---|
| 2881 | if ( strlen(data->keys[i].name) == key_len )
|
|---|
| 2882 | break;
|
|---|
| 2883 |
|
|---|
| 2884 | /* get subkey path */
|
|---|
| 2885 |
|
|---|
| 2886 | p = data->keys[i].name + key_len;
|
|---|
| 2887 | if ( *p == '\\' )
|
|---|
| 2888 | p++;
|
|---|
| 2889 | fstrcpy( subkeyname, p );
|
|---|
| 2890 | if ( (p = strchr( subkeyname, '\\' )) )
|
|---|
| 2891 | *p = '\0';
|
|---|
| 2892 |
|
|---|
| 2893 | /* don't add a key more than once */
|
|---|
| 2894 |
|
|---|
| 2895 | for ( j=0; j<num_subkeys; j++ ) {
|
|---|
| 2896 | if ( strequal( subkeys_ptr[j], subkeyname ) )
|
|---|
| 2897 | break;
|
|---|
| 2898 | }
|
|---|
| 2899 |
|
|---|
| 2900 | if ( j != num_subkeys )
|
|---|
| 2901 | continue;
|
|---|
| 2902 |
|
|---|
| 2903 | /* found a match, so allocate space and copy the name */
|
|---|
| 2904 |
|
|---|
| 2905 | if ( !(subkeys_ptr = SMB_REALLOC_ARRAY( subkeys_ptr, fstring, num_subkeys+2)) ) {
|
|---|
| 2906 | DEBUG(0,("get_printer_subkeys: Realloc failed for [%d] entries!\n",
|
|---|
| 2907 | num_subkeys+1));
|
|---|
| 2908 | return 0;
|
|---|
| 2909 | }
|
|---|
| 2910 |
|
|---|
| 2911 | fstrcpy( subkeys_ptr[num_subkeys], subkeyname );
|
|---|
| 2912 | num_subkeys++;
|
|---|
| 2913 | }
|
|---|
| 2914 |
|
|---|
| 2915 | }
|
|---|
| 2916 |
|
|---|
| 2917 | /* return error if the key was not found */
|
|---|
| 2918 |
|
|---|
| 2919 | if ( i == data->num_keys ) {
|
|---|
| 2920 | SAFE_FREE(subkeys_ptr);
|
|---|
| 2921 | return -1;
|
|---|
| 2922 | }
|
|---|
| 2923 |
|
|---|
| 2924 | done:
|
|---|
| 2925 | /* tag off the end */
|
|---|
| 2926 |
|
|---|
| 2927 | if (num_subkeys)
|
|---|
| 2928 | fstrcpy(subkeys_ptr[num_subkeys], "" );
|
|---|
| 2929 |
|
|---|
| 2930 | *subkeys = subkeys_ptr;
|
|---|
| 2931 |
|
|---|
| 2932 | return num_subkeys;
|
|---|
| 2933 | }
|
|---|
| 2934 |
|
|---|
| 2935 | #ifdef HAVE_ADS
|
|---|
| 2936 | static void map_sz_into_ctr(struct regval_ctr *ctr, const char *val_name,
|
|---|
| 2937 | const char *sz)
|
|---|
| 2938 | {
|
|---|
| 2939 | regval_ctr_delvalue(ctr, val_name);
|
|---|
| 2940 | regval_ctr_addvalue_sz(ctr, val_name, sz);
|
|---|
| 2941 | }
|
|---|
| 2942 |
|
|---|
| 2943 | static void map_dword_into_ctr(struct regval_ctr *ctr, const char *val_name,
|
|---|
| 2944 | uint32 dword)
|
|---|
| 2945 | {
|
|---|
| 2946 | regval_ctr_delvalue(ctr, val_name);
|
|---|
| 2947 | regval_ctr_addvalue(ctr, val_name, REG_DWORD,
|
|---|
| 2948 | (char *) &dword, sizeof(dword));
|
|---|
| 2949 | }
|
|---|
| 2950 |
|
|---|
| 2951 | static void map_bool_into_ctr(struct regval_ctr *ctr, const char *val_name,
|
|---|
| 2952 | bool b)
|
|---|
| 2953 | {
|
|---|
| 2954 | uint8 bin_bool = (b ? 1 : 0);
|
|---|
| 2955 | regval_ctr_delvalue(ctr, val_name);
|
|---|
| 2956 | regval_ctr_addvalue(ctr, val_name, REG_BINARY,
|
|---|
| 2957 | (char *) &bin_bool, sizeof(bin_bool));
|
|---|
| 2958 | }
|
|---|
| 2959 |
|
|---|
| 2960 | static void map_single_multi_sz_into_ctr(struct regval_ctr *ctr, const char *val_name,
|
|---|
| 2961 | const char *multi_sz)
|
|---|
| 2962 | {
|
|---|
| 2963 | const char *a[2];
|
|---|
| 2964 |
|
|---|
| 2965 | a[0] = multi_sz;
|
|---|
| 2966 | a[1] = NULL;
|
|---|
| 2967 |
|
|---|
| 2968 | regval_ctr_delvalue(ctr, val_name);
|
|---|
| 2969 | regval_ctr_addvalue_multi_sz(ctr, val_name, a);
|
|---|
| 2970 | }
|
|---|
| 2971 |
|
|---|
| 2972 | /****************************************************************************
|
|---|
| 2973 | * Map the NT_PRINTER_INFO_LEVEL_2 data into DsSpooler keys for publishing.
|
|---|
| 2974 | *
|
|---|
| 2975 | * @param info2 NT_PRINTER_INFO_LEVEL_2 describing printer - gets modified
|
|---|
| 2976 | * @return bool indicating success or failure
|
|---|
| 2977 | ***************************************************************************/
|
|---|
| 2978 |
|
|---|
| 2979 | static bool map_nt_printer_info2_to_dsspooler(NT_PRINTER_INFO_LEVEL_2 *info2)
|
|---|
| 2980 | {
|
|---|
| 2981 | struct regval_ctr *ctr = NULL;
|
|---|
| 2982 | fstring longname;
|
|---|
| 2983 | const char *dnssuffix;
|
|---|
| 2984 | char *allocated_string = NULL;
|
|---|
| 2985 | const char *ascii_str;
|
|---|
| 2986 | int i;
|
|---|
| 2987 |
|
|---|
| 2988 | if ((i = lookup_printerkey(info2->data, SPOOL_DSSPOOLER_KEY)) < 0)
|
|---|
| 2989 | i = add_new_printer_key(info2->data, SPOOL_DSSPOOLER_KEY);
|
|---|
| 2990 | ctr = info2->data->keys[i].values;
|
|---|
| 2991 |
|
|---|
| 2992 | map_sz_into_ctr(ctr, SPOOL_REG_PRINTERNAME, info2->sharename);
|
|---|
| 2993 | map_sz_into_ctr(ctr, SPOOL_REG_SHORTSERVERNAME, global_myname());
|
|---|
| 2994 |
|
|---|
| 2995 | /* we make the assumption that the netbios name is the same
|
|---|
| 2996 | as the DNS name sinc ethe former will be what we used to
|
|---|
| 2997 | join the domain */
|
|---|
| 2998 |
|
|---|
| 2999 | dnssuffix = get_mydnsdomname(talloc_tos());
|
|---|
| 3000 | if (dnssuffix && *dnssuffix) {
|
|---|
| 3001 | fstr_sprintf( longname, "%s.%s", global_myname(), dnssuffix );
|
|---|
| 3002 | } else {
|
|---|
| 3003 | fstrcpy( longname, global_myname() );
|
|---|
| 3004 | }
|
|---|
| 3005 |
|
|---|
| 3006 | map_sz_into_ctr(ctr, SPOOL_REG_SERVERNAME, longname);
|
|---|
| 3007 |
|
|---|
| 3008 | if (asprintf(&allocated_string, "\\\\%s\\%s", longname, info2->sharename) == -1) {
|
|---|
| 3009 | return false;
|
|---|
| 3010 | }
|
|---|
| 3011 | map_sz_into_ctr(ctr, SPOOL_REG_UNCNAME, allocated_string);
|
|---|
| 3012 | SAFE_FREE(allocated_string);
|
|---|
| 3013 |
|
|---|
| 3014 | map_dword_into_ctr(ctr, SPOOL_REG_VERSIONNUMBER, 4);
|
|---|
| 3015 | map_sz_into_ctr(ctr, SPOOL_REG_DRIVERNAME, info2->drivername);
|
|---|
| 3016 | map_sz_into_ctr(ctr, SPOOL_REG_LOCATION, info2->location);
|
|---|
| 3017 | map_sz_into_ctr(ctr, SPOOL_REG_DESCRIPTION, info2->comment);
|
|---|
| 3018 | map_single_multi_sz_into_ctr(ctr, SPOOL_REG_PORTNAME, info2->portname);
|
|---|
| 3019 | map_sz_into_ctr(ctr, SPOOL_REG_PRINTSEPARATORFILE, info2->sepfile);
|
|---|
| 3020 | map_dword_into_ctr(ctr, SPOOL_REG_PRINTSTARTTIME, info2->starttime);
|
|---|
| 3021 | map_dword_into_ctr(ctr, SPOOL_REG_PRINTENDTIME, info2->untiltime);
|
|---|
| 3022 | map_dword_into_ctr(ctr, SPOOL_REG_PRIORITY, info2->priority);
|
|---|
| 3023 |
|
|---|
| 3024 | map_bool_into_ctr(ctr, SPOOL_REG_PRINTKEEPPRINTEDJOBS,
|
|---|
| 3025 | (info2->attributes &
|
|---|
| 3026 | PRINTER_ATTRIBUTE_KEEPPRINTEDJOBS));
|
|---|
| 3027 |
|
|---|
| 3028 | switch (info2->attributes & 0x3) {
|
|---|
| 3029 | case 0:
|
|---|
| 3030 | ascii_str = SPOOL_REGVAL_PRINTWHILESPOOLING;
|
|---|
| 3031 | break;
|
|---|
| 3032 | case 1:
|
|---|
| 3033 | ascii_str = SPOOL_REGVAL_PRINTAFTERSPOOLED;
|
|---|
| 3034 | break;
|
|---|
| 3035 | case 2:
|
|---|
| 3036 | ascii_str = SPOOL_REGVAL_PRINTDIRECT;
|
|---|
| 3037 | break;
|
|---|
| 3038 | default:
|
|---|
| 3039 | ascii_str = "unknown";
|
|---|
| 3040 | }
|
|---|
| 3041 | map_sz_into_ctr(ctr, SPOOL_REG_PRINTSPOOLING, ascii_str);
|
|---|
| 3042 |
|
|---|
| 3043 | return True;
|
|---|
| 3044 | }
|
|---|
| 3045 |
|
|---|
| 3046 | /*****************************************************************
|
|---|
| 3047 | ****************************************************************/
|
|---|
| 3048 |
|
|---|
| 3049 | static void store_printer_guid(NT_PRINTER_INFO_LEVEL_2 *info2,
|
|---|
| 3050 | struct GUID guid)
|
|---|
| 3051 | {
|
|---|
| 3052 | int i;
|
|---|
| 3053 | struct regval_ctr *ctr=NULL;
|
|---|
| 3054 |
|
|---|
| 3055 | /* find the DsSpooler key */
|
|---|
| 3056 | if ((i = lookup_printerkey(info2->data, SPOOL_DSSPOOLER_KEY)) < 0)
|
|---|
| 3057 | i = add_new_printer_key(info2->data, SPOOL_DSSPOOLER_KEY);
|
|---|
| 3058 | ctr = info2->data->keys[i].values;
|
|---|
| 3059 |
|
|---|
| 3060 | regval_ctr_delvalue(ctr, "objectGUID");
|
|---|
| 3061 |
|
|---|
| 3062 | /* We used to store this as a REG_BINARY but that causes
|
|---|
| 3063 | Vista to whine */
|
|---|
| 3064 |
|
|---|
| 3065 | regval_ctr_addvalue_sz(ctr, "objectGUID",
|
|---|
| 3066 | GUID_string(talloc_tos(), &guid));
|
|---|
| 3067 | }
|
|---|
| 3068 |
|
|---|
| 3069 | static WERROR nt_printer_publish_ads(ADS_STRUCT *ads,
|
|---|
| 3070 | NT_PRINTER_INFO_LEVEL *printer)
|
|---|
| 3071 | {
|
|---|
| 3072 | ADS_STATUS ads_rc;
|
|---|
| 3073 | LDAPMessage *res;
|
|---|
| 3074 | char *prt_dn = NULL, *srv_dn, *srv_cn_0, *srv_cn_escaped, *sharename_escaped;
|
|---|
| 3075 | char *srv_dn_utf8, **srv_cn_utf8;
|
|---|
| 3076 | TALLOC_CTX *ctx;
|
|---|
| 3077 | ADS_MODLIST mods;
|
|---|
| 3078 | const char *attrs[] = {"objectGUID", NULL};
|
|---|
| 3079 | struct GUID guid;
|
|---|
| 3080 | WERROR win_rc = WERR_OK;
|
|---|
| 3081 | size_t converted_size;
|
|---|
| 3082 |
|
|---|
| 3083 | /* build the ads mods */
|
|---|
| 3084 | ctx = talloc_init("nt_printer_publish_ads");
|
|---|
| 3085 | if (ctx == NULL) {
|
|---|
| 3086 | return WERR_NOMEM;
|
|---|
| 3087 | }
|
|---|
| 3088 |
|
|---|
| 3089 | DEBUG(5, ("publishing printer %s\n", printer->info_2->printername));
|
|---|
| 3090 |
|
|---|
| 3091 | /* figure out where to publish */
|
|---|
| 3092 | ads_find_machine_acct(ads, &res, global_myname());
|
|---|
| 3093 |
|
|---|
| 3094 | /* We use ldap_get_dn here as we need the answer
|
|---|
| 3095 | * in utf8 to call ldap_explode_dn(). JRA. */
|
|---|
| 3096 |
|
|---|
| 3097 | srv_dn_utf8 = ldap_get_dn((LDAP *)ads->ldap.ld, (LDAPMessage *)res);
|
|---|
| 3098 | if (!srv_dn_utf8) {
|
|---|
| 3099 | TALLOC_FREE(ctx);
|
|---|
| 3100 | return WERR_SERVER_UNAVAILABLE;
|
|---|
| 3101 | }
|
|---|
| 3102 | ads_msgfree(ads, res);
|
|---|
| 3103 | srv_cn_utf8 = ldap_explode_dn(srv_dn_utf8, 1);
|
|---|
| 3104 | if (!srv_cn_utf8) {
|
|---|
| 3105 | TALLOC_FREE(ctx);
|
|---|
| 3106 | ldap_memfree(srv_dn_utf8);
|
|---|
| 3107 | return WERR_SERVER_UNAVAILABLE;
|
|---|
| 3108 | }
|
|---|
| 3109 | /* Now convert to CH_UNIX. */
|
|---|
| 3110 | if (!pull_utf8_talloc(ctx, &srv_dn, srv_dn_utf8, &converted_size)) {
|
|---|
| 3111 | TALLOC_FREE(ctx);
|
|---|
| 3112 | ldap_memfree(srv_dn_utf8);
|
|---|
| 3113 | ldap_memfree(srv_cn_utf8);
|
|---|
| 3114 | return WERR_SERVER_UNAVAILABLE;
|
|---|
| 3115 | }
|
|---|
| 3116 | if (!pull_utf8_talloc(ctx, &srv_cn_0, srv_cn_utf8[0], &converted_size)) {
|
|---|
| 3117 | TALLOC_FREE(ctx);
|
|---|
| 3118 | ldap_memfree(srv_dn_utf8);
|
|---|
| 3119 | ldap_memfree(srv_cn_utf8);
|
|---|
| 3120 | TALLOC_FREE(srv_dn);
|
|---|
| 3121 | return WERR_SERVER_UNAVAILABLE;
|
|---|
| 3122 | }
|
|---|
| 3123 |
|
|---|
| 3124 | ldap_memfree(srv_dn_utf8);
|
|---|
| 3125 | ldap_memfree(srv_cn_utf8);
|
|---|
| 3126 |
|
|---|
| 3127 | srv_cn_escaped = escape_rdn_val_string_alloc(srv_cn_0);
|
|---|
| 3128 | if (!srv_cn_escaped) {
|
|---|
| 3129 | TALLOC_FREE(ctx);
|
|---|
| 3130 | return WERR_SERVER_UNAVAILABLE;
|
|---|
| 3131 | }
|
|---|
| 3132 | sharename_escaped = escape_rdn_val_string_alloc(printer->info_2->sharename);
|
|---|
| 3133 | if (!sharename_escaped) {
|
|---|
| 3134 | SAFE_FREE(srv_cn_escaped);
|
|---|
| 3135 | TALLOC_FREE(ctx);
|
|---|
| 3136 | return WERR_SERVER_UNAVAILABLE;
|
|---|
| 3137 | }
|
|---|
| 3138 |
|
|---|
| 3139 | prt_dn = talloc_asprintf(ctx, "cn=%s-%s,%s", srv_cn_escaped, sharename_escaped, srv_dn);
|
|---|
| 3140 |
|
|---|
| 3141 | SAFE_FREE(srv_cn_escaped);
|
|---|
| 3142 | SAFE_FREE(sharename_escaped);
|
|---|
| 3143 |
|
|---|
| 3144 | mods = ads_init_mods(ctx);
|
|---|
| 3145 |
|
|---|
| 3146 | if (mods == NULL) {
|
|---|
| 3147 | SAFE_FREE(prt_dn);
|
|---|
| 3148 | TALLOC_FREE(ctx);
|
|---|
| 3149 | return WERR_NOMEM;
|
|---|
| 3150 | }
|
|---|
| 3151 |
|
|---|
| 3152 | get_local_printer_publishing_data(ctx, &mods, printer->info_2->data);
|
|---|
| 3153 | ads_mod_str(ctx, &mods, SPOOL_REG_PRINTERNAME,
|
|---|
| 3154 | printer->info_2->sharename);
|
|---|
| 3155 |
|
|---|
| 3156 | /* publish it */
|
|---|
| 3157 | ads_rc = ads_mod_printer_entry(ads, prt_dn, ctx, &mods);
|
|---|
| 3158 | if (ads_rc.err.rc == LDAP_NO_SUCH_OBJECT) {
|
|---|
| 3159 | int i;
|
|---|
| 3160 | for (i=0; mods[i] != 0; i++)
|
|---|
| 3161 | ;
|
|---|
| 3162 | mods[i] = (LDAPMod *)-1;
|
|---|
| 3163 | ads_rc = ads_add_printer_entry(ads, prt_dn, ctx, &mods);
|
|---|
| 3164 | }
|
|---|
| 3165 |
|
|---|
| 3166 | if (!ADS_ERR_OK(ads_rc))
|
|---|
| 3167 | DEBUG(3, ("error publishing %s: %s\n", printer->info_2->sharename, ads_errstr(ads_rc)));
|
|---|
| 3168 |
|
|---|
| 3169 | /* retreive the guid and store it locally */
|
|---|
| 3170 | if (ADS_ERR_OK(ads_search_dn(ads, &res, prt_dn, attrs))) {
|
|---|
| 3171 | ZERO_STRUCT(guid);
|
|---|
| 3172 | ads_pull_guid(ads, res, &guid);
|
|---|
| 3173 | ads_msgfree(ads, res);
|
|---|
| 3174 | store_printer_guid(printer->info_2, guid);
|
|---|
| 3175 | win_rc = mod_a_printer(printer, 2);
|
|---|
| 3176 | }
|
|---|
| 3177 | TALLOC_FREE(ctx);
|
|---|
| 3178 |
|
|---|
| 3179 | return win_rc;
|
|---|
| 3180 | }
|
|---|
| 3181 |
|
|---|
| 3182 | static WERROR nt_printer_unpublish_ads(ADS_STRUCT *ads,
|
|---|
| 3183 | NT_PRINTER_INFO_LEVEL *printer)
|
|---|
| 3184 | {
|
|---|
| 3185 | ADS_STATUS ads_rc;
|
|---|
| 3186 | LDAPMessage *res = NULL;
|
|---|
| 3187 | char *prt_dn = NULL;
|
|---|
| 3188 |
|
|---|
| 3189 | DEBUG(5, ("unpublishing printer %s\n", printer->info_2->printername));
|
|---|
| 3190 |
|
|---|
| 3191 | /* remove the printer from the directory */
|
|---|
| 3192 | ads_rc = ads_find_printer_on_server(ads, &res,
|
|---|
| 3193 | printer->info_2->sharename, global_myname());
|
|---|
| 3194 |
|
|---|
| 3195 | if (ADS_ERR_OK(ads_rc) && res && ads_count_replies(ads, res)) {
|
|---|
| 3196 | prt_dn = ads_get_dn(ads, talloc_tos(), res);
|
|---|
| 3197 | if (!prt_dn) {
|
|---|
| 3198 | ads_msgfree(ads, res);
|
|---|
| 3199 | return WERR_NOMEM;
|
|---|
| 3200 | }
|
|---|
| 3201 | ads_rc = ads_del_dn(ads, prt_dn);
|
|---|
| 3202 | TALLOC_FREE(prt_dn);
|
|---|
| 3203 | }
|
|---|
| 3204 |
|
|---|
| 3205 | if (res) {
|
|---|
| 3206 | ads_msgfree(ads, res);
|
|---|
| 3207 | }
|
|---|
| 3208 | return WERR_OK;
|
|---|
| 3209 | }
|
|---|
| 3210 |
|
|---|
| 3211 | /****************************************************************************
|
|---|
| 3212 | * Publish a printer in the directory
|
|---|
| 3213 | *
|
|---|
| 3214 | * @param snum describing printer service
|
|---|
| 3215 | * @return WERROR indicating status of publishing
|
|---|
| 3216 | ***************************************************************************/
|
|---|
| 3217 |
|
|---|
| 3218 | WERROR nt_printer_publish(Printer_entry *print_hnd, int snum, int action)
|
|---|
| 3219 | {
|
|---|
| 3220 | ADS_STATUS ads_rc;
|
|---|
| 3221 | ADS_STRUCT *ads = NULL;
|
|---|
| 3222 | NT_PRINTER_INFO_LEVEL *printer = NULL;
|
|---|
| 3223 | WERROR win_rc;
|
|---|
| 3224 |
|
|---|
| 3225 | win_rc = get_a_printer(print_hnd, &printer, 2, lp_servicename(snum));
|
|---|
| 3226 | if (!W_ERROR_IS_OK(win_rc))
|
|---|
| 3227 | goto done;
|
|---|
| 3228 |
|
|---|
| 3229 | switch (action) {
|
|---|
| 3230 | case DSPRINT_PUBLISH:
|
|---|
| 3231 | case DSPRINT_UPDATE:
|
|---|
| 3232 | /* set the DsSpooler info and attributes */
|
|---|
| 3233 | if (!(map_nt_printer_info2_to_dsspooler(printer->info_2))) {
|
|---|
| 3234 | win_rc = WERR_NOMEM;
|
|---|
| 3235 | goto done;
|
|---|
| 3236 | }
|
|---|
| 3237 |
|
|---|
| 3238 | printer->info_2->attributes |= PRINTER_ATTRIBUTE_PUBLISHED;
|
|---|
| 3239 | break;
|
|---|
| 3240 | case DSPRINT_UNPUBLISH:
|
|---|
| 3241 | printer->info_2->attributes ^= PRINTER_ATTRIBUTE_PUBLISHED;
|
|---|
| 3242 | break;
|
|---|
| 3243 | default:
|
|---|
| 3244 | win_rc = WERR_NOT_SUPPORTED;
|
|---|
| 3245 | goto done;
|
|---|
| 3246 | }
|
|---|
| 3247 |
|
|---|
| 3248 | win_rc = mod_a_printer(printer, 2);
|
|---|
| 3249 | if (!W_ERROR_IS_OK(win_rc)) {
|
|---|
| 3250 | DEBUG(3, ("err %d saving data\n", W_ERROR_V(win_rc)));
|
|---|
| 3251 | goto done;
|
|---|
| 3252 | }
|
|---|
| 3253 |
|
|---|
| 3254 | ads = ads_init(lp_realm(), lp_workgroup(), NULL);
|
|---|
| 3255 | if (!ads) {
|
|---|
| 3256 | DEBUG(3, ("ads_init() failed\n"));
|
|---|
| 3257 | win_rc = WERR_SERVER_UNAVAILABLE;
|
|---|
| 3258 | goto done;
|
|---|
| 3259 | }
|
|---|
| 3260 | setenv(KRB5_ENV_CCNAME, "MEMORY:prtpub_cache", 1);
|
|---|
| 3261 | SAFE_FREE(ads->auth.password);
|
|---|
| 3262 | ads->auth.password = secrets_fetch_machine_password(lp_workgroup(),
|
|---|
| 3263 | NULL, NULL);
|
|---|
| 3264 |
|
|---|
| 3265 | /* ads_connect() will find the DC for us */
|
|---|
| 3266 | ads_rc = ads_connect(ads);
|
|---|
| 3267 | if (!ADS_ERR_OK(ads_rc)) {
|
|---|
| 3268 | DEBUG(3, ("ads_connect failed: %s\n", ads_errstr(ads_rc)));
|
|---|
| 3269 | win_rc = WERR_ACCESS_DENIED;
|
|---|
| 3270 | goto done;
|
|---|
| 3271 | }
|
|---|
| 3272 |
|
|---|
| 3273 | switch (action) {
|
|---|
| 3274 | case DSPRINT_PUBLISH:
|
|---|
| 3275 | case DSPRINT_UPDATE:
|
|---|
| 3276 | win_rc = nt_printer_publish_ads(ads, printer);
|
|---|
| 3277 | break;
|
|---|
| 3278 | case DSPRINT_UNPUBLISH:
|
|---|
| 3279 | win_rc = nt_printer_unpublish_ads(ads, printer);
|
|---|
| 3280 | break;
|
|---|
| 3281 | }
|
|---|
| 3282 |
|
|---|
| 3283 | done:
|
|---|
| 3284 | free_a_printer(&printer, 2);
|
|---|
| 3285 | ads_destroy(&ads);
|
|---|
| 3286 | return win_rc;
|
|---|
| 3287 | }
|
|---|
| 3288 |
|
|---|
| 3289 | WERROR check_published_printers(void)
|
|---|
| 3290 | {
|
|---|
| 3291 | ADS_STATUS ads_rc;
|
|---|
| 3292 | ADS_STRUCT *ads = NULL;
|
|---|
| 3293 | int snum;
|
|---|
| 3294 | int n_services = lp_numservices();
|
|---|
| 3295 | NT_PRINTER_INFO_LEVEL *printer = NULL;
|
|---|
| 3296 |
|
|---|
| 3297 | ads = ads_init(lp_realm(), lp_workgroup(), NULL);
|
|---|
| 3298 | if (!ads) {
|
|---|
| 3299 | DEBUG(3, ("ads_init() failed\n"));
|
|---|
| 3300 | return WERR_SERVER_UNAVAILABLE;
|
|---|
| 3301 | }
|
|---|
| 3302 | setenv(KRB5_ENV_CCNAME, "MEMORY:prtpub_cache", 1);
|
|---|
| 3303 | SAFE_FREE(ads->auth.password);
|
|---|
| 3304 | ads->auth.password = secrets_fetch_machine_password(lp_workgroup(),
|
|---|
| 3305 | NULL, NULL);
|
|---|
| 3306 |
|
|---|
| 3307 | /* ads_connect() will find the DC for us */
|
|---|
| 3308 | ads_rc = ads_connect(ads);
|
|---|
| 3309 | if (!ADS_ERR_OK(ads_rc)) {
|
|---|
| 3310 | DEBUG(3, ("ads_connect failed: %s\n", ads_errstr(ads_rc)));
|
|---|
| 3311 | ads_destroy(&ads);
|
|---|
| 3312 | ads_kdestroy("MEMORY:prtpub_cache");
|
|---|
| 3313 | return WERR_ACCESS_DENIED;
|
|---|
| 3314 | }
|
|---|
| 3315 |
|
|---|
| 3316 | for (snum = 0; snum < n_services; snum++) {
|
|---|
| 3317 | if (!(lp_snum_ok(snum) && lp_print_ok(snum)))
|
|---|
| 3318 | continue;
|
|---|
| 3319 |
|
|---|
| 3320 | if (W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2,
|
|---|
| 3321 | lp_servicename(snum))) &&
|
|---|
| 3322 | (printer->info_2->attributes & PRINTER_ATTRIBUTE_PUBLISHED))
|
|---|
| 3323 | nt_printer_publish_ads(ads, printer);
|
|---|
| 3324 |
|
|---|
| 3325 | free_a_printer(&printer, 2);
|
|---|
| 3326 | }
|
|---|
| 3327 |
|
|---|
| 3328 | ads_destroy(&ads);
|
|---|
| 3329 | ads_kdestroy("MEMORY:prtpub_cache");
|
|---|
| 3330 | return WERR_OK;
|
|---|
| 3331 | }
|
|---|
| 3332 |
|
|---|
| 3333 | bool is_printer_published(Printer_entry *print_hnd, int snum,
|
|---|
| 3334 | struct GUID *guid)
|
|---|
| 3335 | {
|
|---|
| 3336 | NT_PRINTER_INFO_LEVEL *printer = NULL;
|
|---|
| 3337 | struct regval_ctr *ctr;
|
|---|
| 3338 | struct regval_blob *guid_val;
|
|---|
| 3339 | WERROR win_rc;
|
|---|
| 3340 | int i;
|
|---|
| 3341 | bool ret = False;
|
|---|
| 3342 | DATA_BLOB blob;
|
|---|
| 3343 |
|
|---|
| 3344 | win_rc = get_a_printer(print_hnd, &printer, 2, lp_servicename(snum));
|
|---|
| 3345 |
|
|---|
| 3346 | if (!W_ERROR_IS_OK(win_rc) ||
|
|---|
| 3347 | !(printer->info_2->attributes & PRINTER_ATTRIBUTE_PUBLISHED) ||
|
|---|
| 3348 | ((i = lookup_printerkey(printer->info_2->data, SPOOL_DSSPOOLER_KEY)) < 0) ||
|
|---|
| 3349 | !(ctr = printer->info_2->data->keys[i].values) ||
|
|---|
| 3350 | !(guid_val = regval_ctr_getvalue(ctr, "objectGUID")))
|
|---|
| 3351 | {
|
|---|
| 3352 | free_a_printer(&printer, 2);
|
|---|
| 3353 | return False;
|
|---|
| 3354 | }
|
|---|
| 3355 |
|
|---|
| 3356 | /* fetching printer guids really ought to be a separate function. */
|
|---|
| 3357 |
|
|---|
| 3358 | if ( guid ) {
|
|---|
| 3359 | char *guid_str;
|
|---|
| 3360 |
|
|---|
| 3361 | /* We used to store the guid as REG_BINARY, then swapped
|
|---|
| 3362 | to REG_SZ for Vista compatibility so check for both */
|
|---|
| 3363 |
|
|---|
| 3364 | switch ( regval_type(guid_val) ){
|
|---|
| 3365 | case REG_SZ:
|
|---|
| 3366 | blob = data_blob_const(regval_data_p(guid_val),
|
|---|
| 3367 | regval_size(guid_val));
|
|---|
| 3368 | pull_reg_sz(talloc_tos(), &blob, (const char **)&guid_str);
|
|---|
| 3369 | ret = NT_STATUS_IS_OK(GUID_from_string( guid_str, guid ));
|
|---|
| 3370 | talloc_free(guid_str);
|
|---|
| 3371 | break;
|
|---|
| 3372 | case REG_BINARY:
|
|---|
| 3373 | if ( regval_size(guid_val) != sizeof(struct GUID) ) {
|
|---|
| 3374 | ret = False;
|
|---|
| 3375 | break;
|
|---|
| 3376 | }
|
|---|
| 3377 | memcpy(guid, regval_data_p(guid_val), sizeof(struct GUID));
|
|---|
| 3378 | break;
|
|---|
| 3379 | default:
|
|---|
| 3380 | DEBUG(0,("is_printer_published: GUID value stored as "
|
|---|
| 3381 | "invaluid type (%d)\n", regval_type(guid_val) ));
|
|---|
| 3382 | break;
|
|---|
| 3383 | }
|
|---|
| 3384 | }
|
|---|
| 3385 |
|
|---|
| 3386 | free_a_printer(&printer, 2);
|
|---|
| 3387 | return ret;
|
|---|
| 3388 | }
|
|---|
| 3389 | #else
|
|---|
| 3390 | WERROR nt_printer_publish(Printer_entry *print_hnd, int snum, int action)
|
|---|
| 3391 | {
|
|---|
| 3392 | return WERR_OK;
|
|---|
| 3393 | }
|
|---|
| 3394 |
|
|---|
| 3395 | WERROR check_published_printers(void)
|
|---|
| 3396 | {
|
|---|
| 3397 | return WERR_OK;
|
|---|
| 3398 | }
|
|---|
| 3399 |
|
|---|
| 3400 | bool is_printer_published(Printer_entry *print_hnd, int snum,
|
|---|
| 3401 | struct GUID *guid)
|
|---|
| 3402 | {
|
|---|
| 3403 | return False;
|
|---|
| 3404 | }
|
|---|
| 3405 | #endif /* HAVE_ADS */
|
|---|
| 3406 |
|
|---|
| 3407 | /****************************************************************************
|
|---|
| 3408 | ***************************************************************************/
|
|---|
| 3409 |
|
|---|
| 3410 | WERROR delete_all_printer_data( NT_PRINTER_INFO_LEVEL_2 *p2, const char *key )
|
|---|
| 3411 | {
|
|---|
| 3412 | NT_PRINTER_DATA *data;
|
|---|
| 3413 | int i;
|
|---|
| 3414 | int removed_keys = 0;
|
|---|
| 3415 | int empty_slot;
|
|---|
| 3416 |
|
|---|
| 3417 | data = p2->data;
|
|---|
| 3418 | empty_slot = data->num_keys;
|
|---|
| 3419 |
|
|---|
| 3420 | if ( !key )
|
|---|
| 3421 | return WERR_INVALID_PARAM;
|
|---|
| 3422 |
|
|---|
| 3423 | /* remove all keys */
|
|---|
| 3424 |
|
|---|
| 3425 | if ( !strlen(key) ) {
|
|---|
| 3426 |
|
|---|
| 3427 | TALLOC_FREE( data );
|
|---|
| 3428 |
|
|---|
| 3429 | p2->data = NULL;
|
|---|
| 3430 |
|
|---|
| 3431 | DEBUG(8,("delete_all_printer_data: Removed all Printer Data from printer [%s]\n",
|
|---|
| 3432 | p2->printername ));
|
|---|
| 3433 |
|
|---|
| 3434 | return WERR_OK;
|
|---|
| 3435 | }
|
|---|
| 3436 |
|
|---|
| 3437 | /* remove a specific key (and all subkeys) */
|
|---|
| 3438 |
|
|---|
| 3439 | for ( i=0; i<data->num_keys; i++ ) {
|
|---|
| 3440 | if ( StrnCaseCmp( data->keys[i].name, key, strlen(key)) == 0 ) {
|
|---|
| 3441 | DEBUG(8,("delete_all_printer_data: Removed all Printer Data from key [%s]\n",
|
|---|
| 3442 | data->keys[i].name));
|
|---|
| 3443 |
|
|---|
| 3444 | TALLOC_FREE( data->keys[i].name );
|
|---|
| 3445 | TALLOC_FREE( data->keys[i].values );
|
|---|
| 3446 |
|
|---|
| 3447 | /* mark the slot as empty */
|
|---|
| 3448 |
|
|---|
| 3449 | ZERO_STRUCTP( &data->keys[i] );
|
|---|
| 3450 | }
|
|---|
| 3451 | }
|
|---|
| 3452 |
|
|---|
| 3453 | /* find the first empty slot */
|
|---|
| 3454 |
|
|---|
| 3455 | for ( i=0; i<data->num_keys; i++ ) {
|
|---|
| 3456 | if ( !data->keys[i].name ) {
|
|---|
| 3457 | empty_slot = i;
|
|---|
| 3458 | removed_keys++;
|
|---|
| 3459 | break;
|
|---|
| 3460 | }
|
|---|
| 3461 | }
|
|---|
| 3462 |
|
|---|
| 3463 | if ( i == data->num_keys )
|
|---|
| 3464 | /* nothing was removed */
|
|---|
| 3465 | return WERR_INVALID_PARAM;
|
|---|
| 3466 |
|
|---|
| 3467 | /* move everything down */
|
|---|
| 3468 |
|
|---|
| 3469 | for ( i=empty_slot+1; i<data->num_keys; i++ ) {
|
|---|
| 3470 | if ( data->keys[i].name ) {
|
|---|
| 3471 | memcpy( &data->keys[empty_slot], &data->keys[i], sizeof(NT_PRINTER_KEY) );
|
|---|
| 3472 | ZERO_STRUCTP( &data->keys[i] );
|
|---|
| 3473 | empty_slot++;
|
|---|
| 3474 | removed_keys++;
|
|---|
| 3475 | }
|
|---|
| 3476 | }
|
|---|
| 3477 |
|
|---|
| 3478 | /* update count */
|
|---|
| 3479 |
|
|---|
| 3480 | data->num_keys -= removed_keys;
|
|---|
| 3481 |
|
|---|
| 3482 | /* sanity check to see if anything is left */
|
|---|
| 3483 |
|
|---|
| 3484 | if ( !data->num_keys ) {
|
|---|
| 3485 | DEBUG(8,("delete_all_printer_data: No keys left for printer [%s]\n", p2->printername ));
|
|---|
| 3486 |
|
|---|
| 3487 | SAFE_FREE( data->keys );
|
|---|
| 3488 | ZERO_STRUCTP( data );
|
|---|
| 3489 | }
|
|---|
| 3490 |
|
|---|
| 3491 | return WERR_OK;
|
|---|
| 3492 | }
|
|---|
| 3493 |
|
|---|
| 3494 | /****************************************************************************
|
|---|
| 3495 | ***************************************************************************/
|
|---|
| 3496 |
|
|---|
| 3497 | WERROR delete_printer_data( NT_PRINTER_INFO_LEVEL_2 *p2, const char *key, const char *value )
|
|---|
| 3498 | {
|
|---|
| 3499 | WERROR result = WERR_OK;
|
|---|
| 3500 | int key_index;
|
|---|
| 3501 |
|
|---|
| 3502 | /* we must have names on non-zero length */
|
|---|
| 3503 |
|
|---|
| 3504 | if ( !key || !*key|| !value || !*value )
|
|---|
| 3505 | return WERR_INVALID_NAME;
|
|---|
| 3506 |
|
|---|
| 3507 | /* find the printer key first */
|
|---|
| 3508 |
|
|---|
| 3509 | key_index = lookup_printerkey( p2->data, key );
|
|---|
| 3510 | if ( key_index == -1 )
|
|---|
| 3511 | return WERR_OK;
|
|---|
| 3512 |
|
|---|
| 3513 | /* make sure the value exists so we can return the correct error code */
|
|---|
| 3514 |
|
|---|
| 3515 | if ( !regval_ctr_getvalue( p2->data->keys[key_index].values, value ) )
|
|---|
| 3516 | return WERR_BADFILE;
|
|---|
| 3517 |
|
|---|
| 3518 | regval_ctr_delvalue( p2->data->keys[key_index].values, value );
|
|---|
| 3519 |
|
|---|
| 3520 | DEBUG(8,("delete_printer_data: Removed key => [%s], value => [%s]\n",
|
|---|
| 3521 | key, value ));
|
|---|
| 3522 |
|
|---|
| 3523 | return result;
|
|---|
| 3524 | }
|
|---|
| 3525 |
|
|---|
| 3526 | /****************************************************************************
|
|---|
| 3527 | ***************************************************************************/
|
|---|
| 3528 |
|
|---|
| 3529 | WERROR add_printer_data( NT_PRINTER_INFO_LEVEL_2 *p2, const char *key, const char *value,
|
|---|
| 3530 | uint32 type, uint8 *data, int real_len )
|
|---|
| 3531 | {
|
|---|
| 3532 | WERROR result = WERR_OK;
|
|---|
| 3533 | int key_index;
|
|---|
| 3534 |
|
|---|
| 3535 | /* we must have names on non-zero length */
|
|---|
| 3536 |
|
|---|
| 3537 | if ( !key || !*key|| !value || !*value )
|
|---|
| 3538 | return WERR_INVALID_NAME;
|
|---|
| 3539 |
|
|---|
| 3540 | /* find the printer key first */
|
|---|
| 3541 |
|
|---|
| 3542 | key_index = lookup_printerkey( p2->data, key );
|
|---|
| 3543 | if ( key_index == -1 )
|
|---|
| 3544 | key_index = add_new_printer_key( p2->data, key );
|
|---|
| 3545 |
|
|---|
| 3546 | if ( key_index == -1 )
|
|---|
| 3547 | return WERR_NOMEM;
|
|---|
| 3548 |
|
|---|
| 3549 | regval_ctr_addvalue( p2->data->keys[key_index].values, value,
|
|---|
| 3550 | type, (const char *)data, real_len );
|
|---|
| 3551 |
|
|---|
| 3552 | DEBUG(8,("add_printer_data: Added key => [%s], value => [%s], type=> [%d], size => [%d]\n",
|
|---|
| 3553 | key, value, type, real_len ));
|
|---|
| 3554 |
|
|---|
| 3555 | return result;
|
|---|
| 3556 | }
|
|---|
| 3557 |
|
|---|
| 3558 | /****************************************************************************
|
|---|
| 3559 | ***************************************************************************/
|
|---|
| 3560 |
|
|---|
| 3561 | struct regval_blob* get_printer_data( NT_PRINTER_INFO_LEVEL_2 *p2, const char *key, const char *value )
|
|---|
| 3562 | {
|
|---|
| 3563 | int key_index;
|
|---|
| 3564 |
|
|---|
| 3565 | if ( (key_index = lookup_printerkey( p2->data, key )) == -1 )
|
|---|
| 3566 | return NULL;
|
|---|
| 3567 |
|
|---|
| 3568 | DEBUG(8,("get_printer_data: Attempting to lookup key => [%s], value => [%s]\n",
|
|---|
| 3569 | key, value ));
|
|---|
| 3570 |
|
|---|
| 3571 | return regval_ctr_getvalue( p2->data->keys[key_index].values, value );
|
|---|
| 3572 | }
|
|---|
| 3573 |
|
|---|
| 3574 | /****************************************************************************
|
|---|
| 3575 | Unpack a list of registry values frem the TDB
|
|---|
| 3576 | ***************************************************************************/
|
|---|
| 3577 |
|
|---|
| 3578 | static int unpack_values(NT_PRINTER_DATA *printer_data, const uint8 *buf, int buflen)
|
|---|
| 3579 | {
|
|---|
| 3580 | int len = 0;
|
|---|
| 3581 | uint32 type;
|
|---|
| 3582 | fstring string;
|
|---|
| 3583 | const char *valuename = NULL;
|
|---|
| 3584 | const char *keyname = NULL;
|
|---|
| 3585 | char *str;
|
|---|
| 3586 | int size;
|
|---|
| 3587 | uint8 *data_p;
|
|---|
| 3588 | struct regval_blob *regval_p;
|
|---|
| 3589 | int key_index;
|
|---|
| 3590 |
|
|---|
| 3591 | /* add the "PrinterDriverData" key first for performance reasons */
|
|---|
| 3592 |
|
|---|
| 3593 | add_new_printer_key( printer_data, SPOOL_PRINTERDATA_KEY );
|
|---|
| 3594 |
|
|---|
| 3595 | /* loop and unpack the rest of the registry values */
|
|---|
| 3596 |
|
|---|
| 3597 | while ( True ) {
|
|---|
| 3598 |
|
|---|
| 3599 | /* check to see if there are any more registry values */
|
|---|
| 3600 |
|
|---|
| 3601 | regval_p = NULL;
|
|---|
| 3602 | len += tdb_unpack(buf+len, buflen-len, "p", ®val_p);
|
|---|
| 3603 | if ( !regval_p )
|
|---|
| 3604 | break;
|
|---|
| 3605 |
|
|---|
| 3606 | /* unpack the next regval */
|
|---|
| 3607 |
|
|---|
| 3608 | len += tdb_unpack(buf+len, buflen-len, "fdB",
|
|---|
| 3609 | string,
|
|---|
| 3610 | &type,
|
|---|
| 3611 | &size,
|
|---|
| 3612 | &data_p);
|
|---|
| 3613 |
|
|---|
| 3614 | /* lookup for subkey names which have a type of REG_NONE */
|
|---|
| 3615 | /* there's no data with this entry */
|
|---|
| 3616 |
|
|---|
| 3617 | if ( type == REG_NONE ) {
|
|---|
| 3618 | if ( (key_index=lookup_printerkey( printer_data, string)) == -1 )
|
|---|
| 3619 | add_new_printer_key( printer_data, string );
|
|---|
| 3620 | continue;
|
|---|
| 3621 | }
|
|---|
| 3622 |
|
|---|
| 3623 | /*
|
|---|
| 3624 | * break of the keyname from the value name.
|
|---|
| 3625 | * Valuenames can have embedded '\'s so be careful.
|
|---|
| 3626 | * only support one level of keys. See the
|
|---|
| 3627 | * "Konica Fiery S300 50C-K v1.1. enu" 2k driver.
|
|---|
| 3628 | * -- jerry
|
|---|
| 3629 | */
|
|---|
| 3630 |
|
|---|
| 3631 | str = strchr_m( string, '\\');
|
|---|
| 3632 |
|
|---|
| 3633 | /* Put in "PrinterDriverData" is no key specified */
|
|---|
| 3634 |
|
|---|
| 3635 | if ( !str ) {
|
|---|
| 3636 | keyname = SPOOL_PRINTERDATA_KEY;
|
|---|
| 3637 | valuename = string;
|
|---|
| 3638 | }
|
|---|
| 3639 | else {
|
|---|
| 3640 | *str = '\0';
|
|---|
| 3641 | keyname = string;
|
|---|
| 3642 | valuename = str+1;
|
|---|
| 3643 | }
|
|---|
| 3644 |
|
|---|
| 3645 | /* see if we need a new key */
|
|---|
| 3646 |
|
|---|
| 3647 | if ( (key_index=lookup_printerkey( printer_data, keyname )) == -1 )
|
|---|
| 3648 | key_index = add_new_printer_key( printer_data, keyname );
|
|---|
| 3649 |
|
|---|
| 3650 | if ( key_index == -1 ) {
|
|---|
| 3651 | DEBUG(0,("unpack_values: Failed to allocate a new key [%s]!\n",
|
|---|
| 3652 | keyname));
|
|---|
| 3653 | break;
|
|---|
| 3654 | }
|
|---|
| 3655 |
|
|---|
| 3656 | DEBUG(8,("specific: [%s:%s], len: %d\n", keyname, valuename, size));
|
|---|
| 3657 |
|
|---|
| 3658 | /* Vista doesn't like unknown REG_BINARY values in DsSpooler.
|
|---|
| 3659 | Thanks to Martin Zielinski for the hint. */
|
|---|
| 3660 |
|
|---|
| 3661 | if ( type == REG_BINARY &&
|
|---|
| 3662 | strequal( keyname, SPOOL_DSSPOOLER_KEY ) &&
|
|---|
| 3663 | strequal( valuename, "objectGUID" ) )
|
|---|
| 3664 | {
|
|---|
| 3665 | struct GUID guid;
|
|---|
| 3666 |
|
|---|
| 3667 | /* convert the GUID to a UNICODE string */
|
|---|
| 3668 |
|
|---|
| 3669 | memcpy( &guid, data_p, sizeof(struct GUID) );
|
|---|
| 3670 |
|
|---|
| 3671 | regval_ctr_addvalue_sz(printer_data->keys[key_index].values,
|
|---|
| 3672 | valuename,
|
|---|
| 3673 | GUID_string(talloc_tos(), &guid));
|
|---|
| 3674 |
|
|---|
| 3675 | } else {
|
|---|
| 3676 | /* add the value */
|
|---|
| 3677 |
|
|---|
| 3678 | regval_ctr_addvalue( printer_data->keys[key_index].values,
|
|---|
| 3679 | valuename, type, (const char *)data_p,
|
|---|
| 3680 | size );
|
|---|
| 3681 | }
|
|---|
| 3682 |
|
|---|
| 3683 | SAFE_FREE(data_p); /* 'B' option to tdbpack does a malloc() */
|
|---|
| 3684 |
|
|---|
| 3685 | }
|
|---|
| 3686 |
|
|---|
| 3687 | return len;
|
|---|
| 3688 | }
|
|---|
| 3689 |
|
|---|
| 3690 | /****************************************************************************
|
|---|
| 3691 | ***************************************************************************/
|
|---|
| 3692 |
|
|---|
| 3693 | static char *last_from;
|
|---|
| 3694 | static char *last_to;
|
|---|
| 3695 |
|
|---|
| 3696 | static const char *get_last_from(void)
|
|---|
| 3697 | {
|
|---|
| 3698 | if (!last_from) {
|
|---|
| 3699 | return "";
|
|---|
| 3700 | }
|
|---|
| 3701 | return last_from;
|
|---|
| 3702 | }
|
|---|
| 3703 |
|
|---|
| 3704 | static const char *get_last_to(void)
|
|---|
| 3705 | {
|
|---|
| 3706 | if (!last_to) {
|
|---|
| 3707 | return "";
|
|---|
| 3708 | }
|
|---|
| 3709 | return last_to;
|
|---|
| 3710 | }
|
|---|
| 3711 |
|
|---|
| 3712 | static bool set_last_from_to(const char *from, const char *to)
|
|---|
| 3713 | {
|
|---|
| 3714 | char *orig_from = last_from;
|
|---|
| 3715 | char *orig_to = last_to;
|
|---|
| 3716 |
|
|---|
| 3717 | last_from = SMB_STRDUP(from);
|
|---|
| 3718 | last_to = SMB_STRDUP(to);
|
|---|
| 3719 |
|
|---|
| 3720 | SAFE_FREE(orig_from);
|
|---|
| 3721 | SAFE_FREE(orig_to);
|
|---|
| 3722 |
|
|---|
| 3723 | if (!last_from || !last_to) {
|
|---|
| 3724 | SAFE_FREE(last_from);
|
|---|
| 3725 | SAFE_FREE(last_to);
|
|---|
| 3726 | return false;
|
|---|
| 3727 | }
|
|---|
| 3728 | return true;
|
|---|
| 3729 | }
|
|---|
| 3730 |
|
|---|
| 3731 | static void map_to_os2_driver(fstring drivername)
|
|---|
| 3732 | {
|
|---|
| 3733 | char *mapfile = lp_os2_driver_map();
|
|---|
| 3734 | char **lines = NULL;
|
|---|
| 3735 | int numlines = 0;
|
|---|
| 3736 | int i;
|
|---|
| 3737 |
|
|---|
| 3738 | if (!strlen(drivername))
|
|---|
| 3739 | return;
|
|---|
| 3740 |
|
|---|
| 3741 | if (!*mapfile)
|
|---|
| 3742 | return;
|
|---|
| 3743 |
|
|---|
| 3744 | if (strequal(drivername,get_last_from())) {
|
|---|
| 3745 | DEBUG(3,("Mapped Windows driver %s to OS/2 driver %s\n",
|
|---|
| 3746 | drivername,get_last_to()));
|
|---|
| 3747 | fstrcpy(drivername,get_last_to());
|
|---|
| 3748 | return;
|
|---|
| 3749 | }
|
|---|
| 3750 |
|
|---|
| 3751 | lines = file_lines_load(mapfile, &numlines,0,NULL);
|
|---|
| 3752 | if (numlines == 0 || lines == NULL) {
|
|---|
| 3753 | DEBUG(0,("No entries in OS/2 driver map %s\n",mapfile));
|
|---|
| 3754 | TALLOC_FREE(lines);
|
|---|
| 3755 | return;
|
|---|
| 3756 | }
|
|---|
| 3757 |
|
|---|
| 3758 | DEBUG(4,("Scanning OS/2 driver map %s\n",mapfile));
|
|---|
| 3759 |
|
|---|
| 3760 | for( i = 0; i < numlines; i++) {
|
|---|
| 3761 | char *nt_name = lines[i];
|
|---|
| 3762 | char *os2_name = strchr(nt_name,'=');
|
|---|
| 3763 |
|
|---|
| 3764 | if (!os2_name)
|
|---|
| 3765 | continue;
|
|---|
| 3766 |
|
|---|
| 3767 | *os2_name++ = 0;
|
|---|
| 3768 |
|
|---|
| 3769 | while (isspace(*nt_name))
|
|---|
| 3770 | nt_name++;
|
|---|
| 3771 |
|
|---|
| 3772 | if (!*nt_name || strchr("#;",*nt_name))
|
|---|
| 3773 | continue;
|
|---|
| 3774 |
|
|---|
| 3775 | {
|
|---|
| 3776 | int l = strlen(nt_name);
|
|---|
| 3777 | while (l && isspace(nt_name[l-1])) {
|
|---|
| 3778 | nt_name[l-1] = 0;
|
|---|
| 3779 | l--;
|
|---|
| 3780 | }
|
|---|
| 3781 | }
|
|---|
| 3782 |
|
|---|
| 3783 | while (isspace(*os2_name))
|
|---|
| 3784 | os2_name++;
|
|---|
| 3785 |
|
|---|
| 3786 | {
|
|---|
| 3787 | int l = strlen(os2_name);
|
|---|
| 3788 | while (l && isspace(os2_name[l-1])) {
|
|---|
| 3789 | os2_name[l-1] = 0;
|
|---|
| 3790 | l--;
|
|---|
| 3791 | }
|
|---|
| 3792 | }
|
|---|
| 3793 |
|
|---|
| 3794 | if (strequal(nt_name,drivername)) {
|
|---|
| 3795 | DEBUG(3,("Mapped windows driver %s to os2 driver%s\n",drivername,os2_name));
|
|---|
| 3796 | set_last_from_to(drivername,os2_name);
|
|---|
| 3797 | fstrcpy(drivername,os2_name);
|
|---|
| 3798 | TALLOC_FREE(lines);
|
|---|
| 3799 | return;
|
|---|
| 3800 | }
|
|---|
| 3801 | }
|
|---|
| 3802 |
|
|---|
| 3803 | TALLOC_FREE(lines);
|
|---|
| 3804 | }
|
|---|
| 3805 |
|
|---|
| 3806 | /****************************************************************************
|
|---|
| 3807 | Get a default printer info 2 struct.
|
|---|
| 3808 | ****************************************************************************/
|
|---|
| 3809 |
|
|---|
| 3810 | static WERROR get_a_printer_2_default(NT_PRINTER_INFO_LEVEL_2 *info,
|
|---|
| 3811 | const char *servername,
|
|---|
| 3812 | const char* sharename,
|
|---|
| 3813 | bool get_loc_com)
|
|---|
| 3814 | {
|
|---|
| 3815 | int snum = lp_servicenumber(sharename);
|
|---|
| 3816 |
|
|---|
| 3817 | slprintf(info->servername, sizeof(info->servername)-1, "\\\\%s", servername);
|
|---|
| 3818 | slprintf(info->printername, sizeof(info->printername)-1, "\\\\%s\\%s",
|
|---|
| 3819 | servername, sharename);
|
|---|
| 3820 | fstrcpy(info->sharename, sharename);
|
|---|
| 3821 | fstrcpy(info->portname, SAMBA_PRINTER_PORT_NAME);
|
|---|
| 3822 |
|
|---|
| 3823 | /* by setting the driver name to an empty string, a local NT admin
|
|---|
| 3824 | can now run the **local** APW to install a local printer driver
|
|---|
| 3825 | for a Samba shared printer in 2.2. Without this, drivers **must** be
|
|---|
| 3826 | installed on the Samba server for NT clients --jerry */
|
|---|
| 3827 | #if 0 /* JERRY --do not uncomment-- */
|
|---|
| 3828 | if (!*info->drivername)
|
|---|
| 3829 | fstrcpy(info->drivername, "NO DRIVER AVAILABLE FOR THIS PRINTER");
|
|---|
| 3830 | #endif
|
|---|
| 3831 |
|
|---|
| 3832 |
|
|---|
| 3833 | DEBUG(10,("get_a_printer_2_default: driver name set to [%s]\n", info->drivername));
|
|---|
| 3834 |
|
|---|
| 3835 | strlcpy(info->comment, "", sizeof(info->comment));
|
|---|
| 3836 | fstrcpy(info->printprocessor, "winprint");
|
|---|
| 3837 | fstrcpy(info->datatype, "RAW");
|
|---|
| 3838 |
|
|---|
| 3839 | #ifdef HAVE_CUPS
|
|---|
| 3840 | if (get_loc_com && (enum printing_types)lp_printing(snum) == PRINT_CUPS ) {
|
|---|
| 3841 | /* Pull the location and comment strings from cups if we don't
|
|---|
| 3842 | already have one */
|
|---|
| 3843 | if ( !strlen(info->location) || !strlen(info->comment) )
|
|---|
| 3844 | cups_pull_comment_location( info );
|
|---|
| 3845 | }
|
|---|
| 3846 | #endif
|
|---|
| 3847 |
|
|---|
| 3848 | info->attributes = PRINTER_ATTRIBUTE_SAMBA;
|
|---|
| 3849 |
|
|---|
| 3850 | info->starttime = 0; /* Minutes since 12:00am GMT */
|
|---|
| 3851 | info->untiltime = 0; /* Minutes since 12:00am GMT */
|
|---|
| 3852 | info->priority = 1;
|
|---|
| 3853 | info->default_priority = 1;
|
|---|
| 3854 | info->setuptime = (uint32)time(NULL);
|
|---|
| 3855 |
|
|---|
| 3856 | /*
|
|---|
| 3857 | * I changed this as I think it is better to have a generic
|
|---|
| 3858 | * DEVMODE than to crash Win2k explorer.exe --jerry
|
|---|
| 3859 | * See the HP Deskjet 990c Win2k drivers for an example.
|
|---|
| 3860 | *
|
|---|
| 3861 | * However the default devmode appears to cause problems
|
|---|
| 3862 | * with the HP CLJ 8500 PCL driver. Hence the addition of
|
|---|
| 3863 | * the "default devmode" parameter --jerry 22/01/2002
|
|---|
| 3864 | */
|
|---|
| 3865 |
|
|---|
| 3866 | if (lp_default_devmode(snum)) {
|
|---|
| 3867 | if ((info->devmode = construct_nt_devicemode(info->printername)) == NULL) {
|
|---|
| 3868 | goto fail;
|
|---|
| 3869 | }
|
|---|
| 3870 | } else {
|
|---|
| 3871 | info->devmode = NULL;
|
|---|
| 3872 | }
|
|---|
| 3873 |
|
|---|
| 3874 | if (!nt_printing_getsec(info, sharename, &info->secdesc_buf)) {
|
|---|
| 3875 | goto fail;
|
|---|
| 3876 | }
|
|---|
| 3877 |
|
|---|
| 3878 | info->data = TALLOC_ZERO_P(info, NT_PRINTER_DATA);
|
|---|
| 3879 | if (!info->data) {
|
|---|
| 3880 | goto fail;
|
|---|
| 3881 | }
|
|---|
| 3882 |
|
|---|
| 3883 | add_new_printer_key(info->data, SPOOL_PRINTERDATA_KEY);
|
|---|
| 3884 |
|
|---|
| 3885 | return WERR_OK;
|
|---|
| 3886 |
|
|---|
| 3887 | fail:
|
|---|
| 3888 | if (info->devmode)
|
|---|
| 3889 | free_nt_devicemode(&info->devmode);
|
|---|
| 3890 |
|
|---|
| 3891 | return WERR_ACCESS_DENIED;
|
|---|
| 3892 | }
|
|---|
| 3893 |
|
|---|
| 3894 | /****************************************************************************
|
|---|
| 3895 | ****************************************************************************/
|
|---|
| 3896 |
|
|---|
| 3897 | static WERROR get_a_printer_2(NT_PRINTER_INFO_LEVEL_2 *info,
|
|---|
| 3898 | const char *servername,
|
|---|
| 3899 | const char *sharename,
|
|---|
| 3900 | bool get_loc_com)
|
|---|
| 3901 | {
|
|---|
| 3902 | int len = 0;
|
|---|
| 3903 | int snum = lp_servicenumber(sharename);
|
|---|
| 3904 | TDB_DATA kbuf, dbuf;
|
|---|
| 3905 | fstring printername;
|
|---|
| 3906 | char adevice[MAXDEVICENAME];
|
|---|
| 3907 | char *comment = NULL;
|
|---|
| 3908 |
|
|---|
| 3909 | kbuf = make_printer_tdbkey(talloc_tos(), sharename);
|
|---|
| 3910 |
|
|---|
| 3911 | dbuf = tdb_fetch(tdb_printers, kbuf);
|
|---|
| 3912 | if (!dbuf.dptr) {
|
|---|
| 3913 | return get_a_printer_2_default(info, servername,
|
|---|
| 3914 | sharename, get_loc_com);
|
|---|
| 3915 | }
|
|---|
| 3916 |
|
|---|
| 3917 | len += tdb_unpack(dbuf.dptr+len, dbuf.dsize-len, "dddddddddddfffffPfffff",
|
|---|
| 3918 | &info->attributes,
|
|---|
| 3919 | &info->priority,
|
|---|
| 3920 | &info->default_priority,
|
|---|
| 3921 | &info->starttime,
|
|---|
| 3922 | &info->untiltime,
|
|---|
| 3923 | &info->status,
|
|---|
| 3924 | &info->cjobs,
|
|---|
| 3925 | &info->averageppm,
|
|---|
| 3926 | &info->changeid,
|
|---|
| 3927 | &info->c_setprinter,
|
|---|
| 3928 | &info->setuptime,
|
|---|
| 3929 | info->servername,
|
|---|
| 3930 | info->printername,
|
|---|
| 3931 | info->sharename,
|
|---|
| 3932 | info->portname,
|
|---|
| 3933 | info->drivername,
|
|---|
| 3934 | &comment,
|
|---|
| 3935 | info->location,
|
|---|
| 3936 | info->sepfile,
|
|---|
| 3937 | info->printprocessor,
|
|---|
| 3938 | info->datatype,
|
|---|
| 3939 | info->parameters);
|
|---|
| 3940 |
|
|---|
| 3941 | if (comment) {
|
|---|
| 3942 | strlcpy(info->comment, comment, sizeof(info->comment));
|
|---|
| 3943 | SAFE_FREE(comment);
|
|---|
| 3944 | }
|
|---|
| 3945 |
|
|---|
| 3946 | /* Samba has to have shared raw drivers. */
|
|---|
| 3947 | info->attributes |= PRINTER_ATTRIBUTE_SAMBA;
|
|---|
| 3948 | info->attributes &= ~PRINTER_ATTRIBUTE_NOT_SAMBA;
|
|---|
| 3949 |
|
|---|
| 3950 | /* Restore the stripped strings. */
|
|---|
| 3951 | slprintf(info->servername, sizeof(info->servername)-1, "\\\\%s", servername);
|
|---|
| 3952 |
|
|---|
| 3953 | if ( lp_force_printername(snum) ) {
|
|---|
| 3954 | slprintf(printername, sizeof(printername)-1, "\\\\%s\\%s", servername, sharename );
|
|---|
| 3955 | } else {
|
|---|
| 3956 | slprintf(printername, sizeof(printername)-1, "\\\\%s\\%s", servername, info->printername);
|
|---|
| 3957 | }
|
|---|
| 3958 |
|
|---|
| 3959 | fstrcpy(info->printername, printername);
|
|---|
| 3960 |
|
|---|
| 3961 | #ifdef HAVE_CUPS
|
|---|
| 3962 | if (get_loc_com && (enum printing_types)lp_printing(snum) == PRINT_CUPS ) {
|
|---|
| 3963 | /* Pull the location and comment strings from cups if we don't
|
|---|
| 3964 | already have one */
|
|---|
| 3965 | if ( !strlen(info->location) || !strlen(info->comment) )
|
|---|
| 3966 | cups_pull_comment_location( info );
|
|---|
| 3967 | }
|
|---|
| 3968 | #endif
|
|---|
| 3969 |
|
|---|
| 3970 | len += unpack_devicemode(&info->devmode,dbuf.dptr+len, dbuf.dsize-len);
|
|---|
| 3971 |
|
|---|
| 3972 | /*
|
|---|
| 3973 | * Some client drivers freak out if there is a NULL devmode
|
|---|
| 3974 | * (probably the driver is not checking before accessing
|
|---|
| 3975 | * the devmode pointer) --jerry
|
|---|
| 3976 | *
|
|---|
| 3977 | * See comments in get_a_printer_2_default()
|
|---|
| 3978 | */
|
|---|
| 3979 |
|
|---|
| 3980 | if (lp_default_devmode(snum) && !info->devmode) {
|
|---|
| 3981 | DEBUG(8,("get_a_printer_2: Constructing a default device mode for [%s]\n",
|
|---|
| 3982 | printername));
|
|---|
| 3983 | info->devmode = construct_nt_devicemode(printername);
|
|---|
| 3984 | }
|
|---|
| 3985 |
|
|---|
| 3986 | slprintf( adevice, sizeof(adevice), "%s", info->printername );
|
|---|
| 3987 | if (info->devmode) {
|
|---|
| 3988 | fstrcpy(info->devmode->devicename, adevice);
|
|---|
| 3989 | }
|
|---|
| 3990 |
|
|---|
| 3991 | if ( !(info->data = TALLOC_ZERO_P( info, NT_PRINTER_DATA )) ) {
|
|---|
| 3992 | DEBUG(0,("unpack_values: talloc() failed!\n"));
|
|---|
| 3993 | SAFE_FREE(dbuf.dptr);
|
|---|
| 3994 | return WERR_NOMEM;
|
|---|
| 3995 | }
|
|---|
| 3996 | len += unpack_values( info->data, dbuf.dptr+len, dbuf.dsize-len );
|
|---|
| 3997 |
|
|---|
| 3998 | /* This will get the current RPC talloc context, but we should be
|
|---|
| 3999 | passing this as a parameter... fixme... JRA ! */
|
|---|
| 4000 |
|
|---|
| 4001 | if (!nt_printing_getsec(info, sharename, &info->secdesc_buf)) {
|
|---|
| 4002 | SAFE_FREE(dbuf.dptr);
|
|---|
| 4003 | return WERR_NOMEM;
|
|---|
| 4004 | }
|
|---|
| 4005 |
|
|---|
| 4006 | /* Fix for OS/2 drivers. */
|
|---|
| 4007 |
|
|---|
| 4008 | if (get_remote_arch() == RA_OS2) {
|
|---|
| 4009 | map_to_os2_driver(info->drivername);
|
|---|
| 4010 | }
|
|---|
| 4011 |
|
|---|
| 4012 | SAFE_FREE(dbuf.dptr);
|
|---|
| 4013 |
|
|---|
| 4014 | DEBUG(9,("Unpacked printer [%s] name [%s] running driver [%s]\n",
|
|---|
| 4015 | sharename, info->printername, info->drivername));
|
|---|
| 4016 |
|
|---|
| 4017 | return WERR_OK;
|
|---|
| 4018 | }
|
|---|
| 4019 |
|
|---|
| 4020 | /****************************************************************************
|
|---|
| 4021 | Debugging function, dump at level 6 the struct in the logs.
|
|---|
| 4022 | ****************************************************************************/
|
|---|
| 4023 | static uint32 dump_a_printer(NT_PRINTER_INFO_LEVEL *printer, uint32 level)
|
|---|
| 4024 | {
|
|---|
| 4025 | uint32 result;
|
|---|
| 4026 | NT_PRINTER_INFO_LEVEL_2 *info2;
|
|---|
| 4027 |
|
|---|
| 4028 | DEBUG(106,("Dumping printer at level [%d]\n", level));
|
|---|
| 4029 |
|
|---|
| 4030 | switch (level) {
|
|---|
| 4031 | case 2:
|
|---|
| 4032 | {
|
|---|
| 4033 | if (printer->info_2 == NULL)
|
|---|
| 4034 | result=5;
|
|---|
| 4035 | else
|
|---|
| 4036 | {
|
|---|
| 4037 | info2=printer->info_2;
|
|---|
| 4038 |
|
|---|
| 4039 | DEBUGADD(106,("attributes:[%d]\n", info2->attributes));
|
|---|
| 4040 | DEBUGADD(106,("priority:[%d]\n", info2->priority));
|
|---|
| 4041 | DEBUGADD(106,("default_priority:[%d]\n", info2->default_priority));
|
|---|
| 4042 | DEBUGADD(106,("starttime:[%d]\n", info2->starttime));
|
|---|
| 4043 | DEBUGADD(106,("untiltime:[%d]\n", info2->untiltime));
|
|---|
| 4044 | DEBUGADD(106,("status:[%d]\n", info2->status));
|
|---|
| 4045 | DEBUGADD(106,("cjobs:[%d]\n", info2->cjobs));
|
|---|
| 4046 | DEBUGADD(106,("averageppm:[%d]\n", info2->averageppm));
|
|---|
| 4047 | DEBUGADD(106,("changeid:[%d]\n", info2->changeid));
|
|---|
| 4048 | DEBUGADD(106,("c_setprinter:[%d]\n", info2->c_setprinter));
|
|---|
| 4049 | DEBUGADD(106,("setuptime:[%d]\n", info2->setuptime));
|
|---|
| 4050 |
|
|---|
| 4051 | DEBUGADD(106,("servername:[%s]\n", info2->servername));
|
|---|
| 4052 | DEBUGADD(106,("printername:[%s]\n", info2->printername));
|
|---|
| 4053 | DEBUGADD(106,("sharename:[%s]\n", info2->sharename));
|
|---|
| 4054 | DEBUGADD(106,("portname:[%s]\n", info2->portname));
|
|---|
| 4055 | DEBUGADD(106,("drivername:[%s]\n", info2->drivername));
|
|---|
| 4056 | DEBUGADD(106,("comment:[%s]\n", info2->comment));
|
|---|
| 4057 | DEBUGADD(106,("location:[%s]\n", info2->location));
|
|---|
| 4058 | DEBUGADD(106,("sepfile:[%s]\n", info2->sepfile));
|
|---|
| 4059 | DEBUGADD(106,("printprocessor:[%s]\n", info2->printprocessor));
|
|---|
| 4060 | DEBUGADD(106,("datatype:[%s]\n", info2->datatype));
|
|---|
| 4061 | DEBUGADD(106,("parameters:[%s]\n", info2->parameters));
|
|---|
| 4062 | result=0;
|
|---|
| 4063 | }
|
|---|
| 4064 | break;
|
|---|
| 4065 | }
|
|---|
| 4066 | default:
|
|---|
| 4067 | DEBUGADD(106,("dump_a_printer: Level %u not implemented\n", (unsigned int)level ));
|
|---|
| 4068 | result=1;
|
|---|
| 4069 | break;
|
|---|
| 4070 | }
|
|---|
| 4071 |
|
|---|
| 4072 | return result;
|
|---|
| 4073 | }
|
|---|
| 4074 |
|
|---|
| 4075 | /****************************************************************************
|
|---|
| 4076 | Update the changeid time.
|
|---|
| 4077 | This is SO NASTY as some drivers need this to change, others need it
|
|---|
| 4078 | static. This value will change every second, and I must hope that this
|
|---|
| 4079 | is enough..... DON'T CHANGE THIS CODE WITHOUT A TEST MATRIX THE SIZE OF
|
|---|
| 4080 | UTAH ! JRA.
|
|---|
| 4081 | ****************************************************************************/
|
|---|
| 4082 |
|
|---|
| 4083 | static uint32 rev_changeid(void)
|
|---|
| 4084 | {
|
|---|
| 4085 | struct timeval tv;
|
|---|
| 4086 |
|
|---|
| 4087 | get_process_uptime(&tv);
|
|---|
| 4088 |
|
|---|
| 4089 | #if 1 /* JERRY */
|
|---|
| 4090 | /* Return changeid as msec since spooler restart */
|
|---|
| 4091 | return tv.tv_sec * 1000 + tv.tv_usec / 1000;
|
|---|
| 4092 | #else
|
|---|
| 4093 | /*
|
|---|
| 4094 | * This setting seems to work well but is too untested
|
|---|
| 4095 | * to replace the above calculation. Left in for experiementation
|
|---|
| 4096 | * of the reader --jerry (Tue Mar 12 09:15:05 CST 2002)
|
|---|
| 4097 | */
|
|---|
| 4098 | return tv.tv_sec * 10 + tv.tv_usec / 100000;
|
|---|
| 4099 | #endif
|
|---|
| 4100 | }
|
|---|
| 4101 |
|
|---|
| 4102 |
|
|---|
| 4103 | /*
|
|---|
| 4104 | * The function below are the high level ones.
|
|---|
| 4105 | * only those ones must be called from the spoolss code.
|
|---|
| 4106 | * JFM.
|
|---|
| 4107 | */
|
|---|
| 4108 |
|
|---|
| 4109 | /****************************************************************************
|
|---|
| 4110 | Modify a printer. This is called from SETPRINTERDATA/DELETEPRINTERDATA.
|
|---|
| 4111 | ****************************************************************************/
|
|---|
| 4112 |
|
|---|
| 4113 | WERROR mod_a_printer(NT_PRINTER_INFO_LEVEL *printer, uint32 level)
|
|---|
| 4114 | {
|
|---|
| 4115 | WERROR result;
|
|---|
| 4116 |
|
|---|
| 4117 | dump_a_printer(printer, level);
|
|---|
| 4118 |
|
|---|
| 4119 | switch (level) {
|
|---|
| 4120 | case 2:
|
|---|
| 4121 | {
|
|---|
| 4122 | /*
|
|---|
| 4123 | * Update the changestamp. Emperical tests show that the
|
|---|
| 4124 | * ChangeID is always updated,but c_setprinter is
|
|---|
| 4125 | * global spooler variable (not per printer).
|
|---|
| 4126 | */
|
|---|
| 4127 |
|
|---|
| 4128 | /* ChangeID **must** be increasing over the lifetime
|
|---|
| 4129 | of client's spoolss service in order for the
|
|---|
| 4130 | client's cache to show updates */
|
|---|
| 4131 |
|
|---|
| 4132 | printer->info_2->changeid = rev_changeid();
|
|---|
| 4133 |
|
|---|
| 4134 | /*
|
|---|
| 4135 | * Because one day someone will ask:
|
|---|
| 4136 | * NT->NT An admin connection to a remote
|
|---|
| 4137 | * printer show changes imeediately in
|
|---|
| 4138 | * the properities dialog
|
|---|
| 4139 | *
|
|---|
| 4140 | * A non-admin connection will only show the
|
|---|
| 4141 | * changes after viewing the properites page
|
|---|
| 4142 | * 2 times. Seems to be related to a
|
|---|
| 4143 | * race condition in the client between the spooler
|
|---|
| 4144 | * updating the local cache and the Explorer.exe GUI
|
|---|
| 4145 | * actually displaying the properties.
|
|---|
| 4146 | *
|
|---|
| 4147 | * This is fixed in Win2k. admin/non-admin
|
|---|
| 4148 | * connections both display changes immediately.
|
|---|
| 4149 | *
|
|---|
| 4150 | * 14/12/01 --jerry
|
|---|
| 4151 | */
|
|---|
| 4152 |
|
|---|
| 4153 | result=update_a_printer_2(printer->info_2);
|
|---|
| 4154 | break;
|
|---|
| 4155 | }
|
|---|
| 4156 | default:
|
|---|
| 4157 | result=WERR_UNKNOWN_LEVEL;
|
|---|
| 4158 | break;
|
|---|
| 4159 | }
|
|---|
| 4160 |
|
|---|
| 4161 | return result;
|
|---|
| 4162 | }
|
|---|
| 4163 |
|
|---|
| 4164 | /****************************************************************************
|
|---|
| 4165 | Initialize printer devmode & data with previously saved driver init values.
|
|---|
| 4166 | ****************************************************************************/
|
|---|
| 4167 |
|
|---|
| 4168 | static bool set_driver_init_2( NT_PRINTER_INFO_LEVEL_2 *info_ptr )
|
|---|
| 4169 | {
|
|---|
| 4170 | int len = 0;
|
|---|
| 4171 | char *key = NULL;
|
|---|
| 4172 | TDB_DATA dbuf;
|
|---|
| 4173 | NT_PRINTER_INFO_LEVEL_2 info;
|
|---|
| 4174 |
|
|---|
| 4175 |
|
|---|
| 4176 | ZERO_STRUCT(info);
|
|---|
| 4177 |
|
|---|
| 4178 | /*
|
|---|
| 4179 | * Delete any printer data 'values' already set. When called for driver
|
|---|
| 4180 | * replace, there will generally be some, but during an add printer, there
|
|---|
| 4181 | * should not be any (if there are delete them).
|
|---|
| 4182 | */
|
|---|
| 4183 |
|
|---|
| 4184 | if ( info_ptr->data )
|
|---|
| 4185 | delete_all_printer_data( info_ptr, "" );
|
|---|
| 4186 |
|
|---|
| 4187 | if (asprintf(&key, "%s%s", DRIVER_INIT_PREFIX,
|
|---|
| 4188 | info_ptr->drivername) < 0) {
|
|---|
| 4189 | return false;
|
|---|
| 4190 | }
|
|---|
| 4191 |
|
|---|
| 4192 | dbuf = tdb_fetch_bystring(tdb_drivers, key);
|
|---|
| 4193 | if (!dbuf.dptr) {
|
|---|
| 4194 | /*
|
|---|
| 4195 | * When changing to a driver that has no init info in the tdb, remove
|
|---|
| 4196 | * the previous drivers init info and leave the new on blank.
|
|---|
| 4197 | */
|
|---|
| 4198 | free_nt_devicemode(&info_ptr->devmode);
|
|---|
| 4199 | SAFE_FREE(key);
|
|---|
| 4200 | return false;
|
|---|
| 4201 | }
|
|---|
| 4202 |
|
|---|
| 4203 | SAFE_FREE(key);
|
|---|
| 4204 | /*
|
|---|
| 4205 | * Get the saved DEVMODE..
|
|---|
| 4206 | */
|
|---|
| 4207 |
|
|---|
| 4208 | len += unpack_devicemode(&info.devmode,dbuf.dptr+len, dbuf.dsize-len);
|
|---|
| 4209 |
|
|---|
| 4210 | /*
|
|---|
| 4211 | * The saved DEVMODE contains the devicename from the printer used during
|
|---|
| 4212 | * the initialization save. Change it to reflect the new printer.
|
|---|
| 4213 | */
|
|---|
| 4214 |
|
|---|
| 4215 | if ( info.devmode ) {
|
|---|
| 4216 | ZERO_STRUCT(info.devmode->devicename);
|
|---|
| 4217 | fstrcpy(info.devmode->devicename, info_ptr->printername);
|
|---|
| 4218 | }
|
|---|
| 4219 |
|
|---|
| 4220 | /*
|
|---|
| 4221 | * NT/2k does not change out the entire DeviceMode of a printer
|
|---|
| 4222 | * when changing the driver. Only the driverextra, private, &
|
|---|
| 4223 | * driverversion fields. --jerry (Thu Mar 14 08:58:43 CST 2002)
|
|---|
| 4224 | *
|
|---|
| 4225 | * Later examination revealed that Windows NT/2k does reset the
|
|---|
| 4226 | * the printer's device mode, bit **only** when you change a
|
|---|
| 4227 | * property of the device mode such as the page orientation.
|
|---|
| 4228 | * --jerry
|
|---|
| 4229 | */
|
|---|
| 4230 |
|
|---|
| 4231 |
|
|---|
| 4232 | /* Bind the saved DEVMODE to the new the printer */
|
|---|
| 4233 |
|
|---|
| 4234 | free_nt_devicemode(&info_ptr->devmode);
|
|---|
| 4235 | info_ptr->devmode = info.devmode;
|
|---|
| 4236 |
|
|---|
| 4237 | DEBUG(10,("set_driver_init_2: Set printer [%s] init %s DEVMODE for driver [%s]\n",
|
|---|
| 4238 | info_ptr->printername, info_ptr->devmode?"VALID":"NULL", info_ptr->drivername));
|
|---|
| 4239 |
|
|---|
| 4240 | /* Add the printer data 'values' to the new printer */
|
|---|
| 4241 |
|
|---|
| 4242 | if ( !(info_ptr->data = TALLOC_ZERO_P( info_ptr, NT_PRINTER_DATA )) ) {
|
|---|
| 4243 | DEBUG(0,("set_driver_init_2: talloc() failed!\n"));
|
|---|
| 4244 | return False;
|
|---|
| 4245 | }
|
|---|
| 4246 |
|
|---|
| 4247 | len += unpack_values( info_ptr->data, dbuf.dptr+len, dbuf.dsize-len );
|
|---|
| 4248 |
|
|---|
| 4249 | SAFE_FREE(dbuf.dptr);
|
|---|
| 4250 |
|
|---|
| 4251 | return true;
|
|---|
| 4252 | }
|
|---|
| 4253 |
|
|---|
| 4254 | /****************************************************************************
|
|---|
| 4255 | Initialize printer devmode & data with previously saved driver init values.
|
|---|
| 4256 | When a printer is created using AddPrinter, the drivername bound to the
|
|---|
| 4257 | printer is used to lookup previously saved driver initialization info, which
|
|---|
| 4258 | is bound to the new printer.
|
|---|
| 4259 | ****************************************************************************/
|
|---|
| 4260 |
|
|---|
| 4261 | bool set_driver_init(NT_PRINTER_INFO_LEVEL *printer, uint32 level)
|
|---|
| 4262 | {
|
|---|
| 4263 | bool result = False;
|
|---|
| 4264 |
|
|---|
| 4265 | switch (level) {
|
|---|
| 4266 | case 2:
|
|---|
| 4267 | result = set_driver_init_2(printer->info_2);
|
|---|
| 4268 | break;
|
|---|
| 4269 |
|
|---|
| 4270 | default:
|
|---|
| 4271 | DEBUG(0,("set_driver_init: Programmer's error! Unknown driver_init level [%d]\n",
|
|---|
| 4272 | level));
|
|---|
| 4273 | break;
|
|---|
| 4274 | }
|
|---|
| 4275 |
|
|---|
| 4276 | return result;
|
|---|
| 4277 | }
|
|---|
| 4278 |
|
|---|
| 4279 | /****************************************************************************
|
|---|
| 4280 | Delete driver init data stored for a specified driver
|
|---|
| 4281 | ****************************************************************************/
|
|---|
| 4282 |
|
|---|
| 4283 | bool del_driver_init(const char *drivername)
|
|---|
| 4284 | {
|
|---|
| 4285 | char *key;
|
|---|
| 4286 | bool ret;
|
|---|
| 4287 |
|
|---|
| 4288 | if (!drivername || !*drivername) {
|
|---|
| 4289 | DEBUG(3,("del_driver_init: No drivername specified!\n"));
|
|---|
| 4290 | return false;
|
|---|
| 4291 | }
|
|---|
| 4292 |
|
|---|
| 4293 | if (asprintf(&key, "%s%s", DRIVER_INIT_PREFIX, drivername) < 0) {
|
|---|
| 4294 | return false;
|
|---|
| 4295 | }
|
|---|
| 4296 |
|
|---|
| 4297 | DEBUG(6,("del_driver_init: Removing driver init data for [%s]\n",
|
|---|
| 4298 | drivername));
|
|---|
| 4299 |
|
|---|
| 4300 | ret = (tdb_delete_bystring(tdb_drivers, key) == 0);
|
|---|
| 4301 | SAFE_FREE(key);
|
|---|
| 4302 | return ret;
|
|---|
| 4303 | }
|
|---|
| 4304 |
|
|---|
| 4305 | /****************************************************************************
|
|---|
| 4306 | Pack up the DEVMODE and values for a printer into a 'driver init' entry
|
|---|
| 4307 | in the tdb. Note: this is different from the driver entry and the printer
|
|---|
| 4308 | entry. There should be a single driver init entry for each driver regardless
|
|---|
| 4309 | of whether it was installed from NT or 2K. Technically, they should be
|
|---|
| 4310 | different, but they work out to the same struct.
|
|---|
| 4311 | ****************************************************************************/
|
|---|
| 4312 |
|
|---|
| 4313 | static uint32 update_driver_init_2(NT_PRINTER_INFO_LEVEL_2 *info)
|
|---|
| 4314 | {
|
|---|
| 4315 | char *key = NULL;
|
|---|
| 4316 | uint8 *buf;
|
|---|
| 4317 | int buflen, len, ret;
|
|---|
| 4318 | int retlen;
|
|---|
| 4319 | TDB_DATA dbuf;
|
|---|
| 4320 |
|
|---|
| 4321 | buf = NULL;
|
|---|
| 4322 | buflen = 0;
|
|---|
| 4323 |
|
|---|
| 4324 | again:
|
|---|
| 4325 | len = 0;
|
|---|
| 4326 | len += pack_devicemode(info->devmode, buf+len, buflen-len);
|
|---|
| 4327 |
|
|---|
| 4328 | retlen = pack_values( info->data, buf+len, buflen-len );
|
|---|
| 4329 | if (retlen == -1) {
|
|---|
| 4330 | ret = -1;
|
|---|
| 4331 | goto done;
|
|---|
| 4332 | }
|
|---|
| 4333 | len += retlen;
|
|---|
| 4334 |
|
|---|
| 4335 | if (buflen < len) {
|
|---|
| 4336 | buf = (uint8 *)SMB_REALLOC(buf, len);
|
|---|
| 4337 | if (!buf) {
|
|---|
| 4338 | DEBUG(0, ("update_driver_init_2: failed to enlarge buffer!\n"));
|
|---|
| 4339 | ret = -1;
|
|---|
| 4340 | goto done;
|
|---|
| 4341 | }
|
|---|
| 4342 | buflen = len;
|
|---|
| 4343 | goto again;
|
|---|
| 4344 | }
|
|---|
| 4345 |
|
|---|
| 4346 | SAFE_FREE(key);
|
|---|
| 4347 | if (asprintf(&key, "%s%s", DRIVER_INIT_PREFIX, info->drivername) < 0) {
|
|---|
| 4348 | ret = (uint32)-1;
|
|---|
| 4349 | goto done;
|
|---|
| 4350 | }
|
|---|
| 4351 |
|
|---|
| 4352 | dbuf.dptr = buf;
|
|---|
| 4353 | dbuf.dsize = len;
|
|---|
| 4354 |
|
|---|
| 4355 | ret = tdb_store_bystring(tdb_drivers, key, dbuf, TDB_REPLACE);
|
|---|
| 4356 |
|
|---|
| 4357 | done:
|
|---|
| 4358 | if (ret == -1)
|
|---|
| 4359 | DEBUG(8, ("update_driver_init_2: error updating printer init to tdb on disk\n"));
|
|---|
| 4360 |
|
|---|
| 4361 | SAFE_FREE(buf);
|
|---|
| 4362 |
|
|---|
| 4363 | DEBUG(10,("update_driver_init_2: Saved printer [%s] init DEVMODE & values for driver [%s]\n",
|
|---|
| 4364 | info->sharename, info->drivername));
|
|---|
| 4365 |
|
|---|
| 4366 | return ret;
|
|---|
| 4367 | }
|
|---|
| 4368 |
|
|---|
| 4369 | /****************************************************************************
|
|---|
| 4370 | Update (i.e. save) the driver init info (DEVMODE and values) for a printer
|
|---|
| 4371 | ****************************************************************************/
|
|---|
| 4372 |
|
|---|
| 4373 | static uint32 update_driver_init(NT_PRINTER_INFO_LEVEL *printer, uint32 level)
|
|---|
| 4374 | {
|
|---|
| 4375 | uint32 result;
|
|---|
| 4376 |
|
|---|
| 4377 | dump_a_printer(printer, level);
|
|---|
| 4378 |
|
|---|
| 4379 | switch (level) {
|
|---|
| 4380 | case 2:
|
|---|
| 4381 | result = update_driver_init_2(printer->info_2);
|
|---|
| 4382 | break;
|
|---|
| 4383 | default:
|
|---|
| 4384 | result = 1;
|
|---|
| 4385 | break;
|
|---|
| 4386 | }
|
|---|
| 4387 |
|
|---|
| 4388 | return result;
|
|---|
| 4389 | }
|
|---|
| 4390 |
|
|---|
| 4391 | /****************************************************************************
|
|---|
| 4392 | Convert the printer data value, a REG_BINARY array, into an initialization
|
|---|
| 4393 | DEVMODE. Note: the array must be parsed as if it was a DEVMODE in an rpc...
|
|---|
| 4394 | got to keep the endians happy :).
|
|---|
| 4395 | ****************************************************************************/
|
|---|
| 4396 |
|
|---|
| 4397 | static bool convert_driver_init(TALLOC_CTX *mem_ctx, NT_DEVICEMODE *nt_devmode,
|
|---|
| 4398 | const uint8_t *data, uint32_t data_len)
|
|---|
| 4399 | {
|
|---|
| 4400 | struct spoolss_DeviceMode devmode;
|
|---|
| 4401 | enum ndr_err_code ndr_err;
|
|---|
| 4402 | DATA_BLOB blob;
|
|---|
| 4403 |
|
|---|
| 4404 | ZERO_STRUCT(devmode);
|
|---|
| 4405 |
|
|---|
| 4406 | blob = data_blob_const(data, data_len);
|
|---|
| 4407 |
|
|---|
| 4408 | ndr_err = ndr_pull_struct_blob(&blob, mem_ctx, NULL, &devmode,
|
|---|
| 4409 | (ndr_pull_flags_fn_t)ndr_pull_spoolss_DeviceMode);
|
|---|
| 4410 | if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
|
|---|
| 4411 | DEBUG(10,("convert_driver_init: error parsing spoolss_DeviceMode\n"));
|
|---|
| 4412 | return false;
|
|---|
| 4413 | }
|
|---|
| 4414 |
|
|---|
| 4415 | return convert_devicemode("", &devmode, &nt_devmode);
|
|---|
| 4416 | }
|
|---|
| 4417 |
|
|---|
| 4418 | /****************************************************************************
|
|---|
| 4419 | Set the DRIVER_INIT info in the tdb. Requires Win32 client code that:
|
|---|
| 4420 |
|
|---|
| 4421 | 1. Use the driver's config DLL to this UNC printername and:
|
|---|
| 4422 | a. Call DrvPrintEvent with PRINTER_EVENT_INITIALIZE
|
|---|
| 4423 | b. Call DrvConvertDevMode with CDM_DRIVER_DEFAULT to get default DEVMODE
|
|---|
| 4424 | 2. Call SetPrinterData with the 'magic' key and the DEVMODE as data.
|
|---|
| 4425 |
|
|---|
| 4426 | The last step triggers saving the "driver initialization" information for
|
|---|
| 4427 | this printer into the tdb. Later, new printers that use this driver will
|
|---|
| 4428 | have this initialization information bound to them. This simulates the
|
|---|
| 4429 | driver initialization, as if it had run on the Samba server (as it would
|
|---|
| 4430 | have done on NT).
|
|---|
| 4431 |
|
|---|
| 4432 | The Win32 client side code requirement sucks! But until we can run arbitrary
|
|---|
| 4433 | Win32 printer driver code on any Unix that Samba runs on, we are stuck with it.
|
|---|
| 4434 |
|
|---|
| 4435 | It would have been easier to use SetPrinter because all the UNMARSHALLING of
|
|---|
| 4436 | the DEVMODE is done there, but 2K/XP clients do not set the DEVMODE... think
|
|---|
| 4437 | about it and you will realize why. JRR 010720
|
|---|
| 4438 | ****************************************************************************/
|
|---|
| 4439 |
|
|---|
| 4440 | static WERROR save_driver_init_2(NT_PRINTER_INFO_LEVEL *printer, uint8 *data, uint32 data_len )
|
|---|
| 4441 | {
|
|---|
| 4442 | WERROR status = WERR_OK;
|
|---|
| 4443 | TALLOC_CTX *ctx = NULL;
|
|---|
| 4444 | NT_DEVICEMODE *nt_devmode = NULL;
|
|---|
| 4445 | NT_DEVICEMODE *tmp_devmode = printer->info_2->devmode;
|
|---|
| 4446 |
|
|---|
| 4447 | /*
|
|---|
| 4448 | * When the DEVMODE is already set on the printer, don't try to unpack it.
|
|---|
| 4449 | */
|
|---|
| 4450 | DEBUG(8,("save_driver_init_2: Enter...\n"));
|
|---|
| 4451 |
|
|---|
| 4452 | if ( !printer->info_2->devmode && data_len ) {
|
|---|
| 4453 | /*
|
|---|
| 4454 | * Set devmode on printer info, so entire printer initialization can be
|
|---|
| 4455 | * saved to tdb.
|
|---|
| 4456 | */
|
|---|
| 4457 |
|
|---|
| 4458 | if ((ctx = talloc_init("save_driver_init_2")) == NULL)
|
|---|
| 4459 | return WERR_NOMEM;
|
|---|
| 4460 |
|
|---|
| 4461 | if ((nt_devmode = SMB_MALLOC_P(NT_DEVICEMODE)) == NULL) {
|
|---|
| 4462 | status = WERR_NOMEM;
|
|---|
| 4463 | goto done;
|
|---|
| 4464 | }
|
|---|
| 4465 |
|
|---|
| 4466 | ZERO_STRUCTP(nt_devmode);
|
|---|
| 4467 |
|
|---|
| 4468 | /*
|
|---|
| 4469 | * The DEVMODE is held in the 'data' component of the param in raw binary.
|
|---|
| 4470 | * Convert it to to a devmode structure
|
|---|
| 4471 | */
|
|---|
| 4472 | if ( !convert_driver_init( ctx, nt_devmode, data, data_len )) {
|
|---|
| 4473 | DEBUG(10,("save_driver_init_2: error converting DEVMODE\n"));
|
|---|
| 4474 | status = WERR_INVALID_PARAM;
|
|---|
| 4475 | goto done;
|
|---|
| 4476 | }
|
|---|
| 4477 |
|
|---|
| 4478 | printer->info_2->devmode = nt_devmode;
|
|---|
| 4479 | }
|
|---|
| 4480 |
|
|---|
| 4481 | /*
|
|---|
| 4482 | * Pack up and add (or update) the DEVMODE and any current printer data to
|
|---|
| 4483 | * a 'driver init' element in the tdb
|
|---|
| 4484 | *
|
|---|
| 4485 | */
|
|---|
| 4486 |
|
|---|
| 4487 | if ( update_driver_init(printer, 2) != 0 ) {
|
|---|
| 4488 | DEBUG(10,("save_driver_init_2: error updating DEVMODE\n"));
|
|---|
| 4489 | status = WERR_NOMEM;
|
|---|
| 4490 | goto done;
|
|---|
| 4491 | }
|
|---|
| 4492 |
|
|---|
| 4493 | /*
|
|---|
| 4494 | * If driver initialization info was successfully saved, set the current
|
|---|
| 4495 | * printer to match it. This allows initialization of the current printer
|
|---|
| 4496 | * as well as the driver.
|
|---|
| 4497 | */
|
|---|
| 4498 | status = mod_a_printer(printer, 2);
|
|---|
| 4499 | if (!W_ERROR_IS_OK(status)) {
|
|---|
| 4500 | DEBUG(10,("save_driver_init_2: error setting DEVMODE on printer [%s]\n",
|
|---|
| 4501 | printer->info_2->printername));
|
|---|
| 4502 | }
|
|---|
| 4503 |
|
|---|
| 4504 | done:
|
|---|
| 4505 | talloc_destroy(ctx);
|
|---|
| 4506 | free_nt_devicemode( &nt_devmode );
|
|---|
| 4507 |
|
|---|
| 4508 | printer->info_2->devmode = tmp_devmode;
|
|---|
| 4509 |
|
|---|
| 4510 | return status;
|
|---|
| 4511 | }
|
|---|
| 4512 |
|
|---|
| 4513 | /****************************************************************************
|
|---|
| 4514 | Update the driver init info (DEVMODE and specifics) for a printer
|
|---|
| 4515 | ****************************************************************************/
|
|---|
| 4516 |
|
|---|
| 4517 | WERROR save_driver_init(NT_PRINTER_INFO_LEVEL *printer, uint32 level, uint8 *data, uint32 data_len)
|
|---|
| 4518 | {
|
|---|
| 4519 | WERROR status = WERR_OK;
|
|---|
| 4520 |
|
|---|
| 4521 | switch (level) {
|
|---|
| 4522 | case 2:
|
|---|
| 4523 | status = save_driver_init_2( printer, data, data_len );
|
|---|
| 4524 | break;
|
|---|
| 4525 | default:
|
|---|
| 4526 | status = WERR_UNKNOWN_LEVEL;
|
|---|
| 4527 | break;
|
|---|
| 4528 | }
|
|---|
| 4529 |
|
|---|
| 4530 | return status;
|
|---|
| 4531 | }
|
|---|
| 4532 |
|
|---|
| 4533 | /****************************************************************************
|
|---|
| 4534 | Get a NT_PRINTER_INFO_LEVEL struct. It returns malloced memory.
|
|---|
| 4535 |
|
|---|
| 4536 | Previously the code had a memory allocation problem because it always
|
|---|
| 4537 | used the TALLOC_CTX from the Printer_entry*. This context lasts
|
|---|
| 4538 | as a long as the original handle is open. So if the client made a lot
|
|---|
| 4539 | of getprinter[data]() calls, the memory usage would climb. Now we use
|
|---|
| 4540 | a short lived TALLOC_CTX for printer_info_2 objects returned. We
|
|---|
| 4541 | still use the Printer_entry->ctx for maintaining the cache copy though
|
|---|
| 4542 | since that object must live as long as the handle by definition.
|
|---|
| 4543 | --jerry
|
|---|
| 4544 |
|
|---|
| 4545 | ****************************************************************************/
|
|---|
| 4546 |
|
|---|
| 4547 | static WERROR get_a_printer_internal( Printer_entry *print_hnd, NT_PRINTER_INFO_LEVEL **pp_printer, uint32 level,
|
|---|
| 4548 | const char *sharename, bool get_loc_com)
|
|---|
| 4549 | {
|
|---|
| 4550 | WERROR result;
|
|---|
| 4551 | fstring servername;
|
|---|
| 4552 |
|
|---|
| 4553 | DEBUG(10,("get_a_printer: [%s] level %u\n", sharename, (unsigned int)level));
|
|---|
| 4554 |
|
|---|
| 4555 | if ( !(*pp_printer = TALLOC_ZERO_P(NULL, NT_PRINTER_INFO_LEVEL)) ) {
|
|---|
| 4556 | DEBUG(0,("get_a_printer: talloc() fail.\n"));
|
|---|
| 4557 | return WERR_NOMEM;
|
|---|
| 4558 | }
|
|---|
| 4559 |
|
|---|
| 4560 | switch (level) {
|
|---|
| 4561 | case 2:
|
|---|
| 4562 | if ( !((*pp_printer)->info_2 = TALLOC_ZERO_P(*pp_printer, NT_PRINTER_INFO_LEVEL_2)) ) {
|
|---|
| 4563 | DEBUG(0,("get_a_printer: talloc() fail.\n"));
|
|---|
| 4564 | TALLOC_FREE( *pp_printer );
|
|---|
| 4565 | return WERR_NOMEM;
|
|---|
| 4566 | }
|
|---|
| 4567 |
|
|---|
| 4568 | if ( print_hnd )
|
|---|
| 4569 | fstrcpy( servername, print_hnd->servername );
|
|---|
| 4570 | else {
|
|---|
| 4571 | fstrcpy( servername, "%L" );
|
|---|
| 4572 | standard_sub_basic( "", "", servername,
|
|---|
| 4573 | sizeof(servername)-1 );
|
|---|
| 4574 | }
|
|---|
| 4575 |
|
|---|
| 4576 | result = get_a_printer_2( (*pp_printer)->info_2,
|
|---|
| 4577 | servername, sharename, get_loc_com);
|
|---|
| 4578 |
|
|---|
| 4579 | /* we have a new printer now. Save it with this handle */
|
|---|
| 4580 |
|
|---|
| 4581 | if ( !W_ERROR_IS_OK(result) ) {
|
|---|
| 4582 | TALLOC_FREE( *pp_printer );
|
|---|
| 4583 | DEBUG(10,("get_a_printer: [%s] level %u returning %s\n",
|
|---|
| 4584 | sharename, (unsigned int)level, win_errstr(result)));
|
|---|
| 4585 | return result;
|
|---|
| 4586 | }
|
|---|
| 4587 |
|
|---|
| 4588 | dump_a_printer( *pp_printer, level);
|
|---|
| 4589 |
|
|---|
| 4590 | break;
|
|---|
| 4591 |
|
|---|
| 4592 | default:
|
|---|
| 4593 | TALLOC_FREE( *pp_printer );
|
|---|
| 4594 | return WERR_UNKNOWN_LEVEL;
|
|---|
| 4595 | }
|
|---|
| 4596 |
|
|---|
| 4597 | return WERR_OK;
|
|---|
| 4598 | }
|
|---|
| 4599 |
|
|---|
| 4600 | WERROR get_a_printer( Printer_entry *print_hnd,
|
|---|
| 4601 | NT_PRINTER_INFO_LEVEL **pp_printer,
|
|---|
| 4602 | uint32 level,
|
|---|
| 4603 | const char *sharename)
|
|---|
| 4604 | {
|
|---|
| 4605 | return get_a_printer_internal(print_hnd, pp_printer, level,
|
|---|
| 4606 | sharename, true);
|
|---|
| 4607 | }
|
|---|
| 4608 |
|
|---|
| 4609 | WERROR get_a_printer_search( Printer_entry *print_hnd,
|
|---|
| 4610 | NT_PRINTER_INFO_LEVEL **pp_printer,
|
|---|
| 4611 | uint32 level,
|
|---|
| 4612 | const char *sharename)
|
|---|
| 4613 | {
|
|---|
| 4614 | return get_a_printer_internal(print_hnd, pp_printer, level,
|
|---|
| 4615 | sharename, false);
|
|---|
| 4616 | }
|
|---|
| 4617 |
|
|---|
| 4618 | /****************************************************************************
|
|---|
| 4619 | Deletes a NT_PRINTER_INFO_LEVEL struct.
|
|---|
| 4620 | ****************************************************************************/
|
|---|
| 4621 |
|
|---|
| 4622 | uint32 free_a_printer(NT_PRINTER_INFO_LEVEL **pp_printer, uint32 level)
|
|---|
| 4623 | {
|
|---|
| 4624 | NT_PRINTER_INFO_LEVEL *printer = *pp_printer;
|
|---|
| 4625 |
|
|---|
| 4626 | if ( !printer )
|
|---|
| 4627 | return 0;
|
|---|
| 4628 |
|
|---|
| 4629 | switch (level) {
|
|---|
| 4630 | case 2:
|
|---|
| 4631 | if ( printer->info_2 )
|
|---|
| 4632 | free_nt_printer_info_level_2(&printer->info_2);
|
|---|
| 4633 | break;
|
|---|
| 4634 |
|
|---|
| 4635 | default:
|
|---|
| 4636 | DEBUG(0,("free_a_printer: unknown level! [%d]\n", level ));
|
|---|
| 4637 | return 1;
|
|---|
| 4638 | }
|
|---|
| 4639 |
|
|---|
| 4640 | TALLOC_FREE(*pp_printer);
|
|---|
| 4641 |
|
|---|
| 4642 | return 0;
|
|---|
| 4643 | }
|
|---|
| 4644 |
|
|---|
| 4645 | /****************************************************************************
|
|---|
| 4646 | ****************************************************************************/
|
|---|
| 4647 |
|
|---|
| 4648 | uint32_t add_a_printer_driver(TALLOC_CTX *mem_ctx,
|
|---|
| 4649 | struct spoolss_AddDriverInfoCtr *r,
|
|---|
| 4650 | char **driver_name,
|
|---|
| 4651 | uint32_t *version)
|
|---|
| 4652 | {
|
|---|
| 4653 | struct spoolss_DriverInfo8 info8;
|
|---|
| 4654 |
|
|---|
| 4655 | ZERO_STRUCT(info8);
|
|---|
| 4656 |
|
|---|
| 4657 | DEBUG(10,("adding a printer at level [%d]\n", r->level));
|
|---|
| 4658 |
|
|---|
| 4659 | switch (r->level) {
|
|---|
| 4660 | case 3:
|
|---|
| 4661 | info8.version = r->info.info3->version;
|
|---|
| 4662 | info8.driver_name = r->info.info3->driver_name;
|
|---|
| 4663 | info8.architecture = r->info.info3->architecture;
|
|---|
| 4664 | info8.driver_path = r->info.info3->driver_path;
|
|---|
| 4665 | info8.data_file = r->info.info3->data_file;
|
|---|
| 4666 | info8.config_file = r->info.info3->config_file;
|
|---|
| 4667 | info8.help_file = r->info.info3->help_file;
|
|---|
| 4668 | info8.monitor_name = r->info.info3->monitor_name;
|
|---|
| 4669 | info8.default_datatype = r->info.info3->default_datatype;
|
|---|
| 4670 | if (r->info.info3->dependent_files && r->info.info3->dependent_files->string) {
|
|---|
| 4671 | info8.dependent_files = r->info.info3->dependent_files->string;
|
|---|
| 4672 | }
|
|---|
| 4673 | break;
|
|---|
| 4674 | case 6:
|
|---|
| 4675 | info8.version = r->info.info6->version;
|
|---|
| 4676 | info8.driver_name = r->info.info6->driver_name;
|
|---|
| 4677 | info8.architecture = r->info.info6->architecture;
|
|---|
| 4678 | info8.driver_path = r->info.info6->driver_path;
|
|---|
| 4679 | info8.data_file = r->info.info6->data_file;
|
|---|
| 4680 | info8.config_file = r->info.info6->config_file;
|
|---|
| 4681 | info8.help_file = r->info.info6->help_file;
|
|---|
| 4682 | info8.monitor_name = r->info.info6->monitor_name;
|
|---|
| 4683 | info8.default_datatype = r->info.info6->default_datatype;
|
|---|
| 4684 | if (r->info.info6->dependent_files && r->info.info6->dependent_files->string) {
|
|---|
| 4685 | info8.dependent_files = r->info.info6->dependent_files->string;
|
|---|
| 4686 | }
|
|---|
| 4687 | info8.driver_date = r->info.info6->driver_date;
|
|---|
| 4688 | info8.driver_version = r->info.info6->driver_version;
|
|---|
| 4689 | info8.manufacturer_name = r->info.info6->manufacturer_name;
|
|---|
| 4690 | info8.manufacturer_url = r->info.info6->manufacturer_url;
|
|---|
| 4691 | info8.hardware_id = r->info.info6->hardware_id;
|
|---|
| 4692 | info8.provider = r->info.info6->provider;
|
|---|
| 4693 | break;
|
|---|
| 4694 | case 8:
|
|---|
| 4695 | info8.version = r->info.info8->version;
|
|---|
| 4696 | info8.driver_name = r->info.info8->driver_name;
|
|---|
| 4697 | info8.architecture = r->info.info8->architecture;
|
|---|
| 4698 | info8.driver_path = r->info.info8->driver_path;
|
|---|
| 4699 | info8.data_file = r->info.info8->data_file;
|
|---|
| 4700 | info8.config_file = r->info.info8->config_file;
|
|---|
| 4701 | info8.help_file = r->info.info8->help_file;
|
|---|
| 4702 | info8.monitor_name = r->info.info8->monitor_name;
|
|---|
| 4703 | info8.default_datatype = r->info.info8->default_datatype;
|
|---|
| 4704 | if (r->info.info8->dependent_files && r->info.info8->dependent_files->string) {
|
|---|
| 4705 | info8.dependent_files = r->info.info8->dependent_files->string;
|
|---|
| 4706 | }
|
|---|
| 4707 | if (r->info.info8->previous_names && r->info.info8->previous_names->string) {
|
|---|
| 4708 | info8.previous_names = r->info.info8->previous_names->string;
|
|---|
| 4709 | }
|
|---|
| 4710 | info8.driver_date = r->info.info8->driver_date;
|
|---|
| 4711 | info8.driver_version = r->info.info8->driver_version;
|
|---|
| 4712 | info8.manufacturer_name = r->info.info8->manufacturer_name;
|
|---|
| 4713 | info8.manufacturer_url = r->info.info8->manufacturer_url;
|
|---|
| 4714 | info8.hardware_id = r->info.info8->hardware_id;
|
|---|
| 4715 | info8.provider = r->info.info8->provider;
|
|---|
| 4716 | info8.print_processor = r->info.info8->print_processor;
|
|---|
| 4717 | info8.vendor_setup = r->info.info8->vendor_setup;
|
|---|
| 4718 | if (r->info.info8->color_profiles && r->info.info8->color_profiles->string) {
|
|---|
| 4719 | info8.color_profiles = r->info.info8->color_profiles->string;
|
|---|
| 4720 | }
|
|---|
| 4721 | info8.inf_path = r->info.info8->inf_path;
|
|---|
| 4722 | info8.printer_driver_attributes = r->info.info8->printer_driver_attributes;
|
|---|
| 4723 | if (r->info.info8->core_driver_dependencies && r->info.info8->core_driver_dependencies->string) {
|
|---|
| 4724 | info8.core_driver_dependencies = r->info.info8->core_driver_dependencies->string;
|
|---|
| 4725 | }
|
|---|
| 4726 | info8.min_inbox_driver_ver_date = r->info.info8->min_inbox_driver_ver_date;
|
|---|
| 4727 | info8.min_inbox_driver_ver_version = r->info.info8->min_inbox_driver_ver_version;
|
|---|
| 4728 | break;
|
|---|
| 4729 | default:
|
|---|
| 4730 | return -1;
|
|---|
| 4731 | }
|
|---|
| 4732 |
|
|---|
| 4733 | *driver_name = talloc_strdup(mem_ctx, info8.driver_name);
|
|---|
| 4734 | if (!*driver_name) {
|
|---|
| 4735 | return -1;
|
|---|
| 4736 | }
|
|---|
| 4737 | *version = info8.version;
|
|---|
| 4738 |
|
|---|
| 4739 | return add_a_printer_driver_8(&info8);
|
|---|
| 4740 | }
|
|---|
| 4741 |
|
|---|
| 4742 | /****************************************************************************
|
|---|
| 4743 | ****************************************************************************/
|
|---|
| 4744 |
|
|---|
| 4745 | WERROR get_a_printer_driver(TALLOC_CTX *mem_ctx,
|
|---|
| 4746 | struct spoolss_DriverInfo8 **driver,
|
|---|
| 4747 | const char *drivername, const char *architecture,
|
|---|
| 4748 | uint32_t version)
|
|---|
| 4749 | {
|
|---|
| 4750 | WERROR result;
|
|---|
| 4751 | struct spoolss_DriverInfo3 info3;
|
|---|
| 4752 | struct spoolss_DriverInfo8 *info8;
|
|---|
| 4753 |
|
|---|
| 4754 | ZERO_STRUCT(info3);
|
|---|
| 4755 |
|
|---|
| 4756 | /* Sometime we just want any version of the driver */
|
|---|
| 4757 |
|
|---|
| 4758 | if (version == DRIVER_ANY_VERSION) {
|
|---|
| 4759 | /* look for Win2k first and then for NT4 */
|
|---|
| 4760 | result = get_a_printer_driver_3(mem_ctx,
|
|---|
| 4761 | &info3,
|
|---|
| 4762 | drivername,
|
|---|
| 4763 | architecture, 3);
|
|---|
| 4764 | if (!W_ERROR_IS_OK(result)) {
|
|---|
| 4765 | result = get_a_printer_driver_3(mem_ctx,
|
|---|
| 4766 | &info3,
|
|---|
| 4767 | drivername,
|
|---|
| 4768 | architecture, 2);
|
|---|
| 4769 | }
|
|---|
| 4770 | } else {
|
|---|
| 4771 | result = get_a_printer_driver_3(mem_ctx,
|
|---|
| 4772 | &info3,
|
|---|
| 4773 | drivername,
|
|---|
| 4774 | architecture,
|
|---|
| 4775 | version);
|
|---|
| 4776 | }
|
|---|
| 4777 |
|
|---|
| 4778 | if (!W_ERROR_IS_OK(result)) {
|
|---|
| 4779 | return result;
|
|---|
| 4780 | }
|
|---|
| 4781 |
|
|---|
| 4782 | info8 = talloc_zero(mem_ctx, struct spoolss_DriverInfo8);
|
|---|
| 4783 | if (!info8) {
|
|---|
| 4784 | return WERR_NOMEM;
|
|---|
| 4785 | }
|
|---|
| 4786 |
|
|---|
| 4787 | info8->version = info3.version;
|
|---|
| 4788 | info8->driver_name = info3.driver_name;
|
|---|
| 4789 | info8->architecture = info3.architecture;
|
|---|
| 4790 | info8->driver_path = info3.driver_path;
|
|---|
| 4791 | info8->data_file = info3.data_file;
|
|---|
| 4792 | info8->config_file = info3.config_file;
|
|---|
| 4793 | info8->help_file = info3.help_file;
|
|---|
| 4794 | info8->dependent_files = info3.dependent_files;
|
|---|
| 4795 | info8->monitor_name = info3.monitor_name;
|
|---|
| 4796 | info8->default_datatype = info3.default_datatype;
|
|---|
| 4797 |
|
|---|
| 4798 | *driver = info8;
|
|---|
| 4799 |
|
|---|
| 4800 | return WERR_OK;
|
|---|
| 4801 | }
|
|---|
| 4802 |
|
|---|
| 4803 | /****************************************************************************
|
|---|
| 4804 | ****************************************************************************/
|
|---|
| 4805 |
|
|---|
| 4806 | uint32_t free_a_printer_driver(struct spoolss_DriverInfo8 *driver)
|
|---|
| 4807 | {
|
|---|
| 4808 | talloc_free(driver);
|
|---|
| 4809 | return 0;
|
|---|
| 4810 | }
|
|---|
| 4811 |
|
|---|
| 4812 |
|
|---|
| 4813 | /****************************************************************************
|
|---|
| 4814 | Determine whether or not a particular driver is currently assigned
|
|---|
| 4815 | to a printer
|
|---|
| 4816 | ****************************************************************************/
|
|---|
| 4817 |
|
|---|
| 4818 | bool printer_driver_in_use(const struct spoolss_DriverInfo8 *r)
|
|---|
| 4819 | {
|
|---|
| 4820 | int snum;
|
|---|
| 4821 | int n_services = lp_numservices();
|
|---|
| 4822 | NT_PRINTER_INFO_LEVEL *printer = NULL;
|
|---|
| 4823 | bool in_use = False;
|
|---|
| 4824 |
|
|---|
| 4825 | if (!r) {
|
|---|
| 4826 | return false;
|
|---|
| 4827 | }
|
|---|
| 4828 |
|
|---|
| 4829 | DEBUG(10,("printer_driver_in_use: Beginning search through ntprinters.tdb...\n"));
|
|---|
| 4830 |
|
|---|
| 4831 | /* loop through the printers.tdb and check for the drivername */
|
|---|
| 4832 |
|
|---|
| 4833 | for (snum=0; snum<n_services && !in_use; snum++) {
|
|---|
| 4834 | if ( !(lp_snum_ok(snum) && lp_print_ok(snum) ) )
|
|---|
| 4835 | continue;
|
|---|
| 4836 |
|
|---|
| 4837 | if ( !W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, lp_servicename(snum))) )
|
|---|
| 4838 | continue;
|
|---|
| 4839 |
|
|---|
| 4840 | if (strequal(r->driver_name, printer->info_2->drivername))
|
|---|
| 4841 | in_use = True;
|
|---|
| 4842 |
|
|---|
| 4843 | free_a_printer( &printer, 2 );
|
|---|
| 4844 | }
|
|---|
| 4845 |
|
|---|
| 4846 | DEBUG(10,("printer_driver_in_use: Completed search through ntprinters.tdb...\n"));
|
|---|
| 4847 |
|
|---|
| 4848 | if ( in_use ) {
|
|---|
| 4849 | struct spoolss_DriverInfo8 *d;
|
|---|
| 4850 | WERROR werr;
|
|---|
| 4851 |
|
|---|
| 4852 | DEBUG(5,("printer_driver_in_use: driver \"%s\" is currently in use\n", r->driver_name));
|
|---|
| 4853 |
|
|---|
| 4854 | /* we can still remove the driver if there is one of
|
|---|
| 4855 | "Windows NT x86" version 2 or 3 left */
|
|---|
| 4856 |
|
|---|
| 4857 | if (!strequal("Windows NT x86", r->architecture)) {
|
|---|
| 4858 | werr = get_a_printer_driver(talloc_tos(), &d, r->driver_name, "Windows NT x86", DRIVER_ANY_VERSION);
|
|---|
| 4859 | }
|
|---|
| 4860 | else {
|
|---|
| 4861 | switch (r->version) {
|
|---|
| 4862 | case 2:
|
|---|
| 4863 | werr = get_a_printer_driver(talloc_tos(), &d, r->driver_name, "Windows NT x86", 3);
|
|---|
| 4864 | break;
|
|---|
| 4865 | case 3:
|
|---|
| 4866 | werr = get_a_printer_driver(talloc_tos(), &d, r->driver_name, "Windows NT x86", 2);
|
|---|
| 4867 | break;
|
|---|
| 4868 | default:
|
|---|
| 4869 | DEBUG(0,("printer_driver_in_use: ERROR! unknown driver version (%d)\n",
|
|---|
| 4870 | r->version));
|
|---|
| 4871 | werr = WERR_UNKNOWN_PRINTER_DRIVER;
|
|---|
| 4872 | break;
|
|---|
| 4873 | }
|
|---|
| 4874 | }
|
|---|
| 4875 |
|
|---|
| 4876 | /* now check the error code */
|
|---|
| 4877 |
|
|---|
| 4878 | if ( W_ERROR_IS_OK(werr) ) {
|
|---|
| 4879 | /* it's ok to remove the driver, we have other architctures left */
|
|---|
| 4880 | in_use = False;
|
|---|
| 4881 | free_a_printer_driver(d);
|
|---|
| 4882 | }
|
|---|
| 4883 | }
|
|---|
| 4884 |
|
|---|
| 4885 | /* report that the driver is not in use by default */
|
|---|
| 4886 |
|
|---|
| 4887 | return in_use;
|
|---|
| 4888 | }
|
|---|
| 4889 |
|
|---|
| 4890 |
|
|---|
| 4891 | /**********************************************************************
|
|---|
| 4892 | Check to see if a ogiven file is in use by *info
|
|---|
| 4893 | *********************************************************************/
|
|---|
| 4894 |
|
|---|
| 4895 | static bool drv_file_in_use(const char *file, const struct spoolss_DriverInfo8 *info)
|
|---|
| 4896 | {
|
|---|
| 4897 | int i = 0;
|
|---|
| 4898 |
|
|---|
| 4899 | if ( !info )
|
|---|
| 4900 | return False;
|
|---|
| 4901 |
|
|---|
| 4902 | /* mz: skip files that are in the list but already deleted */
|
|---|
| 4903 | if (!file || !file[0]) {
|
|---|
| 4904 | return false;
|
|---|
| 4905 | }
|
|---|
| 4906 |
|
|---|
| 4907 | if (strequal(file, info->driver_path))
|
|---|
| 4908 | return True;
|
|---|
| 4909 |
|
|---|
| 4910 | if (strequal(file, info->data_file))
|
|---|
| 4911 | return True;
|
|---|
| 4912 |
|
|---|
| 4913 | if (strequal(file, info->config_file))
|
|---|
| 4914 | return True;
|
|---|
| 4915 |
|
|---|
| 4916 | if (strequal(file, info->help_file))
|
|---|
| 4917 | return True;
|
|---|
| 4918 |
|
|---|
| 4919 | /* see of there are any dependent files to examine */
|
|---|
| 4920 |
|
|---|
| 4921 | if (!info->dependent_files)
|
|---|
| 4922 | return False;
|
|---|
| 4923 |
|
|---|
| 4924 | while (info->dependent_files[i] && *info->dependent_files[i]) {
|
|---|
| 4925 | if (strequal(file, info->dependent_files[i]))
|
|---|
| 4926 | return True;
|
|---|
| 4927 | i++;
|
|---|
| 4928 | }
|
|---|
| 4929 |
|
|---|
| 4930 | return False;
|
|---|
| 4931 |
|
|---|
| 4932 | }
|
|---|
| 4933 |
|
|---|
| 4934 | /**********************************************************************
|
|---|
| 4935 | Utility function to remove the dependent file pointed to by the
|
|---|
| 4936 | input parameter from the list
|
|---|
| 4937 | *********************************************************************/
|
|---|
| 4938 |
|
|---|
| 4939 | static void trim_dependent_file(TALLOC_CTX *mem_ctx, const char **files, int idx)
|
|---|
| 4940 | {
|
|---|
| 4941 |
|
|---|
| 4942 | /* bump everything down a slot */
|
|---|
| 4943 |
|
|---|
| 4944 | while (files && files[idx+1]) {
|
|---|
| 4945 | files[idx] = talloc_strdup(mem_ctx, files[idx+1]);
|
|---|
| 4946 | idx++;
|
|---|
| 4947 | }
|
|---|
| 4948 |
|
|---|
| 4949 | files[idx] = NULL;
|
|---|
| 4950 |
|
|---|
| 4951 | return;
|
|---|
| 4952 | }
|
|---|
| 4953 |
|
|---|
| 4954 | /**********************************************************************
|
|---|
| 4955 | Check if any of the files used by src are also used by drv
|
|---|
| 4956 | *********************************************************************/
|
|---|
| 4957 |
|
|---|
| 4958 | static bool trim_overlap_drv_files(TALLOC_CTX *mem_ctx,
|
|---|
| 4959 | struct spoolss_DriverInfo8 *src,
|
|---|
| 4960 | const struct spoolss_DriverInfo8 *drv)
|
|---|
| 4961 | {
|
|---|
| 4962 | bool in_use = False;
|
|---|
| 4963 | int i = 0;
|
|---|
| 4964 |
|
|---|
| 4965 | if ( !src || !drv )
|
|---|
| 4966 | return False;
|
|---|
| 4967 |
|
|---|
| 4968 | /* check each file. Remove it from the src structure if it overlaps */
|
|---|
| 4969 |
|
|---|
| 4970 | if (drv_file_in_use(src->driver_path, drv)) {
|
|---|
| 4971 | in_use = True;
|
|---|
| 4972 | DEBUG(10,("Removing driverfile [%s] from list\n", src->driver_path));
|
|---|
| 4973 | src->driver_path = talloc_strdup(mem_ctx, "");
|
|---|
| 4974 | if (!src->driver_path) { return false; }
|
|---|
| 4975 | }
|
|---|
| 4976 |
|
|---|
| 4977 | if (drv_file_in_use(src->data_file, drv)) {
|
|---|
| 4978 | in_use = True;
|
|---|
| 4979 | DEBUG(10,("Removing datafile [%s] from list\n", src->data_file));
|
|---|
| 4980 | src->data_file = talloc_strdup(mem_ctx, "");
|
|---|
| 4981 | if (!src->data_file) { return false; }
|
|---|
| 4982 | }
|
|---|
| 4983 |
|
|---|
| 4984 | if (drv_file_in_use(src->config_file, drv)) {
|
|---|
| 4985 | in_use = True;
|
|---|
| 4986 | DEBUG(10,("Removing configfile [%s] from list\n", src->config_file));
|
|---|
| 4987 | src->config_file = talloc_strdup(mem_ctx, "");
|
|---|
| 4988 | if (!src->config_file) { return false; }
|
|---|
| 4989 | }
|
|---|
| 4990 |
|
|---|
| 4991 | if (drv_file_in_use(src->help_file, drv)) {
|
|---|
| 4992 | in_use = True;
|
|---|
| 4993 | DEBUG(10,("Removing helpfile [%s] from list\n", src->help_file));
|
|---|
| 4994 | src->help_file = talloc_strdup(mem_ctx, "");
|
|---|
| 4995 | if (!src->help_file) { return false; }
|
|---|
| 4996 | }
|
|---|
| 4997 |
|
|---|
| 4998 | /* are there any dependentfiles to examine? */
|
|---|
| 4999 |
|
|---|
| 5000 | if (!src->dependent_files)
|
|---|
| 5001 | return in_use;
|
|---|
| 5002 |
|
|---|
| 5003 | while (src->dependent_files[i] && *src->dependent_files[i]) {
|
|---|
| 5004 | if (drv_file_in_use(src->dependent_files[i], drv)) {
|
|---|
| 5005 | in_use = True;
|
|---|
| 5006 | DEBUG(10,("Removing [%s] from dependent file list\n", src->dependent_files[i]));
|
|---|
| 5007 | trim_dependent_file(mem_ctx, src->dependent_files, i);
|
|---|
| 5008 | } else
|
|---|
| 5009 | i++;
|
|---|
| 5010 | }
|
|---|
| 5011 |
|
|---|
| 5012 | return in_use;
|
|---|
| 5013 | }
|
|---|
| 5014 |
|
|---|
| 5015 | /****************************************************************************
|
|---|
| 5016 | Determine whether or not a particular driver files are currently being
|
|---|
| 5017 | used by any other driver.
|
|---|
| 5018 |
|
|---|
| 5019 | Return value is True if any files were in use by other drivers
|
|---|
| 5020 | and False otherwise.
|
|---|
| 5021 |
|
|---|
| 5022 | Upon return, *info has been modified to only contain the driver files
|
|---|
| 5023 | which are not in use
|
|---|
| 5024 |
|
|---|
| 5025 | Fix from mz:
|
|---|
| 5026 |
|
|---|
| 5027 | This needs to check all drivers to ensure that all files in use
|
|---|
| 5028 | have been removed from *info, not just the ones in the first
|
|---|
| 5029 | match.
|
|---|
| 5030 | ****************************************************************************/
|
|---|
| 5031 |
|
|---|
| 5032 | bool printer_driver_files_in_use(TALLOC_CTX *mem_ctx,
|
|---|
| 5033 | struct spoolss_DriverInfo8 *info)
|
|---|
| 5034 | {
|
|---|
| 5035 | int i;
|
|---|
| 5036 | int ndrivers;
|
|---|
| 5037 | uint32 version;
|
|---|
| 5038 | fstring *list = NULL;
|
|---|
| 5039 | struct spoolss_DriverInfo8 *driver;
|
|---|
| 5040 | bool in_use = false;
|
|---|
| 5041 |
|
|---|
| 5042 | if ( !info )
|
|---|
| 5043 | return False;
|
|---|
| 5044 |
|
|---|
| 5045 | version = info->version;
|
|---|
| 5046 |
|
|---|
| 5047 | /* loop over all driver versions */
|
|---|
| 5048 |
|
|---|
| 5049 | DEBUG(5,("printer_driver_files_in_use: Beginning search through ntdrivers.tdb...\n"));
|
|---|
| 5050 |
|
|---|
| 5051 | /* get the list of drivers */
|
|---|
| 5052 |
|
|---|
| 5053 | list = NULL;
|
|---|
| 5054 | ndrivers = get_ntdrivers(&list, info->architecture, version);
|
|---|
| 5055 |
|
|---|
| 5056 | DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n",
|
|---|
| 5057 | ndrivers, info->architecture, version));
|
|---|
| 5058 |
|
|---|
| 5059 | /* check each driver for overlap in files */
|
|---|
| 5060 |
|
|---|
| 5061 | for (i=0; i<ndrivers; i++) {
|
|---|
| 5062 | DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
|
|---|
| 5063 |
|
|---|
| 5064 | driver = NULL;
|
|---|
| 5065 |
|
|---|
| 5066 | if (!W_ERROR_IS_OK(get_a_printer_driver(talloc_tos(), &driver, list[i], info->architecture, version))) {
|
|---|
| 5067 | SAFE_FREE(list);
|
|---|
| 5068 | return True;
|
|---|
| 5069 | }
|
|---|
| 5070 |
|
|---|
| 5071 | /* check if d2 uses any files from d1 */
|
|---|
| 5072 | /* only if this is a different driver than the one being deleted */
|
|---|
| 5073 |
|
|---|
| 5074 | if (!strequal(info->driver_name, driver->driver_name)) {
|
|---|
| 5075 | if (trim_overlap_drv_files(mem_ctx, info, driver)) {
|
|---|
| 5076 | /* mz: Do not instantly return -
|
|---|
| 5077 | * we need to ensure this file isn't
|
|---|
| 5078 | * also in use by other drivers. */
|
|---|
| 5079 | in_use = true;
|
|---|
| 5080 | }
|
|---|
| 5081 | }
|
|---|
| 5082 |
|
|---|
| 5083 | free_a_printer_driver(driver);
|
|---|
| 5084 | }
|
|---|
| 5085 |
|
|---|
| 5086 | SAFE_FREE(list);
|
|---|
| 5087 |
|
|---|
| 5088 | DEBUG(5,("printer_driver_files_in_use: Completed search through ntdrivers.tdb...\n"));
|
|---|
| 5089 |
|
|---|
| 5090 | return in_use;
|
|---|
| 5091 | }
|
|---|
| 5092 |
|
|---|
| 5093 | static NTSTATUS driver_unlink_internals(connection_struct *conn,
|
|---|
| 5094 | const char *name)
|
|---|
| 5095 | {
|
|---|
| 5096 | struct smb_filename *smb_fname = NULL;
|
|---|
| 5097 | NTSTATUS status;
|
|---|
| 5098 |
|
|---|
| 5099 | status = create_synthetic_smb_fname(talloc_tos(), name, NULL, NULL,
|
|---|
| 5100 | &smb_fname);
|
|---|
| 5101 | if (!NT_STATUS_IS_OK(status)) {
|
|---|
| 5102 | return status;
|
|---|
| 5103 | }
|
|---|
| 5104 |
|
|---|
| 5105 | status = unlink_internals(conn, NULL, 0, smb_fname, false);
|
|---|
| 5106 |
|
|---|
| 5107 | TALLOC_FREE(smb_fname);
|
|---|
| 5108 | return status;
|
|---|
| 5109 | }
|
|---|
| 5110 |
|
|---|
| 5111 | /****************************************************************************
|
|---|
| 5112 | Actually delete the driver files. Make sure that
|
|---|
| 5113 | printer_driver_files_in_use() return False before calling
|
|---|
| 5114 | this.
|
|---|
| 5115 | ****************************************************************************/
|
|---|
| 5116 |
|
|---|
| 5117 | static bool delete_driver_files(struct pipes_struct *rpc_pipe,
|
|---|
| 5118 | const struct spoolss_DriverInfo8 *r)
|
|---|
| 5119 | {
|
|---|
| 5120 | int i = 0;
|
|---|
| 5121 | char *s;
|
|---|
| 5122 | const char *file;
|
|---|
| 5123 | connection_struct *conn;
|
|---|
| 5124 | NTSTATUS nt_status;
|
|---|
| 5125 | char *oldcwd;
|
|---|
| 5126 | fstring printdollar;
|
|---|
| 5127 | int printdollar_snum;
|
|---|
| 5128 | bool ret = false;
|
|---|
| 5129 |
|
|---|
| 5130 | if (!r) {
|
|---|
| 5131 | return false;
|
|---|
| 5132 | }
|
|---|
| 5133 |
|
|---|
| 5134 | DEBUG(6,("delete_driver_files: deleting driver [%s] - version [%d]\n",
|
|---|
| 5135 | r->driver_name, r->version));
|
|---|
| 5136 |
|
|---|
| 5137 | fstrcpy(printdollar, "print$");
|
|---|
| 5138 |
|
|---|
| 5139 | printdollar_snum = find_service(printdollar);
|
|---|
| 5140 | if (printdollar_snum == -1) {
|
|---|
| 5141 | return false;
|
|---|
| 5142 | }
|
|---|
| 5143 |
|
|---|
| 5144 | nt_status = create_conn_struct(talloc_tos(), &conn, printdollar_snum,
|
|---|
| 5145 | lp_pathname(printdollar_snum),
|
|---|
| 5146 | rpc_pipe->server_info, &oldcwd);
|
|---|
| 5147 | if (!NT_STATUS_IS_OK(nt_status)) {
|
|---|
| 5148 | DEBUG(0,("delete_driver_files: create_conn_struct "
|
|---|
| 5149 | "returned %s\n", nt_errstr(nt_status)));
|
|---|
| 5150 | return false;
|
|---|
| 5151 | }
|
|---|
| 5152 |
|
|---|
| 5153 | if ( !CAN_WRITE(conn) ) {
|
|---|
| 5154 | DEBUG(3,("delete_driver_files: Cannot delete print driver when [print$] is read-only\n"));
|
|---|
| 5155 | goto fail;
|
|---|
| 5156 | }
|
|---|
| 5157 |
|
|---|
| 5158 | /* now delete the files; must strip the '\print$' string from
|
|---|
| 5159 | fron of path */
|
|---|
| 5160 |
|
|---|
| 5161 | if (r->driver_path && r->driver_path[0]) {
|
|---|
| 5162 | if ((s = strchr(&r->driver_path[1], '\\')) != NULL) {
|
|---|
| 5163 | file = s;
|
|---|
| 5164 | DEBUG(10,("deleting driverfile [%s]\n", s));
|
|---|
| 5165 | driver_unlink_internals(conn, file);
|
|---|
| 5166 | }
|
|---|
| 5167 | }
|
|---|
| 5168 |
|
|---|
| 5169 | if (r->config_file && r->config_file[0]) {
|
|---|
| 5170 | if ((s = strchr(&r->config_file[1], '\\')) != NULL) {
|
|---|
| 5171 | file = s;
|
|---|
| 5172 | DEBUG(10,("deleting configfile [%s]\n", s));
|
|---|
| 5173 | driver_unlink_internals(conn, file);
|
|---|
| 5174 | }
|
|---|
| 5175 | }
|
|---|
| 5176 |
|
|---|
| 5177 | if (r->data_file && r->data_file[0]) {
|
|---|
| 5178 | if ((s = strchr(&r->data_file[1], '\\')) != NULL) {
|
|---|
| 5179 | file = s;
|
|---|
| 5180 | DEBUG(10,("deleting datafile [%s]\n", s));
|
|---|
| 5181 | driver_unlink_internals(conn, file);
|
|---|
| 5182 | }
|
|---|
| 5183 | }
|
|---|
| 5184 |
|
|---|
| 5185 | if (r->help_file && r->help_file[0]) {
|
|---|
| 5186 | if ((s = strchr(&r->help_file[1], '\\')) != NULL) {
|
|---|
| 5187 | file = s;
|
|---|
| 5188 | DEBUG(10,("deleting helpfile [%s]\n", s));
|
|---|
| 5189 | driver_unlink_internals(conn, file);
|
|---|
| 5190 | }
|
|---|
| 5191 | }
|
|---|
| 5192 |
|
|---|
| 5193 | /* check if we are done removing files */
|
|---|
| 5194 |
|
|---|
| 5195 | if (r->dependent_files) {
|
|---|
| 5196 | while (r->dependent_files[i] && r->dependent_files[i][0]) {
|
|---|
| 5197 | char *p;
|
|---|
| 5198 |
|
|---|
| 5199 | /* bypass the "\print$" portion of the path */
|
|---|
| 5200 |
|
|---|
| 5201 | if ((p = strchr(r->dependent_files[i]+1, '\\')) != NULL) {
|
|---|
| 5202 | file = p;
|
|---|
| 5203 | DEBUG(10,("deleting dependent file [%s]\n", file));
|
|---|
| 5204 | driver_unlink_internals(conn, file);
|
|---|
| 5205 | }
|
|---|
| 5206 |
|
|---|
| 5207 | i++;
|
|---|
| 5208 | }
|
|---|
| 5209 | }
|
|---|
| 5210 |
|
|---|
| 5211 | goto done;
|
|---|
| 5212 | fail:
|
|---|
| 5213 | ret = false;
|
|---|
| 5214 | done:
|
|---|
| 5215 | if (conn != NULL) {
|
|---|
| 5216 | vfs_ChDir(conn, oldcwd);
|
|---|
| 5217 | conn_free(conn);
|
|---|
| 5218 | }
|
|---|
| 5219 | return ret;
|
|---|
| 5220 | }
|
|---|
| 5221 |
|
|---|
| 5222 | /****************************************************************************
|
|---|
| 5223 | Remove a printer driver from the TDB. This assumes that the the driver was
|
|---|
| 5224 | previously looked up.
|
|---|
| 5225 | ***************************************************************************/
|
|---|
| 5226 |
|
|---|
| 5227 | WERROR delete_printer_driver(struct pipes_struct *rpc_pipe,
|
|---|
| 5228 | const struct spoolss_DriverInfo8 *r,
|
|---|
| 5229 | uint32 version, bool delete_files )
|
|---|
| 5230 | {
|
|---|
| 5231 | char *key = NULL;
|
|---|
| 5232 | const char *arch;
|
|---|
| 5233 | TDB_DATA dbuf;
|
|---|
| 5234 |
|
|---|
| 5235 | /* delete the tdb data first */
|
|---|
| 5236 |
|
|---|
| 5237 | arch = get_short_archi(r->architecture);
|
|---|
| 5238 | if (!arch) {
|
|---|
| 5239 | return WERR_UNKNOWN_PRINTER_DRIVER;
|
|---|
| 5240 | }
|
|---|
| 5241 | if (asprintf(&key, "%s%s/%d/%s", DRIVERS_PREFIX,
|
|---|
| 5242 | arch, version, r->driver_name) < 0) {
|
|---|
| 5243 | return WERR_NOMEM;
|
|---|
| 5244 | }
|
|---|
| 5245 |
|
|---|
| 5246 | DEBUG(5,("delete_printer_driver: key = [%s] delete_files = %s\n",
|
|---|
| 5247 | key, delete_files ? "TRUE" : "FALSE" ));
|
|---|
| 5248 |
|
|---|
| 5249 | /* check if the driver actually exists for this environment */
|
|---|
| 5250 |
|
|---|
| 5251 | dbuf = tdb_fetch_bystring( tdb_drivers, key );
|
|---|
| 5252 | if ( !dbuf.dptr ) {
|
|---|
| 5253 | DEBUG(8,("delete_printer_driver: Driver unknown [%s]\n", key));
|
|---|
| 5254 | SAFE_FREE(key);
|
|---|
| 5255 | return WERR_UNKNOWN_PRINTER_DRIVER;
|
|---|
| 5256 | }
|
|---|
| 5257 |
|
|---|
| 5258 | SAFE_FREE( dbuf.dptr );
|
|---|
| 5259 |
|
|---|
| 5260 | /* ok... the driver exists so the delete should return success */
|
|---|
| 5261 |
|
|---|
| 5262 | if (tdb_delete_bystring(tdb_drivers, key) == -1) {
|
|---|
| 5263 | DEBUG (0,("delete_printer_driver: fail to delete %s!\n", key));
|
|---|
| 5264 | SAFE_FREE(key);
|
|---|
| 5265 | return WERR_ACCESS_DENIED;
|
|---|
| 5266 | }
|
|---|
| 5267 |
|
|---|
| 5268 | /*
|
|---|
| 5269 | * now delete any associated files if delete_files == True
|
|---|
| 5270 | * even if this part failes, we return succes because the
|
|---|
| 5271 | * driver doesn not exist any more
|
|---|
| 5272 | */
|
|---|
| 5273 |
|
|---|
| 5274 | if ( delete_files )
|
|---|
| 5275 | delete_driver_files(rpc_pipe, r);
|
|---|
| 5276 |
|
|---|
| 5277 | DEBUG(5,("delete_printer_driver: driver delete successful [%s]\n", key));
|
|---|
| 5278 | SAFE_FREE(key);
|
|---|
| 5279 |
|
|---|
| 5280 | return WERR_OK;
|
|---|
| 5281 | }
|
|---|
| 5282 |
|
|---|
| 5283 | /****************************************************************************
|
|---|
| 5284 | Store a security desc for a printer.
|
|---|
| 5285 | ****************************************************************************/
|
|---|
| 5286 |
|
|---|
| 5287 | WERROR nt_printing_setsec(const char *sharename, SEC_DESC_BUF *secdesc_ctr)
|
|---|
| 5288 | {
|
|---|
| 5289 | SEC_DESC_BUF *new_secdesc_ctr = NULL;
|
|---|
| 5290 | SEC_DESC_BUF *old_secdesc_ctr = NULL;
|
|---|
| 5291 | TALLOC_CTX *mem_ctx = NULL;
|
|---|
| 5292 | TDB_DATA kbuf;
|
|---|
| 5293 | TDB_DATA dbuf;
|
|---|
| 5294 | DATA_BLOB blob;
|
|---|
| 5295 | WERROR status;
|
|---|
| 5296 | NTSTATUS nt_status;
|
|---|
| 5297 |
|
|---|
| 5298 | mem_ctx = talloc_init("nt_printing_setsec");
|
|---|
| 5299 | if (mem_ctx == NULL)
|
|---|
| 5300 | return WERR_NOMEM;
|
|---|
| 5301 |
|
|---|
| 5302 | /* The old owner and group sids of the security descriptor are not
|
|---|
| 5303 | present when new ACEs are added or removed by changing printer
|
|---|
| 5304 | permissions through NT. If they are NULL in the new security
|
|---|
| 5305 | descriptor then copy them over from the old one. */
|
|---|
| 5306 |
|
|---|
| 5307 | if (!secdesc_ctr->sd->owner_sid || !secdesc_ctr->sd->group_sid) {
|
|---|
| 5308 | DOM_SID *owner_sid, *group_sid;
|
|---|
| 5309 | SEC_ACL *dacl, *sacl;
|
|---|
| 5310 | SEC_DESC *psd = NULL;
|
|---|
| 5311 | size_t size;
|
|---|
| 5312 |
|
|---|
| 5313 | if (!nt_printing_getsec(mem_ctx, sharename, &old_secdesc_ctr)) {
|
|---|
| 5314 | status = WERR_NOMEM;
|
|---|
| 5315 | goto out;
|
|---|
| 5316 | }
|
|---|
| 5317 |
|
|---|
| 5318 | /* Pick out correct owner and group sids */
|
|---|
| 5319 |
|
|---|
| 5320 | owner_sid = secdesc_ctr->sd->owner_sid ?
|
|---|
| 5321 | secdesc_ctr->sd->owner_sid :
|
|---|
| 5322 | old_secdesc_ctr->sd->owner_sid;
|
|---|
| 5323 |
|
|---|
| 5324 | group_sid = secdesc_ctr->sd->group_sid ?
|
|---|
| 5325 | secdesc_ctr->sd->group_sid :
|
|---|
| 5326 | old_secdesc_ctr->sd->group_sid;
|
|---|
| 5327 |
|
|---|
| 5328 | dacl = secdesc_ctr->sd->dacl ?
|
|---|
| 5329 | secdesc_ctr->sd->dacl :
|
|---|
| 5330 | old_secdesc_ctr->sd->dacl;
|
|---|
| 5331 |
|
|---|
| 5332 | sacl = secdesc_ctr->sd->sacl ?
|
|---|
| 5333 | secdesc_ctr->sd->sacl :
|
|---|
| 5334 | old_secdesc_ctr->sd->sacl;
|
|---|
| 5335 |
|
|---|
| 5336 | /* Make a deep copy of the security descriptor */
|
|---|
| 5337 |
|
|---|
| 5338 | psd = make_sec_desc(mem_ctx, secdesc_ctr->sd->revision, secdesc_ctr->sd->type,
|
|---|
| 5339 | owner_sid, group_sid,
|
|---|
| 5340 | sacl,
|
|---|
| 5341 | dacl,
|
|---|
| 5342 | &size);
|
|---|
| 5343 |
|
|---|
| 5344 | if (!psd) {
|
|---|
| 5345 | status = WERR_NOMEM;
|
|---|
| 5346 | goto out;
|
|---|
| 5347 | }
|
|---|
| 5348 |
|
|---|
| 5349 | new_secdesc_ctr = make_sec_desc_buf(mem_ctx, size, psd);
|
|---|
| 5350 | }
|
|---|
| 5351 |
|
|---|
| 5352 | if (!new_secdesc_ctr) {
|
|---|
| 5353 | new_secdesc_ctr = secdesc_ctr;
|
|---|
| 5354 | }
|
|---|
| 5355 |
|
|---|
| 5356 | /* Store the security descriptor in a tdb */
|
|---|
| 5357 |
|
|---|
| 5358 | nt_status = marshall_sec_desc_buf(mem_ctx, new_secdesc_ctr,
|
|---|
| 5359 | &blob.data, &blob.length);
|
|---|
| 5360 | if (!NT_STATUS_IS_OK(nt_status)) {
|
|---|
| 5361 | status = ntstatus_to_werror(nt_status);
|
|---|
| 5362 | goto out;
|
|---|
| 5363 | }
|
|---|
| 5364 |
|
|---|
| 5365 | kbuf = make_printers_secdesc_tdbkey(mem_ctx, sharename );
|
|---|
| 5366 |
|
|---|
| 5367 | dbuf.dptr = (unsigned char *)blob.data;
|
|---|
| 5368 | dbuf.dsize = blob.length;
|
|---|
| 5369 |
|
|---|
| 5370 | if (tdb_trans_store(tdb_printers, kbuf, dbuf, TDB_REPLACE)==0) {
|
|---|
| 5371 | status = WERR_OK;
|
|---|
| 5372 | } else {
|
|---|
| 5373 | DEBUG(1,("Failed to store secdesc for %s\n", sharename));
|
|---|
| 5374 | status = WERR_BADFUNC;
|
|---|
| 5375 | }
|
|---|
| 5376 |
|
|---|
| 5377 | /* Free malloc'ed memory */
|
|---|
| 5378 | talloc_free(blob.data);
|
|---|
| 5379 |
|
|---|
| 5380 | out:
|
|---|
| 5381 |
|
|---|
| 5382 | if (mem_ctx)
|
|---|
| 5383 | talloc_destroy(mem_ctx);
|
|---|
| 5384 | return status;
|
|---|
| 5385 | }
|
|---|
| 5386 |
|
|---|
| 5387 | /****************************************************************************
|
|---|
| 5388 | Construct a default security descriptor buffer for a printer.
|
|---|
| 5389 | ****************************************************************************/
|
|---|
| 5390 |
|
|---|
| 5391 | static SEC_DESC_BUF *construct_default_printer_sdb(TALLOC_CTX *ctx)
|
|---|
| 5392 | {
|
|---|
| 5393 | SEC_ACE ace[5]; /* max number of ace entries */
|
|---|
| 5394 | int i = 0;
|
|---|
| 5395 | uint32_t sa;
|
|---|
| 5396 | SEC_ACL *psa = NULL;
|
|---|
| 5397 | SEC_DESC_BUF *sdb = NULL;
|
|---|
| 5398 | SEC_DESC *psd = NULL;
|
|---|
| 5399 | DOM_SID adm_sid;
|
|---|
| 5400 | size_t sd_size;
|
|---|
| 5401 |
|
|---|
| 5402 | /* Create an ACE where Everyone is allowed to print */
|
|---|
| 5403 |
|
|---|
| 5404 | sa = PRINTER_ACE_PRINT;
|
|---|
| 5405 | init_sec_ace(&ace[i++], &global_sid_World, SEC_ACE_TYPE_ACCESS_ALLOWED,
|
|---|
| 5406 | sa, SEC_ACE_FLAG_CONTAINER_INHERIT);
|
|---|
| 5407 |
|
|---|
| 5408 | /* Add the domain admins group if we are a DC */
|
|---|
| 5409 |
|
|---|
| 5410 | if ( IS_DC ) {
|
|---|
| 5411 | DOM_SID domadmins_sid;
|
|---|
| 5412 |
|
|---|
| 5413 | sid_copy(&domadmins_sid, get_global_sam_sid());
|
|---|
| 5414 | sid_append_rid(&domadmins_sid, DOMAIN_GROUP_RID_ADMINS);
|
|---|
| 5415 |
|
|---|
| 5416 | sa = PRINTER_ACE_FULL_CONTROL;
|
|---|
| 5417 | init_sec_ace(&ace[i++], &domadmins_sid,
|
|---|
| 5418 | SEC_ACE_TYPE_ACCESS_ALLOWED, sa,
|
|---|
| 5419 | SEC_ACE_FLAG_OBJECT_INHERIT | SEC_ACE_FLAG_INHERIT_ONLY);
|
|---|
| 5420 | init_sec_ace(&ace[i++], &domadmins_sid, SEC_ACE_TYPE_ACCESS_ALLOWED,
|
|---|
| 5421 | sa, SEC_ACE_FLAG_CONTAINER_INHERIT);
|
|---|
| 5422 | }
|
|---|
| 5423 | else if (secrets_fetch_domain_sid(lp_workgroup(), &adm_sid)) {
|
|---|
| 5424 | sid_append_rid(&adm_sid, DOMAIN_USER_RID_ADMIN);
|
|---|
| 5425 |
|
|---|
| 5426 | sa = PRINTER_ACE_FULL_CONTROL;
|
|---|
| 5427 | init_sec_ace(&ace[i++], &adm_sid,
|
|---|
| 5428 | SEC_ACE_TYPE_ACCESS_ALLOWED, sa,
|
|---|
| 5429 | SEC_ACE_FLAG_OBJECT_INHERIT | SEC_ACE_FLAG_INHERIT_ONLY);
|
|---|
| 5430 | init_sec_ace(&ace[i++], &adm_sid, SEC_ACE_TYPE_ACCESS_ALLOWED,
|
|---|
| 5431 | sa, SEC_ACE_FLAG_CONTAINER_INHERIT);
|
|---|
| 5432 | }
|
|---|
| 5433 |
|
|---|
| 5434 | /* add BUILTIN\Administrators as FULL CONTROL */
|
|---|
| 5435 |
|
|---|
| 5436 | sa = PRINTER_ACE_FULL_CONTROL;
|
|---|
| 5437 | init_sec_ace(&ace[i++], &global_sid_Builtin_Administrators,
|
|---|
| 5438 | SEC_ACE_TYPE_ACCESS_ALLOWED, sa,
|
|---|
| 5439 | SEC_ACE_FLAG_OBJECT_INHERIT | SEC_ACE_FLAG_INHERIT_ONLY);
|
|---|
| 5440 | init_sec_ace(&ace[i++], &global_sid_Builtin_Administrators,
|
|---|
| 5441 | SEC_ACE_TYPE_ACCESS_ALLOWED,
|
|---|
| 5442 | sa, SEC_ACE_FLAG_CONTAINER_INHERIT);
|
|---|
| 5443 |
|
|---|
| 5444 | /* Make the security descriptor owned by the BUILTIN\Administrators */
|
|---|
| 5445 |
|
|---|
| 5446 | /* The ACL revision number in rpc_secdesc.h differs from the one
|
|---|
| 5447 | created by NT when setting ACE entries in printer
|
|---|
| 5448 | descriptors. NT4 complains about the property being edited by a
|
|---|
| 5449 | NT5 machine. */
|
|---|
| 5450 |
|
|---|
| 5451 | if ((psa = make_sec_acl(ctx, NT4_ACL_REVISION, i, ace)) != NULL) {
|
|---|
| 5452 | psd = make_sec_desc(ctx, SEC_DESC_REVISION, SEC_DESC_SELF_RELATIVE,
|
|---|
| 5453 | &global_sid_Builtin_Administrators,
|
|---|
| 5454 | &global_sid_Builtin_Administrators,
|
|---|
| 5455 | NULL, psa, &sd_size);
|
|---|
| 5456 | }
|
|---|
| 5457 |
|
|---|
| 5458 | if (!psd) {
|
|---|
| 5459 | DEBUG(0,("construct_default_printer_sd: Failed to make SEC_DESC.\n"));
|
|---|
| 5460 | return NULL;
|
|---|
| 5461 | }
|
|---|
| 5462 |
|
|---|
| 5463 | sdb = make_sec_desc_buf(ctx, sd_size, psd);
|
|---|
| 5464 |
|
|---|
| 5465 | DEBUG(4,("construct_default_printer_sdb: size = %u.\n",
|
|---|
| 5466 | (unsigned int)sd_size));
|
|---|
| 5467 |
|
|---|
| 5468 | return sdb;
|
|---|
| 5469 | }
|
|---|
| 5470 |
|
|---|
| 5471 | /****************************************************************************
|
|---|
| 5472 | Get a security desc for a printer.
|
|---|
| 5473 | ****************************************************************************/
|
|---|
| 5474 |
|
|---|
| 5475 | bool nt_printing_getsec(TALLOC_CTX *ctx, const char *sharename, SEC_DESC_BUF **secdesc_ctr)
|
|---|
| 5476 | {
|
|---|
| 5477 | TDB_DATA kbuf;
|
|---|
| 5478 | TDB_DATA dbuf;
|
|---|
| 5479 | DATA_BLOB blob;
|
|---|
| 5480 | char *temp;
|
|---|
| 5481 | NTSTATUS status;
|
|---|
| 5482 |
|
|---|
| 5483 | if (strlen(sharename) > 2 && (temp = strchr(sharename + 2, '\\'))) {
|
|---|
| 5484 | sharename = temp + 1;
|
|---|
| 5485 | }
|
|---|
| 5486 |
|
|---|
| 5487 | /* Fetch security descriptor from tdb */
|
|---|
| 5488 |
|
|---|
| 5489 | kbuf = make_printers_secdesc_tdbkey(ctx, sharename);
|
|---|
| 5490 |
|
|---|
| 5491 | dbuf = tdb_fetch(tdb_printers, kbuf);
|
|---|
| 5492 | if (dbuf.dptr) {
|
|---|
| 5493 |
|
|---|
| 5494 | status = unmarshall_sec_desc_buf(ctx, dbuf.dptr, dbuf.dsize,
|
|---|
| 5495 | secdesc_ctr);
|
|---|
| 5496 | SAFE_FREE(dbuf.dptr);
|
|---|
| 5497 |
|
|---|
| 5498 | if (NT_STATUS_IS_OK(status)) {
|
|---|
| 5499 | return true;
|
|---|
| 5500 | }
|
|---|
| 5501 | }
|
|---|
| 5502 |
|
|---|
| 5503 | *secdesc_ctr = construct_default_printer_sdb(ctx);
|
|---|
| 5504 | if (!*secdesc_ctr) {
|
|---|
| 5505 | return false;
|
|---|
| 5506 | }
|
|---|
| 5507 |
|
|---|
| 5508 | status = marshall_sec_desc_buf(ctx, *secdesc_ctr,
|
|---|
| 5509 | &blob.data, &blob.length);
|
|---|
| 5510 | if (NT_STATUS_IS_OK(status)) {
|
|---|
| 5511 | dbuf.dptr = (unsigned char *)blob.data;
|
|---|
| 5512 | dbuf.dsize = blob.length;
|
|---|
| 5513 | tdb_trans_store(tdb_printers, kbuf, dbuf, TDB_REPLACE);
|
|---|
| 5514 | talloc_free(blob.data);
|
|---|
| 5515 | }
|
|---|
| 5516 |
|
|---|
| 5517 | /* If security descriptor is owned by S-1-1-0 and winbindd is up,
|
|---|
| 5518 | this security descriptor has been created when winbindd was
|
|---|
| 5519 | down. Take ownership of security descriptor. */
|
|---|
| 5520 |
|
|---|
| 5521 | if (sid_equal((*secdesc_ctr)->sd->owner_sid, &global_sid_World)) {
|
|---|
| 5522 | DOM_SID owner_sid;
|
|---|
| 5523 |
|
|---|
| 5524 | /* Change sd owner to workgroup administrator */
|
|---|
| 5525 |
|
|---|
| 5526 | if (secrets_fetch_domain_sid(lp_workgroup(), &owner_sid)) {
|
|---|
| 5527 | SEC_DESC_BUF *new_secdesc_ctr = NULL;
|
|---|
| 5528 | SEC_DESC *psd = NULL;
|
|---|
| 5529 | size_t size;
|
|---|
| 5530 |
|
|---|
| 5531 | /* Create new sd */
|
|---|
| 5532 |
|
|---|
| 5533 | sid_append_rid(&owner_sid, DOMAIN_USER_RID_ADMIN);
|
|---|
| 5534 |
|
|---|
| 5535 | psd = make_sec_desc(ctx, (*secdesc_ctr)->sd->revision, (*secdesc_ctr)->sd->type,
|
|---|
| 5536 | &owner_sid,
|
|---|
| 5537 | (*secdesc_ctr)->sd->group_sid,
|
|---|
| 5538 | (*secdesc_ctr)->sd->sacl,
|
|---|
| 5539 | (*secdesc_ctr)->sd->dacl,
|
|---|
| 5540 | &size);
|
|---|
| 5541 |
|
|---|
| 5542 | if (!psd) {
|
|---|
| 5543 | return False;
|
|---|
| 5544 | }
|
|---|
| 5545 |
|
|---|
| 5546 | new_secdesc_ctr = make_sec_desc_buf(ctx, size, psd);
|
|---|
| 5547 | if (!new_secdesc_ctr) {
|
|---|
| 5548 | return False;
|
|---|
| 5549 | }
|
|---|
| 5550 |
|
|---|
| 5551 | /* Swap with other one */
|
|---|
| 5552 |
|
|---|
| 5553 | *secdesc_ctr = new_secdesc_ctr;
|
|---|
| 5554 |
|
|---|
| 5555 | /* Set it */
|
|---|
| 5556 |
|
|---|
| 5557 | nt_printing_setsec(sharename, *secdesc_ctr);
|
|---|
| 5558 | }
|
|---|
| 5559 | }
|
|---|
| 5560 |
|
|---|
| 5561 | if (DEBUGLEVEL >= 10) {
|
|---|
| 5562 | SEC_ACL *the_acl = (*secdesc_ctr)->sd->dacl;
|
|---|
| 5563 | int i;
|
|---|
| 5564 |
|
|---|
| 5565 | DEBUG(10, ("secdesc_ctr for %s has %d aces:\n",
|
|---|
| 5566 | sharename, the_acl->num_aces));
|
|---|
| 5567 |
|
|---|
| 5568 | for (i = 0; i < the_acl->num_aces; i++) {
|
|---|
| 5569 | DEBUG(10, ("%s %d %d 0x%08x\n",
|
|---|
| 5570 | sid_string_dbg(&the_acl->aces[i].trustee),
|
|---|
| 5571 | the_acl->aces[i].type, the_acl->aces[i].flags,
|
|---|
| 5572 | the_acl->aces[i].access_mask));
|
|---|
| 5573 | }
|
|---|
| 5574 | }
|
|---|
| 5575 |
|
|---|
| 5576 | return True;
|
|---|
| 5577 | }
|
|---|
| 5578 |
|
|---|
| 5579 | /* error code:
|
|---|
| 5580 | 0: everything OK
|
|---|
| 5581 | 1: level not implemented
|
|---|
| 5582 | 2: file doesn't exist
|
|---|
| 5583 | 3: can't allocate memory
|
|---|
| 5584 | 4: can't free memory
|
|---|
| 5585 | 5: non existant struct
|
|---|
| 5586 | */
|
|---|
| 5587 |
|
|---|
| 5588 | /*
|
|---|
| 5589 | A printer and a printer driver are 2 different things.
|
|---|
| 5590 | NT manages them separatelly, Samba does the same.
|
|---|
| 5591 | Why ? Simply because it's easier and it makes sense !
|
|---|
| 5592 |
|
|---|
| 5593 | Now explanation: You have 3 printers behind your samba server,
|
|---|
| 5594 | 2 of them are the same make and model (laser A and B). But laser B
|
|---|
| 5595 | has an 3000 sheet feeder and laser A doesn't such an option.
|
|---|
| 5596 | Your third printer is an old dot-matrix model for the accounting :-).
|
|---|
| 5597 |
|
|---|
| 5598 | If the /usr/local/samba/lib directory (default dir), you will have
|
|---|
| 5599 | 5 files to describe all of this.
|
|---|
| 5600 |
|
|---|
| 5601 | 3 files for the printers (1 by printer):
|
|---|
| 5602 | NTprinter_laser A
|
|---|
| 5603 | NTprinter_laser B
|
|---|
| 5604 | NTprinter_accounting
|
|---|
| 5605 | 2 files for the drivers (1 for the laser and 1 for the dot matrix)
|
|---|
| 5606 | NTdriver_printer model X
|
|---|
| 5607 | NTdriver_printer model Y
|
|---|
| 5608 |
|
|---|
| 5609 | jfm: I should use this comment for the text file to explain
|
|---|
| 5610 | same thing for the forms BTW.
|
|---|
| 5611 | Je devrais mettre mes commentaires en francais, ca serait mieux :-)
|
|---|
| 5612 |
|
|---|
| 5613 | */
|
|---|
| 5614 |
|
|---|
| 5615 | /* Convert generic access rights to printer object specific access rights.
|
|---|
| 5616 | It turns out that NT4 security descriptors use generic access rights and
|
|---|
| 5617 | NT5 the object specific ones. */
|
|---|
| 5618 |
|
|---|
| 5619 | void map_printer_permissions(SEC_DESC *sd)
|
|---|
| 5620 | {
|
|---|
| 5621 | int i;
|
|---|
| 5622 |
|
|---|
| 5623 | for (i = 0; sd->dacl && i < sd->dacl->num_aces; i++) {
|
|---|
| 5624 | se_map_generic(&sd->dacl->aces[i].access_mask,
|
|---|
| 5625 | &printer_generic_mapping);
|
|---|
| 5626 | }
|
|---|
| 5627 | }
|
|---|
| 5628 |
|
|---|
| 5629 | void map_job_permissions(SEC_DESC *sd)
|
|---|
| 5630 | {
|
|---|
| 5631 | int i;
|
|---|
| 5632 |
|
|---|
| 5633 | for (i = 0; sd->dacl && i < sd->dacl->num_aces; i++) {
|
|---|
| 5634 | se_map_generic(&sd->dacl->aces[i].access_mask,
|
|---|
| 5635 | &job_generic_mapping);
|
|---|
| 5636 | }
|
|---|
| 5637 | }
|
|---|
| 5638 |
|
|---|
| 5639 |
|
|---|
| 5640 | /****************************************************************************
|
|---|
| 5641 | Check a user has permissions to perform the given operation. We use the
|
|---|
| 5642 | permission constants defined in include/rpc_spoolss.h to check the various
|
|---|
| 5643 | actions we perform when checking printer access.
|
|---|
| 5644 |
|
|---|
| 5645 | PRINTER_ACCESS_ADMINISTER:
|
|---|
| 5646 | print_queue_pause, print_queue_resume, update_printer_sec,
|
|---|
| 5647 | update_printer, spoolss_addprinterex_level_2,
|
|---|
| 5648 | _spoolss_setprinterdata
|
|---|
| 5649 |
|
|---|
| 5650 | PRINTER_ACCESS_USE:
|
|---|
| 5651 | print_job_start
|
|---|
| 5652 |
|
|---|
| 5653 | JOB_ACCESS_ADMINISTER:
|
|---|
| 5654 | print_job_delete, print_job_pause, print_job_resume,
|
|---|
| 5655 | print_queue_purge
|
|---|
| 5656 |
|
|---|
| 5657 | Try access control in the following order (for performance reasons):
|
|---|
| 5658 | 1) root and SE_PRINT_OPERATOR can do anything (easy check)
|
|---|
| 5659 | 2) check security descriptor (bit comparisons in memory)
|
|---|
| 5660 | 3) "printer admins" (may result in numerous calls to winbind)
|
|---|
| 5661 |
|
|---|
| 5662 | ****************************************************************************/
|
|---|
| 5663 | bool print_access_check(struct auth_serversupplied_info *server_info, int snum,
|
|---|
| 5664 | int access_type)
|
|---|
| 5665 | {
|
|---|
| 5666 | SEC_DESC_BUF *secdesc = NULL;
|
|---|
| 5667 | uint32 access_granted;
|
|---|
| 5668 | NTSTATUS status;
|
|---|
| 5669 | const char *pname;
|
|---|
| 5670 | TALLOC_CTX *mem_ctx = NULL;
|
|---|
| 5671 | SE_PRIV se_printop = SE_PRINT_OPERATOR;
|
|---|
| 5672 |
|
|---|
| 5673 | /* If user is NULL then use the current_user structure */
|
|---|
| 5674 |
|
|---|
| 5675 | /* Always allow root or SE_PRINT_OPERATROR to do anything */
|
|---|
| 5676 |
|
|---|
| 5677 | if (server_info->utok.uid == sec_initial_uid()
|
|---|
| 5678 | || user_has_privileges(server_info->ptok, &se_printop ) ) {
|
|---|
| 5679 | return True;
|
|---|
| 5680 | }
|
|---|
| 5681 |
|
|---|
| 5682 | /* Get printer name */
|
|---|
| 5683 |
|
|---|
| 5684 | pname = PRINTERNAME(snum);
|
|---|
| 5685 |
|
|---|
| 5686 | if (!pname || !*pname) {
|
|---|
| 5687 | errno = EACCES;
|
|---|
| 5688 | return False;
|
|---|
| 5689 | }
|
|---|
| 5690 |
|
|---|
| 5691 | /* Get printer security descriptor */
|
|---|
| 5692 |
|
|---|
| 5693 | if(!(mem_ctx = talloc_init("print_access_check"))) {
|
|---|
| 5694 | errno = ENOMEM;
|
|---|
| 5695 | return False;
|
|---|
| 5696 | }
|
|---|
| 5697 |
|
|---|
| 5698 | if (!nt_printing_getsec(mem_ctx, pname, &secdesc)) {
|
|---|
| 5699 | talloc_destroy(mem_ctx);
|
|---|
| 5700 | errno = ENOMEM;
|
|---|
| 5701 | return False;
|
|---|
| 5702 | }
|
|---|
| 5703 |
|
|---|
| 5704 | if (access_type == JOB_ACCESS_ADMINISTER) {
|
|---|
| 5705 | SEC_DESC_BUF *parent_secdesc = secdesc;
|
|---|
| 5706 |
|
|---|
| 5707 | /* Create a child security descriptor to check permissions
|
|---|
| 5708 | against. This is because print jobs are child objects
|
|---|
| 5709 | objects of a printer. */
|
|---|
| 5710 |
|
|---|
| 5711 | status = se_create_child_secdesc_buf(mem_ctx, &secdesc, parent_secdesc->sd, False);
|
|---|
| 5712 |
|
|---|
| 5713 | if (!NT_STATUS_IS_OK(status)) {
|
|---|
| 5714 | talloc_destroy(mem_ctx);
|
|---|
| 5715 | errno = map_errno_from_nt_status(status);
|
|---|
| 5716 | return False;
|
|---|
| 5717 | }
|
|---|
| 5718 |
|
|---|
| 5719 | map_job_permissions(secdesc->sd);
|
|---|
| 5720 | } else {
|
|---|
| 5721 | map_printer_permissions(secdesc->sd);
|
|---|
| 5722 | }
|
|---|
| 5723 |
|
|---|
| 5724 | /* Check access */
|
|---|
| 5725 | status = se_access_check(secdesc->sd, server_info->ptok, access_type,
|
|---|
| 5726 | &access_granted);
|
|---|
| 5727 |
|
|---|
| 5728 | DEBUG(4, ("access check was %s\n", NT_STATUS_IS_OK(status) ? "SUCCESS" : "FAILURE"));
|
|---|
| 5729 |
|
|---|
| 5730 | /* see if we need to try the printer admin list */
|
|---|
| 5731 |
|
|---|
| 5732 | if (!NT_STATUS_IS_OK(status) &&
|
|---|
| 5733 | (token_contains_name_in_list(uidtoname(server_info->utok.uid),
|
|---|
| 5734 | pdb_get_domain(server_info->sam_account),
|
|---|
| 5735 | NULL,
|
|---|
| 5736 | server_info->ptok,
|
|---|
| 5737 | lp_printer_admin(snum)))) {
|
|---|
| 5738 | talloc_destroy(mem_ctx);
|
|---|
| 5739 | return True;
|
|---|
| 5740 | }
|
|---|
| 5741 |
|
|---|
| 5742 | talloc_destroy(mem_ctx);
|
|---|
| 5743 |
|
|---|
| 5744 | if (!NT_STATUS_IS_OK(status)) {
|
|---|
| 5745 | errno = EACCES;
|
|---|
| 5746 | }
|
|---|
| 5747 |
|
|---|
| 5748 | return NT_STATUS_IS_OK(status);
|
|---|
| 5749 | }
|
|---|
| 5750 |
|
|---|
| 5751 | /****************************************************************************
|
|---|
| 5752 | Check the time parameters allow a print operation.
|
|---|
| 5753 | *****************************************************************************/
|
|---|
| 5754 |
|
|---|
| 5755 | bool print_time_access_check(const char *servicename)
|
|---|
| 5756 | {
|
|---|
| 5757 | NT_PRINTER_INFO_LEVEL *printer = NULL;
|
|---|
| 5758 | bool ok = False;
|
|---|
| 5759 | time_t now = time(NULL);
|
|---|
| 5760 | struct tm *t;
|
|---|
| 5761 | uint32 mins;
|
|---|
| 5762 |
|
|---|
| 5763 | if (!W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, servicename)))
|
|---|
| 5764 | return False;
|
|---|
| 5765 |
|
|---|
| 5766 | if (printer->info_2->starttime == 0 && printer->info_2->untiltime == 0)
|
|---|
| 5767 | ok = True;
|
|---|
| 5768 |
|
|---|
| 5769 | t = gmtime(&now);
|
|---|
| 5770 | mins = (uint32)t->tm_hour*60 + (uint32)t->tm_min;
|
|---|
| 5771 |
|
|---|
| 5772 | if (mins >= printer->info_2->starttime && mins <= printer->info_2->untiltime)
|
|---|
| 5773 | ok = True;
|
|---|
| 5774 |
|
|---|
| 5775 | free_a_printer(&printer, 2);
|
|---|
| 5776 |
|
|---|
| 5777 | if (!ok)
|
|---|
| 5778 | errno = EACCES;
|
|---|
| 5779 |
|
|---|
| 5780 | return ok;
|
|---|
| 5781 | }
|
|---|
| 5782 |
|
|---|
| 5783 | /****************************************************************************
|
|---|
| 5784 | Fill in the servername sent in the _spoolss_open_printer_ex() call
|
|---|
| 5785 | ****************************************************************************/
|
|---|
| 5786 |
|
|---|
| 5787 | char* get_server_name( Printer_entry *printer )
|
|---|
| 5788 | {
|
|---|
| 5789 | return printer->servername;
|
|---|
| 5790 | }
|
|---|
| 5791 |
|
|---|
| 5792 |
|
|---|