2000-11-15 00:56:32 +03:00
/*
2002-03-22 09:24:38 +03:00
* Unix SMB / CIFS implementation .
2000-03-10 20:12:24 +03:00
* RPC Pipe client / server routines
* Copyright ( C ) Andrew Tridgell 1992 - 2000 ,
2004-04-13 18:39:48 +04:00
* Copyright ( C ) Jean François Micouleau 1998 - 2000.
2003-02-25 23:53:53 +03:00
* Copyright ( C ) Gerald Carter 2002 - 2003.
2000-11-15 00:56:32 +03:00
*
2000-03-10 20:12:24 +03:00
* This program is free software ; you can redistribute it and / or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation ; either version 2 of the License , or
* ( at your option ) any later version .
2000-11-15 00:56:32 +03:00
*
2000-03-10 20:12:24 +03:00
* This program is distributed in the hope that it will be useful ,
* but WITHOUT ANY WARRANTY ; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the
* GNU General Public License for more details .
2000-11-15 00:56:32 +03:00
*
2000-03-10 20:12:24 +03:00
* You should have received a copy of the GNU General Public License
* along with this program ; if not , write to the Free Software
* Foundation , Inc . , 675 Mass Ave , Cambridge , MA 0213 9 , USA .
*/
2000-02-07 19:17:59 +03:00
# include "includes.h"
2000-11-15 00:56:32 +03:00
extern DOM_SID global_sid_World ;
2000-02-07 19:17:59 +03:00
2001-07-09 22:19:04 +04:00
static TDB_CONTEXT * tdb_forms ; /* used for forms files */
static TDB_CONTEXT * tdb_drivers ; /* used for driver files */
static TDB_CONTEXT * tdb_printers ; /* used for printers files */
2000-05-24 10:10:21 +04:00
# define FORMS_PREFIX "FORMS / "
# define DRIVERS_PREFIX "DRIVERS / "
2001-08-10 23:38:53 +04:00
# define DRIVER_INIT_PREFIX "DRIVER_INIT / "
2000-05-24 10:10:21 +04:00
# define PRINTERS_PREFIX "PRINTERS / "
2001-07-09 22:19:04 +04:00
# define SECDESC_PREFIX "SECDESC / "
2002-02-09 07:10:24 +03:00
# define GLOBAL_C_SETPRINTER "GLOBALS / c_setprinter"
2001-08-10 23:38:53 +04:00
2001-07-09 22:19:04 +04:00
# define NTDRIVERS_DATABASE_VERSION_1 1
# define NTDRIVERS_DATABASE_VERSION_2 2
2002-01-09 08:24:07 +03:00
# define NTDRIVERS_DATABASE_VERSION_3 3 /* little endian version of v2 */
2001-08-10 23:38:53 +04:00
2002-01-09 08:24:07 +03:00
# define NTDRIVERS_DATABASE_VERSION NTDRIVERS_DATABASE_VERSION_3
2000-05-24 10:10:21 +04:00
2001-01-04 22:27:08 +03:00
/* Map generic permissions to printer object specific permissions */
2002-03-15 11:14:10 +03:00
GENERIC_MAPPING printer_generic_mapping = {
PRINTER_READ ,
2002-04-11 07:15:02 +04:00
PRINTER_WRITE ,
2002-03-15 11:14:10 +03:00
PRINTER_EXECUTE ,
PRINTER_ALL_ACCESS
} ;
STANDARD_MAPPING printer_std_mapping = {
2001-01-04 22:27:08 +03:00
PRINTER_READ ,
PRINTER_WRITE ,
PRINTER_EXECUTE ,
PRINTER_ALL_ACCESS
} ;
2002-04-15 07:49:53 +04:00
/* Map generic permissions to print server object specific permissions */
GENERIC_MAPPING printserver_generic_mapping = {
SERVER_READ ,
SERVER_WRITE ,
SERVER_EXECUTE ,
SERVER_ALL_ACCESS
} ;
STANDARD_MAPPING printserver_std_mapping = {
SERVER_READ ,
SERVER_WRITE ,
SERVER_EXECUTE ,
SERVER_ALL_ACCESS
} ;
2000-09-29 01:33:08 +04:00
/* We need one default form to support our default printer. Msoft adds the
forms it wants and in the ORDER it wants them ( note : DEVMODE papersize is an
array index ) . Letter is always first , so ( for the current code ) additions
always put things in the correct order . */
2003-01-03 11:28:12 +03:00
static const nt_forms_struct default_forms [ ] = {
2001-04-04 02:41:31 +04:00
{ " Letter " , 0x1 , 0x34b5c , 0x44368 , 0x0 , 0x0 , 0x34b5c , 0x44368 } ,
{ " Letter Small " , 0x1 , 0x34b5c , 0x44368 , 0x0 , 0x0 , 0x34b5c , 0x44368 } ,
{ " Tabloid " , 0x1 , 0x44368 , 0x696b8 , 0x0 , 0x0 , 0x44368 , 0x696b8 } ,
{ " Ledger " , 0x1 , 0x696b8 , 0x44368 , 0x0 , 0x0 , 0x696b8 , 0x44368 } ,
{ " Legal " , 0x1 , 0x34b5c , 0x56d10 , 0x0 , 0x0 , 0x34b5c , 0x56d10 } ,
{ " Statement " , 0x1 , 0x221b4 , 0x34b5c , 0x0 , 0x0 , 0x221b4 , 0x34b5c } ,
{ " Executive " , 0x1 , 0x2cf56 , 0x411cc , 0x0 , 0x0 , 0x2cf56 , 0x411cc } ,
{ " A3 " , 0x1 , 0x48828 , 0x668a0 , 0x0 , 0x0 , 0x48828 , 0x668a0 } ,
{ " A4 " , 0x1 , 0x33450 , 0x48828 , 0x0 , 0x0 , 0x33450 , 0x48828 } ,
{ " A4 Small " , 0x1 , 0x33450 , 0x48828 , 0x0 , 0x0 , 0x33450 , 0x48828 } ,
{ " A5 " , 0x1 , 0x24220 , 0x33450 , 0x0 , 0x0 , 0x24220 , 0x33450 } ,
{ " B4 (JIS) " , 0x1 , 0x3ebe8 , 0x58de0 , 0x0 , 0x0 , 0x3ebe8 , 0x58de0 } ,
{ " B5 (JIS) " , 0x1 , 0x2c6f0 , 0x3ebe8 , 0x0 , 0x0 , 0x2c6f0 , 0x3ebe8 } ,
{ " Folio " , 0x1 , 0x34b5c , 0x509d8 , 0x0 , 0x0 , 0x34b5c , 0x509d8 } ,
{ " Quarto " , 0x1 , 0x347d8 , 0x43238 , 0x0 , 0x0 , 0x347d8 , 0x43238 } ,
{ " 10x14 " , 0x1 , 0x3e030 , 0x56d10 , 0x0 , 0x0 , 0x3e030 , 0x56d10 } ,
{ " 11x17 " , 0x1 , 0x44368 , 0x696b8 , 0x0 , 0x0 , 0x44368 , 0x696b8 } ,
{ " Note " , 0x1 , 0x34b5c , 0x44368 , 0x0 , 0x0 , 0x34b5c , 0x44368 } ,
{ " Envelope #9 " , 0x1 , 0x18079 , 0x37091 , 0x0 , 0x0 , 0x18079 , 0x37091 } ,
{ " Envelope #10 " , 0x1 , 0x19947 , 0x3ae94 , 0x0 , 0x0 , 0x19947 , 0x3ae94 } ,
{ " Envelope #11 " , 0x1 , 0x1be7c , 0x40565 , 0x0 , 0x0 , 0x1be7c , 0x40565 } ,
{ " Envelope #12 " , 0x1 , 0x1d74a , 0x44368 , 0x0 , 0x0 , 0x1d74a , 0x44368 } ,
{ " Envelope #14 " , 0x1 , 0x1f018 , 0x47504 , 0x0 , 0x0 , 0x1f018 , 0x47504 } ,
{ " C size sheet " , 0x1 , 0x696b8 , 0x886d0 , 0x0 , 0x0 , 0x696b8 , 0x886d0 } ,
{ " D size sheet " , 0x1 , 0x886d0 , 0xd2d70 , 0x0 , 0x0 , 0x886d0 , 0xd2d70 } ,
{ " E size sheet " , 0x1 , 0xd2d70 , 0x110da0 , 0x0 , 0x0 , 0xd2d70 , 0x110da0 } ,
{ " Envelope DL " , 0x1 , 0x1adb0 , 0x35b60 , 0x0 , 0x0 , 0x1adb0 , 0x35b60 } ,
{ " Envelope C5 " , 0x1 , 0x278d0 , 0x37e88 , 0x0 , 0x0 , 0x278d0 , 0x37e88 } ,
{ " Envelope C3 " , 0x1 , 0x4f1a0 , 0x6fd10 , 0x0 , 0x0 , 0x4f1a0 , 0x6fd10 } ,
{ " Envelope C4 " , 0x1 , 0x37e88 , 0x4f1a0 , 0x0 , 0x0 , 0x37e88 , 0x4f1a0 } ,
{ " Envelope C6 " , 0x1 , 0x1bd50 , 0x278d0 , 0x0 , 0x0 , 0x1bd50 , 0x278d0 } ,
{ " Envelope C65 " , 0x1 , 0x1bd50 , 0x37e88 , 0x0 , 0x0 , 0x1bd50 , 0x37e88 } ,
{ " Envelope B4 " , 0x1 , 0x3d090 , 0x562e8 , 0x0 , 0x0 , 0x3d090 , 0x562e8 } ,
{ " Envelope B5 " , 0x1 , 0x2af80 , 0x3d090 , 0x0 , 0x0 , 0x2af80 , 0x3d090 } ,
{ " Envelope B6 " , 0x1 , 0x2af80 , 0x1e848 , 0x0 , 0x0 , 0x2af80 , 0x1e848 } ,
{ " Envelope " , 0x1 , 0x1adb0 , 0x38270 , 0x0 , 0x0 , 0x1adb0 , 0x38270 } ,
{ " Envelope Monarch " , 0x1 , 0x18079 , 0x2e824 , 0x0 , 0x0 , 0x18079 , 0x2e824 } ,
{ " 6 3/4 Envelope " , 0x1 , 0x167ab , 0x284ec , 0x0 , 0x0 , 0x167ab , 0x284ec } ,
{ " US Std Fanfold " , 0x1 , 0x5c3e1 , 0x44368 , 0x0 , 0x0 , 0x5c3e1 , 0x44368 } ,
{ " German Std Fanfold " , 0x1 , 0x34b5c , 0x4a6a0 , 0x0 , 0x0 , 0x34b5c , 0x4a6a0 } ,
{ " German Legal Fanfold " , 0x1 , 0x34b5c , 0x509d8 , 0x0 , 0x0 , 0x34b5c , 0x509d8 } ,
{ " B4 (ISO) " , 0x1 , 0x3d090 , 0x562e8 , 0x0 , 0x0 , 0x3d090 , 0x562e8 } ,
{ " Japanese Postcard " , 0x1 , 0x186a0 , 0x24220 , 0x0 , 0x0 , 0x186a0 , 0x24220 } ,
{ " 9x11 " , 0x1 , 0x37cf8 , 0x44368 , 0x0 , 0x0 , 0x37cf8 , 0x44368 } ,
{ " 10x11 " , 0x1 , 0x3e030 , 0x44368 , 0x0 , 0x0 , 0x3e030 , 0x44368 } ,
{ " 15x11 " , 0x1 , 0x5d048 , 0x44368 , 0x0 , 0x0 , 0x5d048 , 0x44368 } ,
{ " Envelope Invite " , 0x1 , 0x35b60 , 0x35b60 , 0x0 , 0x0 , 0x35b60 , 0x35b60 } ,
{ " Reserved48 " , 0x1 , 0x1 , 0x1 , 0x0 , 0x0 , 0x1 , 0x1 } ,
{ " Reserved49 " , 0x1 , 0x1 , 0x1 , 0x0 , 0x0 , 0x1 , 0x1 } ,
{ " Letter Extra " , 0x1 , 0x3ae94 , 0x4a6a0 , 0x0 , 0x0 , 0x3ae94 , 0x4a6a0 } ,
{ " Legal Extra " , 0x1 , 0x3ae94 , 0x5d048 , 0x0 , 0x0 , 0x3ae94 , 0x5d048 } ,
{ " Tabloid Extra " , 0x1 , 0x4a6a0 , 0x6f9f0 , 0x0 , 0x0 , 0x4a6a0 , 0x6f9f0 } ,
{ " A4 Extra " , 0x1 , 0x397c2 , 0x4eb16 , 0x0 , 0x0 , 0x397c2 , 0x4eb16 } ,
{ " Letter Transverse " , 0x1 , 0x34b5c , 0x44368 , 0x0 , 0x0 , 0x34b5c , 0x44368 } ,
{ " A4 Transverse " , 0x1 , 0x33450 , 0x48828 , 0x0 , 0x0 , 0x33450 , 0x48828 } ,
{ " Letter Extra Transverse " , 0x1 , 0x3ae94 , 0x4a6a0 , 0x0 , 0x0 , 0x3ae94 , 0x4a6a0 } ,
{ " Super A " , 0x1 , 0x376b8 , 0x56ea0 , 0x0 , 0x0 , 0x376b8 , 0x56ea0 } ,
{ " Super B " , 0x1 , 0x4a768 , 0x76e58 , 0x0 , 0x0 , 0x4a768 , 0x76e58 } ,
{ " Letter Plus " , 0x1 , 0x34b5c , 0x4eb16 , 0x0 , 0x0 , 0x34b5c , 0x4eb16 } ,
{ " A4 Plus " , 0x1 , 0x33450 , 0x50910 , 0x0 , 0x0 , 0x33450 , 0x50910 } ,
{ " A5 Transverse " , 0x1 , 0x24220 , 0x33450 , 0x0 , 0x0 , 0x24220 , 0x33450 } ,
{ " B5 (JIS) Transverse " , 0x1 , 0x2c6f0 , 0x3ebe8 , 0x0 , 0x0 , 0x2c6f0 , 0x3ebe8 } ,
{ " A3 Extra " , 0x1 , 0x4e9d0 , 0x6ca48 , 0x0 , 0x0 , 0x4e9d0 , 0x6ca48 } ,
{ " A5 Extra " , 0x1 , 0x2a7b0 , 0x395f8 , 0x0 , 0x0 , 0x2a7b0 , 0x395f8 } ,
{ " B5 (ISO) Extra " , 0x1 , 0x31128 , 0x43620 , 0x0 , 0x0 , 0x31128 , 0x43620 } ,
{ " A2 " , 0x1 , 0x668a0 , 0x91050 , 0x0 , 0x0 , 0x668a0 , 0x91050 } ,
{ " A3 Transverse " , 0x1 , 0x48828 , 0x668a0 , 0x0 , 0x0 , 0x48828 , 0x668a0 } ,
{ " A3 Extra Transverse " , 0x1 , 0x4e9d0 , 0x6ca48 , 0x0 , 0x0 , 0x4e9d0 , 0x6ca48 } ,
{ " Japanese Double Postcard " , 0x1 , 0x30d40 , 0x24220 , 0x0 , 0x0 , 0x30d40 , 0x24220 } ,
{ " A6 " , 0x1 , 0x19a28 , 0x24220 , 0x0 , 0x0 , 0x19a28 , 0x24220 } ,
{ " Japanese Envelope Kaku #2 " , 0x1 , 0x3a980 , 0x510e0 , 0x0 , 0x0 , 0x3a980 , 0x510e0 } ,
{ " Japanese Envelope Kaku #3 " , 0x1 , 0x34bc0 , 0x43a08 , 0x0 , 0x0 , 0x34bc0 , 0x43a08 } ,
{ " Japanese Envelope Chou #3 " , 0x1 , 0x1d4c0 , 0x395f8 , 0x0 , 0x0 , 0x1d4c0 , 0x395f8 } ,
{ " Japanese Envelope Chou #4 " , 0x1 , 0x15f90 , 0x320c8 , 0x0 , 0x0 , 0x15f90 , 0x320c8 } ,
{ " Letter Rotated " , 0x1 , 0x44368 , 0x34b5c , 0x0 , 0x0 , 0x44368 , 0x34b5c } ,
{ " A3 Rotated " , 0x1 , 0x668a0 , 0x48828 , 0x0 , 0x0 , 0x668a0 , 0x48828 } ,
{ " A4 Rotated " , 0x1 , 0x48828 , 0x33450 , 0x0 , 0x0 , 0x48828 , 0x33450 } ,
{ " A5 Rotated " , 0x1 , 0x33450 , 0x24220 , 0x0 , 0x0 , 0x33450 , 0x24220 } ,
{ " B4 (JIS) Rotated " , 0x1 , 0x58de0 , 0x3ebe8 , 0x0 , 0x0 , 0x58de0 , 0x3ebe8 } ,
{ " B5 (JIS) Rotated " , 0x1 , 0x3ebe8 , 0x2c6f0 , 0x0 , 0x0 , 0x3ebe8 , 0x2c6f0 } ,
{ " Japanese Postcard Rotated " , 0x1 , 0x24220 , 0x186a0 , 0x0 , 0x0 , 0x24220 , 0x186a0 } ,
{ " Double Japan Postcard Rotated " , 0x1 , 0x24220 , 0x30d40 , 0x0 , 0x0 , 0x24220 , 0x30d40 } ,
{ " A6 Rotated " , 0x1 , 0x24220 , 0x19a28 , 0x0 , 0x0 , 0x24220 , 0x19a28 } ,
{ " Japan Envelope Kaku #2 Rotated " , 0x1 , 0x510e0 , 0x3a980 , 0x0 , 0x0 , 0x510e0 , 0x3a980 } ,
{ " Japan Envelope Kaku #3 Rotated " , 0x1 , 0x43a08 , 0x34bc0 , 0x0 , 0x0 , 0x43a08 , 0x34bc0 } ,
{ " Japan Envelope Chou #3 Rotated " , 0x1 , 0x395f8 , 0x1d4c0 , 0x0 , 0x0 , 0x395f8 , 0x1d4c0 } ,
{ " Japan Envelope Chou #4 Rotated " , 0x1 , 0x320c8 , 0x15f90 , 0x0 , 0x0 , 0x320c8 , 0x15f90 } ,
{ " B6 (JIS) " , 0x1 , 0x1f400 , 0x2c6f0 , 0x0 , 0x0 , 0x1f400 , 0x2c6f0 } ,
{ " B6 (JIS) Rotated " , 0x1 , 0x2c6f0 , 0x1f400 , 0x0 , 0x0 , 0x2c6f0 , 0x1f400 } ,
{ " 12x11 " , 0x1 , 0x4a724 , 0x443e1 , 0x0 , 0x0 , 0x4a724 , 0x443e1 } ,
{ " Japan Envelope You #4 " , 0x1 , 0x19a28 , 0x395f8 , 0x0 , 0x0 , 0x19a28 , 0x395f8 } ,
{ " Japan Envelope You #4 Rotated " , 0x1 , 0x395f8 , 0x19a28 , 0x0 , 0x0 , 0x395f8 , 0x19a28 } ,
{ " PRC 16K " , 0x1 , 0x2de60 , 0x3f7a0 , 0x0 , 0x0 , 0x2de60 , 0x3f7a0 } ,
{ " PRC 32K " , 0x1 , 0x1fbd0 , 0x2cec0 , 0x0 , 0x0 , 0x1fbd0 , 0x2cec0 } ,
{ " PRC 32K(Big) " , 0x1 , 0x222e0 , 0x318f8 , 0x0 , 0x0 , 0x222e0 , 0x318f8 } ,
{ " PRC Envelope #1 " , 0x1 , 0x18e70 , 0x28488 , 0x0 , 0x0 , 0x18e70 , 0x28488 } ,
{ " PRC Envelope #2 " , 0x1 , 0x18e70 , 0x2af80 , 0x0 , 0x0 , 0x18e70 , 0x2af80 } ,
{ " PRC Envelope #3 " , 0x1 , 0x1e848 , 0x2af80 , 0x0 , 0x0 , 0x1e848 , 0x2af80 } ,
{ " PRC Envelope #4 " , 0x1 , 0x1adb0 , 0x32c80 , 0x0 , 0x0 , 0x1adb0 , 0x32c80 } ,
{ " PRC Envelope #5 " , 0x1 , 0x1adb0 , 0x35b60 , 0x0 , 0x0 , 0x1adb0 , 0x35b60 } ,
{ " PRC Envelope #6 " , 0x1 , 0x1d4c0 , 0x38270 , 0x0 , 0x0 , 0x1d4c0 , 0x38270 } ,
{ " PRC Envelope #7 " , 0x1 , 0x27100 , 0x38270 , 0x0 , 0x0 , 0x27100 , 0x38270 } ,
{ " PRC Envelope #8 " , 0x1 , 0x1d4c0 , 0x4b708 , 0x0 , 0x0 , 0x1d4c0 , 0x4b708 } ,
{ " PRC Envelope #9 " , 0x1 , 0x37e88 , 0x4f1a0 , 0x0 , 0x0 , 0x37e88 , 0x4f1a0 } ,
{ " PRC Envelope #10 " , 0x1 , 0x4f1a0 , 0x6fd10 , 0x0 , 0x0 , 0x4f1a0 , 0x6fd10 } ,
{ " PRC 16K Rotated " , 0x1 , 0x3f7a0 , 0x2de60 , 0x0 , 0x0 , 0x3f7a0 , 0x2de60 } ,
{ " PRC 32K Rotated " , 0x1 , 0x2cec0 , 0x1fbd0 , 0x0 , 0x0 , 0x2cec0 , 0x1fbd0 } ,
{ " PRC 32K(Big) Rotated " , 0x1 , 0x318f8 , 0x222e0 , 0x0 , 0x0 , 0x318f8 , 0x222e0 } ,
{ " PRC Envelope #1 Rotated " , 0x1 , 0x28488 , 0x18e70 , 0x0 , 0x0 , 0x28488 , 0x18e70 } ,
{ " PRC Envelope #2 Rotated " , 0x1 , 0x2af80 , 0x18e70 , 0x0 , 0x0 , 0x2af80 , 0x18e70 } ,
{ " PRC Envelope #3 Rotated " , 0x1 , 0x2af80 , 0x1e848 , 0x0 , 0x0 , 0x2af80 , 0x1e848 } ,
{ " PRC Envelope #4 Rotated " , 0x1 , 0x32c80 , 0x1adb0 , 0x0 , 0x0 , 0x32c80 , 0x1adb0 } ,
{ " PRC Envelope #5 Rotated " , 0x1 , 0x35b60 , 0x1adb0 , 0x0 , 0x0 , 0x35b60 , 0x1adb0 } ,
{ " PRC Envelope #6 Rotated " , 0x1 , 0x38270 , 0x1d4c0 , 0x0 , 0x0 , 0x38270 , 0x1d4c0 } ,
{ " PRC Envelope #7 Rotated " , 0x1 , 0x38270 , 0x27100 , 0x0 , 0x0 , 0x38270 , 0x27100 } ,
{ " PRC Envelope #8 Rotated " , 0x1 , 0x4b708 , 0x1d4c0 , 0x0 , 0x0 , 0x4b708 , 0x1d4c0 } ,
{ " PRC Envelope #9 Rotated " , 0x1 , 0x4f1a0 , 0x37e88 , 0x0 , 0x0 , 0x4f1a0 , 0x37e88 } ,
{ " PRC Envelope #10 Rotated " , 0x1 , 0x6fd10 , 0x4f1a0 , 0x0 , 0x0 , 0x6fd10 , 0x4f1a0 }
2000-06-06 05:47:11 +04:00
} ;
2003-04-23 17:27:35 +04:00
struct table_node {
const char * long_archi ;
const char * short_archi ;
int version ;
} ;
2003-08-15 00:51:41 +04:00
# define SPL_ARCH_WIN40 "WIN40"
# define SPL_ARCH_W32X86 "W32X86"
# define SPL_ARCH_W32MIPS "W32MIPS"
# define SPL_ARCH_W32ALPHA "W32ALPHA"
# define SPL_ARCH_W32PPC "W32PPC"
2003-04-23 17:27:35 +04:00
static const struct table_node archi_table [ ] = {
2003-08-15 00:51:41 +04:00
{ " Windows 4.0 " , SPL_ARCH_WIN40 , 0 } ,
{ " Windows NT x86 " , SPL_ARCH_W32X86 , 2 } ,
{ " Windows NT R4000 " , SPL_ARCH_W32MIPS , 2 } ,
{ " Windows NT Alpha_AXP " , SPL_ARCH_W32ALPHA , 2 } ,
{ " Windows NT PowerPC " , SPL_ARCH_W32PPC , 2 } ,
2003-04-23 17:27:35 +04:00
{ NULL , " " , - 1 }
} ;
2002-01-09 08:24:07 +03:00
static BOOL upgrade_to_version_3 ( void )
2001-07-09 22:19:04 +04:00
{
TDB_DATA kbuf , newkey , dbuf ;
2001-07-31 03:12:48 +04:00
2002-01-09 08:24:07 +03:00
DEBUG ( 0 , ( " upgrade_to_version_3: upgrading print tdb's to version 3 \n " ) ) ;
2001-07-31 03:12:48 +04:00
for ( kbuf = tdb_firstkey ( tdb_drivers ) ; kbuf . dptr ;
2001-11-22 09:23:49 +03:00
newkey = tdb_nextkey ( tdb_drivers , kbuf ) , safe_free ( kbuf . dptr ) , kbuf = newkey ) {
2001-07-09 22:19:04 +04:00
dbuf = tdb_fetch ( tdb_drivers , kbuf ) ;
if ( strncmp ( kbuf . dptr , FORMS_PREFIX , strlen ( FORMS_PREFIX ) ) = = 0 ) {
2002-01-09 08:24:07 +03:00
DEBUG ( 0 , ( " upgrade_to_version_3:moving form \n " ) ) ;
2001-07-31 03:12:48 +04:00
if ( tdb_store ( tdb_forms , kbuf , dbuf , TDB_REPLACE ) ! = 0 ) {
2002-11-23 05:52:36 +03:00
SAFE_FREE ( dbuf . dptr ) ;
2002-01-09 08:24:07 +03:00
DEBUG ( 0 , ( " upgrade_to_version_3: failed to move form. Error (%s). \n " , tdb_errorstr ( tdb_forms ) ) ) ;
2001-07-31 03:12:48 +04:00
return False ;
}
if ( tdb_delete ( tdb_drivers , kbuf ) ! = 0 ) {
2002-11-23 05:52:36 +03:00
SAFE_FREE ( dbuf . dptr ) ;
2002-01-09 08:24:07 +03:00
DEBUG ( 0 , ( " upgrade_to_version_3: failed to delete form. Error (%s) \n " , tdb_errorstr ( tdb_drivers ) ) ) ;
2001-07-31 03:12:48 +04:00
return False ;
}
2001-07-09 22:19:04 +04:00
}
2001-07-31 03:12:48 +04:00
2001-07-09 22:19:04 +04:00
if ( strncmp ( kbuf . dptr , PRINTERS_PREFIX , strlen ( PRINTERS_PREFIX ) ) = = 0 ) {
2002-01-09 08:24:07 +03:00
DEBUG ( 0 , ( " upgrade_to_version_3:moving printer \n " ) ) ;
2001-07-31 03:12:48 +04:00
if ( tdb_store ( tdb_printers , kbuf , dbuf , TDB_REPLACE ) ! = 0 ) {
2002-11-23 05:52:36 +03:00
SAFE_FREE ( dbuf . dptr ) ;
2002-01-09 08:24:07 +03:00
DEBUG ( 0 , ( " upgrade_to_version_3: failed to move printer. Error (%s) \n " , tdb_errorstr ( tdb_printers ) ) ) ;
2001-07-31 03:12:48 +04:00
return False ;
}
if ( tdb_delete ( tdb_drivers , kbuf ) ! = 0 ) {
2002-11-23 05:52:36 +03:00
SAFE_FREE ( dbuf . dptr ) ;
2002-01-09 08:24:07 +03:00
DEBUG ( 0 , ( " upgrade_to_version_3: failed to delete printer. Error (%s) \n " , tdb_errorstr ( tdb_drivers ) ) ) ;
2001-07-31 03:12:48 +04:00
return False ;
}
2001-07-09 22:19:04 +04:00
}
2001-07-31 03:12:48 +04:00
2001-07-09 22:19:04 +04:00
if ( strncmp ( kbuf . dptr , SECDESC_PREFIX , strlen ( SECDESC_PREFIX ) ) = = 0 ) {
2002-01-09 08:24:07 +03:00
DEBUG ( 0 , ( " upgrade_to_version_3:moving secdesc \n " ) ) ;
2001-07-31 03:12:48 +04:00
if ( tdb_store ( tdb_printers , kbuf , dbuf , TDB_REPLACE ) ! = 0 ) {
2002-11-23 05:52:36 +03:00
SAFE_FREE ( dbuf . dptr ) ;
2002-01-09 08:24:07 +03:00
DEBUG ( 0 , ( " upgrade_to_version_3: failed to move secdesc. Error (%s) \n " , tdb_errorstr ( tdb_printers ) ) ) ;
2001-07-31 03:12:48 +04:00
return False ;
}
if ( tdb_delete ( tdb_drivers , kbuf ) ! = 0 ) {
2002-11-23 05:52:36 +03:00
SAFE_FREE ( dbuf . dptr ) ;
2002-01-09 08:24:07 +03:00
DEBUG ( 0 , ( " upgrade_to_version_3: failed to delete secdesc. Error (%s) \n " , tdb_errorstr ( tdb_drivers ) ) ) ;
2001-07-31 03:12:48 +04:00
return False ;
}
2001-07-09 22:19:04 +04:00
}
2001-07-31 03:12:48 +04:00
2001-09-17 13:25:57 +04:00
SAFE_FREE ( dbuf . dptr ) ;
2001-07-09 22:19:04 +04:00
}
2001-07-31 03:12:48 +04:00
return True ;
2001-07-09 22:19:04 +04:00
}
2000-02-07 19:17:59 +03:00
/****************************************************************************
2002-11-01 02:41:00 +03:00
Open the NT printing tdbs . Done once before fork ( ) .
2000-02-07 19:17:59 +03:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2002-01-09 08:24:07 +03:00
2000-05-27 11:27:21 +04:00
BOOL nt_printing_init ( void )
2000-02-07 19:17:59 +03:00
{
2000-05-24 10:10:21 +04:00
static pid_t local_pid ;
2003-01-03 11:28:12 +03:00
const char * vstring = " INFO/version " ;
2000-05-24 10:10:21 +04:00
2001-08-10 23:38:53 +04:00
if ( tdb_drivers & & tdb_printers & & tdb_forms & & local_pid = = sys_getpid ( ) )
return True ;
2002-11-01 02:41:00 +03:00
if ( tdb_drivers )
tdb_close ( tdb_drivers ) ;
2001-09-07 02:08:19 +04:00
tdb_drivers = tdb_open_log ( lock_path ( " ntdrivers.tdb " ) , 0 , TDB_DEFAULT , O_RDWR | O_CREAT , 0600 ) ;
2001-07-09 22:19:04 +04:00
if ( ! tdb_drivers ) {
2001-08-10 23:38:53 +04:00
DEBUG ( 0 , ( " nt_printing_init: Failed to open nt drivers database %s (%s) \n " ,
2001-04-09 00:01:51 +04:00
lock_path ( " ntdrivers.tdb " ) , strerror ( errno ) ) ) ;
2000-05-27 11:27:21 +04:00
return False ;
}
2001-08-10 23:38:53 +04:00
2002-11-01 02:41:00 +03:00
if ( tdb_printers )
tdb_close ( tdb_printers ) ;
2001-09-07 02:08:19 +04:00
tdb_printers = tdb_open_log ( lock_path ( " ntprinters.tdb " ) , 0 , TDB_DEFAULT , O_RDWR | O_CREAT , 0600 ) ;
2001-07-09 22:19:04 +04:00
if ( ! tdb_printers ) {
2001-08-10 23:38:53 +04:00
DEBUG ( 0 , ( " nt_printing_init: Failed to open nt printers database %s (%s) \n " ,
2001-07-09 22:19:04 +04:00
lock_path ( " ntprinters.tdb " ) , strerror ( errno ) ) ) ;
return False ;
}
2001-08-10 23:38:53 +04:00
2002-11-01 02:41:00 +03:00
if ( tdb_forms )
tdb_close ( tdb_forms ) ;
2001-09-07 02:08:19 +04:00
tdb_forms = tdb_open_log ( lock_path ( " ntforms.tdb " ) , 0 , TDB_DEFAULT , O_RDWR | O_CREAT , 0600 ) ;
2001-07-09 22:19:04 +04:00
if ( ! tdb_forms ) {
2001-08-10 23:38:53 +04:00
DEBUG ( 0 , ( " nt_printing_init: Failed to open nt forms database %s (%s) \n " ,
2001-07-09 22:19:04 +04:00
lock_path ( " ntforms.tdb " ) , strerror ( errno ) ) ) ;
return False ;
}
2001-08-10 23:38:53 +04:00
2000-05-24 10:10:21 +04:00
local_pid = sys_getpid ( ) ;
2001-08-10 23:38:53 +04:00
2000-05-24 10:10:21 +04:00
/* handle a Samba upgrade */
2002-10-05 02:53:18 +04:00
tdb_lock_bystring ( tdb_drivers , vstring , 0 ) ;
2002-01-09 07:13:30 +03:00
{
int32 vers_id ;
/* Cope with byte-reversed older versions of the db. */
vers_id = tdb_fetch_int32 ( tdb_drivers , vstring ) ;
2002-01-09 08:24:07 +03:00
if ( ( vers_id = = NTDRIVERS_DATABASE_VERSION_2 ) | | ( IREV ( vers_id ) = = NTDRIVERS_DATABASE_VERSION_2 ) ) {
2002-01-09 07:13:30 +03:00
/* Written on a bigendian machine with old fetch_int code. Save as le. */
2002-01-09 08:24:07 +03:00
/* The only upgrade between V2 and V3 is to save the version in little-endian. */
2002-01-09 07:13:30 +03:00
tdb_store_int32 ( tdb_drivers , vstring , NTDRIVERS_DATABASE_VERSION ) ;
vers_id = NTDRIVERS_DATABASE_VERSION ;
}
if ( vers_id ! = NTDRIVERS_DATABASE_VERSION ) {
2002-02-09 07:10:24 +03:00
if ( ( vers_id = = NTDRIVERS_DATABASE_VERSION_1 ) | | ( IREV ( vers_id ) = = NTDRIVERS_DATABASE_VERSION_1 ) ) {
2002-01-09 08:24:07 +03:00
if ( ! upgrade_to_version_3 ( ) )
2002-01-09 07:13:30 +03:00
return False ;
} else
tdb_traverse ( tdb_drivers , tdb_traverse_delete_fn , NULL ) ;
2002-02-09 07:10:24 +03:00
2002-01-09 07:13:30 +03:00
tdb_store_int32 ( tdb_drivers , vstring , NTDRIVERS_DATABASE_VERSION ) ;
}
2000-05-24 10:10:21 +04:00
}
2001-07-09 22:19:04 +04:00
tdb_unlock_bystring ( tdb_drivers , vstring ) ;
2000-05-24 10:10:21 +04:00
2002-02-09 07:10:24 +03:00
update_c_setprinter ( True ) ;
2002-07-15 14:35:28 +04:00
/*
* register callback to handle updating printers as new
* drivers are installed
*/
2002-08-17 20:31:24 +04:00
message_register ( MSG_PRINTER_DRVUPGRADE , do_drv_upgrade_printer ) ;
/*
* register callback to handle updating printer data
* when a driver is initialized
*/
message_register ( MSG_PRINTERDATA_INIT_RESET , reset_all_printerdata ) ;
2000-05-24 10:10:21 +04:00
return True ;
}
2000-02-07 19:17:59 +03:00
2004-05-03 20:38:37 +04:00
/*******************************************************************
Function to allow filename parsing " the old way " .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static BOOL driver_unix_convert ( char * name , connection_struct * conn ,
char * saved_last_component , BOOL * bad_path , SMB_STRUCT_STAT * pst )
{
unix_format ( name ) ;
unix_clean_name ( name ) ;
trim_string ( name , " / " , " / " ) ;
return unix_convert ( name , conn , saved_last_component , bad_path , pst ) ;
}
2002-02-09 07:10:24 +03:00
/*******************************************************************
tdb traversal function for counting printers .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static int traverse_counting_printers ( TDB_CONTEXT * t , TDB_DATA key ,
TDB_DATA data , void * context )
{
int * printer_count = ( int * ) context ;
if ( memcmp ( PRINTERS_PREFIX , key . dptr , sizeof ( PRINTERS_PREFIX ) - 1 ) = = 0 ) {
( * printer_count ) + + ;
DEBUG ( 10 , ( " traverse_counting_printers: printer = [%s] printer_count = %d \n " , key . dptr , * printer_count ) ) ;
}
return 0 ;
}
/*******************************************************************
Update the spooler global c_setprinter . This variable is initialized
when the parent smbd starts with the number of existing printers . It
is monotonically increased by the current number of printers * after *
each add or delete printer RPC . Only Microsoft knows why . . . JRR020119
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
uint32 update_c_setprinter ( BOOL initialize )
{
int32 c_setprinter ;
int32 printer_count = 0 ;
2002-10-05 02:53:18 +04:00
tdb_lock_bystring ( tdb_printers , GLOBAL_C_SETPRINTER , 0 ) ;
2002-02-09 07:10:24 +03:00
/* Traverse the tdb, counting the printers */
tdb_traverse ( tdb_printers , traverse_counting_printers , ( void * ) & printer_count ) ;
/* If initializing, set c_setprinter to current printers count
* otherwise , bump it by the current printer count
*/
if ( ! initialize )
c_setprinter = tdb_fetch_int32 ( tdb_printers , GLOBAL_C_SETPRINTER ) + printer_count ;
else
c_setprinter = printer_count ;
DEBUG ( 10 , ( " update_c_setprinter: c_setprinter = %u \n " , ( unsigned int ) c_setprinter ) ) ;
tdb_store_int32 ( tdb_printers , GLOBAL_C_SETPRINTER , c_setprinter ) ;
tdb_unlock_bystring ( tdb_printers , GLOBAL_C_SETPRINTER ) ;
return ( uint32 ) c_setprinter ;
}
/*******************************************************************
Get the spooler global c_setprinter , accounting for initialization .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
uint32 get_c_setprinter ( void )
{
int32 c_setprinter = tdb_fetch_int32 ( tdb_printers , GLOBAL_C_SETPRINTER ) ;
if ( c_setprinter = = ( int32 ) - 1 )
c_setprinter = update_c_setprinter ( True ) ;
DEBUG ( 10 , ( " get_c_setprinter: c_setprinter = %d \n " , c_setprinter ) ) ;
return ( uint32 ) c_setprinter ;
}
2001-04-04 02:41:31 +04:00
/****************************************************************************
2002-02-09 07:10:24 +03:00
Get builtin form struct list .
2001-04-04 02:41:31 +04:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2002-02-09 07:10:24 +03:00
2001-04-04 02:41:31 +04:00
int get_builtin_ntforms ( nt_forms_struct * * list )
{
* list = ( nt_forms_struct * ) memdup ( & default_forms [ 0 ] , sizeof ( default_forms ) ) ;
return sizeof ( default_forms ) / sizeof ( default_forms [ 0 ] ) ;
}
/****************************************************************************
get a builtin form struct
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
BOOL get_a_builtin_ntform ( UNISTR2 * uni_formname , nt_forms_struct * form )
{
int i , count ;
fstring form_name ;
unistr2_to_ascii ( form_name , uni_formname , sizeof ( form_name ) - 1 ) ;
DEBUGADD ( 6 , ( " Looking for builtin form %s \n " , form_name ) ) ;
count = sizeof ( default_forms ) / sizeof ( default_forms [ 0 ] ) ;
for ( i = 0 ; i < count ; i + + ) {
if ( strequal ( form_name , default_forms [ i ] . name ) ) {
DEBUGADD ( 6 , ( " Found builtin form %s \n " , form_name ) ) ;
memcpy ( form , & default_forms [ i ] , sizeof ( * form ) ) ;
break ;
}
}
return ( i ! = count ) ;
}
2001-03-03 08:27:26 +03:00
2000-02-07 19:17:59 +03:00
/****************************************************************************
2001-03-03 08:27:26 +03:00
get a form struct list
2000-02-07 19:17:59 +03:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2001-03-03 08:27:26 +03:00
int get_ntforms ( nt_forms_struct * * list )
2000-02-07 19:17:59 +03:00
{
2000-05-27 07:37:05 +04:00
TDB_DATA kbuf , newkey , dbuf ;
2001-08-12 21:30:01 +04:00
nt_forms_struct * tl ;
2000-05-24 10:10:21 +04:00
nt_forms_struct form ;
int ret ;
2000-09-29 01:33:08 +04:00
int i ;
2000-05-24 10:10:21 +04:00
int n = 0 ;
2001-07-09 22:19:04 +04:00
for ( kbuf = tdb_firstkey ( tdb_forms ) ;
2000-11-15 00:56:32 +03:00
kbuf . dptr ;
2002-08-17 20:31:24 +04:00
newkey = tdb_nextkey ( tdb_forms , kbuf ) , safe_free ( kbuf . dptr ) , kbuf = newkey )
{
if ( strncmp ( kbuf . dptr , FORMS_PREFIX , strlen ( FORMS_PREFIX ) ) ! = 0 )
continue ;
2000-05-24 10:10:21 +04:00
2001-07-09 22:19:04 +04:00
dbuf = tdb_fetch ( tdb_forms , kbuf ) ;
2002-08-17 20:31:24 +04:00
if ( ! dbuf . dptr )
continue ;
2000-05-24 10:10:21 +04:00
2000-06-06 05:47:11 +04:00
fstrcpy ( form . name , kbuf . dptr + strlen ( FORMS_PREFIX ) ) ;
2000-09-29 01:33:08 +04:00
ret = tdb_unpack ( dbuf . dptr , dbuf . dsize , " dddddddd " ,
& i , & form . flag , & form . width , & form . length , & form . left ,
2000-05-24 10:10:21 +04:00
& form . top , & form . right , & form . bottom ) ;
2001-09-17 13:25:57 +04:00
SAFE_FREE ( dbuf . dptr ) ;
2002-08-17 20:31:24 +04:00
if ( ret ! = dbuf . dsize )
continue ;
2000-05-24 10:10:21 +04:00
2001-08-12 21:30:01 +04:00
tl = Realloc ( * list , sizeof ( nt_forms_struct ) * ( n + 1 ) ) ;
if ( ! tl ) {
2001-04-04 02:41:31 +04:00
DEBUG ( 0 , ( " get_ntforms: Realloc fail. \n " ) ) ;
return 0 ;
2000-09-29 01:33:08 +04:00
}
2002-08-17 20:31:24 +04:00
* list = tl ;
2001-04-04 02:41:31 +04:00
( * list ) [ n ] = form ;
n + + ;
2000-06-06 05:47:11 +04:00
}
2000-05-24 10:10:21 +04:00
return n ;
2000-02-07 19:17:59 +03:00
}
/****************************************************************************
write a form struct list
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
int write_ntforms ( nt_forms_struct * * list , int number )
{
2000-05-24 10:10:21 +04:00
pstring buf , key ;
int len ;
TDB_DATA kbuf , dbuf ;
int i ;
2000-02-07 19:17:59 +03:00
2000-05-24 10:10:21 +04:00
for ( i = 0 ; i < number ; i + + ) {
2000-09-29 01:33:08 +04:00
/* save index, so list is rebuilt in correct order */
len = tdb_pack ( buf , sizeof ( buf ) , " dddddddd " ,
i , ( * list ) [ i ] . flag , ( * list ) [ i ] . width , ( * list ) [ i ] . length ,
2000-11-15 00:56:32 +03:00
( * list ) [ i ] . left , ( * list ) [ i ] . top , ( * list ) [ i ] . right ,
2000-05-24 10:10:21 +04:00
( * list ) [ i ] . bottom ) ;
2001-03-03 08:27:26 +03:00
if ( len > sizeof ( buf ) ) break ;
2001-04-09 00:01:51 +04:00
slprintf ( key , sizeof ( key ) - 1 , " %s%s " , FORMS_PREFIX , ( * list ) [ i ] . name ) ;
2000-05-24 10:10:21 +04:00
kbuf . dsize = strlen ( key ) + 1 ;
kbuf . dptr = key ;
dbuf . dsize = len ;
dbuf . dptr = buf ;
2001-07-09 22:19:04 +04:00
if ( tdb_store ( tdb_forms , kbuf , dbuf , TDB_REPLACE ) ! = 0 ) break ;
2001-03-03 08:27:26 +03:00
}
2000-02-07 19:17:59 +03:00
2001-03-03 08:27:26 +03:00
return i ;
2000-02-07 19:17:59 +03:00
}
/****************************************************************************
add a form struct at the end of the list
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2001-03-03 08:27:26 +03:00
BOOL add_a_form ( nt_forms_struct * * list , const FORM * form , int * count )
2000-02-07 19:17:59 +03:00
{
int n = 0 ;
BOOL update ;
fstring form_name ;
2001-08-12 21:30:01 +04:00
nt_forms_struct * tl ;
2000-02-07 19:17:59 +03:00
2000-11-15 00:56:32 +03:00
/*
* NT tries to add forms even when
2000-02-07 19:17:59 +03:00
* they are already in the base
* only update the values if already present
*/
update = False ;
2000-08-31 23:04:51 +04:00
unistr2_to_ascii ( form_name , & form - > name , sizeof ( form_name ) - 1 ) ;
2000-11-17 03:31:29 +03:00
for ( n = 0 ; n < * count ; n + + ) {
if ( ! strncmp ( ( * list ) [ n ] . name , form_name , strlen ( form_name ) ) ) {
2000-02-15 21:07:45 +03:00
DEBUG ( 103 , ( " NT workaround, [%s] already exists \n " , form_name ) ) ;
2000-02-07 19:17:59 +03:00
update = True ;
2000-11-17 03:31:29 +03:00
break ;
2000-02-07 19:17:59 +03:00
}
}
2000-11-17 03:31:29 +03:00
if ( update = = False ) {
2001-08-12 21:30:01 +04:00
if ( ( tl = Realloc ( * list , ( n + 1 ) * sizeof ( nt_forms_struct ) ) ) = = NULL ) {
DEBUG ( 0 , ( " add_a_form: failed to enlarge forms list! \n " ) ) ;
2000-04-07 02:48:53 +04:00
return False ;
2001-08-12 21:30:01 +04:00
}
* list = tl ;
2000-08-31 23:04:51 +04:00
unistr2_to_ascii ( ( * list ) [ n ] . name , & form - > name , sizeof ( ( * list ) [ n ] . name ) - 1 ) ;
2000-02-07 19:17:59 +03:00
( * count ) + + ;
}
( * list ) [ n ] . flag = form - > flags ;
( * list ) [ n ] . width = form - > size_x ;
( * list ) [ n ] . length = form - > size_y ;
( * list ) [ n ] . left = form - > left ;
( * list ) [ n ] . top = form - > top ;
( * list ) [ n ] . right = form - > right ;
( * list ) [ n ] . bottom = form - > bottom ;
2000-04-07 02:48:53 +04:00
return True ;
2000-02-07 19:17:59 +03:00
}
2000-08-31 23:04:51 +04:00
/****************************************************************************
2003-02-25 23:53:53 +03:00
Delete a named form struct .
2000-08-31 23:04:51 +04:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2003-02-25 23:53:53 +03:00
2001-09-04 11:13:01 +04:00
BOOL delete_a_form ( nt_forms_struct * * list , UNISTR2 * del_name , int * count , WERROR * ret )
2000-08-31 23:04:51 +04:00
{
pstring key ;
TDB_DATA kbuf ;
int n = 0 ;
fstring form_name ;
2001-09-04 11:13:01 +04:00
* ret = WERR_OK ;
2000-08-31 23:04:51 +04:00
unistr2_to_ascii ( form_name , del_name , sizeof ( form_name ) - 1 ) ;
for ( n = 0 ; n < * count ; n + + ) {
if ( ! strncmp ( ( * list ) [ n ] . name , form_name , strlen ( form_name ) ) ) {
DEBUG ( 103 , ( " delete_a_form, [%s] in list \n " , form_name ) ) ;
break ;
}
}
if ( n = = * count ) {
DEBUG ( 10 , ( " delete_a_form, [%s] not found \n " , form_name ) ) ;
2001-09-04 11:13:01 +04:00
* ret = WERR_INVALID_PARAM ;
2000-08-31 23:04:51 +04:00
return False ;
}
2001-04-09 00:01:51 +04:00
slprintf ( key , sizeof ( key ) - 1 , " %s%s " , FORMS_PREFIX , ( * list ) [ n ] . name ) ;
2000-08-31 23:04:51 +04:00
kbuf . dsize = strlen ( key ) + 1 ;
kbuf . dptr = key ;
2001-07-09 22:19:04 +04:00
if ( tdb_delete ( tdb_forms , kbuf ) ! = 0 ) {
2001-09-04 11:13:01 +04:00
* ret = WERR_NOMEM ;
2000-08-31 23:04:51 +04:00
return False ;
}
return True ;
}
2000-02-07 19:17:59 +03:00
/****************************************************************************
2003-02-25 23:53:53 +03:00
Update a form struct .
2000-02-07 19:17:59 +03:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2003-02-25 23:53:53 +03:00
2000-02-07 19:17:59 +03:00
void update_a_form ( nt_forms_struct * * list , const FORM * form , int count )
{
int n = 0 ;
fstring form_name ;
unistr2_to_ascii ( form_name , & ( form - > name ) , sizeof ( form_name ) - 1 ) ;
2000-02-15 21:07:45 +03:00
DEBUG ( 106 , ( " [%s] \n " , form_name ) ) ;
2003-02-25 23:53:53 +03:00
for ( n = 0 ; n < count ; n + + ) {
2000-02-15 21:07:45 +03:00
DEBUGADD ( 106 , ( " n [%d]:[%s] \n " , n , ( * list ) [ n ] . name ) ) ;
2000-02-07 19:17:59 +03:00
if ( ! strncmp ( ( * list ) [ n ] . name , form_name , strlen ( form_name ) ) )
break ;
}
if ( n = = count ) return ;
( * list ) [ n ] . flag = form - > flags ;
( * list ) [ n ] . width = form - > size_x ;
( * list ) [ n ] . length = form - > size_y ;
( * list ) [ n ] . left = form - > left ;
( * list ) [ n ] . top = form - > top ;
( * list ) [ n ] . right = form - > right ;
( * list ) [ n ] . bottom = form - > bottom ;
}
2000-11-15 00:56:32 +03:00
2000-02-07 19:17:59 +03:00
/****************************************************************************
2003-02-25 23:53:53 +03:00
Get the nt drivers list .
Traverse the database and look - up the matching names .
2000-02-07 19:17:59 +03:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2003-01-03 11:28:12 +03:00
int get_ntdrivers ( fstring * * list , const char * architecture , uint32 version )
2000-02-07 19:17:59 +03:00
{
int total = 0 ;
2003-04-23 17:27:35 +04:00
const char * short_archi ;
2001-08-12 21:30:01 +04:00
fstring * fl ;
2000-05-24 10:10:21 +04:00
pstring key ;
2000-05-27 07:37:05 +04:00
TDB_DATA kbuf , newkey ;
2000-02-07 19:17:59 +03:00
2003-04-23 17:27:35 +04:00
short_archi = get_short_archi ( architecture ) ;
2001-04-09 00:01:51 +04:00
slprintf ( key , sizeof ( key ) - 1 , " %s%s/%d/ " , DRIVERS_PREFIX , short_archi , version ) ;
2000-04-07 02:48:53 +04:00
2001-07-09 22:19:04 +04:00
for ( kbuf = tdb_firstkey ( tdb_drivers ) ;
2000-11-15 00:56:32 +03:00
kbuf . dptr ;
2001-11-22 09:23:49 +03:00
newkey = tdb_nextkey ( tdb_drivers , kbuf ) , safe_free ( kbuf . dptr ) , kbuf = newkey ) {
2003-02-25 23:53:53 +03:00
if ( strncmp ( kbuf . dptr , key , strlen ( key ) ) ! = 0 )
continue ;
2000-05-24 10:10:21 +04:00
2001-08-12 21:30:01 +04:00
if ( ( fl = Realloc ( * list , sizeof ( fstring ) * ( total + 1 ) ) ) = = NULL ) {
DEBUG ( 0 , ( " get_ntdrivers: failed to enlarge list! \n " ) ) ;
2000-05-24 10:10:21 +04:00
return - 1 ;
2001-08-12 21:30:01 +04:00
}
else * list = fl ;
2000-04-07 02:48:53 +04:00
2000-05-24 10:10:21 +04:00
fstrcpy ( ( * list ) [ total ] , kbuf . dptr + strlen ( key ) ) ;
total + + ;
2000-02-07 19:17:59 +03:00
}
return ( total ) ;
}
/****************************************************************************
2003-04-23 17:27:35 +04:00
function to do the mapping between the long architecture name and
the short one .
2000-02-07 19:17:59 +03:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2003-04-23 17:27:35 +04:00
const char * get_short_archi ( const char * long_archi )
2000-02-07 19:17:59 +03:00
{
2003-04-23 17:27:35 +04:00
int i = - 1 ;
2000-02-07 19:17:59 +03:00
2003-04-23 17:27:35 +04:00
DEBUG ( 107 , ( " Getting architecture dependant directory \n " ) ) ;
do {
i + + ;
} while ( ( archi_table [ i ] . long_archi ! = NULL ) & &
StrCaseCmp ( long_archi , archi_table [ i ] . long_archi ) ) ;
2002-10-31 21:42:38 +03:00
2003-04-23 17:27:35 +04:00
if ( archi_table [ i ] . long_archi = = NULL ) {
DEBUGADD ( 10 , ( " Unknown architecture [%s] ! \n " , long_archi ) ) ;
return NULL ;
}
2002-10-31 21:42:38 +03:00
2003-04-23 17:27:35 +04:00
/* this might be client code - but shouldn't this be an fstrcpy etc? */
2000-02-07 19:17:59 +03:00
2000-07-25 17:15:16 +04:00
2003-04-23 17:27:35 +04:00
DEBUGADD ( 108 , ( " index: [%d] \n " , i ) ) ;
DEBUGADD ( 108 , ( " long architecture: [%s] \n " , archi_table [ i ] . long_archi ) ) ;
DEBUGADD ( 108 , ( " short architecture: [%s] \n " , archi_table [ i ] . short_archi ) ) ;
2000-02-07 19:17:59 +03:00
2003-04-23 17:27:35 +04:00
return archi_table [ i ] . short_archi ;
2000-07-25 17:15:16 +04:00
}
/****************************************************************************
2002-01-08 04:22:23 +03:00
Version information in Microsoft files is held in a VS_VERSION_INFO structure .
There are two case to be covered here : PE ( Portable Executable ) and NE ( New
Executable ) files . Both files support the same INFO structure , but PE files
store the signature in unicode , and NE files store it as ! unicode .
returns - 1 on error , 1 on version info found , and 0 on no version info found .
2000-07-25 17:15:16 +04:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2002-01-08 04:22:23 +03:00
static int get_file_version ( files_struct * fsp , char * fname , uint32 * major , uint32 * minor )
2000-07-25 17:15:16 +04:00
{
2001-08-10 23:38:53 +04:00
int i ;
2003-10-30 00:28:00 +03:00
char * buf = NULL ;
2001-08-10 23:38:53 +04:00
ssize_t byte_count ;
2000-11-28 02:59:42 +03:00
2001-08-10 23:38:53 +04:00
if ( ( buf = malloc ( PE_HEADER_SIZE ) ) = = NULL ) {
DEBUG ( 0 , ( " get_file_version: PE file [%s] PE Header malloc failed bytes = %d \n " ,
fname , PE_HEADER_SIZE ) ) ;
2000-10-25 21:56:38 +04:00
goto error_exit ;
}
2000-11-15 00:56:32 +03:00
2001-08-10 23:38:53 +04:00
/* Note: DOS_HEADER_SIZE < malloc'ed PE_HEADER_SIZE */
2000-11-15 00:56:32 +03:00
if ( ( byte_count = vfs_read_data ( fsp , buf , DOS_HEADER_SIZE ) ) < DOS_HEADER_SIZE ) {
2003-11-03 17:34:25 +03:00
DEBUG ( 3 , ( " get_file_version: File [%s] DOS header too short, bytes read = %lu \n " ,
fname , ( unsigned long ) byte_count ) ) ;
2001-08-10 23:38:53 +04:00
goto no_version_info ;
2000-10-25 21:56:38 +04:00
}
/* Is this really a DOS header? */
if ( SVAL ( buf , DOS_HEADER_MAGIC_OFFSET ) ! = DOS_HEADER_MAGIC ) {
2001-08-10 23:38:53 +04:00
DEBUG ( 6 , ( " get_file_version: File [%s] bad DOS magic = 0x%x \n " ,
fname , SVAL ( buf , DOS_HEADER_MAGIC_OFFSET ) ) ) ;
goto no_version_info ;
2000-10-25 21:56:38 +04:00
}
/* Skip OEM header (if any) and the DOS stub to start of Windows header */
2003-05-14 14:59:01 +04:00
if ( SMB_VFS_LSEEK ( fsp , fsp - > fd , SVAL ( buf , DOS_HEADER_LFANEW_OFFSET ) , SEEK_SET ) = = ( SMB_OFF_T ) - 1 ) {
2001-08-10 23:38:53 +04:00
DEBUG ( 3 , ( " get_file_version: File [%s] too short, errno = %d \n " ,
fname , errno ) ) ;
/* Assume this isn't an error... the file just looks sort of like a PE/NE file */
goto no_version_info ;
2000-10-25 21:56:38 +04:00
}
2000-11-15 00:56:32 +03:00
if ( ( byte_count = vfs_read_data ( fsp , buf , PE_HEADER_SIZE ) ) < PE_HEADER_SIZE ) {
2003-11-03 17:34:25 +03:00
DEBUG ( 3 , ( " get_file_version: File [%s] Windows header too short, bytes read = %lu \n " ,
fname , ( unsigned long ) byte_count ) ) ;
2001-08-10 23:38:53 +04:00
/* Assume this isn't an error... the file just looks sort of like a PE/NE file */
goto no_version_info ;
2000-10-25 21:56:38 +04:00
}
/* The header may be a PE (Portable Executable) or an NE (New Executable) */
if ( IVAL ( buf , PE_HEADER_SIGNATURE_OFFSET ) = = PE_HEADER_SIGNATURE ) {
2003-10-30 00:28:00 +03:00
unsigned int num_sections ;
unsigned int section_table_bytes ;
2001-08-10 23:38:53 +04:00
if ( SVAL ( buf , PE_HEADER_MACHINE_OFFSET ) ! = PE_HEADER_MACHINE_I386 ) {
DEBUG ( 3 , ( " get_file_version: PE file [%s] wrong machine = 0x%x \n " ,
fname , SVAL ( buf , PE_HEADER_MACHINE_OFFSET ) ) ) ;
/* At this point, we assume the file is in error. It still could be somthing
* else besides a PE file , but it unlikely at this point .
*/
2000-10-25 21:56:38 +04:00
goto error_exit ;
}
2001-08-10 23:38:53 +04:00
/* get the section table */
num_sections = SVAL ( buf , PE_HEADER_NUMBER_OF_SECTIONS ) ;
section_table_bytes = num_sections * PE_HEADER_SECT_HEADER_SIZE ;
2003-10-30 00:28:00 +03:00
if ( section_table_bytes = = 0 )
goto error_exit ;
2001-09-17 13:25:57 +04:00
SAFE_FREE ( buf ) ;
2001-08-10 23:38:53 +04:00
if ( ( buf = malloc ( section_table_bytes ) ) = = NULL ) {
DEBUG ( 0 , ( " get_file_version: PE file [%s] section table malloc failed bytes = %d \n " ,
fname , section_table_bytes ) ) ;
2000-10-25 21:56:38 +04:00
goto error_exit ;
}
2001-08-10 23:38:53 +04:00
if ( ( byte_count = vfs_read_data ( fsp , buf , section_table_bytes ) ) < section_table_bytes ) {
2003-11-03 17:34:25 +03:00
DEBUG ( 3 , ( " get_file_version: PE file [%s] Section header too short, bytes read = %lu \n " ,
fname , ( unsigned long ) byte_count ) ) ;
2001-08-10 23:38:53 +04:00
goto error_exit ;
}
2000-11-15 00:56:32 +03:00
2001-08-10 23:38:53 +04:00
/* Iterate the section table looking for the resource section ".rsrc" */
for ( i = 0 ; i < num_sections ; i + + ) {
int sec_offset = i * PE_HEADER_SECT_HEADER_SIZE ;
2000-10-25 21:56:38 +04:00
2001-08-10 23:38:53 +04:00
if ( strcmp ( " .rsrc " , & buf [ sec_offset + PE_HEADER_SECT_NAME_OFFSET ] ) = = 0 ) {
2003-10-30 00:28:00 +03:00
unsigned int section_pos = IVAL ( buf , sec_offset + PE_HEADER_SECT_PTR_DATA_OFFSET ) ;
unsigned int section_bytes = IVAL ( buf , sec_offset + PE_HEADER_SECT_SIZE_DATA_OFFSET ) ;
if ( section_bytes = = 0 )
goto error_exit ;
2000-07-25 17:15:16 +04:00
2001-09-17 13:25:57 +04:00
SAFE_FREE ( buf ) ;
2001-08-10 23:38:53 +04:00
if ( ( buf = malloc ( section_bytes ) ) = = NULL ) {
DEBUG ( 0 , ( " get_file_version: PE file [%s] version malloc failed bytes = %d \n " ,
fname , section_bytes ) ) ;
goto error_exit ;
}
2000-07-25 17:15:16 +04:00
2001-08-10 23:38:53 +04:00
/* Seek to the start of the .rsrc section info */
2003-05-14 14:59:01 +04:00
if ( SMB_VFS_LSEEK ( fsp , fsp - > fd , section_pos , SEEK_SET ) = = ( SMB_OFF_T ) - 1 ) {
2001-08-10 23:38:53 +04:00
DEBUG ( 3 , ( " get_file_version: PE file [%s] too short for section info, errno = %d \n " ,
fname , errno ) ) ;
goto error_exit ;
}
2000-07-25 17:15:16 +04:00
2001-08-10 23:38:53 +04:00
if ( ( byte_count = vfs_read_data ( fsp , buf , section_bytes ) ) < section_bytes ) {
2003-11-03 17:34:25 +03:00
DEBUG ( 3 , ( " get_file_version: PE file [%s] .rsrc section too short, bytes read = %lu \n " ,
fname , ( unsigned long ) byte_count ) ) ;
2001-08-10 23:38:53 +04:00
goto error_exit ;
}
2000-07-25 17:15:16 +04:00
2003-10-30 00:28:00 +03:00
if ( section_bytes < VS_VERSION_INFO_UNICODE_SIZE )
goto error_exit ;
2001-08-10 23:38:53 +04:00
for ( i = 0 ; i < section_bytes - VS_VERSION_INFO_UNICODE_SIZE ; i + + ) {
/* Scan for 1st 3 unicoded bytes followed by word aligned magic value */
if ( buf [ i ] = = ' V ' & & buf [ i + 1 ] = = ' \0 ' & & buf [ i + 2 ] = = ' S ' ) {
/* Align to next long address */
int pos = ( i + sizeof ( VS_SIGNATURE ) * 2 + 3 ) & 0xfffffffc ;
2000-07-25 17:15:16 +04:00
2001-08-10 23:38:53 +04:00
if ( IVAL ( buf , pos ) = = VS_MAGIC_VALUE ) {
* major = IVAL ( buf , pos + VS_MAJOR_OFFSET ) ;
* minor = IVAL ( buf , pos + VS_MINOR_OFFSET ) ;
DEBUG ( 6 , ( " get_file_version: PE file [%s] Version = %08x:%08x (%d.%d.%d.%d) \n " ,
fname , * major , * minor ,
( * major > > 16 ) & 0xffff , * major & 0xffff ,
( * minor > > 16 ) & 0xffff , * minor & 0xffff ) ) ;
2001-09-17 13:25:57 +04:00
SAFE_FREE ( buf ) ;
2002-01-08 04:22:23 +03:00
return 1 ;
2001-08-10 23:38:53 +04:00
}
}
}
2000-11-15 00:56:32 +03:00
}
}
/* Version info not found, fall back to origin date/time */
DEBUG ( 10 , ( " get_file_version: PE file [%s] has no version info \n " , fname ) ) ;
2001-09-17 13:25:57 +04:00
SAFE_FREE ( buf ) ;
2002-01-08 04:22:23 +03:00
return 0 ;
2000-11-15 00:56:32 +03:00
} else if ( SVAL ( buf , NE_HEADER_SIGNATURE_OFFSET ) = = NE_HEADER_SIGNATURE ) {
if ( CVAL ( buf , NE_HEADER_TARGET_OS_OFFSET ) ! = NE_HEADER_TARGOS_WIN ) {
DEBUG ( 3 , ( " get_file_version: NE file [%s] wrong target OS = 0x%x \n " ,
fname , CVAL ( buf , NE_HEADER_TARGET_OS_OFFSET ) ) ) ;
/* At this point, we assume the file is in error. It still could be somthing
* else besides a NE file , but it unlikely at this point . */
goto error_exit ;
}
/* Allocate a bit more space to speed up things */
2001-09-17 13:25:57 +04:00
SAFE_FREE ( buf ) ;
2000-11-15 00:56:32 +03:00
if ( ( buf = malloc ( VS_NE_BUF_SIZE ) ) = = NULL ) {
DEBUG ( 0 , ( " get_file_version: NE file [%s] malloc failed bytes = %d \n " ,
fname , PE_HEADER_SIZE ) ) ;
goto error_exit ;
}
/* This is a HACK! I got tired of trying to sort through the messy
* ' NE ' file format . If anyone wants to clean this up please have at
* it , but this works . ' NE ' files will eventually fade away . JRR */
while ( ( byte_count = vfs_read_data ( fsp , buf , VS_NE_BUF_SIZE ) ) > 0 ) {
/* Cover case that should not occur in a well formed 'NE' .dll file */
if ( byte_count - VS_VERSION_INFO_SIZE < = 0 ) break ;
for ( i = 0 ; i < byte_count ; i + + ) {
/* Fast skip past data that can't possibly match */
if ( buf [ i ] ! = ' V ' ) continue ;
/* Potential match data crosses buf boundry, move it to beginning
* of buf , and fill the buf with as much as it will hold . */
if ( i > byte_count - VS_VERSION_INFO_SIZE ) {
int bc ;
memcpy ( buf , & buf [ i ] , byte_count - i ) ;
if ( ( bc = vfs_read_data ( fsp , & buf [ byte_count - i ] , VS_NE_BUF_SIZE -
( byte_count - i ) ) ) < 0 ) {
DEBUG ( 0 , ( " get_file_version: NE file [%s] Read error, errno=%d \n " ,
fname , errno ) ) ;
goto error_exit ;
}
byte_count = bc + ( byte_count - i ) ;
if ( byte_count < VS_VERSION_INFO_SIZE ) break ;
i = 0 ;
}
/* Check that the full signature string and the magic number that
* follows exist ( not a perfect solution , but the chances that this
* occurs in code is , well , remote . Yes I know I ' m comparing the ' V '
* twice , as it is simpler to read the code . */
if ( strcmp ( & buf [ i ] , VS_SIGNATURE ) = = 0 ) {
/* Compute skip alignment to next long address */
2003-05-14 14:59:01 +04:00
int skip = - ( SMB_VFS_LSEEK ( fsp , fsp - > fd , 0 , SEEK_CUR ) - ( byte_count - i ) +
2000-11-15 00:56:32 +03:00
sizeof ( VS_SIGNATURE ) ) & 3 ;
if ( IVAL ( buf , i + sizeof ( VS_SIGNATURE ) + skip ) ! = 0xfeef04bd ) continue ;
* major = IVAL ( buf , i + sizeof ( VS_SIGNATURE ) + skip + VS_MAJOR_OFFSET ) ;
* minor = IVAL ( buf , i + sizeof ( VS_SIGNATURE ) + skip + VS_MINOR_OFFSET ) ;
DEBUG ( 6 , ( " get_file_version: NE file [%s] Version = %08x:%08x (%d.%d.%d.%d) \n " ,
fname , * major , * minor ,
( * major > > 16 ) & 0xffff , * major & 0xffff ,
( * minor > > 16 ) & 0xffff , * minor & 0xffff ) ) ;
2001-09-17 13:25:57 +04:00
SAFE_FREE ( buf ) ;
2002-01-08 04:22:23 +03:00
return 1 ;
2000-11-15 00:56:32 +03:00
}
}
}
/* Version info not found, fall back to origin date/time */
DEBUG ( 0 , ( " get_file_version: NE file [%s] Version info not found \n " , fname ) ) ;
2001-09-17 13:25:57 +04:00
SAFE_FREE ( buf ) ;
2002-01-08 04:22:23 +03:00
return 0 ;
2000-11-15 00:56:32 +03:00
} else
/* Assume this isn't an error... the file just looks sort of like a PE/NE file */
DEBUG ( 3 , ( " get_file_version: File [%s] unknown file format, signature = 0x%x \n " ,
fname , IVAL ( buf , PE_HEADER_SIGNATURE_OFFSET ) ) ) ;
no_version_info :
2001-09-17 13:25:57 +04:00
SAFE_FREE ( buf ) ;
2002-01-08 04:22:23 +03:00
return 0 ;
2000-11-15 00:56:32 +03:00
error_exit :
2001-09-17 13:25:57 +04:00
SAFE_FREE ( buf ) ;
2000-11-15 00:56:32 +03:00
return - 1 ;
}
/****************************************************************************
Drivers for Microsoft systems contain multiple files . Often , multiple drivers
share one or more files . During the MS installation process files are checked
to insure that only a newer version of a shared file is installed over an
older version . There are several possibilities for this comparison . If there
is no previous version , the new one is newer ( obviously ) . If either file is
missing the version info structure , compare the creation date ( on Unix use
the modification date ) . Otherwise chose the numerically larger version number .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2003-02-25 23:53:53 +03:00
static int file_version_is_newer ( connection_struct * conn , fstring new_file , fstring old_file )
2000-11-15 00:56:32 +03:00
{
BOOL use_version = True ;
pstring filepath ;
uint32 new_major ;
uint32 new_minor ;
time_t new_create_time ;
uint32 old_major ;
uint32 old_minor ;
time_t old_create_time ;
int access_mode ;
int action ;
files_struct * fsp = NULL ;
SMB_STRUCT_STAT st ;
SMB_STRUCT_STAT stat_buf ;
2000-11-28 02:59:42 +03:00
BOOL bad_path ;
2000-11-15 05:39:11 +03:00
ZERO_STRUCT ( st ) ;
ZERO_STRUCT ( stat_buf ) ;
new_create_time = ( time_t ) 0 ;
old_create_time = ( time_t ) 0 ;
2000-11-15 00:56:32 +03:00
/* Get file version info (if available) for previous file (if it exists) */
pstrcpy ( filepath , old_file ) ;
2004-05-03 20:38:37 +04:00
driver_unix_convert ( filepath , conn , NULL , & bad_path , & stat_buf ) ;
2000-11-28 02:59:42 +03:00
2000-11-15 00:56:32 +03:00
fsp = open_file_shared ( conn , filepath , & stat_buf ,
SET_OPEN_MODE ( DOS_OPEN_RDONLY ) ,
( FILE_FAIL_IF_NOT_EXIST | FILE_EXISTS_OPEN ) ,
2004-04-02 22:46:19 +04:00
FILE_ATTRIBUTE_NORMAL , 0 , & access_mode , & action ) ;
2000-11-15 00:56:32 +03:00
if ( ! fsp ) {
/* Old file not found, so by definition new file is in fact newer */
DEBUG ( 10 , ( " file_version_is_newer: Can't open old file [%s], errno = %d \n " ,
filepath , errno ) ) ;
return True ;
} else {
int ret = get_file_version ( fsp , old_file , & old_major , & old_minor ) ;
if ( ret = = - 1 ) goto error_exit ;
if ( ! ret ) {
DEBUG ( 6 , ( " file_version_is_newer: Version info not found [%s], use mod time \n " ,
old_file ) ) ;
use_version = False ;
2003-05-14 14:59:01 +04:00
if ( SMB_VFS_FSTAT ( fsp , fsp - > fd , & st ) = = - 1 ) goto error_exit ;
2000-11-15 00:56:32 +03:00
old_create_time = st . st_mtime ;
DEBUGADD ( 6 , ( " file_version_is_newer: mod time = %ld sec \n " , old_create_time ) ) ;
}
}
2001-06-22 22:58:35 +04:00
close_file ( fsp , True ) ;
2000-11-15 00:56:32 +03:00
/* Get file version info (if available) for new file */
pstrcpy ( filepath , new_file ) ;
2004-05-03 20:38:37 +04:00
driver_unix_convert ( filepath , conn , NULL , & bad_path , & stat_buf ) ;
2000-11-28 02:59:42 +03:00
2000-11-15 00:56:32 +03:00
fsp = open_file_shared ( conn , filepath , & stat_buf ,
SET_OPEN_MODE ( DOS_OPEN_RDONLY ) ,
( FILE_FAIL_IF_NOT_EXIST | FILE_EXISTS_OPEN ) ,
2004-04-02 22:46:19 +04:00
FILE_ATTRIBUTE_NORMAL , 0 , & access_mode , & action ) ;
2000-11-15 00:56:32 +03:00
if ( ! fsp ) {
/* New file not found, this shouldn't occur if the caller did its job */
DEBUG ( 3 , ( " file_version_is_newer: Can't open new file [%s], errno = %d \n " ,
filepath , errno ) ) ;
goto error_exit ;
} else {
int ret = get_file_version ( fsp , new_file , & new_major , & new_minor ) ;
if ( ret = = - 1 ) goto error_exit ;
if ( ! ret ) {
DEBUG ( 6 , ( " file_version_is_newer: Version info not found [%s], use mod time \n " ,
new_file ) ) ;
use_version = False ;
2003-05-14 14:59:01 +04:00
if ( SMB_VFS_FSTAT ( fsp , fsp - > fd , & st ) = = - 1 ) goto error_exit ;
2000-11-15 00:56:32 +03:00
new_create_time = st . st_mtime ;
DEBUGADD ( 6 , ( " file_version_is_newer: mod time = %ld sec \n " , new_create_time ) ) ;
}
}
2001-06-22 22:58:35 +04:00
close_file ( fsp , True ) ;
2000-11-15 00:56:32 +03:00
2002-08-17 20:31:24 +04:00
if ( use_version & & ( new_major ! = old_major | | new_minor ! = old_minor ) ) {
2000-11-15 00:56:32 +03:00
/* Compare versions and choose the larger version number */
if ( new_major > old_major | |
( new_major = = old_major & & new_minor > old_minor ) ) {
DEBUG ( 6 , ( " file_version_is_newer: Replacing [%s] with [%s] \n " , old_file , new_file ) ) ;
return True ;
}
else {
DEBUG ( 6 , ( " file_version_is_newer: Leaving [%s] unchanged \n " , old_file ) ) ;
return False ;
}
2001-08-10 23:38:53 +04:00
} else {
/* Compare modification time/dates and choose the newest time/date */
if ( new_create_time > old_create_time ) {
DEBUG ( 6 , ( " file_version_is_newer: Replacing [%s] with [%s] \n " , old_file , new_file ) ) ;
return True ;
}
else {
DEBUG ( 6 , ( " file_version_is_newer: Leaving [%s] unchanged \n " , old_file ) ) ;
return False ;
}
}
error_exit :
if ( fsp )
close_file ( fsp , True ) ;
return - 1 ;
}
/****************************************************************************
Determine the correct cVersion associated with an architecture and driver
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2003-04-23 17:27:35 +04:00
static uint32 get_correct_cversion ( const char * architecture , fstring driverpath_in ,
2001-09-04 11:13:01 +04:00
struct current_user * user , WERROR * perr )
2001-08-10 23:38:53 +04:00
{
int cversion ;
int access_mode ;
int action ;
2001-09-16 03:32:19 +04:00
NTSTATUS nt_status ;
2002-02-09 07:10:24 +03:00
pstring driverpath ;
2001-10-31 13:46:25 +03:00
DATA_BLOB null_pw ;
2003-03-05 04:30:15 +03:00
fstring res_type ;
2001-08-10 23:38:53 +04:00
files_struct * fsp = NULL ;
BOOL bad_path ;
SMB_STRUCT_STAT st ;
connection_struct * conn ;
ZERO_STRUCT ( st ) ;
2001-12-29 23:29:43 +03:00
* perr = WERR_INVALID_PARAM ;
2001-08-10 23:38:53 +04:00
/* If architecture is Windows 95/98/ME, the version is always 0. */
if ( strcmp ( architecture , " WIN40 " ) = = 0 ) {
DEBUG ( 10 , ( " get_correct_cversion: Driver is Win9x, cversion = 0 \n " ) ) ;
2001-12-29 23:29:43 +03:00
* perr = WERR_OK ;
2001-08-10 23:38:53 +04:00
return 0 ;
}
2002-02-09 07:10:24 +03:00
/*
* Connect to the print $ share under the same account as the user connected
* to the rpc pipe . Note we must still be root to do this .
*/
2001-08-10 23:38:53 +04:00
/* Null password is ok - we are already an authenticated user... */
2001-10-31 13:46:25 +03:00
null_pw = data_blob ( NULL , 0 ) ;
2003-03-05 04:30:15 +03:00
fstrcpy ( res_type , " A: " ) ;
2002-02-09 07:10:24 +03:00
become_root ( ) ;
2003-03-05 04:30:15 +03:00
conn = make_connection_with_chdir ( " print$ " , null_pw , res_type , user - > vuid , & nt_status ) ;
2001-10-19 00:15:12 +04:00
unbecome_root ( ) ;
2001-08-10 23:38:53 +04:00
if ( conn = = NULL ) {
DEBUG ( 0 , ( " get_correct_cversion: Unable to connect \n " ) ) ;
2001-09-16 03:32:19 +04:00
* perr = ntstatus_to_werror ( nt_status ) ;
2001-08-10 23:38:53 +04:00
return - 1 ;
}
2001-11-22 08:56:09 +03:00
/* We are temporarily becoming the connection user. */
2003-04-23 17:27:35 +04:00
if ( ! become_user ( conn , user - > vuid ) ) {
2001-09-16 03:32:19 +04:00
DEBUG ( 0 , ( " get_correct_cversion: Can't become user! \n " ) ) ;
2001-09-04 11:13:01 +04:00
* perr = WERR_ACCESS_DENIED ;
2001-08-10 23:38:53 +04:00
return - 1 ;
}
/* Open the driver file (Portable Executable format) and determine the
* deriver the cversion . */
slprintf ( driverpath , sizeof ( driverpath ) - 1 , " %s/%s " , architecture , driverpath_in ) ;
2004-05-03 20:38:37 +04:00
driver_unix_convert ( driverpath , conn , NULL , & bad_path , & st ) ;
2001-08-10 23:38:53 +04:00
fsp = open_file_shared ( conn , driverpath , & st ,
SET_OPEN_MODE ( DOS_OPEN_RDONLY ) ,
( FILE_FAIL_IF_NOT_EXIST | FILE_EXISTS_OPEN ) ,
2004-04-02 22:46:19 +04:00
FILE_ATTRIBUTE_NORMAL , 0 , & access_mode , & action ) ;
2001-08-10 23:38:53 +04:00
if ( ! fsp ) {
DEBUG ( 3 , ( " get_correct_cversion: Can't open file [%s], errno = %d \n " ,
driverpath , errno ) ) ;
2001-09-04 11:13:01 +04:00
* perr = WERR_ACCESS_DENIED ;
2001-08-10 23:38:53 +04:00
goto error_exit ;
}
else {
uint32 major ;
uint32 minor ;
int ret = get_file_version ( fsp , driverpath , & major , & minor ) ;
if ( ret = = - 1 ) goto error_exit ;
if ( ! ret ) {
DEBUG ( 6 , ( " get_correct_cversion: Version info not found [%s] \n " , driverpath ) ) ;
goto error_exit ;
}
/*
* This is a Microsoft ' ism . See references in MSDN to VER_FILEVERSION
* for more details . Version in this case is not just the version of the
* file , but the version in the sense of kernal mode ( 2 ) vs . user mode
* ( 3 ) drivers . Other bits of the version fields are the version info .
* JRR 010716
*/
cversion = major & 0x0000ffff ;
switch ( cversion ) {
case 2 : /* WinNT drivers */
case 3 : /* Win2K drivers */
break ;
default :
DEBUG ( 6 , ( " get_correct_cversion: cversion invalid [%s] cversion = %d \n " ,
driverpath , cversion ) ) ;
goto error_exit ;
}
DEBUG ( 10 , ( " get_correct_cversion: Version info found [%s] major = 0x%x minor = 0x%x \n " ,
driverpath , major , minor ) ) ;
}
2002-02-09 07:10:24 +03:00
DEBUG ( 10 , ( " get_correct_cversion: Driver file [%s] cversion = %d \n " ,
driverpath , cversion ) ) ;
2001-08-10 23:38:53 +04:00
close_file ( fsp , True ) ;
close_cnum ( conn , user - > vuid ) ;
2001-10-19 00:15:12 +04:00
unbecome_user ( ) ;
2001-12-29 23:29:43 +03:00
* perr = WERR_OK ;
2001-08-10 23:38:53 +04:00
return cversion ;
2002-02-09 07:10:24 +03:00
2001-10-19 00:15:12 +04:00
error_exit :
2001-08-10 23:38:53 +04:00
2001-09-04 11:13:01 +04:00
if ( fsp )
close_file ( fsp , True ) ;
2002-02-09 07:10:24 +03:00
2001-09-04 11:13:01 +04:00
close_cnum ( conn , user - > vuid ) ;
2001-10-19 00:15:12 +04:00
unbecome_user ( ) ;
2001-09-04 11:13:01 +04:00
return - 1 ;
2001-08-10 23:38:53 +04:00
}
/****************************************************************************
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2001-09-04 11:13:01 +04:00
static WERROR clean_up_driver_struct_level_3 ( NT_PRINTER_DRIVER_INFO_LEVEL_3 * driver ,
2002-02-09 07:10:24 +03:00
struct current_user * user )
2001-08-10 23:38:53 +04:00
{
2003-04-23 17:27:35 +04:00
const char * architecture ;
2001-08-10 23:38:53 +04:00
fstring new_name ;
char * p ;
int i ;
2001-09-04 11:13:01 +04:00
WERROR err ;
2001-08-10 23:38:53 +04:00
/* clean up the driver name.
* we can get . \ driver . dll
* or worse c : \ windows \ system \ driver . dll !
*/
/* using an intermediate string to not have overlaping memcpy()'s */
if ( ( p = strrchr ( driver - > driverpath , ' \\ ' ) ) ! = NULL ) {
fstrcpy ( new_name , p + 1 ) ;
fstrcpy ( driver - > driverpath , new_name ) ;
}
if ( ( p = strrchr ( driver - > datafile , ' \\ ' ) ) ! = NULL ) {
fstrcpy ( new_name , p + 1 ) ;
fstrcpy ( driver - > datafile , new_name ) ;
}
if ( ( p = strrchr ( driver - > configfile , ' \\ ' ) ) ! = NULL ) {
fstrcpy ( new_name , p + 1 ) ;
fstrcpy ( driver - > configfile , new_name ) ;
}
if ( ( p = strrchr ( driver - > helpfile , ' \\ ' ) ) ! = NULL ) {
fstrcpy ( new_name , p + 1 ) ;
fstrcpy ( driver - > helpfile , new_name ) ;
}
if ( driver - > dependentfiles ) {
for ( i = 0 ; * driver - > dependentfiles [ i ] ; i + + ) {
if ( ( p = strrchr ( driver - > dependentfiles [ i ] , ' \\ ' ) ) ! = NULL ) {
fstrcpy ( new_name , p + 1 ) ;
fstrcpy ( driver - > dependentfiles [ i ] , new_name ) ;
}
}
}
2003-04-23 17:27:35 +04:00
architecture = get_short_archi ( driver - > environment ) ;
2001-08-10 23:38:53 +04:00
/* jfm:7/16/2000 the client always sends the cversion=0.
* The server should check which version the driver is by reading
* the PE header of driver - > driverpath .
*
* For Windows 95 / 98 the version is 0 ( so the value sent is correct )
* For Windows NT ( the architecture doesn ' t matter )
* NT 3.1 : cversion = 0
* NT 3.5 / 3.51 : cversion = 1
* NT 4 : cversion = 2
* NT2K : cversion = 3
*/
if ( ( driver - > cversion = get_correct_cversion ( architecture ,
2002-02-09 07:10:24 +03:00
driver - > driverpath , user , & err ) ) = = - 1 )
2001-08-10 23:38:53 +04:00
return err ;
2001-09-04 11:13:01 +04:00
return WERR_OK ;
2001-08-10 23:38:53 +04:00
}
/****************************************************************************
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2002-08-17 20:31:24 +04:00
static WERROR clean_up_driver_struct_level_6 ( NT_PRINTER_DRIVER_INFO_LEVEL_6 * driver , struct current_user * user )
2001-08-10 23:38:53 +04:00
{
2003-04-23 17:27:35 +04:00
const char * architecture ;
2001-08-10 23:38:53 +04:00
fstring new_name ;
char * p ;
int i ;
2001-09-04 11:13:01 +04:00
WERROR err ;
2001-08-10 23:38:53 +04:00
/* clean up the driver name.
* we can get . \ driver . dll
* or worse c : \ windows \ system \ driver . dll !
*/
/* using an intermediate string to not have overlaping memcpy()'s */
if ( ( p = strrchr ( driver - > driverpath , ' \\ ' ) ) ! = NULL ) {
fstrcpy ( new_name , p + 1 ) ;
fstrcpy ( driver - > driverpath , new_name ) ;
}
if ( ( p = strrchr ( driver - > datafile , ' \\ ' ) ) ! = NULL ) {
fstrcpy ( new_name , p + 1 ) ;
fstrcpy ( driver - > datafile , new_name ) ;
}
if ( ( p = strrchr ( driver - > configfile , ' \\ ' ) ) ! = NULL ) {
fstrcpy ( new_name , p + 1 ) ;
fstrcpy ( driver - > configfile , new_name ) ;
}
if ( ( p = strrchr ( driver - > helpfile , ' \\ ' ) ) ! = NULL ) {
fstrcpy ( new_name , p + 1 ) ;
fstrcpy ( driver - > helpfile , new_name ) ;
}
if ( driver - > dependentfiles ) {
for ( i = 0 ; * driver - > dependentfiles [ i ] ; i + + ) {
if ( ( p = strrchr ( driver - > dependentfiles [ i ] , ' \\ ' ) ) ! = NULL ) {
fstrcpy ( new_name , p + 1 ) ;
fstrcpy ( driver - > dependentfiles [ i ] , new_name ) ;
}
}
}
2003-04-23 17:27:35 +04:00
architecture = get_short_archi ( driver - > environment ) ;
2001-08-10 23:38:53 +04:00
/* jfm:7/16/2000 the client always sends the cversion=0.
* The server should check which version the driver is by reading
* the PE header of driver - > driverpath .
*
* For Windows 95 / 98 the version is 0 ( so the value sent is correct )
* For Windows NT ( the architecture doesn ' t matter )
* NT 3.1 : cversion = 0
* NT 3.5 / 3.51 : cversion = 1
* NT 4 : cversion = 2
* NT2K : cversion = 3
*/
2002-08-17 20:31:24 +04:00
if ( ( driver - > version = get_correct_cversion ( architecture , driver - > driverpath , user , & err ) ) = = - 1 )
2001-08-10 23:38:53 +04:00
return err ;
2001-09-04 11:13:01 +04:00
return WERR_OK ;
2001-08-10 23:38:53 +04:00
}
/****************************************************************************
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2001-09-04 11:13:01 +04:00
WERROR clean_up_driver_struct ( NT_PRINTER_DRIVER_INFO_LEVEL driver_abstract ,
2001-08-10 23:38:53 +04:00
uint32 level , struct current_user * user )
{
switch ( level ) {
case 3 :
{
NT_PRINTER_DRIVER_INFO_LEVEL_3 * driver ;
driver = driver_abstract . info_3 ;
return clean_up_driver_struct_level_3 ( driver , user ) ;
2000-11-15 00:56:32 +03:00
}
2001-08-10 23:38:53 +04:00
case 6 :
{
NT_PRINTER_DRIVER_INFO_LEVEL_6 * driver ;
driver = driver_abstract . info_6 ;
return clean_up_driver_struct_level_6 ( driver , user ) ;
2000-11-15 00:56:32 +03:00
}
2001-08-10 23:38:53 +04:00
default :
2001-09-04 11:13:01 +04:00
return WERR_INVALID_PARAM ;
2000-11-15 00:56:32 +03:00
}
2001-08-10 23:38:53 +04:00
}
2000-11-15 00:56:32 +03:00
2001-08-10 23:38:53 +04:00
/****************************************************************************
This function sucks and should be replaced . JRA .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static void convert_level_6_to_level3 ( NT_PRINTER_DRIVER_INFO_LEVEL_3 * dst , NT_PRINTER_DRIVER_INFO_LEVEL_6 * src )
{
dst - > cversion = src - > version ;
fstrcpy ( dst - > name , src - > name ) ;
fstrcpy ( dst - > environment , src - > environment ) ;
fstrcpy ( dst - > driverpath , src - > driverpath ) ;
fstrcpy ( dst - > datafile , src - > datafile ) ;
fstrcpy ( dst - > configfile , src - > configfile ) ;
fstrcpy ( dst - > helpfile , src - > helpfile ) ;
fstrcpy ( dst - > monitorname , src - > monitorname ) ;
fstrcpy ( dst - > defaultdatatype , src - > defaultdatatype ) ;
dst - > dependentfiles = src - > dependentfiles ;
}
#if 0 /* Debugging function */
static char * ffmt ( unsigned char * c ) {
int i ;
static char ffmt_str [ 17 ] ;
for ( i = 0 ; i < 16 ; i + + ) {
if ( ( c [ i ] < ' ' ) | | ( c [ i ] > ' ~ ' ) )
ffmt_str [ i ] = ' . ' ;
else
ffmt_str [ i ] = c [ i ] ;
}
ffmt_str [ 16 ] = ' \0 ' ;
return ffmt_str ;
2000-11-15 00:56:32 +03:00
}
2001-08-10 23:38:53 +04:00
# endif
2000-11-15 00:56:32 +03:00
/****************************************************************************
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2001-09-04 11:13:01 +04:00
BOOL move_driver_to_download_area ( NT_PRINTER_DRIVER_INFO_LEVEL driver_abstract , uint32 level ,
struct current_user * user , WERROR * perr )
2000-07-25 17:15:16 +04:00
{
NT_PRINTER_DRIVER_INFO_LEVEL_3 * driver ;
2000-09-07 03:20:35 +04:00
NT_PRINTER_DRIVER_INFO_LEVEL_3 converted_driver ;
2003-04-23 17:27:35 +04:00
const char * architecture ;
2000-07-25 17:15:16 +04:00
pstring new_dir ;
pstring old_name ;
pstring new_name ;
2001-10-31 13:46:25 +03:00
DATA_BLOB null_pw ;
2000-07-25 17:15:16 +04:00
connection_struct * conn ;
2001-09-16 03:32:19 +04:00
NTSTATUS nt_status ;
2002-02-09 07:10:24 +03:00
pstring inbuf ;
pstring outbuf ;
2003-03-05 04:30:15 +03:00
fstring res_type ;
2004-05-03 20:38:37 +04:00
BOOL bad_path ;
SMB_STRUCT_STAT st ;
2000-11-15 00:56:32 +03:00
int ver = 0 ;
2000-07-25 17:15:16 +04:00
int i ;
2002-02-09 07:10:24 +03:00
memset ( inbuf , ' \0 ' , sizeof ( inbuf ) ) ;
memset ( outbuf , ' \0 ' , sizeof ( outbuf ) ) ;
2001-09-04 11:13:01 +04:00
* perr = WERR_OK ;
2000-08-31 01:09:21 +04:00
2000-07-25 17:15:16 +04:00
if ( level = = 3 )
driver = driver_abstract . info_3 ;
2000-09-07 03:20:35 +04:00
else if ( level = = 6 ) {
convert_level_6_to_level3 ( & converted_driver , driver_abstract . info_6 ) ;
driver = & converted_driver ;
} else {
DEBUG ( 0 , ( " move_driver_to_download_area: Unknown info level (%u) \n " , ( unsigned int ) level ) ) ;
return False ;
}
2003-04-23 17:27:35 +04:00
architecture = get_short_archi ( driver - > environment ) ;
2000-07-25 17:15:16 +04:00
2002-02-09 07:10:24 +03:00
/*
* Connect to the print $ share under the same account as the user connected to the rpc pipe .
* Note we must be root to do this .
*/
2001-10-31 13:46:25 +03:00
null_pw = data_blob ( NULL , 0 ) ;
2003-03-05 04:30:15 +03:00
fstrcpy ( res_type , " A: " ) ;
become_root ( ) ;
conn = make_connection_with_chdir ( " print$ " , null_pw , res_type , user - > vuid , & nt_status ) ;
2002-02-09 07:10:24 +03:00
unbecome_root ( ) ;
2000-07-25 17:15:16 +04:00
2000-07-25 21:09:29 +04:00
if ( conn = = NULL ) {
DEBUG ( 0 , ( " move_driver_to_download_area: Unable to connect \n " ) ) ;
2001-09-16 03:32:19 +04:00
* perr = ntstatus_to_werror ( nt_status ) ;
2000-07-26 02:35:57 +04:00
return False ;
}
2000-08-09 22:40:48 +04:00
/*
* Save who we are - we are temporarily becoming the connection user .
*/
2000-07-26 02:35:57 +04:00
if ( ! become_user ( conn , conn - > vuid ) ) {
2001-09-16 03:32:19 +04:00
DEBUG ( 0 , ( " move_driver_to_download_area: Can't become user! \n " ) ) ;
2000-07-25 21:09:29 +04:00
return False ;
}
2000-11-15 00:56:32 +03:00
/*
* make the directories version and version \ driver_name
2000-07-25 17:15:16 +04:00
* under the architecture directory .
*/
DEBUG ( 5 , ( " Creating first directory \n " ) ) ;
2001-04-09 00:01:51 +04:00
slprintf ( new_dir , sizeof ( new_dir ) - 1 , " %s/%d " , architecture , driver - > cversion ) ;
2004-05-03 20:38:37 +04:00
driver_unix_convert ( new_dir , conn , NULL , & bad_path , & st ) ;
2001-09-04 11:13:01 +04:00
mkdir_internal ( conn , new_dir ) ;
2000-07-25 17:15:16 +04:00
2000-11-15 00:56:32 +03:00
/* For each driver file, archi\filexxx.yyy, if there is a duplicate file
* listed for this driver which has already been moved , skip it ( note :
* drivers may list the same file name several times . Then check if the
* file already exists in archi \ cversion \ , if so , check that the version
* info ( or time stamps if version info is unavailable ) is newer ( or the
* date is later ) . If it is , move it to archi \ cversion \ filexxx . yyy .
* Otherwise , delete the file .
2000-08-01 00:41:51 +04:00
*
2000-11-15 00:56:32 +03:00
* If a file is not moved to archi \ cversion \ because of an error , all the
* rest of the ' unmoved ' driver files are removed from archi \ . If one or
* more of the driver ' s files was already moved to archi \ cversion \ , it
* potentially leaves the driver in a partially updated state . Version
* trauma will most likely occur if an client attempts to use any printer
* bound to the driver . Perhaps a rewrite to make sure the moves can be
* done is appropriate . . . later JRR
2000-07-25 17:15:16 +04:00
*/
2000-11-15 00:56:32 +03:00
DEBUG ( 5 , ( " Moving files now ! \n " ) ) ;
2000-10-25 21:56:38 +04:00
if ( driver - > driverpath & & strlen ( driver - > driverpath ) ) {
2001-04-09 00:01:51 +04:00
slprintf ( new_name , sizeof ( new_name ) - 1 , " %s/%s " , architecture , driver - > driverpath ) ;
slprintf ( old_name , sizeof ( old_name ) - 1 , " %s/%s " , new_dir , driver - > driverpath ) ;
2000-11-15 00:56:32 +03:00
if ( ver ! = - 1 & & ( ver = file_version_is_newer ( conn , new_name , old_name ) ) > 0 ) {
2001-09-04 11:13:01 +04:00
NTSTATUS status ;
2004-05-03 20:38:37 +04:00
driver_unix_convert ( new_name , conn , NULL , & bad_path , & st ) ;
2004-03-03 23:55:59 +03:00
status = rename_internals ( conn , new_name , old_name , 0 , True ) ;
2001-09-04 11:13:01 +04:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
2000-11-15 00:56:32 +03:00
DEBUG ( 0 , ( " move_driver_to_download_area: Unable to rename [%s] to [%s] \n " ,
new_name , old_name ) ) ;
2001-09-04 11:13:01 +04:00
* perr = ntstatus_to_werror ( status ) ;
unlink_internals ( conn , 0 , new_name ) ;
2000-11-15 00:56:32 +03:00
ver = - 1 ;
}
2004-05-03 20:38:37 +04:00
} else {
driver_unix_convert ( new_name , conn , NULL , & bad_path , & st ) ;
2001-09-04 11:13:01 +04:00
unlink_internals ( conn , 0 , new_name ) ;
2004-05-03 20:38:37 +04:00
}
2000-10-25 21:56:38 +04:00
}
2000-07-25 17:15:16 +04:00
2000-10-25 21:56:38 +04:00
if ( driver - > datafile & & strlen ( driver - > datafile ) ) {
2000-11-15 00:56:32 +03:00
if ( ! strequal ( driver - > datafile , driver - > driverpath ) ) {
2001-04-09 00:01:51 +04:00
slprintf ( new_name , sizeof ( new_name ) - 1 , " %s/%s " , architecture , driver - > datafile ) ;
slprintf ( old_name , sizeof ( old_name ) - 1 , " %s/%s " , new_dir , driver - > datafile ) ;
2000-11-15 00:56:32 +03:00
if ( ver ! = - 1 & & ( ver = file_version_is_newer ( conn , new_name , old_name ) ) > 0 ) {
2001-09-04 11:13:01 +04:00
NTSTATUS status ;
2004-05-03 20:38:37 +04:00
driver_unix_convert ( new_name , conn , NULL , & bad_path , & st ) ;
2004-03-03 23:55:59 +03:00
status = rename_internals ( conn , new_name , old_name , 0 , True ) ;
2001-09-04 11:13:01 +04:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
2000-11-15 00:56:32 +03:00
DEBUG ( 0 , ( " move_driver_to_download_area: Unable to rename [%s] to [%s] \n " ,
new_name , old_name ) ) ;
2001-09-04 11:13:01 +04:00
* perr = ntstatus_to_werror ( status ) ;
unlink_internals ( conn , 0 , new_name ) ;
2000-11-15 00:56:32 +03:00
ver = - 1 ;
}
2004-05-03 20:38:37 +04:00
} else {
driver_unix_convert ( new_name , conn , NULL , & bad_path , & st ) ;
2001-09-04 11:13:01 +04:00
unlink_internals ( conn , 0 , new_name ) ;
2004-05-03 20:38:37 +04:00
}
2000-08-09 22:40:48 +04:00
}
2000-08-01 00:41:51 +04:00
}
2000-07-25 17:15:16 +04:00
2000-10-25 21:56:38 +04:00
if ( driver - > configfile & & strlen ( driver - > configfile ) ) {
2000-11-15 00:56:32 +03:00
if ( ! strequal ( driver - > configfile , driver - > driverpath ) & &
! strequal ( driver - > configfile , driver - > datafile ) ) {
2001-04-09 00:01:51 +04:00
slprintf ( new_name , sizeof ( new_name ) - 1 , " %s/%s " , architecture , driver - > configfile ) ;
slprintf ( old_name , sizeof ( old_name ) - 1 , " %s/%s " , new_dir , driver - > configfile ) ;
2000-11-15 00:56:32 +03:00
if ( ver ! = - 1 & & ( ver = file_version_is_newer ( conn , new_name , old_name ) ) > 0 ) {
2001-09-04 11:13:01 +04:00
NTSTATUS status ;
2004-05-03 20:38:37 +04:00
driver_unix_convert ( new_name , conn , NULL , & bad_path , & st ) ;
2004-03-03 23:55:59 +03:00
status = rename_internals ( conn , new_name , old_name , 0 , True ) ;
2001-09-04 11:13:01 +04:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
2000-11-15 00:56:32 +03:00
DEBUG ( 0 , ( " move_driver_to_download_area: Unable to rename [%s] to [%s] \n " ,
new_name , old_name ) ) ;
2001-09-04 11:13:01 +04:00
* perr = ntstatus_to_werror ( status ) ;
unlink_internals ( conn , 0 , new_name ) ;
2000-11-15 00:56:32 +03:00
ver = - 1 ;
}
2004-05-03 20:38:37 +04:00
} else {
driver_unix_convert ( new_name , conn , NULL , & bad_path , & st ) ;
2001-09-04 11:13:01 +04:00
unlink_internals ( conn , 0 , new_name ) ;
2004-05-03 20:38:37 +04:00
}
2000-08-09 22:40:48 +04:00
}
2000-08-01 00:41:51 +04:00
}
2000-07-25 17:15:16 +04:00
2000-10-25 21:56:38 +04:00
if ( driver - > helpfile & & strlen ( driver - > helpfile ) ) {
2000-11-15 00:56:32 +03:00
if ( ! strequal ( driver - > helpfile , driver - > driverpath ) & &
2000-08-09 22:40:48 +04:00
! strequal ( driver - > helpfile , driver - > datafile ) & &
! strequal ( driver - > helpfile , driver - > configfile ) ) {
2001-04-09 00:01:51 +04:00
slprintf ( new_name , sizeof ( new_name ) - 1 , " %s/%s " , architecture , driver - > helpfile ) ;
slprintf ( old_name , sizeof ( old_name ) - 1 , " %s/%s " , new_dir , driver - > helpfile ) ;
2000-11-15 00:56:32 +03:00
if ( ver ! = - 1 & & ( ver = file_version_is_newer ( conn , new_name , old_name ) ) > 0 ) {
2001-09-04 11:13:01 +04:00
NTSTATUS status ;
2004-05-03 20:38:37 +04:00
driver_unix_convert ( new_name , conn , NULL , & bad_path , & st ) ;
2004-03-03 23:55:59 +03:00
status = rename_internals ( conn , new_name , old_name , 0 , True ) ;
2001-09-04 11:13:01 +04:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
2000-11-15 00:56:32 +03:00
DEBUG ( 0 , ( " move_driver_to_download_area: Unable to rename [%s] to [%s] \n " ,
new_name , old_name ) ) ;
2001-09-04 11:13:01 +04:00
* perr = ntstatus_to_werror ( status ) ;
unlink_internals ( conn , 0 , new_name ) ;
2000-11-15 00:56:32 +03:00
ver = - 1 ;
}
2004-05-03 20:38:37 +04:00
} else {
driver_unix_convert ( new_name , conn , NULL , & bad_path , & st ) ;
2001-09-04 11:13:01 +04:00
unlink_internals ( conn , 0 , new_name ) ;
2004-05-03 20:38:37 +04:00
}
2000-08-09 22:40:48 +04:00
}
2000-08-01 00:41:51 +04:00
}
2000-07-25 17:15:16 +04:00
if ( driver - > dependentfiles ) {
for ( i = 0 ; * driver - > dependentfiles [ i ] ; i + + ) {
2000-08-01 00:41:51 +04:00
if ( ! strequal ( driver - > dependentfiles [ i ] , driver - > driverpath ) & &
2000-11-15 00:56:32 +03:00
! strequal ( driver - > dependentfiles [ i ] , driver - > datafile ) & &
! strequal ( driver - > dependentfiles [ i ] , driver - > configfile ) & &
! strequal ( driver - > dependentfiles [ i ] , driver - > helpfile ) ) {
2000-08-22 10:28:33 +04:00
int j ;
for ( j = 0 ; j < i ; j + + ) {
if ( strequal ( driver - > dependentfiles [ i ] , driver - > dependentfiles [ j ] ) ) {
goto NextDriver ;
}
}
2001-04-09 00:01:51 +04:00
slprintf ( new_name , sizeof ( new_name ) - 1 , " %s/%s " , architecture , driver - > dependentfiles [ i ] ) ;
slprintf ( old_name , sizeof ( old_name ) - 1 , " %s/%s " , new_dir , driver - > dependentfiles [ i ] ) ;
2000-11-15 00:56:32 +03:00
if ( ver ! = - 1 & & ( ver = file_version_is_newer ( conn , new_name , old_name ) ) > 0 ) {
2001-09-04 11:13:01 +04:00
NTSTATUS status ;
2004-05-03 20:38:37 +04:00
driver_unix_convert ( new_name , conn , NULL , & bad_path , & st ) ;
2004-03-03 23:55:59 +03:00
status = rename_internals ( conn , new_name , old_name , 0 , True ) ;
2001-09-04 11:13:01 +04:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
2000-11-15 00:56:32 +03:00
DEBUG ( 0 , ( " move_driver_to_download_area: Unable to rename [%s] to [%s] \n " ,
new_name , old_name ) ) ;
2001-09-04 11:13:01 +04:00
* perr = ntstatus_to_werror ( status ) ;
unlink_internals ( conn , 0 , new_name ) ;
2000-11-15 00:56:32 +03:00
ver = - 1 ;
}
2004-05-03 20:38:37 +04:00
} else {
driver_unix_convert ( new_name , conn , NULL , & bad_path , & st ) ;
2001-09-04 11:13:01 +04:00
unlink_internals ( conn , 0 , new_name ) ;
2004-05-03 20:38:37 +04:00
}
2000-08-01 00:41:51 +04:00
}
2000-09-27 03:28:04 +04:00
NextDriver : ;
2000-07-25 17:15:16 +04:00
}
}
close_cnum ( conn , user - > vuid ) ;
2002-02-09 07:10:24 +03:00
unbecome_user ( ) ;
2000-07-25 21:09:29 +04:00
2000-11-15 00:56:32 +03:00
return ver = = - 1 ? False : True ;
2000-02-07 19:17:59 +03:00
}
/****************************************************************************
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static uint32 add_a_printer_driver_3 ( NT_PRINTER_DRIVER_INFO_LEVEL_3 * driver )
{
2000-05-24 10:10:21 +04:00
int len , buflen ;
2003-04-23 17:27:35 +04:00
const char * architecture ;
2000-07-25 17:15:16 +04:00
pstring directory ;
2003-01-14 11:53:59 +03:00
fstring temp_name ;
2000-05-24 10:10:21 +04:00
pstring key ;
char * buf ;
int i , ret ;
TDB_DATA kbuf , dbuf ;
2000-02-07 19:17:59 +03:00
2003-04-23 17:27:35 +04:00
architecture = get_short_archi ( driver - > environment ) ;
2000-02-07 19:17:59 +03:00
2000-08-01 00:41:51 +04:00
/* The names are relative. We store them in the form: \print$\arch\version\driver.xxx
2000-07-25 17:15:16 +04:00
* \ \ server is added in the rpc server layer .
* It does make sense to NOT store the server ' s name in the printer TDB .
2000-02-07 19:17:59 +03:00
*/
2000-07-25 17:15:16 +04:00
2001-04-09 00:01:51 +04:00
slprintf ( directory , sizeof ( directory ) - 1 , " \\ print$ \\ %s \\ %d \\ " , architecture , driver - > cversion ) ;
2000-07-25 17:15:16 +04:00
2002-02-09 07:10:24 +03:00
/* .inf files do not always list a file for each of the four standard files.
* Don ' t prepend a path to a null filename , or client claims :
* " The server on which the printer resides does not have a suitable
* < printer driver name > printer driver installed . Click OK if you
* wish to install the driver on your local machine . "
*/
2001-01-11 23:41:19 +03:00
if ( strlen ( driver - > driverpath ) ) {
2002-02-09 07:10:24 +03:00
fstrcpy ( temp_name , driver - > driverpath ) ;
slprintf ( driver - > driverpath , sizeof ( driver - > driverpath ) - 1 , " %s%s " , directory , temp_name ) ;
}
2000-07-25 17:15:16 +04:00
2001-01-11 23:41:19 +03:00
if ( strlen ( driver - > datafile ) ) {
2002-02-09 07:10:24 +03:00
fstrcpy ( temp_name , driver - > datafile ) ;
slprintf ( driver - > datafile , sizeof ( driver - > datafile ) - 1 , " %s%s " , directory , temp_name ) ;
}
2000-07-25 17:15:16 +04:00
2001-01-11 23:41:19 +03:00
if ( strlen ( driver - > configfile ) ) {
2002-02-09 07:10:24 +03:00
fstrcpy ( temp_name , driver - > configfile ) ;
slprintf ( driver - > configfile , sizeof ( driver - > configfile ) - 1 , " %s%s " , directory , temp_name ) ;
}
2000-07-25 17:15:16 +04:00
2001-01-11 23:41:19 +03:00
if ( strlen ( driver - > helpfile ) ) {
2002-02-09 07:10:24 +03:00
fstrcpy ( temp_name , driver - > helpfile ) ;
slprintf ( driver - > helpfile , sizeof ( driver - > helpfile ) - 1 , " %s%s " , directory , temp_name ) ;
}
2000-07-25 17:15:16 +04:00
if ( driver - > dependentfiles ) {
for ( i = 0 ; * driver - > dependentfiles [ i ] ; i + + ) {
2002-02-09 07:10:24 +03:00
fstrcpy ( temp_name , driver - > dependentfiles [ i ] ) ;
slprintf ( driver - > dependentfiles [ i ] , sizeof ( driver - > dependentfiles [ i ] ) - 1 , " %s%s " , directory , temp_name ) ;
2000-07-25 17:15:16 +04:00
}
}
2001-04-09 00:01:51 +04:00
slprintf ( key , sizeof ( key ) - 1 , " %s%s/%d/%s " , DRIVERS_PREFIX , architecture , driver - > cversion , driver - > name ) ;
2000-07-25 17:15:16 +04:00
2000-09-15 04:15:10 +04:00
DEBUG ( 5 , ( " add_a_printer_driver_3: Adding driver with key %s \n " , key ) ) ;
2000-05-24 10:10:21 +04:00
buf = NULL ;
len = buflen = 0 ;
again :
len = 0 ;
2000-11-15 00:56:32 +03:00
len + = tdb_pack ( buf + len , buflen - len , " dffffffff " ,
2000-05-24 10:10:21 +04:00
driver - > cversion ,
driver - > name ,
driver - > environment ,
driver - > driverpath ,
driver - > datafile ,
driver - > configfile ,
driver - > helpfile ,
driver - > monitorname ,
driver - > defaultdatatype ) ;
2000-07-25 17:15:16 +04:00
2000-05-24 10:10:21 +04:00
if ( driver - > dependentfiles ) {
for ( i = 0 ; * driver - > dependentfiles [ i ] ; i + + ) {
2000-11-15 00:56:32 +03:00
len + = tdb_pack ( buf + len , buflen - len , " f " ,
2000-05-24 10:10:21 +04:00
driver - > dependentfiles [ i ] ) ;
}
2000-02-07 19:17:59 +03:00
}
2000-05-24 10:10:21 +04:00
if ( len ! = buflen ) {
2001-08-12 21:30:01 +04:00
char * tb ;
2002-02-09 07:10:24 +03:00
2001-08-12 21:30:01 +04:00
tb = ( char * ) Realloc ( buf , len ) ;
if ( ! tb ) {
DEBUG ( 0 , ( " add_a_printer_driver_3: failed to enlarge buffer \n ! " ) ) ;
ret = - 1 ;
goto done ;
}
else buf = tb ;
2000-05-24 10:10:21 +04:00
buflen = len ;
goto again ;
}
kbuf . dptr = key ;
kbuf . dsize = strlen ( key ) + 1 ;
dbuf . dptr = buf ;
dbuf . dsize = len ;
2000-02-07 19:17:59 +03:00
2001-07-09 22:19:04 +04:00
ret = tdb_store ( tdb_drivers , kbuf , dbuf , TDB_REPLACE ) ;
2000-05-24 10:10:21 +04:00
2001-08-12 21:30:01 +04:00
done :
2000-09-15 04:15:10 +04:00
if ( ret )
DEBUG ( 0 , ( " add_a_printer_driver_3: Adding driver with key %s failed. \n " , key ) ) ;
2001-09-17 13:25:57 +04:00
SAFE_FREE ( buf ) ;
2000-05-24 10:10:21 +04:00
return ret ;
2000-02-07 19:17:59 +03:00
}
2000-05-12 18:28:46 +04:00
/****************************************************************************
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static uint32 add_a_printer_driver_6 ( NT_PRINTER_DRIVER_INFO_LEVEL_6 * driver )
{
2000-05-24 10:10:21 +04:00
NT_PRINTER_DRIVER_INFO_LEVEL_3 info3 ;
2000-06-21 03:58:56 +04:00
ZERO_STRUCT ( info3 ) ;
2000-05-24 10:10:21 +04:00
info3 . cversion = driver - > version ;
2000-09-15 04:15:10 +04:00
fstrcpy ( info3 . name , driver - > name ) ;
2000-05-24 10:10:21 +04:00
fstrcpy ( info3 . environment , driver - > environment ) ;
fstrcpy ( info3 . driverpath , driver - > driverpath ) ;
fstrcpy ( info3 . datafile , driver - > datafile ) ;
fstrcpy ( info3 . configfile , driver - > configfile ) ;
fstrcpy ( info3 . helpfile , driver - > helpfile ) ;
fstrcpy ( info3 . monitorname , driver - > monitorname ) ;
fstrcpy ( info3 . defaultdatatype , driver - > defaultdatatype ) ;
info3 . dependentfiles = driver - > dependentfiles ;
return add_a_printer_driver_3 ( & info3 ) ;
}
2000-05-12 18:28:46 +04:00
2000-05-24 10:10:21 +04:00
/****************************************************************************
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2003-01-03 11:28:12 +03:00
static WERROR get_a_printer_driver_3_default ( NT_PRINTER_DRIVER_INFO_LEVEL_3 * * info_ptr , const char * driver , const char * arch )
2000-05-24 10:10:21 +04:00
{
NT_PRINTER_DRIVER_INFO_LEVEL_3 info ;
2000-05-12 18:28:46 +04:00
2000-05-24 10:10:21 +04:00
ZERO_STRUCT ( info ) ;
2000-05-12 18:28:46 +04:00
2002-07-15 14:35:28 +04:00
fstrcpy ( info . name , driver ) ;
2000-05-24 10:10:21 +04:00
fstrcpy ( info . defaultdatatype , " RAW " ) ;
2000-05-12 18:28:46 +04:00
2000-06-22 05:39:17 +04:00
fstrcpy ( info . driverpath , " " ) ;
fstrcpy ( info . datafile , " " ) ;
fstrcpy ( info . configfile , " " ) ;
fstrcpy ( info . helpfile , " " ) ;
2000-06-21 03:58:56 +04:00
if ( ( info . dependentfiles = ( fstring * ) malloc ( 2 * sizeof ( fstring ) ) ) = = NULL )
2001-09-04 11:13:01 +04:00
return WERR_NOMEM ;
2000-06-02 01:00:37 +04:00
2000-06-21 03:58:56 +04:00
memset ( info . dependentfiles , ' \0 ' , 2 * sizeof ( fstring ) ) ;
2000-06-22 05:39:17 +04:00
fstrcpy ( info . dependentfiles [ 0 ] , " " ) ;
2000-05-24 10:10:21 +04:00
* info_ptr = memdup ( & info , sizeof ( info ) ) ;
2000-05-12 18:28:46 +04:00
2001-09-04 11:13:01 +04:00
return WERR_OK ;
2000-05-12 18:28:46 +04:00
}
2000-02-07 19:17:59 +03:00
/****************************************************************************
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2003-01-03 11:28:12 +03:00
static WERROR get_a_printer_driver_3 ( NT_PRINTER_DRIVER_INFO_LEVEL_3 * * info_ptr , fstring drivername , const char * arch , uint32 version )
2000-02-07 19:17:59 +03:00
{
2000-05-24 10:10:21 +04:00
NT_PRINTER_DRIVER_INFO_LEVEL_3 driver ;
TDB_DATA kbuf , dbuf ;
2003-04-23 17:27:35 +04:00
const char * architecture ;
2000-05-24 10:10:21 +04:00
int len = 0 ;
int i ;
pstring key ;
2000-04-05 23:48:06 +04:00
2000-05-24 10:10:21 +04:00
ZERO_STRUCT ( driver ) ;
2000-04-05 23:48:06 +04:00
2003-04-23 17:27:35 +04:00
architecture = get_short_archi ( arch ) ;
2003-08-15 00:51:41 +04:00
/* Windows 4.0 (i.e. win9x) should always use a version of 0 */
2003-08-16 05:40:38 +04:00
if ( strcmp ( architecture , SPL_ARCH_WIN40 ) = = 0 )
2003-08-15 00:51:41 +04:00
version = 0 ;
2000-07-25 17:15:16 +04:00
2002-07-15 14:35:28 +04:00
DEBUG ( 8 , ( " get_a_printer_driver_3: [%s%s/%d/%s] \n " , DRIVERS_PREFIX , architecture , version , drivername ) ) ;
2000-07-25 17:15:16 +04:00
2002-07-15 14:35:28 +04:00
slprintf ( key , sizeof ( key ) - 1 , " %s%s/%d/%s " , DRIVERS_PREFIX , architecture , version , drivername ) ;
2000-05-24 10:10:21 +04:00
kbuf . dptr = key ;
kbuf . dsize = strlen ( key ) + 1 ;
2001-07-09 22:19:04 +04:00
dbuf = tdb_fetch ( tdb_drivers , kbuf ) ;
2002-07-15 14:35:28 +04:00
if ( ! dbuf . dptr )
2002-09-25 19:19:00 +04:00
return WERR_UNKNOWN_PRINTER_DRIVER ;
2002-07-15 14:35:28 +04:00
2000-11-15 00:56:32 +03:00
len + = tdb_unpack ( dbuf . dptr , dbuf . dsize , " dffffffff " ,
2000-05-24 10:10:21 +04:00
& driver . cversion ,
driver . name ,
driver . environment ,
driver . driverpath ,
driver . datafile ,
driver . configfile ,
driver . helpfile ,
driver . monitorname ,
driver . defaultdatatype ) ;
i = 0 ;
2002-11-23 05:52:36 +03:00
while ( len < dbuf . dsize ) {
2001-08-12 21:30:01 +04:00
fstring * tddfs ;
2002-02-09 07:10:24 +03:00
2001-08-12 21:30:01 +04:00
tddfs = ( fstring * ) Realloc ( driver . dependentfiles ,
2000-05-24 10:10:21 +04:00
sizeof ( fstring ) * ( i + 2 ) ) ;
2001-08-12 21:30:01 +04:00
if ( tddfs = = NULL ) {
DEBUG ( 0 , ( " get_a_printer_driver_3: failed to enlarge buffer! \n " ) ) ;
2000-06-02 01:00:37 +04:00
break ;
2001-08-12 21:30:01 +04:00
}
else driver . dependentfiles = tddfs ;
2000-06-02 01:00:37 +04:00
2000-11-15 00:56:32 +03:00
len + = tdb_unpack ( dbuf . dptr + len , dbuf . dsize - len , " f " ,
2000-06-02 01:00:37 +04:00
& driver . dependentfiles [ i ] ) ;
2000-05-24 10:10:21 +04:00
i + + ;
2000-04-05 23:48:06 +04:00
}
2002-08-17 20:31:24 +04:00
2000-06-02 01:00:37 +04:00
if ( driver . dependentfiles ! = NULL )
fstrcpy ( driver . dependentfiles [ i ] , " " ) ;
2000-04-05 23:48:06 +04:00
2001-09-17 13:25:57 +04:00
SAFE_FREE ( dbuf . dptr ) ;
2000-05-29 02:50:30 +04:00
2002-11-23 05:52:36 +03:00
if ( len ! = dbuf . dsize ) {
2002-08-17 20:31:24 +04:00
SAFE_FREE ( driver . dependentfiles ) ;
2000-06-02 01:00:37 +04:00
2002-07-15 14:35:28 +04:00
return get_a_printer_driver_3_default ( info_ptr , drivername , arch ) ;
2000-05-29 02:50:30 +04:00
}
* info_ptr = ( NT_PRINTER_DRIVER_INFO_LEVEL_3 * ) memdup ( & driver , sizeof ( driver ) ) ;
2001-09-03 12:50:59 +04:00
return WERR_OK ;
2000-02-07 19:17:59 +03:00
}
/****************************************************************************
2002-02-09 07:10:24 +03:00
Debugging function , dump at level 6 the struct in the logs .
2000-02-07 19:17:59 +03:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2002-02-09 07:10:24 +03:00
2000-02-07 19:17:59 +03:00
static uint32 dump_a_printer_driver ( NT_PRINTER_DRIVER_INFO_LEVEL driver , uint32 level )
{
2000-12-06 03:37:25 +03:00
uint32 result ;
2000-02-07 19:17:59 +03:00
NT_PRINTER_DRIVER_INFO_LEVEL_3 * info3 ;
2000-05-24 10:10:21 +04:00
int i ;
2000-02-07 19:17:59 +03:00
2002-09-25 19:19:00 +04:00
DEBUG ( 20 , ( " Dumping printer driver at level [%d] \n " , level ) ) ;
2000-02-07 19:17:59 +03:00
switch ( level )
{
2000-11-15 00:56:32 +03:00
case 3 :
2000-02-07 19:17:59 +03:00
{
if ( driver . info_3 = = NULL )
2000-12-06 03:37:25 +03:00
result = 5 ;
2000-03-10 20:12:24 +03:00
else {
2000-02-07 19:17:59 +03:00
info3 = driver . info_3 ;
2002-07-15 14:35:28 +04:00
DEBUGADD ( 20 , ( " version:[%d] \n " , info3 - > cversion ) ) ;
DEBUGADD ( 20 , ( " name:[%s] \n " , info3 - > name ) ) ;
DEBUGADD ( 20 , ( " environment:[%s] \n " , info3 - > environment ) ) ;
DEBUGADD ( 20 , ( " driverpath:[%s] \n " , info3 - > driverpath ) ) ;
DEBUGADD ( 20 , ( " datafile:[%s] \n " , info3 - > datafile ) ) ;
DEBUGADD ( 20 , ( " configfile:[%s] \n " , info3 - > configfile ) ) ;
DEBUGADD ( 20 , ( " helpfile:[%s] \n " , info3 - > helpfile ) ) ;
DEBUGADD ( 20 , ( " monitorname:[%s] \n " , info3 - > monitorname ) ) ;
DEBUGADD ( 20 , ( " defaultdatatype:[%s] \n " , info3 - > defaultdatatype ) ) ;
2000-02-07 19:17:59 +03:00
2000-05-29 02:50:30 +04:00
for ( i = 0 ; info3 - > dependentfiles & &
* info3 - > dependentfiles [ i ] ; i + + ) {
2002-07-15 14:35:28 +04:00
DEBUGADD ( 20 , ( " dependentfile:[%s] \n " ,
2000-05-24 10:10:21 +04:00
info3 - > dependentfiles [ i ] ) ) ;
2000-02-07 19:17:59 +03:00
}
2000-12-06 03:37:25 +03:00
result = 0 ;
2000-02-07 19:17:59 +03:00
}
break ;
}
default :
2002-07-15 14:35:28 +04:00
DEBUGADD ( 20 , ( " dump_a_printer_driver: Level %u not implemented \n " , ( unsigned int ) level ) ) ;
2000-12-06 03:37:25 +03:00
result = 1 ;
2000-02-07 19:17:59 +03:00
break ;
}
2000-12-06 03:37:25 +03:00
return result ;
2000-02-07 19:17:59 +03:00
}
/****************************************************************************
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2002-09-25 19:19:00 +04:00
int pack_devicemode ( NT_DEVICEMODE * nt_devmode , char * buf , int buflen )
2000-02-07 19:17:59 +03:00
{
2000-05-24 10:10:21 +04:00
int len = 0 ;
len + = tdb_pack ( buf + len , buflen - len , " p " , nt_devmode ) ;
2003-02-25 23:53:53 +03:00
if ( ! nt_devmode )
return len ;
2000-05-24 10:10:21 +04:00
2000-06-27 02:08:20 +04:00
len + = tdb_pack ( buf + len , buflen - len , " ffwwwwwwwwwwwwwwwwwwddddddddddddddp " ,
nt_devmode - > devicename ,
2000-06-04 06:29:00 +04:00
nt_devmode - > formname ,
nt_devmode - > specversion ,
nt_devmode - > driverversion ,
nt_devmode - > size ,
nt_devmode - > driverextra ,
nt_devmode - > orientation ,
nt_devmode - > papersize ,
nt_devmode - > paperlength ,
nt_devmode - > paperwidth ,
nt_devmode - > scale ,
nt_devmode - > copies ,
nt_devmode - > defaultsource ,
nt_devmode - > printquality ,
nt_devmode - > color ,
nt_devmode - > duplex ,
nt_devmode - > yresolution ,
nt_devmode - > ttoption ,
nt_devmode - > collate ,
nt_devmode - > logpixels ,
nt_devmode - > fields ,
nt_devmode - > bitsperpel ,
nt_devmode - > pelswidth ,
nt_devmode - > pelsheight ,
nt_devmode - > displayflags ,
nt_devmode - > displayfrequency ,
nt_devmode - > icmmethod ,
nt_devmode - > icmintent ,
nt_devmode - > mediatype ,
nt_devmode - > dithertype ,
nt_devmode - > reserved1 ,
nt_devmode - > reserved2 ,
nt_devmode - > panningwidth ,
nt_devmode - > panningheight ,
nt_devmode - > private ) ;
2000-05-24 10:10:21 +04:00
if ( nt_devmode - > private ) {
len + = tdb_pack ( buf + len , buflen - len , " B " ,
nt_devmode - > driverextra ,
nt_devmode - > private ) ;
2000-02-07 19:17:59 +03:00
}
2000-05-24 10:10:21 +04:00
2000-06-04 06:29:00 +04:00
DEBUG ( 8 , ( " Packed devicemode [%s] \n " , nt_devmode - > formname ) ) ;
2000-05-24 10:10:21 +04:00
return len ;
2000-02-07 19:17:59 +03:00
}
/****************************************************************************
2002-08-17 20:31:24 +04:00
Pack all values in all printer keys
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static int pack_values ( NT_PRINTER_DATA * data , char * buf , int buflen )
2000-02-07 19:17:59 +03:00
{
2002-08-17 20:31:24 +04:00
int len = 0 ;
int i , j ;
REGISTRY_VALUE * val ;
REGVAL_CTR * val_ctr ;
pstring path ;
int num_values ;
2000-05-24 10:10:21 +04:00
2002-08-17 20:31:24 +04:00
if ( ! data )
return 0 ;
/* loop over all keys */
2003-02-25 23:53:53 +03:00
for ( i = 0 ; i < data - > num_keys ; i + + ) {
2002-08-17 20:31:24 +04:00
val_ctr = & data - > keys [ i ] . values ;
num_values = regval_ctr_numvals ( val_ctr ) ;
/* loop over all values */
2003-02-25 23:53:53 +03:00
for ( j = 0 ; j < num_values ; j + + ) {
2002-08-17 20:31:24 +04:00
/* pathname should be stored as <key>\<value> */
val = regval_ctr_specific_value ( val_ctr , j ) ;
pstrcpy ( path , data - > keys [ i ] . name ) ;
pstrcat ( path , " \\ " ) ;
pstrcat ( path , regval_name ( val ) ) ;
len + = tdb_pack ( buf + len , buflen - len , " pPdB " ,
val ,
path ,
regval_type ( val ) ,
regval_size ( val ) ,
regval_data_p ( val ) ) ;
}
2000-02-07 19:17:59 +03:00
}
2000-05-24 10:10:21 +04:00
2002-08-17 20:31:24 +04:00
/* terminator */
len + = tdb_pack ( buf + len , buflen - len , " p " , NULL ) ;
2000-05-24 10:10:21 +04:00
return len ;
2000-02-07 19:17:59 +03:00
}
2000-05-02 19:31:55 +04:00
/****************************************************************************
2002-02-09 07:10:24 +03:00
Delete a printer - this just deletes the printer info file , any open
handles are not affected .
2000-05-02 19:31:55 +04:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2002-02-09 07:10:24 +03:00
2000-07-22 04:48:29 +04:00
uint32 del_a_printer ( char * sharename )
2000-05-02 19:31:55 +04:00
{
2000-05-24 10:10:21 +04:00
pstring key ;
TDB_DATA kbuf ;
2001-04-09 00:01:51 +04:00
slprintf ( key , sizeof ( key ) - 1 , " %s%s " , PRINTERS_PREFIX , sharename ) ;
2000-05-24 10:10:21 +04:00
kbuf . dptr = key ;
kbuf . dsize = strlen ( key ) + 1 ;
2001-07-09 22:19:04 +04:00
tdb_delete ( tdb_printers , kbuf ) ;
2000-05-02 19:31:55 +04:00
return 0 ;
}
2001-01-26 21:13:17 +03:00
/* FIXME!!! Reorder so this forward declaration is not necessary --jerry */
2003-02-25 23:53:53 +03:00
static WERROR get_a_printer_2 ( NT_PRINTER_INFO_LEVEL_2 * * , const char * sharename ) ;
2001-01-26 21:13:17 +03:00
static void free_nt_printer_info_level_2 ( NT_PRINTER_INFO_LEVEL_2 * * ) ;
2000-02-07 19:17:59 +03:00
/****************************************************************************
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2001-09-04 11:13:01 +04:00
static WERROR update_a_printer_2 ( NT_PRINTER_INFO_LEVEL_2 * info )
2000-02-07 19:17:59 +03:00
{
2000-05-24 10:10:21 +04:00
pstring key ;
char * buf ;
2001-09-04 11:13:01 +04:00
int buflen , len ;
WERROR ret ;
2000-05-24 10:10:21 +04:00
TDB_DATA kbuf , dbuf ;
2000-02-07 19:17:59 +03:00
2000-11-15 00:56:32 +03:00
/*
2000-02-07 19:17:59 +03:00
* in addprinter : no servername and the printer is the name
* in setprinter : servername is \ \ server
* and printer is \ \ server \ \ printer
*
* Samba manages only local printers .
* we currently don ' t support things like path = \ \ other_server \ printer
*/
2000-07-22 04:48:29 +04:00
if ( info - > servername [ 0 ] ! = ' \0 ' ) {
2000-02-07 19:17:59 +03:00
trim_string ( info - > printername , info - > servername , NULL ) ;
2003-09-05 23:59:55 +04:00
trim_char ( info - > printername , ' \\ ' , ' \0 ' ) ;
2000-02-07 19:17:59 +03:00
info - > servername [ 0 ] = ' \0 ' ;
}
2000-05-24 10:10:21 +04:00
/*
* JFM : one day I ' ll forget .
* below that ' s info - > portname because that ' s the SAMBA sharename
* and I made NT ' thinks ' it ' s the portname
* the info - > sharename is the thing you can name when you add a printer
* that ' s the short - name when you create shared printer for 95 / 98
* So I ' ve made a limitation in SAMBA : you can only have 1 printer model
* behind a SAMBA share .
*/
buf = NULL ;
buflen = 0 ;
again :
len = 0 ;
2000-08-01 00:41:51 +04:00
len + = tdb_pack ( buf + len , buflen - len , " dddddddddddfffffPfffff " ,
2000-05-24 10:10:21 +04:00
info - > attributes ,
info - > priority ,
info - > default_priority ,
info - > starttime ,
info - > untiltime ,
info - > status ,
info - > cjobs ,
info - > averageppm ,
info - > changeid ,
info - > c_setprinter ,
info - > setuptime ,
info - > servername ,
info - > printername ,
info - > sharename ,
info - > portname ,
info - > drivername ,
2000-07-22 04:48:29 +04:00
info - > comment ,
2000-05-24 10:10:21 +04:00
info - > location ,
info - > sepfile ,
info - > printprocessor ,
info - > datatype ,
info - > parameters ) ;
2001-01-30 00:34:08 +03:00
len + = pack_devicemode ( info - > devmode , buf + len , buflen - len ) ;
2001-01-26 21:13:17 +03:00
2002-08-17 20:31:24 +04:00
len + = pack_values ( & info - > data , buf + len , buflen - len ) ;
2000-05-24 10:10:21 +04:00
if ( buflen ! = len ) {
2001-08-12 21:30:01 +04:00
char * tb ;
2002-02-09 07:10:24 +03:00
2001-08-12 21:30:01 +04:00
tb = ( char * ) Realloc ( buf , len ) ;
if ( ! tb ) {
DEBUG ( 0 , ( " update_a_printer_2: failed to enlarge buffer! \n " ) ) ;
2001-09-04 11:13:01 +04:00
ret = WERR_NOMEM ;
2001-08-12 21:30:01 +04:00
goto done ;
}
else buf = tb ;
2000-05-24 10:10:21 +04:00
buflen = len ;
goto again ;
2000-02-07 19:17:59 +03:00
}
2001-04-09 00:01:51 +04:00
slprintf ( key , sizeof ( key ) - 1 , " %s%s " , PRINTERS_PREFIX , info - > sharename ) ;
2000-02-07 19:17:59 +03:00
2000-05-24 10:10:21 +04:00
kbuf . dptr = key ;
kbuf . dsize = strlen ( key ) + 1 ;
dbuf . dptr = buf ;
dbuf . dsize = len ;
2000-02-07 19:17:59 +03:00
2001-09-04 11:13:01 +04:00
ret = ( tdb_store ( tdb_printers , kbuf , dbuf , TDB_REPLACE ) = = 0 ? WERR_OK : WERR_NOMEM ) ;
2000-02-07 19:17:59 +03:00
2001-08-12 21:30:01 +04:00
done :
2001-09-04 11:13:01 +04:00
if ( ! W_ERROR_IS_OK ( ret ) )
2000-07-12 18:10:40 +04:00
DEBUG ( 8 , ( " error updating printer to tdb on disk \n " ) ) ;
2001-09-17 13:25:57 +04:00
SAFE_FREE ( buf ) ;
2000-02-07 19:17:59 +03:00
2000-11-15 00:56:32 +03:00
DEBUG ( 8 , ( " packed printer [%s] with driver [%s] portname=[%s] len=%d \n " ,
2000-07-25 17:15:16 +04:00
info - > sharename , info - > drivername , info - > portname , len ) ) ;
2000-06-04 06:29:00 +04:00
2000-05-24 10:10:21 +04:00
return ret ;
2000-02-07 19:17:59 +03:00
}
2000-06-01 21:01:34 +04:00
/****************************************************************************
Malloc and return an NT devicemode .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2000-06-27 02:08:20 +04:00
NT_DEVICEMODE * construct_nt_devicemode ( const fstring default_devicename )
2000-06-01 21:01:34 +04:00
{
2003-04-14 07:50:38 +04:00
char adevice [ MAXDEVICENAME ] ;
2000-06-01 21:01:34 +04:00
NT_DEVICEMODE * nt_devmode = ( NT_DEVICEMODE * ) malloc ( sizeof ( NT_DEVICEMODE ) ) ;
if ( nt_devmode = = NULL ) {
DEBUG ( 0 , ( " construct_nt_devicemode: malloc fail. \n " ) ) ;
return NULL ;
}
ZERO_STRUCTP ( nt_devmode ) ;
2003-03-14 05:10:26 +03:00
safe_strcpy ( adevice , default_devicename , sizeof ( adevice ) - 1 ) ;
2000-11-08 06:12:16 +03:00
fstrcpy ( nt_devmode - > devicename , adevice ) ;
2000-07-01 13:34:37 +04:00
2000-06-06 05:47:11 +04:00
fstrcpy ( nt_devmode - > formname , " Letter " ) ;
2000-06-01 21:01:34 +04:00
nt_devmode - > specversion = 0x0401 ;
nt_devmode - > driverversion = 0x0400 ;
nt_devmode - > size = 0x00DC ;
nt_devmode - > driverextra = 0x0000 ;
2000-11-15 00:56:32 +03:00
nt_devmode - > fields = FORMNAME | TTOPTION | PRINTQUALITY |
DEFAULTSOURCE | COPIES | SCALE |
2000-06-01 21:01:34 +04:00
PAPERSIZE | ORIENTATION ;
nt_devmode - > orientation = 1 ;
2000-06-06 05:47:11 +04:00
nt_devmode - > papersize = PAPER_LETTER ;
2000-06-01 21:01:34 +04:00
nt_devmode - > paperlength = 0 ;
nt_devmode - > paperwidth = 0 ;
nt_devmode - > scale = 0x64 ;
2001-12-03 05:30:27 +03:00
nt_devmode - > copies = 1 ;
2000-06-01 21:01:34 +04:00
nt_devmode - > defaultsource = BIN_FORMSOURCE ;
2000-09-30 00:08:00 +04:00
nt_devmode - > printquality = RES_HIGH ; /* 0x0258 */
2000-06-01 21:01:34 +04:00
nt_devmode - > color = COLOR_MONOCHROME ;
nt_devmode - > duplex = DUP_SIMPLEX ;
nt_devmode - > yresolution = 0 ;
nt_devmode - > ttoption = TT_SUBDEV ;
nt_devmode - > collate = COLLATE_FALSE ;
nt_devmode - > icmmethod = 0 ;
nt_devmode - > icmintent = 0 ;
nt_devmode - > mediatype = 0 ;
nt_devmode - > dithertype = 0 ;
2004-04-13 18:39:48 +04:00
/* non utilisés par un driver d'imprimante */
2000-06-01 21:01:34 +04:00
nt_devmode - > logpixels = 0 ;
nt_devmode - > bitsperpel = 0 ;
nt_devmode - > pelswidth = 0 ;
nt_devmode - > pelsheight = 0 ;
nt_devmode - > displayflags = 0 ;
nt_devmode - > displayfrequency = 0 ;
nt_devmode - > reserved1 = 0 ;
nt_devmode - > reserved2 = 0 ;
nt_devmode - > panningwidth = 0 ;
nt_devmode - > panningheight = 0 ;
2001-01-30 00:34:08 +03:00
nt_devmode - > private = NULL ;
2000-06-01 21:01:34 +04:00
return nt_devmode ;
}
/****************************************************************************
Deepcopy an NT devicemode .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
NT_DEVICEMODE * dup_nt_devicemode ( NT_DEVICEMODE * nt_devicemode )
{
NT_DEVICEMODE * new_nt_devicemode = NULL ;
2003-02-25 23:53:53 +03:00
if ( ! nt_devicemode )
return NULL ;
2000-06-01 21:01:34 +04:00
if ( ( new_nt_devicemode = ( NT_DEVICEMODE * ) memdup ( nt_devicemode , sizeof ( NT_DEVICEMODE ) ) ) = = NULL ) {
DEBUG ( 0 , ( " dup_nt_devicemode: malloc fail. \n " ) ) ;
return NULL ;
}
new_nt_devicemode - > private = NULL ;
if ( nt_devicemode - > private ! = NULL ) {
if ( ( new_nt_devicemode - > private = memdup ( nt_devicemode - > private , nt_devicemode - > driverextra ) ) = = NULL ) {
2001-09-17 13:25:57 +04:00
SAFE_FREE ( new_nt_devicemode ) ;
2000-06-01 21:01:34 +04:00
DEBUG ( 0 , ( " dup_nt_devicemode: malloc fail. \n " ) ) ;
return NULL ;
}
}
return new_nt_devicemode ;
}
2000-04-05 23:48:06 +04:00
/****************************************************************************
Clean up and deallocate a ( maybe partially ) allocated NT_DEVICEMODE .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2000-06-01 21:01:34 +04:00
void free_nt_devicemode ( NT_DEVICEMODE * * devmode_ptr )
2000-04-05 23:48:06 +04:00
{
NT_DEVICEMODE * nt_devmode = * devmode_ptr ;
if ( nt_devmode = = NULL )
return ;
2000-04-07 02:48:53 +04:00
DEBUG ( 106 , ( " free_nt_devicemode: deleting DEVMODE \n " ) ) ;
2002-08-17 20:31:24 +04:00
SAFE_FREE ( nt_devmode - > private ) ;
2001-09-17 13:25:57 +04:00
SAFE_FREE ( * devmode_ptr ) ;
2000-04-05 23:48:06 +04:00
}
/****************************************************************************
Clean up and deallocate a ( maybe partially ) allocated NT_PRINTER_INFO_LEVEL_2 .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static void free_nt_printer_info_level_2 ( NT_PRINTER_INFO_LEVEL_2 * * info_ptr )
{
NT_PRINTER_INFO_LEVEL_2 * info = * info_ptr ;
2002-08-17 20:31:24 +04:00
NT_PRINTER_DATA * data ;
int i ;
2000-04-05 23:48:06 +04:00
2002-08-17 20:31:24 +04:00
if ( ! info )
2000-04-05 23:48:06 +04:00
return ;
2000-04-07 02:48:53 +04:00
DEBUG ( 106 , ( " free_nt_printer_info_level_2: deleting info \n " ) ) ;
2000-04-05 23:48:06 +04:00
free_nt_devicemode ( & info - > devmode ) ;
2002-08-17 20:31:24 +04:00
/* clean up all registry keys */
data = & info - > data ;
2003-02-25 23:53:53 +03:00
for ( i = 0 ; i < data - > num_keys ; i + + ) {
2002-08-17 20:31:24 +04:00
SAFE_FREE ( data - > keys [ i ] . name ) ;
regval_ctr_destroy ( & data - > keys [ i ] . values ) ;
2000-04-05 23:48:06 +04:00
}
2002-08-17 20:31:24 +04:00
SAFE_FREE ( data - > keys ) ;
2000-04-05 23:48:06 +04:00
2002-08-17 20:31:24 +04:00
/* finally the top level structure */
SAFE_FREE ( * info_ptr ) ;
2000-04-05 23:48:06 +04:00
}
2000-05-24 10:10:21 +04:00
2000-02-07 19:17:59 +03:00
/****************************************************************************
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2002-09-25 19:19:00 +04:00
int unpack_devicemode ( NT_DEVICEMODE * * nt_devmode , char * buf , int buflen )
2000-02-07 19:17:59 +03:00
{
2000-05-24 10:10:21 +04:00
int len = 0 ;
2000-07-27 11:59:39 +04:00
int extra_len = 0 ;
2000-05-24 10:10:21 +04:00
NT_DEVICEMODE devmode ;
2003-08-23 07:34:24 +04:00
2000-05-24 10:10:21 +04:00
ZERO_STRUCT ( devmode ) ;
2000-05-27 13:53:11 +04:00
len + = tdb_unpack ( buf + len , buflen - len , " p " , nt_devmode ) ;
2000-05-24 10:10:21 +04:00
if ( ! * nt_devmode ) return len ;
2000-06-27 02:08:20 +04:00
len + = tdb_unpack ( buf + len , buflen - len , " ffwwwwwwwwwwwwwwwwwwddddddddddddddp " ,
devmode . devicename ,
2000-06-04 06:29:00 +04:00
devmode . formname ,
& devmode . specversion ,
& devmode . driverversion ,
& devmode . size ,
& devmode . driverextra ,
& devmode . orientation ,
& devmode . papersize ,
& devmode . paperlength ,
& devmode . paperwidth ,
& devmode . scale ,
& devmode . copies ,
& devmode . defaultsource ,
& devmode . printquality ,
& devmode . color ,
& devmode . duplex ,
& devmode . yresolution ,
& devmode . ttoption ,
& devmode . collate ,
& devmode . logpixels ,
2000-11-15 00:56:32 +03:00
2000-06-04 06:29:00 +04:00
& devmode . fields ,
& devmode . bitsperpel ,
& devmode . pelswidth ,
& devmode . pelsheight ,
& devmode . displayflags ,
& devmode . displayfrequency ,
& devmode . icmmethod ,
& devmode . icmintent ,
& devmode . mediatype ,
& devmode . dithertype ,
& devmode . reserved1 ,
& devmode . reserved2 ,
& devmode . panningwidth ,
& devmode . panningheight ,
& devmode . private ) ;
2000-05-24 10:10:21 +04:00
2000-07-27 11:59:39 +04:00
if ( devmode . private ) {
/* the len in tdb_unpack is an int value and
2001-01-30 00:34:08 +03:00
* devmode . driverextra is only a short
2000-07-27 11:59:39 +04:00
*/
len + = tdb_unpack ( buf + len , buflen - len , " B " , & extra_len , & devmode . private ) ;
devmode . driverextra = ( uint16 ) extra_len ;
2000-12-22 02:38:47 +03:00
/* check to catch an invalid TDB entry so we don't segfault */
if ( devmode . driverextra = = 0 ) {
devmode . private = NULL ;
}
2000-07-27 11:59:39 +04:00
}
2000-02-07 19:17:59 +03:00
2000-05-24 10:10:21 +04:00
* nt_devmode = ( NT_DEVICEMODE * ) memdup ( & devmode , sizeof ( devmode ) ) ;
2000-02-07 19:17:59 +03:00
2000-07-12 18:10:40 +04:00
DEBUG ( 8 , ( " Unpacked devicemode [%s](%s) \n " , devmode . devicename , devmode . formname ) ) ;
if ( devmode . private )
DEBUG ( 8 , ( " with a private section of %d bytes \n " , devmode . driverextra ) ) ;
2000-06-04 06:29:00 +04:00
2000-05-24 10:10:21 +04:00
return len ;
}
2000-02-07 19:17:59 +03:00
2000-05-24 10:10:21 +04:00
/****************************************************************************
2003-02-25 23:53:53 +03:00
Allocate and initialize a new slot .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2002-08-17 20:31:24 +04:00
2003-01-03 11:28:12 +03:00
static int add_new_printer_key ( NT_PRINTER_DATA * data , const char * name )
2000-05-24 10:10:21 +04:00
{
2002-08-17 20:31:24 +04:00
NT_PRINTER_KEY * d ;
int key_index ;
if ( ! data | | ! name )
return - 1 ;
/* allocate another slot in the NT_PRINTER_KEY array */
d = Realloc ( data - > keys , sizeof ( NT_PRINTER_KEY ) * ( data - > num_keys + 1 ) ) ;
if ( d )
data - > keys = d ;
key_index = data - > num_keys ;
/* initialze new key */
data - > num_keys + + ;
data - > keys [ key_index ] . name = strdup ( name ) ;
ZERO_STRUCTP ( & data - > keys [ key_index ] . values ) ;
regval_ctr_init ( & data - > keys [ key_index ] . values ) ;
DEBUG ( 10 , ( " add_new_printer_key: Inserted new data key [%s] \n " , name ) ) ;
return key_index ;
}
2000-02-07 19:17:59 +03:00
2002-08-17 20:31:24 +04:00
/****************************************************************************
search for a registry key name in the existing printer data
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2003-01-03 11:28:12 +03:00
int lookup_printerkey ( NT_PRINTER_DATA * data , const char * name )
2002-08-17 20:31:24 +04:00
{
int key_index = - 1 ;
int i ;
if ( ! data | | ! name )
return - 1 ;
2000-02-07 19:17:59 +03:00
2002-08-17 20:31:24 +04:00
DEBUG ( 12 , ( " lookup_printerkey: Looking for [%s] \n " , name ) ) ;
2000-05-24 10:10:21 +04:00
2002-08-17 20:31:24 +04:00
/* loop over all existing keys */
2003-02-25 23:53:53 +03:00
for ( i = 0 ; i < data - > num_keys ; i + + ) {
2002-09-25 19:19:00 +04:00
if ( strequal ( data - > keys [ i ] . name , name ) ) {
2002-08-17 20:31:24 +04:00
DEBUG ( 12 , ( " lookup_printerkey: Found [%s]! \n " , name ) ) ;
key_index = i ;
break ;
}
}
return key_index ;
}
2002-09-25 19:19:00 +04:00
/****************************************************************************
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2003-01-03 11:28:12 +03:00
uint32 get_printer_subkeys ( NT_PRINTER_DATA * data , const char * key , fstring * * subkeys )
2002-09-25 19:19:00 +04:00
{
int i , j ;
int key_len ;
int num_subkeys = 0 ;
char * p ;
fstring * ptr , * subkeys_ptr = NULL ;
fstring subkeyname ;
if ( ! data )
return 0 ;
2003-02-25 23:53:53 +03:00
for ( i = 0 ; i < data - > num_keys ; i + + ) {
if ( StrnCaseCmp ( data - > keys [ i ] . name , key , strlen ( key ) ) = = 0 ) {
2002-09-25 19:19:00 +04:00
/* match sure it is a subkey and not the key itself */
key_len = strlen ( key ) ;
if ( strlen ( data - > keys [ i ] . name ) = = key_len )
continue ;
/* get subkey path */
p = data - > keys [ i ] . name + key_len ;
if ( * p = = ' \\ ' )
p + + ;
fstrcpy ( subkeyname , p ) ;
if ( ( p = strchr ( subkeyname , ' \\ ' ) ) )
* p = ' \0 ' ;
/* don't add a key more than once */
for ( j = 0 ; j < num_subkeys ; j + + ) {
if ( strequal ( subkeys_ptr [ j ] , subkeyname ) )
break ;
}
if ( j ! = num_subkeys )
continue ;
/* found a match, so allocate space and copy the name */
if ( ! ( ptr = Realloc ( subkeys_ptr , ( num_subkeys + 2 ) * sizeof ( fstring ) ) ) ) {
DEBUG ( 0 , ( " get_printer_subkeys: Realloc failed for [%d] entries! \n " ,
num_subkeys + 1 ) ) ;
SAFE_FREE ( subkeys ) ;
return 0 ;
}
subkeys_ptr = ptr ;
fstrcpy ( subkeys_ptr [ num_subkeys ] , subkeyname ) ;
num_subkeys + + ;
}
}
/* tag of the end */
2002-11-07 10:13:29 +03:00
if ( num_subkeys )
2003-02-25 23:53:53 +03:00
fstrcpy ( subkeys_ptr [ num_subkeys ] , " " ) ;
2002-09-25 19:19:00 +04:00
* subkeys = subkeys_ptr ;
return num_subkeys ;
}
2002-12-04 20:40:50 +03:00
2003-06-25 23:49:27 +04:00
# ifdef HAVE_ADS
2002-12-05 22:13:40 +03:00
static void map_sz_into_ctr ( REGVAL_CTR * ctr , const char * val_name ,
const char * sz )
{
smb_ucs2_t conv_str [ 1024 ] ;
size_t str_size ;
regval_ctr_delvalue ( ctr , val_name ) ;
str_size = push_ucs2 ( NULL , conv_str , sz , sizeof ( conv_str ) ,
STR_TERMINATE | STR_NOALIGN ) ;
regval_ctr_addvalue ( ctr , val_name , REG_SZ ,
( char * ) conv_str , str_size ) ;
}
static void map_dword_into_ctr ( REGVAL_CTR * ctr , const char * val_name ,
uint32 dword )
{
regval_ctr_delvalue ( ctr , val_name ) ;
regval_ctr_addvalue ( ctr , val_name , REG_DWORD ,
( char * ) & dword , sizeof ( dword ) ) ;
}
static void map_bool_into_ctr ( REGVAL_CTR * ctr , const char * val_name ,
2003-05-27 11:29:13 +04:00
BOOL b )
2002-12-05 22:13:40 +03:00
{
2003-05-27 11:29:13 +04:00
uint8 bin_bool = ( b ? 1 : 0 ) ;
2002-12-05 22:13:40 +03:00
regval_ctr_delvalue ( ctr , val_name ) ;
regval_ctr_addvalue ( ctr , val_name , REG_BINARY ,
( char * ) & bin_bool , sizeof ( bin_bool ) ) ;
}
static void map_single_multi_sz_into_ctr ( REGVAL_CTR * ctr , const char * val_name ,
const char * multi_sz )
{
smb_ucs2_t * conv_strs = NULL ;
size_t str_size ;
/* a multi-sz has to have a null string terminator, i.e., the last
string must be followed by two nulls */
str_size = ( strlen ( multi_sz ) + 2 ) * sizeof ( smb_ucs2_t ) ;
conv_strs = calloc ( str_size , 1 ) ;
push_ucs2 ( NULL , conv_strs , multi_sz , str_size ,
STR_TERMINATE | STR_NOALIGN ) ;
regval_ctr_delvalue ( ctr , val_name ) ;
regval_ctr_addvalue ( ctr , val_name , REG_MULTI_SZ ,
( char * ) conv_strs , str_size ) ;
safe_free ( conv_strs ) ;
}
2002-12-04 20:40:50 +03:00
/****************************************************************************
* Map the NT_PRINTER_INFO_LEVEL_2 data into DsSpooler keys for publishing .
*
* @ param info2 NT_PRINTER_INFO_LEVEL_2 describing printer - gets modified
* @ return BOOL indicating success or failure
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static BOOL map_nt_printer_info2_to_dsspooler ( NT_PRINTER_INFO_LEVEL_2 * info2 )
{
REGVAL_CTR * ctr = NULL ;
fstring longname ;
2003-01-03 11:28:12 +03:00
char * allocated_string = NULL ;
const char * ascii_str ;
2002-12-04 20:40:50 +03:00
int i ;
2002-12-14 00:56:34 +03:00
if ( ( i = lookup_printerkey ( & info2 - > data , SPOOL_DSSPOOLER_KEY ) ) < 0 )
i = add_new_printer_key ( & info2 - > data , SPOOL_DSSPOOLER_KEY ) ;
ctr = & info2 - > data . keys [ i ] . values ;
2002-12-04 20:40:50 +03:00
2002-12-05 22:13:40 +03:00
map_sz_into_ctr ( ctr , SPOOL_REG_PRINTERNAME , info2 - > sharename ) ;
map_sz_into_ctr ( ctr , SPOOL_REG_SHORTSERVERNAME , global_myname ( ) ) ;
2002-12-04 20:40:50 +03:00
2004-01-30 21:38:48 +03:00
get_mydnsfullname ( longname ) ;
2002-12-05 22:13:40 +03:00
map_sz_into_ctr ( ctr , SPOOL_REG_SERVERNAME , longname ) ;
2003-01-03 11:28:12 +03:00
asprintf ( & allocated_string , " \\ \\ %s \\ %s " , longname , info2 - > sharename ) ;
map_sz_into_ctr ( ctr , SPOOL_REG_UNCNAME , allocated_string ) ;
SAFE_FREE ( allocated_string ) ;
2002-12-05 22:13:40 +03:00
map_dword_into_ctr ( ctr , SPOOL_REG_VERSIONNUMBER , 4 ) ;
map_sz_into_ctr ( ctr , SPOOL_REG_DRIVERNAME , info2 - > drivername ) ;
map_sz_into_ctr ( ctr , SPOOL_REG_LOCATION , info2 - > location ) ;
map_sz_into_ctr ( ctr , SPOOL_REG_DESCRIPTION , info2 - > comment ) ;
map_single_multi_sz_into_ctr ( ctr , SPOOL_REG_PORTNAME , info2 - > portname ) ;
map_sz_into_ctr ( ctr , SPOOL_REG_PRINTSEPARATORFILE , info2 - > sepfile ) ;
map_dword_into_ctr ( ctr , SPOOL_REG_PRINTSTARTTIME , info2 - > starttime ) ;
map_dword_into_ctr ( ctr , SPOOL_REG_PRINTENDTIME , info2 - > untiltime ) ;
map_dword_into_ctr ( ctr , SPOOL_REG_PRIORITY , info2 - > priority ) ;
map_bool_into_ctr ( ctr , SPOOL_REG_PRINTKEEPPRINTEDJOBS ,
2002-12-13 22:01:27 +03:00
( info2 - > attributes &
PRINTER_ATTRIBUTE_KEEPPRINTEDJOBS ) ) ;
2002-12-05 22:13:40 +03:00
switch ( info2 - > attributes & 0x3 ) {
case 0 :
ascii_str = SPOOL_REGVAL_PRINTWHILESPOOLING ;
break ;
case 1 :
ascii_str = SPOOL_REGVAL_PRINTAFTERSPOOLED ;
break ;
case 2 :
ascii_str = SPOOL_REGVAL_PRINTDIRECT ;
break ;
default :
ascii_str = " unknown " ;
}
map_sz_into_ctr ( ctr , SPOOL_REG_PRINTSPOOLING , ascii_str ) ;
2002-12-04 20:40:50 +03:00
return True ;
}
2004-04-13 18:39:48 +04:00
static void store_printer_guid ( NT_PRINTER_INFO_LEVEL_2 * info2 ,
struct uuid guid )
2002-12-14 00:56:34 +03:00
{
int i ;
REGVAL_CTR * ctr = NULL ;
/* find the DsSpooler key */
if ( ( i = lookup_printerkey ( & info2 - > data , SPOOL_DSSPOOLER_KEY ) ) < 0 )
i = add_new_printer_key ( & info2 - > data , SPOOL_DSSPOOLER_KEY ) ;
ctr = & info2 - > data . keys [ i ] . values ;
regval_ctr_delvalue ( ctr , " objectGUID " ) ;
regval_ctr_addvalue ( ctr , " objectGUID " , REG_BINARY ,
2004-04-13 18:39:48 +04:00
( char * ) & guid , sizeof ( struct uuid ) ) ;
2002-12-14 00:56:34 +03:00
}
static WERROR publish_it ( NT_PRINTER_INFO_LEVEL * printer )
{
ADS_STATUS ads_rc ;
2002-12-20 23:21:31 +03:00
TALLOC_CTX * ctx = talloc_init ( " publish_it " ) ;
2002-12-14 00:56:34 +03:00
ADS_MODLIST mods = ads_init_mods ( ctx ) ;
2003-09-11 02:33:06 +04:00
char * prt_dn = NULL , * srv_dn , * srv_cn_0 ;
char * srv_dn_utf8 , * * srv_cn_utf8 ;
2002-12-14 00:56:34 +03:00
void * res = NULL ;
ADS_STRUCT * ads ;
const char * attrs [ ] = { " objectGUID " , NULL } ;
2004-04-13 18:39:48 +04:00
struct uuid guid ;
2002-12-14 00:56:34 +03:00
WERROR win_rc = WERR_OK ;
ZERO_STRUCT ( guid ) ;
/* set the DsSpooler info and attributes */
if ( ! ( map_nt_printer_info2_to_dsspooler ( printer - > info_2 ) ) )
return WERR_NOMEM ;
printer - > info_2 - > attributes | = PRINTER_ATTRIBUTE_PUBLISHED ;
win_rc = mod_a_printer ( * printer , 2 ) ;
if ( ! W_ERROR_IS_OK ( win_rc ) ) {
DEBUG ( 3 , ( " err %d saving data \n " ,
W_ERROR_V ( win_rc ) ) ) ;
return win_rc ;
}
/* Build the ads mods */
get_local_printer_publishing_data ( ctx , & mods ,
& printer - > info_2 - > data ) ;
ads_mod_str ( ctx , & mods , SPOOL_REG_PRINTERNAME ,
printer - > info_2 - > sharename ) ;
2003-06-25 21:41:05 +04:00
/* initial ads structure */
ads = ads_init ( NULL , NULL , NULL ) ;
2002-12-14 00:56:34 +03:00
if ( ! ads ) {
DEBUG ( 3 , ( " ads_init() failed \n " ) ) ;
return WERR_SERVER_UNAVAILABLE ;
}
2003-05-09 13:37:12 +04:00
setenv ( KRB5_ENV_CCNAME , " MEMORY:prtpub_cache " , 1 ) ;
2003-04-26 01:51:26 +04:00
SAFE_FREE ( ads - > auth . password ) ;
ads - > auth . password = secrets_fetch_machine_password ( lp_workgroup ( ) ,
2003-06-25 21:41:05 +04:00
NULL , NULL ) ;
/* ads_connect() will find the DC for us */
2002-12-14 00:56:34 +03:00
ads_rc = ads_connect ( ads ) ;
if ( ! ADS_ERR_OK ( ads_rc ) ) {
DEBUG ( 3 , ( " ads_connect failed: %s \n " , ads_errstr ( ads_rc ) ) ) ;
ads_destroy ( & ads ) ;
return WERR_ACCESS_DENIED ;
}
/* figure out where to publish */
ads_find_machine_acct ( ads , & res , global_myname ( ) ) ;
2003-09-11 02:33:06 +04:00
/* We use ldap_get_dn here as we need the answer
* in utf8 to call ldap_explode_dn ( ) . JRA . */
srv_dn_utf8 = ldap_get_dn ( ads - > ld , res ) ;
if ( ! srv_dn_utf8 ) {
ads_destroy ( & ads ) ;
return WERR_SERVER_UNAVAILABLE ;
}
2002-12-14 00:56:34 +03:00
ads_msgfree ( ads , res ) ;
2003-09-11 02:33:06 +04:00
srv_cn_utf8 = ldap_explode_dn ( srv_dn_utf8 , 1 ) ;
if ( ! srv_cn_utf8 ) {
ldap_memfree ( srv_dn_utf8 ) ;
ads_destroy ( & ads ) ;
return WERR_SERVER_UNAVAILABLE ;
}
/* Now convert to CH_UNIX. */
2003-12-31 03:31:43 +03:00
if ( pull_utf8_allocate ( & srv_dn , srv_dn_utf8 ) = = ( size_t ) - 1 ) {
2003-09-11 02:33:06 +04:00
ldap_memfree ( srv_dn_utf8 ) ;
ldap_memfree ( srv_cn_utf8 ) ;
ads_destroy ( & ads ) ;
return WERR_SERVER_UNAVAILABLE ;
}
2003-12-31 03:31:43 +03:00
if ( pull_utf8_allocate ( & srv_cn_0 , srv_cn_utf8 [ 0 ] ) = = ( size_t ) - 1 ) {
2003-09-11 02:33:06 +04:00
ldap_memfree ( srv_dn_utf8 ) ;
ldap_memfree ( srv_cn_utf8 ) ;
ads_destroy ( & ads ) ;
SAFE_FREE ( srv_dn ) ;
return WERR_SERVER_UNAVAILABLE ;
}
ldap_memfree ( srv_dn_utf8 ) ;
ldap_memfree ( srv_cn_utf8 ) ;
asprintf ( & prt_dn , " cn=%s-%s,%s " , srv_cn_0 ,
2002-12-14 00:56:34 +03:00
printer - > info_2 - > sharename , srv_dn ) ;
2003-09-11 02:33:06 +04:00
SAFE_FREE ( srv_dn ) ;
SAFE_FREE ( srv_cn_0 ) ;
2002-12-14 00:56:34 +03:00
/* publish it */
ads_rc = ads_add_printer_entry ( ads , prt_dn , ctx , & mods ) ;
if ( LDAP_ALREADY_EXISTS = = ads_rc . err . rc )
ads_rc = ads_mod_printer_entry ( ads , prt_dn , ctx , & mods ) ;
/* retreive the guid and store it locally */
if ( ADS_ERR_OK ( ads_search_dn ( ads , & res , prt_dn , attrs ) ) ) {
ads_memfree ( ads , prt_dn ) ;
ads_pull_guid ( ads , res , & guid ) ;
ads_msgfree ( ads , res ) ;
store_printer_guid ( printer - > info_2 , guid ) ;
win_rc = mod_a_printer ( * printer , 2 ) ;
}
safe_free ( prt_dn ) ;
ads_destroy ( & ads ) ;
return WERR_OK ;
}
WERROR unpublish_it ( NT_PRINTER_INFO_LEVEL * printer )
{
ADS_STATUS ads_rc ;
ADS_STRUCT * ads ;
void * res ;
char * prt_dn = NULL ;
WERROR win_rc ;
printer - > info_2 - > attributes ^ = PRINTER_ATTRIBUTE_PUBLISHED ;
win_rc = mod_a_printer ( * printer , 2 ) ;
if ( ! W_ERROR_IS_OK ( win_rc ) ) {
DEBUG ( 3 , ( " err %d saving data \n " ,
W_ERROR_V ( win_rc ) ) ) ;
return win_rc ;
}
2003-06-25 21:41:05 +04:00
ads = ads_init ( NULL , NULL , NULL ) ;
2002-12-14 00:56:34 +03:00
if ( ! ads ) {
DEBUG ( 3 , ( " ads_init() failed \n " ) ) ;
return WERR_SERVER_UNAVAILABLE ;
}
2003-05-09 13:37:12 +04:00
setenv ( KRB5_ENV_CCNAME , " MEMORY:prtpub_cache " , 1 ) ;
2003-04-26 01:51:26 +04:00
SAFE_FREE ( ads - > auth . password ) ;
ads - > auth . password = secrets_fetch_machine_password ( lp_workgroup ( ) ,
2003-06-25 21:41:05 +04:00
NULL , NULL ) ;
/* ads_connect() will find the DC for us */
2002-12-14 00:56:34 +03:00
ads_rc = ads_connect ( ads ) ;
if ( ! ADS_ERR_OK ( ads_rc ) ) {
DEBUG ( 3 , ( " ads_connect failed: %s \n " , ads_errstr ( ads_rc ) ) ) ;
ads_destroy ( & ads ) ;
return WERR_ACCESS_DENIED ;
}
/* remove the printer from the directory */
ads_rc = ads_find_printer_on_server ( ads , & res ,
printer - > info_2 - > sharename , global_myname ( ) ) ;
if ( ADS_ERR_OK ( ads_rc ) & & ads_count_replies ( ads , res ) ) {
prt_dn = ads_get_dn ( ads , res ) ;
ads_msgfree ( ads , res ) ;
ads_rc = ads_del_dn ( ads , prt_dn ) ;
ads_memfree ( ads , prt_dn ) ;
}
ads_destroy ( & ads ) ;
return WERR_OK ;
}
2002-12-04 20:40:50 +03:00
/****************************************************************************
* Publish a printer in the directory
*
* @ param snum describing printer service
* @ return WERROR indicating status of publishing
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2003-02-25 23:53:53 +03:00
WERROR nt_printer_publish ( Printer_entry * print_hnd , int snum , int action )
2002-12-04 20:40:50 +03:00
{
NT_PRINTER_INFO_LEVEL * printer = NULL ;
WERROR win_rc ;
2003-02-25 23:53:53 +03:00
win_rc = get_a_printer ( print_hnd , & printer , 2 , lp_servicename ( snum ) ) ;
2002-12-04 20:40:50 +03:00
if ( ! W_ERROR_IS_OK ( win_rc ) )
return win_rc ;
2002-12-14 00:56:34 +03:00
switch ( action ) {
case SPOOL_DS_PUBLISH :
case SPOOL_DS_UPDATE :
win_rc = publish_it ( printer ) ;
break ;
case SPOOL_DS_UNPUBLISH :
win_rc = unpublish_it ( printer ) ;
break ;
default :
win_rc = WERR_NOT_SUPPORTED ;
}
2002-12-04 20:40:50 +03:00
2002-12-14 00:56:34 +03:00
free_a_printer ( & printer , 2 ) ;
return win_rc ;
}
2002-12-13 22:01:27 +03:00
2004-04-13 18:39:48 +04:00
BOOL is_printer_published ( Printer_entry * print_hnd , int snum ,
struct uuid * guid )
2002-12-14 00:56:34 +03:00
{
NT_PRINTER_INFO_LEVEL * printer = NULL ;
REGVAL_CTR * ctr ;
REGISTRY_VALUE * guid_val ;
WERROR win_rc ;
int i ;
2002-12-04 20:40:50 +03:00
2003-02-25 23:53:53 +03:00
win_rc = get_a_printer ( print_hnd , & printer , 2 , lp_servicename ( snum ) ) ;
2002-12-14 00:56:34 +03:00
if ( ! W_ERROR_IS_OK ( win_rc ) )
return False ;
2002-12-04 20:40:50 +03:00
2002-12-14 00:56:34 +03:00
if ( ! ( printer - > info_2 - > attributes & PRINTER_ATTRIBUTE_PUBLISHED ) )
return False ;
2002-12-04 20:40:50 +03:00
2002-12-14 00:56:34 +03:00
if ( ( i = lookup_printerkey ( & printer - > info_2 - > data ,
SPOOL_DSSPOOLER_KEY ) ) < 0 )
return False ;
2002-12-04 20:40:50 +03:00
2003-01-15 21:57:41 +03:00
if ( ! ( ctr = & printer - > info_2 - > data . keys [ i ] . values ) ) {
return False ;
}
if ( ! ( guid_val = regval_ctr_getvalue ( ctr , " objectGUID " ) ) ) {
return False ;
}
2002-12-04 20:40:50 +03:00
2004-04-13 18:39:48 +04:00
if ( regval_size ( guid_val ) = = sizeof ( struct uuid ) )
memcpy ( guid , regval_data_p ( guid_val ) , sizeof ( struct uuid ) ) ;
2002-12-14 00:56:34 +03:00
return True ;
}
2002-12-04 20:40:50 +03:00
# else
2003-02-25 23:53:53 +03:00
WERROR nt_printer_publish ( Printer_entry * print_hnd , int snum , int action )
2002-12-14 00:56:34 +03:00
{
2002-12-04 20:40:50 +03:00
return WERR_OK ;
}
2004-04-13 18:39:48 +04:00
BOOL is_printer_published ( Printer_entry * print_hnd , int snum ,
struct uuid * guid )
2002-12-14 00:56:34 +03:00
{
return False ;
}
# endif
2002-08-17 20:31:24 +04:00
/****************************************************************************
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2003-01-03 11:28:12 +03:00
WERROR delete_all_printer_data ( NT_PRINTER_INFO_LEVEL_2 * p2 , const char * key )
2002-08-17 20:31:24 +04:00
{
NT_PRINTER_DATA * data ;
int i ;
2002-09-25 19:19:00 +04:00
int removed_keys = 0 ;
int empty_slot ;
2002-08-17 20:31:24 +04:00
data = & p2 - > data ;
2002-09-25 19:19:00 +04:00
empty_slot = data - > num_keys ;
if ( ! key )
return WERR_INVALID_PARAM ;
2002-08-17 20:31:24 +04:00
2002-09-25 19:19:00 +04:00
/* remove all keys */
2003-02-25 23:53:53 +03:00
if ( ! strlen ( key ) ) {
for ( i = 0 ; i < data - > num_keys ; i + + ) {
2002-09-25 19:19:00 +04:00
DEBUG ( 8 , ( " delete_all_printer_data: Removed all Printer Data from key [%s] \n " ,
data - > keys [ i ] . name ) ) ;
2002-08-17 20:31:24 +04:00
2002-09-25 19:19:00 +04:00
SAFE_FREE ( data - > keys [ i ] . name ) ;
regval_ctr_destroy ( & data - > keys [ i ] . values ) ;
}
2002-08-17 20:31:24 +04:00
2002-09-25 19:19:00 +04:00
DEBUG ( 8 , ( " delete_all_printer_data: Removed all Printer Data from printer [%s] \n " ,
p2 - > printername ) ) ;
SAFE_FREE ( data - > keys ) ;
ZERO_STRUCTP ( data ) ;
return WERR_OK ;
}
2002-08-17 20:31:24 +04:00
2002-09-25 19:19:00 +04:00
/* remove a specific key (and all subkeys) */
2002-08-17 20:31:24 +04:00
2003-02-25 23:53:53 +03:00
for ( i = 0 ; i < data - > num_keys ; i + + ) {
if ( StrnCaseCmp ( data - > keys [ i ] . name , key , strlen ( key ) ) = = 0 ) {
2002-09-25 19:19:00 +04:00
DEBUG ( 8 , ( " delete_all_printer_data: Removed all Printer Data from key [%s] \n " ,
data - > keys [ i ] . name ) ) ;
SAFE_FREE ( data - > keys [ i ] . name ) ;
regval_ctr_destroy ( & data - > keys [ i ] . values ) ;
/* mark the slot as empty */
ZERO_STRUCTP ( & data - > keys [ i ] ) ;
}
}
/* find the first empty slot */
for ( i = 0 ; i < data - > num_keys ; i + + ) {
if ( ! data - > keys [ i ] . name ) {
empty_slot = i ;
removed_keys + + ;
break ;
}
}
if ( i = = data - > num_keys )
/* nothing was removed */
return WERR_INVALID_PARAM ;
/* move everything down */
2002-08-17 20:31:24 +04:00
2002-09-25 19:19:00 +04:00
for ( i = empty_slot + 1 ; i < data - > num_keys ; i + + ) {
if ( data - > keys [ i ] . name ) {
memcpy ( & data - > keys [ empty_slot ] , & data - > keys [ i ] , sizeof ( NT_PRINTER_KEY ) ) ;
ZERO_STRUCTP ( & data - > keys [ i ] ) ;
empty_slot + + ;
removed_keys + + ;
}
}
/* update count */
data - > num_keys - = removed_keys ;
/* sanity check to see if anything is left */
2003-02-25 23:53:53 +03:00
if ( ! data - > num_keys ) {
2002-09-25 19:19:00 +04:00
DEBUG ( 8 , ( " delete_all_printer_data: No keys left for printer [%s] \n " , p2 - > printername ) ) ;
SAFE_FREE ( data - > keys ) ;
ZERO_STRUCTP ( data ) ;
}
return WERR_OK ;
2002-08-17 20:31:24 +04:00
}
/****************************************************************************
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2003-01-03 11:28:12 +03:00
WERROR delete_printer_data ( NT_PRINTER_INFO_LEVEL_2 * p2 , const char * key , const char * value )
2002-08-17 20:31:24 +04:00
{
WERROR result = WERR_OK ;
int key_index ;
/* we must have names on non-zero length */
if ( ! key | | ! * key | | ! value | | ! * value )
return WERR_INVALID_NAME ;
/* find the printer key first */
key_index = lookup_printerkey ( & p2 - > data , key ) ;
if ( key_index = = - 1 )
2002-09-25 19:19:00 +04:00
return WERR_OK ;
2003-08-25 17:05:48 +04:00
/* make sure the value exists so we can return the correct error code */
if ( ! regval_ctr_getvalue ( & p2 - > data . keys [ key_index ] . values , value ) )
return WERR_BADFILE ;
2002-08-17 20:31:24 +04:00
regval_ctr_delvalue ( & p2 - > data . keys [ key_index ] . values , value ) ;
DEBUG ( 8 , ( " delete_printer_data: Removed key => [%s], value => [%s] \n " ,
key , value ) ) ;
return result ;
}
/****************************************************************************
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2003-01-03 11:28:12 +03:00
WERROR add_printer_data ( NT_PRINTER_INFO_LEVEL_2 * p2 , const char * key , const char * value ,
2002-08-17 20:31:24 +04:00
uint32 type , uint8 * data , int real_len )
{
WERROR result = WERR_OK ;
int key_index ;
/* we must have names on non-zero length */
if ( ! key | | ! * key | | ! value | | ! * value )
return WERR_INVALID_NAME ;
/* find the printer key first */
key_index = lookup_printerkey ( & p2 - > data , key ) ;
if ( key_index = = - 1 )
key_index = add_new_printer_key ( & p2 - > data , key ) ;
if ( key_index = = - 1 )
return WERR_NOMEM ;
regval_ctr_addvalue ( & p2 - > data . keys [ key_index ] . values , value ,
2003-08-15 08:42:05 +04:00
type , ( const char * ) data , real_len ) ;
2002-08-17 20:31:24 +04:00
2002-09-25 19:19:00 +04:00
DEBUG ( 8 , ( " add_printer_data: Added key => [%s], value => [%s], type=> [%d], size => [%d] \n " ,
key , value , type , real_len ) ) ;
2002-08-17 20:31:24 +04:00
return result ;
}
/****************************************************************************
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2003-01-03 11:28:12 +03:00
REGISTRY_VALUE * get_printer_data ( NT_PRINTER_INFO_LEVEL_2 * p2 , const char * key , const char * value )
2002-08-17 20:31:24 +04:00
{
int key_index ;
if ( ( key_index = lookup_printerkey ( & p2 - > data , key ) ) = = - 1 )
return NULL ;
DEBUG ( 8 , ( " get_printer_data: Attempting to lookup key => [%s], value => [%s] \n " ,
key , value ) ) ;
return regval_ctr_getvalue ( & p2 - > data . keys [ key_index ] . values , value ) ;
}
/****************************************************************************
Unpack a list of registry values frem the TDB
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static int unpack_values ( NT_PRINTER_DATA * printer_data , char * buf , int buflen )
{
int len = 0 ;
uint32 type ;
pstring string , valuename , keyname ;
char * str ;
int size ;
uint8 * data_p ;
REGISTRY_VALUE * regval_p ;
int key_index ;
/* add the "PrinterDriverData" key first for performance reasons */
add_new_printer_key ( printer_data , SPOOL_PRINTERDATA_KEY ) ;
/* loop and unpack the rest of the registry values */
2003-02-25 23:53:53 +03:00
while ( True ) {
2002-08-17 20:31:24 +04:00
/* check to see if there are any more registry values */
2004-05-07 07:15:54 +04:00
regval_p = NULL ;
2002-08-17 20:31:24 +04:00
len + = tdb_unpack ( buf + len , buflen - len , " p " , & regval_p ) ;
if ( ! regval_p )
break ;
/* unpack the next regval */
2000-05-24 10:10:21 +04:00
len + = tdb_unpack ( buf + len , buflen - len , " fdB " ,
2002-08-17 20:31:24 +04:00
string ,
& type ,
& size ,
& data_p ) ;
/*
* break of the keyname from the value name .
* Should only be one ' \ ' in the string returned .
*/
2002-09-25 19:19:00 +04:00
str = strrchr ( string , ' \\ ' ) ;
2002-08-17 20:31:24 +04:00
/* Put in "PrinterDriverData" is no key specified */
if ( ! str ) {
pstrcpy ( keyname , SPOOL_PRINTERDATA_KEY ) ;
pstrcpy ( valuename , string ) ;
}
else {
* str = ' \0 ' ;
pstrcpy ( keyname , string ) ;
pstrcpy ( valuename , str + 1 ) ;
}
/* see if we need a new key */
if ( ( key_index = lookup_printerkey ( printer_data , keyname ) ) = = - 1 )
key_index = add_new_printer_key ( printer_data , keyname ) ;
if ( key_index = = - 1 ) {
DEBUG ( 0 , ( " unpack_values: Failed to allocate a new key [%s]! \n " ,
keyname ) ) ;
break ;
}
/* add the new value */
2003-08-15 08:42:05 +04:00
regval_ctr_addvalue ( & printer_data - > keys [ key_index ] . values , valuename , type , ( const char * ) data_p , size ) ;
2002-08-17 20:31:24 +04:00
2003-02-25 23:53:53 +03:00
SAFE_FREE ( data_p ) ; /* 'B' option to tdbpack does a malloc() */
2002-09-25 19:19:00 +04:00
DEBUG ( 8 , ( " specific: [%s:%s], len: %d \n " , keyname , valuename , size ) ) ;
2000-05-24 10:10:21 +04:00
}
2000-02-07 19:17:59 +03:00
2000-05-24 10:10:21 +04:00
return len ;
}
2000-02-07 19:17:59 +03:00
2002-08-17 20:31:24 +04:00
/****************************************************************************
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2001-03-23 06:12:58 +03:00
static void map_to_os2_driver ( fstring drivername )
{
static BOOL initialised = False ;
static fstring last_from , last_to ;
char * mapfile = lp_os2_driver_map ( ) ;
char * * lines = NULL ;
int numlines = 0 ;
int i ;
if ( ! strlen ( drivername ) )
return ;
if ( ! * mapfile )
return ;
if ( ! initialised ) {
* last_from = * last_to = 0 ;
initialised = True ;
}
if ( strequal ( drivername , last_from ) ) {
DEBUG ( 3 , ( " Mapped Windows driver %s to OS/2 driver %s \n " , drivername , last_to ) ) ;
fstrcpy ( drivername , last_to ) ;
return ;
}
2001-07-04 11:15:53 +04:00
lines = file_lines_load ( mapfile , & numlines ) ;
2001-03-23 06:12:58 +03:00
if ( numlines = = 0 ) {
DEBUG ( 0 , ( " No entries in OS/2 driver map %s \n " , mapfile ) ) ;
return ;
}
DEBUG ( 4 , ( " Scanning OS/2 driver map %s \n " , mapfile ) ) ;
for ( i = 0 ; i < numlines ; i + + ) {
char * nt_name = lines [ i ] ;
2001-08-10 23:38:53 +04:00
char * os2_name = strchr ( nt_name , ' = ' ) ;
2001-03-23 06:12:58 +03:00
if ( ! os2_name )
continue ;
* os2_name + + = 0 ;
while ( isspace ( * nt_name ) )
nt_name + + ;
2001-08-10 23:38:53 +04:00
if ( ! * nt_name | | strchr ( " #; " , * nt_name ) )
2001-03-23 06:12:58 +03:00
continue ;
{
int l = strlen ( nt_name ) ;
while ( l & & isspace ( nt_name [ l - 1 ] ) ) {
nt_name [ l - 1 ] = 0 ;
l - - ;
}
}
while ( isspace ( * os2_name ) )
os2_name + + ;
{
int l = strlen ( os2_name ) ;
while ( l & & isspace ( os2_name [ l - 1 ] ) ) {
os2_name [ l - 1 ] = 0 ;
l - - ;
}
}
if ( strequal ( nt_name , drivername ) ) {
DEBUG ( 3 , ( " Mapped windows driver %s to os2 driver%s \n " , drivername , os2_name ) ) ;
fstrcpy ( last_from , drivername ) ;
fstrcpy ( last_to , os2_name ) ;
fstrcpy ( drivername , os2_name ) ;
file_lines_free ( lines ) ;
return ;
}
}
file_lines_free ( lines ) ;
}
2000-02-07 19:17:59 +03:00
2000-05-24 10:10:21 +04:00
/****************************************************************************
2003-02-25 23:53:53 +03:00
Get a default printer info 2 struct .
2000-05-24 10:10:21 +04:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2003-02-25 23:53:53 +03:00
static WERROR get_a_printer_2_default ( NT_PRINTER_INFO_LEVEL_2 * * info_ptr , const char * sharename )
2000-05-24 10:10:21 +04:00
{
int snum ;
NT_PRINTER_INFO_LEVEL_2 info ;
2000-02-07 19:17:59 +03:00
2000-05-24 10:10:21 +04:00
ZERO_STRUCT ( info ) ;
2000-02-07 19:17:59 +03:00
2000-05-24 10:10:21 +04:00
snum = lp_servicenumber ( sharename ) ;
2000-02-07 19:17:59 +03:00
2002-01-08 03:46:56 +03:00
slprintf ( info . servername , sizeof ( info . servername ) - 1 , " \\ \\ %s " , get_called_name ( ) ) ;
2002-03-15 11:14:10 +03:00
slprintf ( info . printername , sizeof ( info . printername ) - 1 , " \\ \\ %s \\ %s " ,
get_called_name ( ) , sharename ) ;
2000-11-08 06:12:16 +03:00
fstrcpy ( info . sharename , sharename ) ;
2000-08-01 04:41:19 +04:00
fstrcpy ( info . portname , SAMBA_PRINTER_PORT_NAME ) ;
2000-11-14 05:14:58 +03:00
2001-05-03 06:51:08 +04:00
/* by setting the driver name to an empty string, a local NT admin
can now run the * * local * * APW to install a local printer driver
for a Samba shared printer in 2.2 . Without this , drivers * * must * * be
installed on the Samba server for NT clients - - jerry */
2001-11-22 08:56:09 +03:00
#if 0 /* JERRY --do not uncomment-- */
2001-05-03 06:51:08 +04:00
if ( ! * info . drivername )
2001-11-22 08:56:09 +03:00
fstrcpy ( info . drivername , " NO DRIVER AVAILABLE FOR THIS PRINTER " ) ;
2001-05-03 06:51:08 +04:00
# endif
2000-11-15 00:56:32 +03:00
DEBUG ( 10 , ( " get_a_printer_2_default: driver name set to [%s] \n " , info . drivername ) ) ;
2000-08-01 00:41:51 +04:00
pstrcpy ( info . comment , " " ) ;
2000-05-24 10:10:21 +04:00
fstrcpy ( info . printprocessor , " winprint " ) ;
fstrcpy ( info . datatype , " RAW " ) ;
2000-02-07 19:17:59 +03:00
2003-02-16 02:33:30 +03:00
info . attributes = PRINTER_ATTRIBUTE_SAMBA ;
2000-06-06 05:34:20 +04:00
info . starttime = 0 ; /* Minutes since 12:00am GMT */
2000-06-09 18:08:03 +04:00
info . untiltime = 0 ; /* Minutes since 12:00am GMT */
2000-07-01 13:34:37 +04:00
info . priority = 1 ;
info . default_priority = 1 ;
2002-02-09 07:10:24 +03:00
info . setuptime = ( uint32 ) time ( NULL ) ;
2001-11-22 08:56:09 +03:00
/*
* I changed this as I think it is better to have a generic
* DEVMODE than to crash Win2k explorer . exe - - jerry
* See the HP Deskjet 990 c Win2k drivers for an example .
2002-01-22 21:14:31 +03:00
*
* However the default devmode appears to cause problems
* with the HP CLJ 8500 PCL driver . Hence the addition of
* the " default devmode " parameter - - jerry 22 / 01 / 2002
2001-11-22 08:56:09 +03:00
*/
2000-06-06 05:34:20 +04:00
2002-01-22 21:14:31 +03:00
if ( lp_default_devmode ( snum ) ) {
if ( ( info . devmode = construct_nt_devicemode ( info . printername ) ) = = NULL )
goto fail ;
}
2002-01-23 08:10:27 +03:00
else {
info . devmode = NULL ;
}
2000-04-05 23:48:06 +04:00
2001-02-28 03:51:02 +03:00
/* This will get the current RPC talloc context, but we should be
passing this as a parameter . . . fixme . . . JRA ! */
if ( ! nt_printing_getsec ( get_talloc_ctx ( ) , sharename , & info . secdesc_buf ) )
2000-06-01 21:01:34 +04:00
goto fail ;
2000-05-27 06:15:08 +04:00
2000-05-24 10:10:21 +04:00
* info_ptr = ( NT_PRINTER_INFO_LEVEL_2 * ) memdup ( & info , sizeof ( info ) ) ;
2000-06-01 21:01:34 +04:00
if ( ! * info_ptr ) {
DEBUG ( 0 , ( " get_a_printer_2_default: malloc fail. \n " ) ) ;
goto fail ;
}
2000-04-05 23:48:06 +04:00
2001-09-04 11:13:01 +04:00
return WERR_OK ;
2000-06-01 21:01:34 +04:00
fail :
if ( info . devmode )
free_nt_devicemode ( & info . devmode ) ;
2001-09-04 11:13:01 +04:00
return WERR_ACCESS_DENIED ;
2000-05-24 10:10:21 +04:00
}
2000-04-05 23:48:06 +04:00
2000-05-24 10:10:21 +04:00
/****************************************************************************
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2003-02-25 23:53:53 +03:00
static WERROR get_a_printer_2 ( NT_PRINTER_INFO_LEVEL_2 * * info_ptr , const char * sharename )
2000-05-24 10:10:21 +04:00
{
pstring key ;
NT_PRINTER_INFO_LEVEL_2 info ;
2001-11-24 17:16:41 +03:00
int len = 0 ;
2000-05-24 10:10:21 +04:00
TDB_DATA kbuf , dbuf ;
2000-11-10 22:36:34 +03:00
fstring printername ;
2003-08-23 07:34:24 +04:00
char adevice [ MAXDEVICENAME ] ;
2000-05-24 10:10:21 +04:00
ZERO_STRUCT ( info ) ;
2001-04-09 00:01:51 +04:00
slprintf ( key , sizeof ( key ) - 1 , " %s%s " , PRINTERS_PREFIX , sharename ) ;
2000-05-24 10:10:21 +04:00
kbuf . dptr = key ;
kbuf . dsize = strlen ( key ) + 1 ;
2001-07-09 22:19:04 +04:00
dbuf = tdb_fetch ( tdb_printers , kbuf ) ;
2000-08-01 04:41:19 +04:00
if ( ! dbuf . dptr )
return get_a_printer_2_default ( info_ptr , sharename ) ;
2000-05-24 10:10:21 +04:00
2000-08-01 00:41:51 +04:00
len + = tdb_unpack ( dbuf . dptr + len , dbuf . dsize - len , " dddddddddddfffffPfffff " ,
2000-05-24 10:10:21 +04:00
& info . attributes ,
& info . priority ,
& info . default_priority ,
& info . starttime ,
& info . untiltime ,
& info . status ,
& info . cjobs ,
& info . averageppm ,
& info . changeid ,
& info . c_setprinter ,
& info . setuptime ,
info . servername ,
info . printername ,
info . sharename ,
info . portname ,
info . drivername ,
2000-07-22 04:48:29 +04:00
info . comment ,
2000-05-24 10:10:21 +04:00
info . location ,
info . sepfile ,
info . printprocessor ,
info . datatype ,
info . parameters ) ;
2000-07-22 04:48:29 +04:00
/* Samba has to have shared raw drivers. */
2004-03-24 22:15:17 +03:00
info . attributes = PRINTER_ATTRIBUTE_SAMBA ;
2000-06-06 05:34:20 +04:00
2000-11-10 22:36:34 +03:00
/* Restore the stripped strings. */
2002-03-15 11:14:10 +03:00
slprintf ( info . servername , sizeof ( info . servername ) - 1 , " \\ \\ %s " , get_called_name ( ) ) ;
2002-03-14 04:48:59 +03:00
slprintf ( printername , sizeof ( printername ) - 1 , " \\ \\ %s \\ %s " , get_called_name ( ) ,
info . printername ) ;
fstrcpy ( info . printername , printername ) ;
2000-11-10 22:36:34 +03:00
2000-05-24 10:10:21 +04:00
len + = unpack_devicemode ( & info . devmode , dbuf . dptr + len , dbuf . dsize - len ) ;
2002-01-22 21:14:31 +03:00
2001-11-22 08:56:09 +03:00
/*
* Some client drivers freak out if there is a NULL devmode
* ( probably the driver is not checking before accessing
* the devmode pointer ) - - jerry
2002-01-22 21:14:31 +03:00
*
* See comments in get_a_printer_2_default ( )
2001-11-22 08:56:09 +03:00
*/
2002-01-22 21:14:31 +03:00
2002-11-23 05:52:36 +03:00
if ( lp_default_devmode ( lp_servicenumber ( sharename ) ) & & ! info . devmode ) {
2001-11-22 08:56:09 +03:00
DEBUG ( 8 , ( " get_a_printer_2: Constructing a default device mode for [%s] \n " ,
printername ) ) ;
info . devmode = construct_nt_devicemode ( printername ) ;
}
2003-08-23 07:34:24 +04:00
2003-10-20 18:02:02 +04:00
safe_strcpy ( adevice , info . printername , sizeof ( adevice ) - 1 ) ;
if ( info . devmode ) {
fstrcpy ( info . devmode - > devicename , adevice ) ;
}
2002-01-22 21:14:31 +03:00
2002-08-17 20:31:24 +04:00
len + = unpack_values ( & info . data , dbuf . dptr + len , dbuf . dsize - len ) ;
2000-05-24 10:10:21 +04:00
2001-02-28 03:51:02 +03:00
/* This will get the current RPC talloc context, but we should be
2002-08-17 20:31:24 +04:00
passing this as a parameter . . . fixme . . . JRA ! */
2001-02-28 03:51:02 +03:00
nt_printing_getsec ( get_talloc_ctx ( ) , sharename , & info . secdesc_buf ) ;
2000-06-06 05:47:11 +04:00
2001-03-23 06:12:58 +03:00
/* Fix for OS/2 drivers. */
if ( get_remote_arch ( ) = = RA_OS2 )
map_to_os2_driver ( info . drivername ) ;
2001-09-17 13:25:57 +04:00
SAFE_FREE ( dbuf . dptr ) ;
2000-05-24 10:10:21 +04:00
* info_ptr = memdup ( & info , sizeof ( info ) ) ;
2000-06-04 08:17:59 +04:00
2000-11-10 22:36:34 +03:00
DEBUG ( 9 , ( " Unpacked printer [%s] name [%s] running driver [%s] \n " ,
sharename , info . printername , info . drivername ) ) ;
2000-06-04 08:17:59 +04:00
2001-09-03 12:50:59 +04:00
return WERR_OK ;
2000-02-07 19:17:59 +03:00
}
/****************************************************************************
2003-02-25 23:53:53 +03:00
Debugging function , dump at level 6 the struct in the logs .
2000-02-07 19:17:59 +03:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static uint32 dump_a_printer ( NT_PRINTER_INFO_LEVEL printer , uint32 level )
{
2000-12-06 03:37:25 +03:00
uint32 result ;
2000-02-07 19:17:59 +03:00
NT_PRINTER_INFO_LEVEL_2 * info2 ;
2000-02-15 21:07:45 +03:00
DEBUG ( 106 , ( " Dumping printer at level [%d] \n " , level ) ) ;
2000-02-07 19:17:59 +03:00
2003-02-25 23:53:53 +03:00
switch ( level ) {
2000-11-15 00:56:32 +03:00
case 2 :
2000-02-07 19:17:59 +03:00
{
if ( printer . info_2 = = NULL )
2000-12-06 03:37:25 +03:00
result = 5 ;
2000-02-07 19:17:59 +03:00
else
{
info2 = printer . info_2 ;
2000-03-10 20:12:24 +03:00
DEBUGADD ( 106 , ( " attributes:[%d] \n " , info2 - > attributes ) ) ;
DEBUGADD ( 106 , ( " priority:[%d] \n " , info2 - > priority ) ) ;
2000-02-15 21:07:45 +03:00
DEBUGADD ( 106 , ( " default_priority:[%d] \n " , info2 - > default_priority ) ) ;
2000-03-10 20:12:24 +03:00
DEBUGADD ( 106 , ( " starttime:[%d] \n " , info2 - > starttime ) ) ;
DEBUGADD ( 106 , ( " untiltime:[%d] \n " , info2 - > untiltime ) ) ;
2002-01-07 09:13:40 +03:00
DEBUGADD ( 106 , ( " status:[%d] \n " , info2 - > status ) ) ;
2000-03-10 20:12:24 +03:00
DEBUGADD ( 106 , ( " cjobs:[%d] \n " , info2 - > cjobs ) ) ;
DEBUGADD ( 106 , ( " averageppm:[%d] \n " , info2 - > averageppm ) ) ;
DEBUGADD ( 106 , ( " changeid:[%d] \n " , info2 - > changeid ) ) ;
DEBUGADD ( 106 , ( " c_setprinter:[%d] \n " , info2 - > c_setprinter ) ) ;
2000-05-24 10:10:21 +04:00
DEBUGADD ( 106 , ( " setuptime:[%d] \n " , info2 - > setuptime ) ) ;
2000-03-10 20:12:24 +03:00
DEBUGADD ( 106 , ( " servername:[%s] \n " , info2 - > servername ) ) ;
DEBUGADD ( 106 , ( " printername:[%s] \n " , info2 - > printername ) ) ;
DEBUGADD ( 106 , ( " sharename:[%s] \n " , info2 - > sharename ) ) ;
DEBUGADD ( 106 , ( " portname:[%s] \n " , info2 - > portname ) ) ;
DEBUGADD ( 106 , ( " drivername:[%s] \n " , info2 - > drivername ) ) ;
2000-07-22 04:48:29 +04:00
DEBUGADD ( 106 , ( " comment:[%s] \n " , info2 - > comment ) ) ;
2000-03-10 20:12:24 +03:00
DEBUGADD ( 106 , ( " location:[%s] \n " , info2 - > location ) ) ;
DEBUGADD ( 106 , ( " sepfile:[%s] \n " , info2 - > sepfile ) ) ;
DEBUGADD ( 106 , ( " printprocessor:[%s] \n " , info2 - > printprocessor ) ) ;
DEBUGADD ( 106 , ( " datatype:[%s] \n " , info2 - > datatype ) ) ;
DEBUGADD ( 106 , ( " parameters:[%s] \n " , info2 - > parameters ) ) ;
2000-12-06 03:37:25 +03:00
result = 0 ;
2000-02-07 19:17:59 +03:00
}
break ;
}
default :
2002-02-09 07:10:24 +03:00
DEBUGADD ( 106 , ( " dump_a_printer: Level %u not implemented \n " , ( unsigned int ) level ) ) ;
2000-12-06 03:37:25 +03:00
result = 1 ;
2000-02-07 19:17:59 +03:00
break ;
}
2000-12-06 03:37:25 +03:00
return result ;
2000-02-07 19:17:59 +03:00
}
2002-01-08 08:39:27 +03:00
/****************************************************************************
Update the changeid time .
2002-01-09 02:50:14 +03:00
This is SO NASTY as some drivers need this to change , others need it
static . This value will change every second , and I must hope that this
is enough . . . . . DON ' T CHANGE THIS CODE WITHOUT A TEST MATRIX THE SIZE OF
UTAH ! JRA .
2002-01-08 08:39:27 +03:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2002-01-09 02:50:14 +03:00
static uint32 rev_changeid ( void )
2002-01-08 08:39:27 +03:00
{
2002-01-12 00:52:46 +03:00
struct timeval tv ;
get_process_uptime ( & tv ) ;
2002-02-09 07:10:24 +03:00
2002-03-15 11:14:10 +03:00
# if 1 /* JERRY */
2002-02-09 07:10:24 +03:00
/* Return changeid as msec since spooler restart */
return tv . tv_sec * 1000 + tv . tv_usec / 1000 ;
2002-03-15 11:14:10 +03:00
# else
/*
* This setting seems to work well but is too untested
* to replace the above calculation . Left in for experiementation
* of the reader - - jerry ( Tue Mar 12 09 : 15 : 05 CST 2002 )
*/
return tv . tv_sec * 10 + tv . tv_usec / 100000 ;
# endif
2002-01-08 08:39:27 +03:00
}
2000-02-07 19:17:59 +03:00
/*
* The function below are the high level ones .
* only those ones must be called from the spoolss code .
* JFM .
*/
/****************************************************************************
2000-10-27 01:43:13 +04:00
Modify a printer . This is called from SETPRINTERDATA / DELETEPRINTERDATA .
2000-02-07 19:17:59 +03:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2000-10-27 01:43:13 +04:00
2001-09-04 11:13:01 +04:00
WERROR mod_a_printer ( NT_PRINTER_INFO_LEVEL printer , uint32 level )
2000-10-27 01:43:13 +04:00
{
2001-09-04 11:13:01 +04:00
WERROR result ;
2000-10-27 01:43:13 +04:00
dump_a_printer ( printer , level ) ;
2003-02-25 23:53:53 +03:00
/*
* invalidate cache for all open handles to this printer .
* cache for a given handle will be updated on the next
* get_a_printer ( )
*/
invalidate_printer_hnd_cache ( printer . info_2 - > sharename ) ;
switch ( level ) {
2000-10-27 01:43:13 +04:00
case 2 :
{
2001-12-14 23:38:04 +03:00
/*
* Update the changestamp . Emperical tests show that the
2002-02-09 07:10:24 +03:00
* ChangeID is always updated , but c_setprinter is
* global spooler variable ( not per printer ) .
2001-12-14 23:38:04 +03:00
*/
/* ChangeID **must** be increasing over the lifetime
2002-01-08 08:39:27 +03:00
of client ' s spoolss service in order for the
2001-12-14 23:38:04 +03:00
client ' s cache to show updates */
2002-01-09 02:50:14 +03:00
printer . info_2 - > changeid = rev_changeid ( ) ;
2001-12-14 23:38:04 +03:00
/*
* Because one day someone will ask :
* NT - > NT An admin connection to a remote
* printer show changes imeediately in
* the properities dialog
*
* A non - admin connection will only show the
* changes after viewing the properites page
* 2 times . Seems to be related to a
* race condition in the client between the spooler
* updating the local cache and the Explorer . exe GUI
* actually displaying the properties .
*
* This is fixed in Win2k . admin / non - admin
* connections both display changes immediately .
*
* 14 / 12 / 01 - - jerry
*/
2000-12-06 03:37:25 +03:00
result = update_a_printer_2 ( printer . info_2 ) ;
2003-02-25 23:53:53 +03:00
2000-10-27 01:43:13 +04:00
break ;
}
default :
2001-09-04 11:13:01 +04:00
result = WERR_UNKNOWN_LEVEL ;
2000-10-27 01:43:13 +04:00
break ;
}
2000-12-06 03:37:25 +03:00
return result ;
2000-10-27 01:43:13 +04:00
}
2001-08-10 23:38:53 +04:00
/****************************************************************************
Initialize printer devmode & data with previously saved driver init values .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2002-02-09 07:10:24 +03:00
2002-08-17 20:31:24 +04:00
static BOOL set_driver_init_2 ( NT_PRINTER_INFO_LEVEL_2 * info_ptr )
2001-08-10 23:38:53 +04:00
{
int len = 0 ;
pstring key ;
TDB_DATA kbuf , dbuf ;
NT_PRINTER_INFO_LEVEL_2 info ;
2002-08-17 20:31:24 +04:00
ZERO_STRUCT ( info ) ;
2002-02-09 07:10:24 +03:00
/*
2002-08-17 20:31:24 +04:00
* Delete any printer data ' values ' already set . When called for driver
2002-02-09 07:10:24 +03:00
* replace , there will generally be some , but during an add printer , there
* should not be any ( if there are delete them ) .
*/
2002-08-17 20:31:24 +04:00
2002-09-25 19:19:00 +04:00
delete_all_printer_data ( info_ptr , " " ) ;
2002-08-17 20:31:24 +04:00
2001-08-10 23:38:53 +04:00
slprintf ( key , sizeof ( key ) - 1 , " %s%s " , DRIVER_INIT_PREFIX , info_ptr - > drivername ) ;
kbuf . dptr = key ;
kbuf . dsize = strlen ( key ) + 1 ;
dbuf = tdb_fetch ( tdb_drivers , kbuf ) ;
2002-08-17 20:31:24 +04:00
if ( ! dbuf . dptr ) {
2002-02-09 07:10:24 +03:00
/*
* When changing to a driver that has no init info in the tdb , remove
* the previous drivers init info and leave the new on blank .
*/
free_nt_devicemode ( & info_ptr - > devmode ) ;
2001-08-10 23:38:53 +04:00
return False ;
2002-02-09 07:10:24 +03:00
}
2002-08-17 20:31:24 +04:00
2001-08-10 23:38:53 +04:00
/*
* Get the saved DEVMODE . .
*/
2002-08-17 20:31:24 +04:00
2001-08-10 23:38:53 +04:00
len + = unpack_devicemode ( & info . devmode , dbuf . dptr + len , dbuf . dsize - len ) ;
/*
* The saved DEVMODE contains the devicename from the printer used during
* the initialization save . Change it to reflect the new printer .
*/
2002-08-17 20:31:24 +04:00
2002-09-25 19:19:00 +04:00
if ( info . devmode ) {
2002-11-23 05:52:36 +03:00
ZERO_STRUCT ( info . devmode - > devicename ) ;
fstrcpy ( info . devmode - > devicename , info_ptr - > printername ) ;
2002-09-25 19:19:00 +04:00
}
2002-03-15 11:14:10 +03:00
/*
* NT / 2 k does not change out the entire DeviceMode of a printer
* when changing the driver . Only the driverextra , private , &
* driverversion fields . - - jerry ( Thu Mar 14 08 : 58 : 43 CST 2002 )
2002-07-15 14:35:28 +04:00
*
2002-09-25 19:19:00 +04:00
* Later examination revealed that Windows NT / 2 k does reset the
2002-07-15 14:35:28 +04:00
* the printer ' s device mode , bit * * only * * when you change a
* property of the device mode such as the page orientation .
* - - jerry
2002-03-15 11:14:10 +03:00
*/
2002-08-17 20:31:24 +04:00
/* Bind the saved DEVMODE to the new the printer */
2001-08-10 23:38:53 +04:00
free_nt_devicemode ( & info_ptr - > devmode ) ;
info_ptr - > devmode = info . devmode ;
2002-03-15 11:14:10 +03:00
2002-09-25 19:19:00 +04:00
DEBUG ( 10 , ( " set_driver_init_2: Set printer [%s] init %s DEVMODE for driver [%s] \n " ,
info_ptr - > printername , info_ptr - > devmode ? " VALID " : " NULL " , info_ptr - > drivername ) ) ;
2001-08-10 23:38:53 +04:00
2002-08-17 20:31:24 +04:00
/* Add the printer data 'values' to the new printer */
len + = unpack_values ( & info_ptr - > data , dbuf . dptr + len , dbuf . dsize - len ) ;
2001-08-10 23:38:53 +04:00
2001-09-17 13:25:57 +04:00
SAFE_FREE ( dbuf . dptr ) ;
2001-08-10 23:38:53 +04:00
return True ;
}
/****************************************************************************
Initialize printer devmode & data with previously saved driver init values .
When a printer is created using AddPrinter , the drivername bound to the
printer is used to lookup previously saved driver initialization info , which
is bound to the new printer .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2002-07-15 14:35:28 +04:00
BOOL set_driver_init ( NT_PRINTER_INFO_LEVEL * printer , uint32 level )
2001-08-10 23:38:53 +04:00
{
2002-07-15 14:35:28 +04:00
BOOL result = False ;
2001-08-10 23:38:53 +04:00
2003-02-25 23:53:53 +03:00
switch ( level ) {
2001-08-10 23:38:53 +04:00
case 2 :
2002-08-17 20:31:24 +04:00
result = set_driver_init_2 ( printer - > info_2 ) ;
2001-08-10 23:38:53 +04:00
break ;
2002-07-15 14:35:28 +04:00
2001-08-10 23:38:53 +04:00
default :
2002-07-15 14:35:28 +04:00
DEBUG ( 0 , ( " set_driver_init: Programmer's error! Unknown driver_init level [%d] \n " ,
level ) ) ;
2001-08-10 23:38:53 +04:00
break ;
}
return result ;
}
2002-07-15 14:35:28 +04:00
/****************************************************************************
Delete driver init data stored for a specified driver
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
BOOL del_driver_init ( char * drivername )
{
pstring key ;
TDB_DATA kbuf ;
if ( ! drivername | | ! * drivername ) {
DEBUG ( 3 , ( " del_driver_init: No drivername specified! \n " ) ) ;
return False ;
}
slprintf ( key , sizeof ( key ) - 1 , " %s%s " , DRIVER_INIT_PREFIX , drivername ) ;
kbuf . dptr = key ;
kbuf . dsize = strlen ( key ) + 1 ;
DEBUG ( 6 , ( " del_driver_init: Removing driver init data for [%s] \n " , drivername ) ) ;
return ( tdb_delete ( tdb_drivers , kbuf ) = = 0 ) ;
}
2001-08-10 23:38:53 +04:00
/****************************************************************************
2002-08-17 20:31:24 +04:00
Pack up the DEVMODE and values for a printer into a ' driver init ' entry
2001-08-10 23:38:53 +04:00
in the tdb . Note : this is different from the driver entry and the printer
entry . There should be a single driver init entry for each driver regardless
of whether it was installed from NT or 2 K . Technically , they should be
different , but they work out to the same struct .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2002-02-09 07:10:24 +03:00
2001-08-10 23:38:53 +04:00
static uint32 update_driver_init_2 ( NT_PRINTER_INFO_LEVEL_2 * info )
{
pstring key ;
char * buf ;
int buflen , len , ret ;
TDB_DATA kbuf , dbuf ;
buf = NULL ;
buflen = 0 ;
again :
len = 0 ;
len + = pack_devicemode ( info - > devmode , buf + len , buflen - len ) ;
2002-08-17 20:31:24 +04:00
len + = pack_values ( & info - > data , buf + len , buflen - len ) ;
2001-08-10 23:38:53 +04:00
if ( buflen ! = len ) {
2001-08-12 21:30:01 +04:00
char * tb ;
2002-02-09 07:10:24 +03:00
2001-08-12 21:30:01 +04:00
tb = ( char * ) Realloc ( buf , len ) ;
if ( ! tb ) {
DEBUG ( 0 , ( " update_driver_init_2: failed to enlarge buffer! \n " ) ) ;
ret = - 1 ;
goto done ;
}
2003-02-25 23:53:53 +03:00
else
buf = tb ;
2001-08-10 23:38:53 +04:00
buflen = len ;
goto again ;
}
slprintf ( key , sizeof ( key ) - 1 , " %s%s " , DRIVER_INIT_PREFIX , info - > drivername ) ;
kbuf . dptr = key ;
kbuf . dsize = strlen ( key ) + 1 ;
dbuf . dptr = buf ;
dbuf . dsize = len ;
ret = tdb_store ( tdb_drivers , kbuf , dbuf , TDB_REPLACE ) ;
2001-08-12 21:30:01 +04:00
done :
2001-08-10 23:38:53 +04:00
if ( ret = = - 1 )
DEBUG ( 8 , ( " update_driver_init_2: error updating printer init to tdb on disk \n " ) ) ;
2001-09-17 13:25:57 +04:00
SAFE_FREE ( buf ) ;
2001-08-10 23:38:53 +04:00
2002-08-17 20:31:24 +04:00
DEBUG ( 10 , ( " update_driver_init_2: Saved printer [%s] init DEVMODE & values for driver [%s] \n " ,
2001-08-10 23:38:53 +04:00
info - > sharename , info - > drivername ) ) ;
return ret ;
}
/****************************************************************************
2002-08-17 20:31:24 +04:00
Update ( i . e . save ) the driver init info ( DEVMODE and values ) for a printer
2001-08-10 23:38:53 +04:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2002-02-09 07:10:24 +03:00
uint32 update_driver_init ( NT_PRINTER_INFO_LEVEL printer , uint32 level )
2001-08-10 23:38:53 +04:00
{
uint32 result ;
dump_a_printer ( printer , level ) ;
2003-02-25 23:53:53 +03:00
switch ( level ) {
2001-08-10 23:38:53 +04:00
case 2 :
2002-09-25 19:19:00 +04:00
result = update_driver_init_2 ( printer . info_2 ) ;
2001-08-10 23:38:53 +04:00
break ;
default :
2002-09-25 19:19:00 +04:00
result = 1 ;
2001-08-10 23:38:53 +04:00
break ;
}
return result ;
}
2002-09-25 19:19:00 +04:00
/****************************************************************************
Convert the printer data value , a REG_BINARY array , into an initialization
DEVMODE . Note : the array must be parsed as if it was a DEVMODE in an rpc . . .
got to keep the endians happy : ) .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static BOOL convert_driver_init ( TALLOC_CTX * ctx , NT_DEVICEMODE * nt_devmode , uint8 * data , uint32 data_len )
{
BOOL result = False ;
prs_struct ps ;
DEVICEMODE devmode ;
ZERO_STRUCT ( devmode ) ;
prs_init ( & ps , 0 , ctx , UNMARSHALL ) ;
ps . data_p = ( char * ) data ;
ps . buffer_size = data_len ;
if ( spoolss_io_devmode ( " phantom DEVMODE " , & ps , 0 , & devmode ) )
result = convert_devicemode ( " " , & devmode , & nt_devmode ) ;
else
DEBUG ( 10 , ( " convert_driver_init: error parsing DEVMODE \n " ) ) ;
return result ;
}
/****************************************************************************
Set the DRIVER_INIT info in the tdb . Requires Win32 client code that :
1. Use the driver ' s config DLL to this UNC printername and :
a . Call DrvPrintEvent with PRINTER_EVENT_INITIALIZE
b . Call DrvConvertDevMode with CDM_DRIVER_DEFAULT to get default DEVMODE
2. Call SetPrinterData with the ' magic ' key and the DEVMODE as data .
The last step triggers saving the " driver initialization " information for
this printer into the tdb . Later , new printers that use this driver will
have this initialization information bound to them . This simulates the
driver initialization , as if it had run on the Samba server ( as it would
have done on NT ) .
The Win32 client side code requirement sucks ! But until we can run arbitrary
Win32 printer driver code on any Unix that Samba runs on , we are stuck with it .
It would have been easier to use SetPrinter because all the UNMARSHALLING of
the DEVMODE is done there , but 2 K / XP clients do not set the DEVMODE . . . think
about it and you will realize why . JRR 010720
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static WERROR save_driver_init_2 ( NT_PRINTER_INFO_LEVEL * printer , uint8 * data , uint32 data_len )
{
WERROR status = WERR_OK ;
TALLOC_CTX * ctx = NULL ;
NT_DEVICEMODE * nt_devmode = NULL ;
NT_DEVICEMODE * tmp_devmode = printer - > info_2 - > devmode ;
/*
* When the DEVMODE is already set on the printer , don ' t try to unpack it .
*/
DEBUG ( 8 , ( " save_driver_init_2: Enter... \n " ) ) ;
2003-02-25 23:53:53 +03:00
if ( ! printer - > info_2 - > devmode & & data_len ) {
2002-09-25 19:19:00 +04:00
/*
* Set devmode on printer info , so entire printer initialization can be
* saved to tdb .
*/
2002-12-20 23:21:31 +03:00
if ( ( ctx = talloc_init ( " save_driver_init_2 " ) ) = = NULL )
2002-09-25 19:19:00 +04:00
return WERR_NOMEM ;
if ( ( nt_devmode = ( NT_DEVICEMODE * ) malloc ( sizeof ( NT_DEVICEMODE ) ) ) = = NULL ) {
status = WERR_NOMEM ;
goto done ;
}
ZERO_STRUCTP ( nt_devmode ) ;
/*
* The DEVMODE is held in the ' data ' component of the param in raw binary .
* Convert it to to a devmode structure
*/
if ( ! convert_driver_init ( ctx , nt_devmode , data , data_len ) ) {
DEBUG ( 10 , ( " save_driver_init_2: error converting DEVMODE \n " ) ) ;
status = WERR_INVALID_PARAM ;
goto done ;
}
printer - > info_2 - > devmode = nt_devmode ;
}
/*
* Pack up and add ( or update ) the DEVMODE and any current printer data to
* a ' driver init ' element in the tdb
*
*/
if ( update_driver_init ( * printer , 2 ) ! = 0 ) {
DEBUG ( 10 , ( " save_driver_init_2: error updating DEVMODE \n " ) ) ;
status = WERR_NOMEM ;
goto done ;
}
/*
* If driver initialization info was successfully saved , set the current
* printer to match it . This allows initialization of the current printer
* as well as the driver .
*/
status = mod_a_printer ( * printer , 2 ) ;
if ( ! W_ERROR_IS_OK ( status ) ) {
DEBUG ( 10 , ( " save_driver_init_2: error setting DEVMODE on printer [%s] \n " ,
printer - > info_2 - > printername ) ) ;
}
done :
talloc_destroy ( ctx ) ;
free_nt_devicemode ( & nt_devmode ) ;
printer - > info_2 - > devmode = tmp_devmode ;
return status ;
}
/****************************************************************************
Update the driver init info ( DEVMODE and specifics ) for a printer
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
WERROR save_driver_init ( NT_PRINTER_INFO_LEVEL * printer , uint32 level , uint8 * data , uint32 data_len )
{
WERROR status = WERR_OK ;
2003-02-25 23:53:53 +03:00
switch ( level ) {
2002-09-25 19:19:00 +04:00
case 2 :
status = save_driver_init_2 ( printer , data , data_len ) ;
break ;
default :
status = WERR_UNKNOWN_LEVEL ;
break ;
}
return status ;
}
2003-02-25 23:53:53 +03:00
/****************************************************************************
Deep copy a NT_PRINTER_DATA
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static NTSTATUS copy_printer_data ( NT_PRINTER_DATA * dst , NT_PRINTER_DATA * src )
{
int i , j , num_vals , new_key_index ;
REGVAL_CTR * src_key , * dst_key ;
if ( ! dst | | ! src )
return NT_STATUS_NO_MEMORY ;
for ( i = 0 ; i < src - > num_keys ; i + + ) {
/* create a new instance of the printerkey in the destination
printer_data object */
new_key_index = add_new_printer_key ( dst , src - > keys [ i ] . name ) ;
dst_key = & dst - > keys [ new_key_index ] . values ;
src_key = & src - > keys [ i ] . values ;
num_vals = regval_ctr_numvals ( src_key ) ;
/* dup the printer entire printer key */
for ( j = 0 ; j < num_vals ; j + + ) {
regval_ctr_copyvalue ( dst_key , regval_ctr_specific_value ( src_key , j ) ) ;
}
}
return NT_STATUS_OK ;
}
/****************************************************************************
Deep copy a NT_PRINTER_INFO_LEVEL_2 structure using malloc ( ) ' d memeory
Caller must free .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2003-07-14 23:51:34 +04:00
NT_PRINTER_INFO_LEVEL_2 * dup_printer_2 ( TALLOC_CTX * ctx , NT_PRINTER_INFO_LEVEL_2 * printer )
2003-02-25 23:53:53 +03:00
{
NT_PRINTER_INFO_LEVEL_2 * copy ;
if ( ! printer )
return NULL ;
if ( ! ( copy = ( NT_PRINTER_INFO_LEVEL_2 * ) malloc ( sizeof ( NT_PRINTER_INFO_LEVEL_2 ) ) ) )
return NULL ;
memcpy ( copy , printer , sizeof ( NT_PRINTER_INFO_LEVEL_2 ) ) ;
/* malloc()'d members copied here */
copy - > devmode = dup_nt_devicemode ( printer - > devmode ) ;
ZERO_STRUCT ( copy - > data ) ;
copy_printer_data ( & copy - > data , & printer - > data ) ;
/* this is talloc()'d; very ugly that we have a structure that
is half malloc ( ) ' d and half talloc ( ) ' d but that is the way
that the PRINTER_INFO stuff is written right now . - - jerry */
copy - > secdesc_buf = dup_sec_desc_buf ( ctx , printer - > secdesc_buf ) ;
return copy ;
}
2000-02-07 19:17:59 +03:00
/****************************************************************************
2000-06-01 21:01:34 +04:00
Get a NT_PRINTER_INFO_LEVEL struct . It returns malloced memory .
2003-12-31 01:17:14 +03:00
Previously the code had a memory allocation problem because it always
used the TALLOC_CTX from the Printer_entry * . This context lasts
as a long as the original handle is open . So if the client made a lot
of getprinter [ data ] ( ) calls , the memory usage would climb . Now we use
a short lived TALLOC_CTX for printer_info_2 objects returned . We
still use the Printer_entry - > ctx for maintaining the cache copy though
since that object must live as long as the handle by definition .
- - jerry
2000-02-07 19:17:59 +03:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2000-06-01 21:01:34 +04:00
2003-02-25 23:53:53 +03:00
WERROR get_a_printer ( Printer_entry * print_hnd , NT_PRINTER_INFO_LEVEL * * pp_printer , uint32 level ,
const char * sharename )
2000-02-07 19:17:59 +03:00
{
2001-09-03 12:50:59 +04:00
WERROR result ;
2000-06-01 21:01:34 +04:00
NT_PRINTER_INFO_LEVEL * printer = NULL ;
2000-02-07 19:17:59 +03:00
2000-06-01 21:01:34 +04:00
* pp_printer = NULL ;
2000-04-07 02:48:53 +04:00
DEBUG ( 10 , ( " get_a_printer: [%s] level %u \n " , sharename , ( unsigned int ) level ) ) ;
2003-02-25 23:53:53 +03:00
switch ( level ) {
2000-11-15 00:56:32 +03:00
case 2 :
2000-06-01 21:01:34 +04:00
if ( ( printer = ( NT_PRINTER_INFO_LEVEL * ) malloc ( sizeof ( NT_PRINTER_INFO_LEVEL ) ) ) = = NULL ) {
DEBUG ( 0 , ( " get_a_printer: malloc fail. \n " ) ) ;
2001-09-04 11:13:01 +04:00
return WERR_NOMEM ;
2000-06-01 21:01:34 +04:00
}
ZERO_STRUCTP ( printer ) ;
2003-02-25 23:53:53 +03:00
/*
* check for cache first . A Printer handle cannot changed
* to another printer object so we only check that the printer
* is actually for a printer and that the printer_info pointer
* is valid
*/
if ( print_hnd
& & ( print_hnd - > printer_type = = PRINTER_HANDLE_IS_PRINTER )
& & print_hnd - > printer_info )
{
2003-12-31 01:17:14 +03:00
/* get_talloc_ctx() works here because we need a short
lived talloc context */
if ( ! ( printer - > info_2 = dup_printer_2 ( get_talloc_ctx ( ) , print_hnd - > printer_info - > info_2 ) ) )
{
2003-02-25 23:53:53 +03:00
DEBUG ( 0 , ( " get_a_printer: unable to copy cached printer info! \n " ) ) ;
SAFE_FREE ( printer ) ;
return WERR_NOMEM ;
}
DEBUG ( 10 , ( " get_a_printer: using cached copy of printer_info_2 \n " ) ) ;
* pp_printer = printer ;
result = WERR_OK ;
break ;
}
2003-12-31 01:17:14 +03:00
/* no cache for this handle; see if we can match one from another handle.
Make sure to use a short lived talloc ctx */
2003-07-14 23:51:34 +04:00
if ( print_hnd )
2003-12-31 01:17:14 +03:00
result = find_printer_in_print_hnd_cache ( get_talloc_ctx ( ) , & printer - > info_2 , sharename ) ;
2003-07-14 23:51:34 +04:00
/* fail to disk if we don't have it with any open handle */
2003-02-25 23:53:53 +03:00
2003-07-14 23:51:34 +04:00
if ( ! print_hnd | | ! W_ERROR_IS_OK ( result ) )
result = get_a_printer_2 ( & printer - > info_2 , sharename ) ;
/* we have a new printer now. Save it with this handle */
if ( W_ERROR_IS_OK ( result ) ) {
dump_a_printer ( * printer , level ) ;
2003-02-25 23:53:53 +03:00
/* save a copy in cache */
if ( print_hnd & & ( print_hnd - > printer_type = = PRINTER_HANDLE_IS_PRINTER ) ) {
if ( ! print_hnd - > printer_info )
print_hnd - > printer_info = ( NT_PRINTER_INFO_LEVEL * ) malloc ( sizeof ( NT_PRINTER_INFO_LEVEL ) ) ;
2003-07-14 23:51:34 +04:00
2003-02-25 23:53:53 +03:00
if ( print_hnd - > printer_info ) {
2003-12-31 01:17:14 +03:00
/* make sure to use the handle's talloc ctx here since
the printer_2 object must last until the handle is closed */
2003-02-25 23:53:53 +03:00
print_hnd - > printer_info - > info_2 = dup_printer_2 ( print_hnd - > ctx , printer - > info_2 ) ;
/* don't fail the lookup just because the cache update failed */
if ( ! print_hnd - > printer_info - > info_2 )
DEBUG ( 0 , ( " get_a_printer: unable to copy new printer info! \n " ) ) ;
}
}
2003-07-14 23:51:34 +04:00
* pp_printer = printer ;
2000-06-01 21:01:34 +04:00
}
2003-07-14 23:51:34 +04:00
else
2003-02-25 23:53:53 +03:00
SAFE_FREE ( printer ) ;
2003-07-14 23:51:34 +04:00
2000-02-07 19:17:59 +03:00
break ;
2003-07-14 23:51:34 +04:00
2000-02-07 19:17:59 +03:00
default :
2001-09-04 11:13:01 +04:00
result = WERR_UNKNOWN_LEVEL ;
2000-02-07 19:17:59 +03:00
break ;
}
2002-03-17 09:04:15 +03:00
DEBUG ( 10 , ( " get_a_printer: [%s] level %u returning %s \n " , sharename , ( unsigned int ) level , dos_errstr ( result ) ) ) ;
2000-04-07 02:48:53 +04:00
2000-12-06 03:37:25 +03:00
return result ;
2000-02-07 19:17:59 +03:00
}
/****************************************************************************
2000-06-01 21:01:34 +04:00
Deletes a NT_PRINTER_INFO_LEVEL struct .
2000-02-07 19:17:59 +03:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2000-06-01 21:01:34 +04:00
uint32 free_a_printer ( NT_PRINTER_INFO_LEVEL * * pp_printer , uint32 level )
2000-02-07 19:17:59 +03:00
{
2000-12-06 03:37:25 +03:00
uint32 result ;
2000-06-01 21:01:34 +04:00
NT_PRINTER_INFO_LEVEL * printer = * pp_printer ;
2000-02-15 21:07:45 +03:00
DEBUG ( 104 , ( " freeing a printer at level [%d] \n " , level ) ) ;
2000-06-01 21:01:34 +04:00
if ( printer = = NULL )
return 0 ;
2000-02-07 19:17:59 +03:00
2003-02-25 23:53:53 +03:00
switch ( level ) {
2000-11-15 00:56:32 +03:00
case 2 :
2003-02-25 23:53:53 +03:00
if ( printer - > info_2 ! = NULL ) {
2000-06-01 21:01:34 +04:00
free_nt_printer_info_level_2 ( & printer - > info_2 ) ;
2000-12-06 03:37:25 +03:00
result = 0 ;
2003-02-25 23:53:53 +03:00
} else
2000-12-06 03:37:25 +03:00
result = 4 ;
2000-02-07 19:17:59 +03:00
break ;
2003-02-25 23:53:53 +03:00
2000-02-07 19:17:59 +03:00
default :
2000-12-06 03:37:25 +03:00
result = 1 ;
2000-02-07 19:17:59 +03:00
break ;
}
2000-06-01 21:01:34 +04:00
2001-09-17 13:25:57 +04:00
SAFE_FREE ( * pp_printer ) ;
2000-12-06 03:37:25 +03:00
return result ;
2000-02-07 19:17:59 +03:00
}
/****************************************************************************
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
uint32 add_a_printer_driver ( NT_PRINTER_DRIVER_INFO_LEVEL driver , uint32 level )
{
2000-12-06 03:37:25 +03:00
uint32 result ;
2000-02-15 21:07:45 +03:00
DEBUG ( 104 , ( " adding a printer at level [%d] \n " , level ) ) ;
2000-02-07 19:17:59 +03:00
dump_a_printer_driver ( driver , level ) ;
2003-02-25 23:53:53 +03:00
switch ( level ) {
2000-11-15 00:56:32 +03:00
case 3 :
2000-12-06 03:37:25 +03:00
result = add_a_printer_driver_3 ( driver . info_3 ) ;
2000-02-07 19:17:59 +03:00
break ;
2000-05-12 18:28:46 +04:00
2000-11-15 00:56:32 +03:00
case 6 :
2000-12-06 03:37:25 +03:00
result = add_a_printer_driver_6 ( driver . info_6 ) ;
2000-05-12 18:28:46 +04:00
break ;
2003-02-25 23:53:53 +03:00
2000-02-07 19:17:59 +03:00
default :
2000-12-06 03:37:25 +03:00
result = 1 ;
2000-02-07 19:17:59 +03:00
break ;
}
2000-12-06 03:37:25 +03:00
return result ;
2000-02-07 19:17:59 +03:00
}
/****************************************************************************
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2003-02-25 23:53:53 +03:00
2001-09-03 12:50:59 +04:00
WERROR get_a_printer_driver ( NT_PRINTER_DRIVER_INFO_LEVEL * driver , uint32 level ,
2003-01-03 11:28:12 +03:00
fstring drivername , const char * architecture , uint32 version )
2000-02-07 19:17:59 +03:00
{
2001-09-03 12:50:59 +04:00
WERROR result ;
2000-02-07 19:17:59 +03:00
2003-02-25 23:53:53 +03:00
switch ( level ) {
2000-11-15 00:56:32 +03:00
case 3 :
2002-07-15 14:35:28 +04:00
/* Sometime we just want any version of the driver */
if ( version = = DRIVER_ANY_VERSION ) {
/* look for Win2k first and then for NT4 */
result = get_a_printer_driver_3 ( & driver - > info_3 , drivername ,
architecture , 3 ) ;
if ( ! W_ERROR_IS_OK ( result ) ) {
result = get_a_printer_driver_3 ( & driver - > info_3 ,
drivername , architecture , 2 ) ;
}
2003-02-25 23:53:53 +03:00
} else {
2002-07-15 14:35:28 +04:00
result = get_a_printer_driver_3 ( & driver - > info_3 , drivername ,
architecture , version ) ;
}
2000-02-07 19:17:59 +03:00
break ;
2002-07-15 14:35:28 +04:00
2000-02-07 19:17:59 +03:00
default :
2001-09-03 12:50:59 +04:00
result = W_ERROR ( 1 ) ;
2000-02-07 19:17:59 +03:00
break ;
}
2001-09-04 11:13:01 +04:00
if ( W_ERROR_IS_OK ( result ) )
2000-09-12 03:43:44 +04:00
dump_a_printer_driver ( * driver , level ) ;
2002-07-15 14:35:28 +04:00
2000-12-06 03:37:25 +03:00
return result ;
2000-02-07 19:17:59 +03:00
}
/****************************************************************************
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
uint32 free_a_printer_driver ( NT_PRINTER_DRIVER_INFO_LEVEL driver , uint32 level )
{
2000-12-06 03:37:25 +03:00
uint32 result ;
2000-02-07 19:17:59 +03:00
2003-02-25 23:53:53 +03:00
switch ( level ) {
2000-11-15 00:56:32 +03:00
case 3 :
2000-02-07 19:17:59 +03:00
{
2000-06-02 01:52:49 +04:00
NT_PRINTER_DRIVER_INFO_LEVEL_3 * info3 ;
2000-02-07 19:17:59 +03:00
if ( driver . info_3 ! = NULL )
{
info3 = driver . info_3 ;
2001-09-17 13:25:57 +04:00
SAFE_FREE ( info3 - > dependentfiles ) ;
2000-05-24 10:10:21 +04:00
ZERO_STRUCTP ( info3 ) ;
2001-09-17 13:25:57 +04:00
SAFE_FREE ( info3 ) ;
2000-12-06 03:37:25 +03:00
result = 0 ;
2003-02-25 23:53:53 +03:00
} else {
2000-12-06 03:37:25 +03:00
result = 4 ;
2000-06-02 01:52:49 +04:00
}
break ;
}
2000-11-15 00:56:32 +03:00
case 6 :
2000-06-02 01:52:49 +04:00
{
2000-06-03 11:20:44 +04:00
NT_PRINTER_DRIVER_INFO_LEVEL_6 * info6 ;
2003-02-25 23:53:53 +03:00
if ( driver . info_6 ! = NULL ) {
2000-06-02 01:52:49 +04:00
info6 = driver . info_6 ;
2001-09-17 13:25:57 +04:00
SAFE_FREE ( info6 - > dependentfiles ) ;
SAFE_FREE ( info6 - > previousnames ) ;
2000-06-02 01:52:49 +04:00
ZERO_STRUCTP ( info6 ) ;
2001-09-17 13:25:57 +04:00
SAFE_FREE ( info6 ) ;
2000-12-06 03:37:25 +03:00
result = 0 ;
2003-02-25 23:53:53 +03:00
} else {
2000-12-06 03:37:25 +03:00
result = 4 ;
2000-02-07 19:17:59 +03:00
}
break ;
}
default :
2000-12-06 03:37:25 +03:00
result = 1 ;
2000-02-07 19:17:59 +03:00
break ;
}
2000-12-06 03:37:25 +03:00
return result ;
2000-02-07 19:17:59 +03:00
}
2001-05-18 08:11:17 +04:00
/****************************************************************************
Determine whether or not a particular driver is currently assigned
to a printer
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2002-07-15 14:35:28 +04:00
2002-09-25 19:19:00 +04:00
BOOL printer_driver_in_use ( NT_PRINTER_DRIVER_INFO_LEVEL_3 * info_3 )
2001-05-18 08:11:17 +04:00
{
2002-07-15 14:35:28 +04:00
int snum ;
int n_services = lp_numservices ( ) ;
NT_PRINTER_INFO_LEVEL * printer = NULL ;
2001-05-18 08:11:17 +04:00
2002-09-25 19:19:00 +04:00
if ( ! info_3 )
2002-07-15 14:35:28 +04:00
return False ;
2001-05-18 08:11:17 +04:00
2002-07-15 14:35:28 +04:00
DEBUG ( 5 , ( " printer_driver_in_use: Beginning search through ntprinters.tdb... \n " ) ) ;
2001-05-18 08:11:17 +04:00
/* loop through the printers.tdb and check for the drivername */
2002-07-15 14:35:28 +04:00
2003-02-25 23:53:53 +03:00
for ( snum = 0 ; snum < n_services ; snum + + ) {
2002-07-15 14:35:28 +04:00
if ( ! ( lp_snum_ok ( snum ) & & lp_print_ok ( snum ) ) )
2001-05-18 08:11:17 +04:00
continue ;
2002-07-15 14:35:28 +04:00
2003-02-25 23:53:53 +03:00
if ( ! W_ERROR_IS_OK ( get_a_printer ( NULL , & printer , 2 , lp_servicename ( snum ) ) ) )
2001-05-18 08:11:17 +04:00
continue ;
2002-07-15 14:35:28 +04:00
2002-09-25 19:19:00 +04:00
if ( ! StrCaseCmp ( info_3 - > name , printer - > info_2 - > drivername ) ) {
2002-07-15 14:35:28 +04:00
free_a_printer ( & printer , 2 ) ;
return True ;
}
free_a_printer ( & printer , 2 ) ;
}
DEBUG ( 5 , ( " printer_driver_in_use: Completed search through ntprinters.tdb... \n " ) ) ;
/* report that the driver is not in use by default */
return False ;
}
2001-05-18 08:11:17 +04:00
2002-07-15 14:35:28 +04:00
/**********************************************************************
Check to see if a ogiven file is in use by * info
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static BOOL drv_file_in_use ( char * file , NT_PRINTER_DRIVER_INFO_LEVEL_3 * info )
{
2002-09-25 19:19:00 +04:00
int i = 0 ;
2002-07-15 14:35:28 +04:00
if ( ! info )
return False ;
if ( strequal ( file , info - > driverpath ) )
return True ;
2001-06-27 00:23:45 +04:00
2002-07-15 14:35:28 +04:00
if ( strequal ( file , info - > datafile ) )
return True ;
if ( strequal ( file , info - > configfile ) )
return True ;
if ( strequal ( file , info - > helpfile ) )
return True ;
2002-09-25 19:19:00 +04:00
/* see of there are any dependent files to examine */
if ( ! info - > dependentfiles )
return False ;
2003-02-25 23:53:53 +03:00
while ( * info - > dependentfiles [ i ] ) {
2002-09-25 19:19:00 +04:00
if ( strequal ( file , info - > dependentfiles [ i ] ) )
return True ;
i + + ;
2002-07-15 14:35:28 +04:00
}
return False ;
}
/**********************************************************************
Utility function to remove the dependent file pointed to by the
input parameter from the list
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2002-09-25 19:19:00 +04:00
static void trim_dependent_file ( fstring files [ ] , int idx )
2002-07-15 14:35:28 +04:00
{
2002-09-25 19:19:00 +04:00
/* bump everything down a slot */
2003-02-25 23:53:53 +03:00
while ( * files [ idx + 1 ] ) {
2002-09-25 19:19:00 +04:00
fstrcpy ( files [ idx ] , files [ idx + 1 ] ) ;
idx + + ;
2002-07-15 14:35:28 +04:00
}
2002-09-25 19:19:00 +04:00
* files [ idx ] = ' \0 ' ;
return ;
2002-07-15 14:35:28 +04:00
}
/**********************************************************************
Check if any of the files used by src are also used by drv
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static BOOL trim_overlap_drv_files ( NT_PRINTER_DRIVER_INFO_LEVEL_3 * src ,
NT_PRINTER_DRIVER_INFO_LEVEL_3 * drv )
{
2002-09-25 19:19:00 +04:00
BOOL in_use = False ;
int i = 0 ;
2002-07-15 14:35:28 +04:00
if ( ! src | | ! drv )
return False ;
/* check each file. Remove it from the src structure if it overlaps */
if ( drv_file_in_use ( src - > driverpath , drv ) ) {
in_use = True ;
2002-09-25 19:19:00 +04:00
DEBUG ( 10 , ( " Removing driverfile [%s] from list \n " , src - > driverpath ) ) ;
2002-07-15 14:35:28 +04:00
fstrcpy ( src - > driverpath , " " ) ;
}
if ( drv_file_in_use ( src - > datafile , drv ) ) {
in_use = True ;
2002-09-25 19:19:00 +04:00
DEBUG ( 10 , ( " Removing datafile [%s] from list \n " , src - > datafile ) ) ;
2002-07-15 14:35:28 +04:00
fstrcpy ( src - > datafile , " " ) ;
}
if ( drv_file_in_use ( src - > configfile , drv ) ) {
in_use = True ;
2002-09-25 19:19:00 +04:00
DEBUG ( 10 , ( " Removing configfile [%s] from list \n " , src - > configfile ) ) ;
2002-07-15 14:35:28 +04:00
fstrcpy ( src - > configfile , " " ) ;
}
2002-09-25 19:19:00 +04:00
if ( drv_file_in_use ( src - > helpfile , drv ) ) {
in_use = True ;
DEBUG ( 10 , ( " Removing helpfile [%s] from list \n " , src - > helpfile ) ) ;
fstrcpy ( src - > helpfile , " " ) ;
2002-07-15 14:35:28 +04:00
}
2002-09-25 19:19:00 +04:00
/* are there any dependentfiles to examine? */
if ( ! src - > dependentfiles )
return in_use ;
2002-07-15 14:35:28 +04:00
2003-02-25 23:53:53 +03:00
while ( * src - > dependentfiles [ i ] ) {
2002-09-25 19:19:00 +04:00
if ( drv_file_in_use ( src - > dependentfiles [ i ] , drv ) ) {
in_use = True ;
DEBUG ( 10 , ( " Removing [%s] from dependent file list \n " , src - > dependentfiles [ i ] ) ) ;
trim_dependent_file ( src - > dependentfiles , i ) ;
2003-02-25 23:53:53 +03:00
} else
2002-09-25 19:19:00 +04:00
i + + ;
}
2001-05-18 08:11:17 +04:00
2002-07-15 14:35:28 +04:00
return in_use ;
}
/****************************************************************************
Determine whether or not a particular driver files are currently being
used by any other driver .
Return value is True if any files were in use by other drivers
and False otherwise .
Upon return , * info has been modified to only contain the driver files
which are not in use
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
BOOL printer_driver_files_in_use ( NT_PRINTER_DRIVER_INFO_LEVEL_3 * info )
{
int i ;
int ndrivers ;
uint32 version ;
fstring * list = NULL ;
NT_PRINTER_DRIVER_INFO_LEVEL driver ;
2002-09-25 19:19:00 +04:00
if ( ! info )
return False ;
version = info - > cversion ;
2002-07-15 14:35:28 +04:00
/* loop over all driver versions */
DEBUG ( 5 , ( " printer_driver_files_in_use: Beginning search through ntdrivers.tdb... \n " ) ) ;
2002-09-25 19:19:00 +04:00
/* get the list of drivers */
2002-07-15 14:35:28 +04:00
2002-09-25 19:19:00 +04:00
list = NULL ;
ndrivers = get_ntdrivers ( & list , info - > environment , version ) ;
2002-07-15 14:35:28 +04:00
2002-09-25 19:19:00 +04:00
DEBUGADD ( 4 , ( " we have:[%d] drivers in environment [%s] and version [%d] \n " ,
ndrivers , info - > environment , version ) ) ;
2002-07-15 14:35:28 +04:00
2002-09-25 19:19:00 +04:00
/* check each driver for overlap in files */
2002-07-15 14:35:28 +04:00
2003-02-25 23:53:53 +03:00
for ( i = 0 ; i < ndrivers ; i + + ) {
2002-09-25 19:19:00 +04:00
DEBUGADD ( 5 , ( " \t driver: [%s] \n " , list [ i ] ) ) ;
2002-07-15 14:35:28 +04:00
2002-09-25 19:19:00 +04:00
ZERO_STRUCT ( driver ) ;
2002-07-15 14:35:28 +04:00
2003-02-25 23:53:53 +03:00
if ( ! W_ERROR_IS_OK ( get_a_printer_driver ( & driver , 3 , list [ i ] , info - > environment , version ) ) ) {
2002-09-25 19:19:00 +04:00
SAFE_FREE ( list ) ;
return True ;
}
2002-07-15 14:35:28 +04:00
2002-09-25 19:19:00 +04:00
/* check if d2 uses any files from d1 */
/* only if this is a different driver than the one being deleted */
2002-07-15 14:35:28 +04:00
2003-02-25 23:53:53 +03:00
if ( ! strequal ( info - > name , driver . info_3 - > name ) ) {
2002-09-25 19:19:00 +04:00
if ( trim_overlap_drv_files ( info , driver . info_3 ) ) {
free_a_printer_driver ( driver , 3 ) ;
SAFE_FREE ( list ) ;
return True ;
2002-07-15 14:35:28 +04:00
}
2002-09-25 19:19:00 +04:00
}
2002-07-15 14:35:28 +04:00
2002-09-25 19:19:00 +04:00
free_a_printer_driver ( driver , 3 ) ;
}
SAFE_FREE ( list ) ;
2001-05-18 08:11:17 +04:00
2002-07-15 14:35:28 +04:00
DEBUG ( 5 , ( " printer_driver_files_in_use: Completed search through ntdrivers.tdb... \n " ) ) ;
2001-05-18 08:11:17 +04:00
2002-09-25 19:19:00 +04:00
driver . info_3 = info ;
if ( DEBUGLEVEL > = 20 )
dump_a_printer_driver ( driver , 3 ) ;
2001-05-18 08:11:17 +04:00
return False ;
}
2002-07-15 14:35:28 +04:00
/****************************************************************************
Actually delete the driver files . Make sure that
printer_driver_files_in_use ( ) return False before calling
this .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2002-09-25 19:19:00 +04:00
static BOOL delete_driver_files ( NT_PRINTER_DRIVER_INFO_LEVEL_3 * info_3 , struct current_user * user )
2002-07-15 14:35:28 +04:00
{
2002-09-25 19:19:00 +04:00
int i = 0 ;
2002-07-15 14:35:28 +04:00
char * s ;
connection_struct * conn ;
DATA_BLOB null_pw ;
NTSTATUS nt_status ;
2003-03-05 04:30:15 +03:00
fstring res_type ;
2004-05-03 20:38:37 +04:00
BOOL bad_path ;
SMB_STRUCT_STAT st ;
2003-03-05 04:30:15 +03:00
2002-09-25 19:19:00 +04:00
if ( ! info_3 )
2002-07-15 14:35:28 +04:00
return False ;
2002-09-25 19:19:00 +04:00
DEBUG ( 6 , ( " delete_driver_files: deleting driver [%s] - version [%d] \n " , info_3 - > name , info_3 - > cversion ) ) ;
2002-07-15 14:35:28 +04:00
/*
* Connect to the print $ share under the same account as the
* user connected to the rpc pipe . Note we must be root to
* do this .
*/
null_pw = data_blob ( NULL , 0 ) ;
2003-03-05 04:30:15 +03:00
fstrcpy ( res_type , " A: " ) ;
become_root ( ) ;
conn = make_connection_with_chdir ( " print$ " , null_pw , res_type , user - > vuid , & nt_status ) ;
2002-07-15 14:35:28 +04:00
unbecome_root ( ) ;
if ( ! conn ) {
DEBUG ( 0 , ( " delete_driver_files: Unable to connect \n " ) ) ;
return False ;
}
/* Save who we are - we are temporarily becoming the connection user. */
if ( ! become_user ( conn , conn - > vuid ) ) {
DEBUG ( 0 , ( " delete_driver_files: Can't become user! \n " ) ) ;
return False ;
}
/* now delete the files; must strip the '\print$' string from
fron of path */
2002-09-25 19:19:00 +04:00
if ( * info_3 - > driverpath ) {
if ( ( s = strchr ( & info_3 - > driverpath [ 1 ] , ' \\ ' ) ) ! = NULL ) {
2004-05-03 20:38:37 +04:00
driver_unix_convert ( s , conn , NULL , & bad_path , & st ) ;
2002-07-15 14:35:28 +04:00
DEBUG ( 10 , ( " deleting driverfile [%s] \n " , s ) ) ;
unlink_internals ( conn , 0 , s ) ;
}
}
2002-09-25 19:19:00 +04:00
if ( * info_3 - > configfile ) {
if ( ( s = strchr ( & info_3 - > configfile [ 1 ] , ' \\ ' ) ) ! = NULL ) {
2004-05-03 20:38:37 +04:00
driver_unix_convert ( s , conn , NULL , & bad_path , & st ) ;
2002-07-15 14:35:28 +04:00
DEBUG ( 10 , ( " deleting configfile [%s] \n " , s ) ) ;
unlink_internals ( conn , 0 , s ) ;
}
}
2002-09-25 19:19:00 +04:00
if ( * info_3 - > datafile ) {
if ( ( s = strchr ( & info_3 - > datafile [ 1 ] , ' \\ ' ) ) ! = NULL ) {
2004-05-03 20:38:37 +04:00
driver_unix_convert ( s , conn , NULL , & bad_path , & st ) ;
2002-07-15 14:35:28 +04:00
DEBUG ( 10 , ( " deleting datafile [%s] \n " , s ) ) ;
unlink_internals ( conn , 0 , s ) ;
}
}
2002-09-25 19:19:00 +04:00
if ( * info_3 - > helpfile ) {
if ( ( s = strchr ( & info_3 - > helpfile [ 1 ] , ' \\ ' ) ) ! = NULL ) {
2004-05-03 20:38:37 +04:00
driver_unix_convert ( s , conn , NULL , & bad_path , & st ) ;
2002-07-15 14:35:28 +04:00
DEBUG ( 10 , ( " deleting helpfile [%s] \n " , s ) ) ;
unlink_internals ( conn , 0 , s ) ;
}
}
2002-09-25 19:19:00 +04:00
/* check if we are done removing files */
2002-07-15 14:35:28 +04:00
2003-02-25 23:53:53 +03:00
if ( info_3 - > dependentfiles ) {
2002-09-25 19:19:00 +04:00
while ( * info_3 - > dependentfiles [ i ] ) {
char * file ;
2002-07-15 14:35:28 +04:00
2002-09-25 19:19:00 +04:00
/* bypass the "\print$" portion of the path */
2003-02-25 23:53:53 +03:00
if ( ( file = strchr ( info_3 - > dependentfiles [ i ] + 1 , ' \\ ' ) ) ! = NULL ) {
2004-05-03 20:38:37 +04:00
driver_unix_convert ( file , conn , NULL , & bad_path , & st ) ;
2002-09-25 19:19:00 +04:00
DEBUG ( 10 , ( " deleting dependent file [%s] \n " , file ) ) ;
unlink_internals ( conn , 0 , file ) ;
}
i + + ;
2002-07-15 14:35:28 +04:00
}
}
2002-09-25 19:19:00 +04:00
unbecome_user ( ) ;
2002-07-15 14:35:28 +04:00
return True ;
}
2001-05-18 08:11:17 +04:00
/****************************************************************************
Remove a printer driver from the TDB . This assumes that the the driver was
previously looked up .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2002-07-15 14:35:28 +04:00
2002-09-25 19:19:00 +04:00
WERROR delete_printer_driver ( NT_PRINTER_DRIVER_INFO_LEVEL_3 * info_3 , struct current_user * user ,
2002-07-15 14:35:28 +04:00
uint32 version , BOOL delete_files )
2001-05-18 08:11:17 +04:00
{
pstring key ;
2003-04-23 17:27:35 +04:00
const char * arch ;
2002-08-17 20:31:24 +04:00
TDB_DATA kbuf , dbuf ;
2002-07-15 14:35:28 +04:00
NT_PRINTER_DRIVER_INFO_LEVEL ctr ;
2001-05-18 08:11:17 +04:00
2002-07-15 14:35:28 +04:00
/* delete the tdb data first */
2001-05-18 08:11:17 +04:00
2003-04-23 17:27:35 +04:00
arch = get_short_archi ( info_3 - > environment ) ;
2001-05-18 08:11:17 +04:00
slprintf ( key , sizeof ( key ) - 1 , " %s%s/%d/%s " , DRIVERS_PREFIX ,
2002-09-25 19:19:00 +04:00
arch , version , info_3 - > name ) ;
2002-07-15 14:35:28 +04:00
DEBUG ( 5 , ( " delete_printer_driver: key = [%s] delete_files = %s \n " ,
key , delete_files ? " TRUE " : " FALSE " ) ) ;
2002-09-25 19:19:00 +04:00
ctr . info_3 = info_3 ;
2002-07-15 14:35:28 +04:00
dump_a_printer_driver ( ctr , 3 ) ;
2001-05-18 08:11:17 +04:00
kbuf . dptr = key ;
kbuf . dsize = strlen ( key ) + 1 ;
2002-08-17 20:31:24 +04:00
/* check if the driver actually exists for this environment */
dbuf = tdb_fetch ( tdb_drivers , kbuf ) ;
if ( ! dbuf . dptr ) {
2002-09-25 19:19:00 +04:00
DEBUG ( 8 , ( " delete_printer_driver: Driver unknown [%s] \n " , key ) ) ;
2002-08-17 20:31:24 +04:00
return WERR_UNKNOWN_PRINTER_DRIVER ;
}
SAFE_FREE ( dbuf . dptr ) ;
/* ok... the driver exists so the delete should return success */
2001-07-09 22:19:04 +04:00
if ( tdb_delete ( tdb_drivers , kbuf ) = = - 1 ) {
2002-09-25 19:19:00 +04:00
DEBUG ( 0 , ( " delete_printer_driver: fail to delete %s! \n " , key ) ) ;
2001-09-04 11:13:01 +04:00
return WERR_ACCESS_DENIED ;
2001-05-18 08:11:17 +04:00
}
2002-07-15 14:35:28 +04:00
/*
* now delete any associated files if delete_files = = True
* even if this part failes , we return succes because the
* driver doesn not exist any more
*/
if ( delete_files )
2002-09-25 19:19:00 +04:00
delete_driver_files ( info_3 , user ) ;
2002-08-17 20:31:24 +04:00
2002-09-25 19:19:00 +04:00
DEBUG ( 5 , ( " delete_printer_driver: driver delete successful [%s] \n " , key ) ) ;
2002-07-15 14:35:28 +04:00
2001-09-04 11:13:01 +04:00
return WERR_OK ;
2000-02-07 19:17:59 +03:00
}
2000-05-27 13:53:11 +04:00
/****************************************************************************
2000-08-01 04:41:19 +04:00
Store a security desc for a printer .
2000-05-27 13:53:11 +04:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2000-08-01 04:41:19 +04:00
2002-07-15 14:35:28 +04:00
WERROR nt_printing_setsec ( const char * printername , SEC_DESC_BUF * secdesc_ctr )
2000-05-27 13:53:11 +04:00
{
2000-11-15 00:56:32 +03:00
SEC_DESC_BUF * new_secdesc_ctr = NULL ;
SEC_DESC_BUF * old_secdesc_ctr = NULL ;
2000-05-27 13:53:11 +04:00
prs_struct ps ;
2000-07-27 04:47:19 +04:00
TALLOC_CTX * mem_ctx = NULL ;
2000-05-27 13:53:11 +04:00
fstring key ;
2001-09-03 14:38:13 +04:00
WERROR status ;
2000-07-10 09:08:21 +04:00
2002-12-20 23:21:31 +03:00
mem_ctx = talloc_init ( " nt_printing_setsec " ) ;
2000-11-15 00:56:32 +03:00
if ( mem_ctx = = NULL )
2001-09-03 14:38:13 +04:00
return WERR_NOMEM ;
2000-11-15 00:56:32 +03:00
/* The old owner and group sids of the security descriptor are not
present when new ACEs are added or removed by changing printer
permissions through NT . If they are NULL in the new security
descriptor then copy them over from the old one . */
if ( ! secdesc_ctr - > sec - > owner_sid | | ! secdesc_ctr - > sec - > grp_sid ) {
DOM_SID * owner_sid , * group_sid ;
SEC_ACL * dacl , * sacl ;
SEC_DESC * psd = NULL ;
size_t size ;
2001-02-28 03:51:02 +03:00
nt_printing_getsec ( mem_ctx , printername , & old_secdesc_ctr ) ;
2000-11-15 00:56:32 +03:00
/* Pick out correct owner and group sids */
owner_sid = secdesc_ctr - > sec - > owner_sid ?
secdesc_ctr - > sec - > owner_sid :
old_secdesc_ctr - > sec - > owner_sid ;
group_sid = secdesc_ctr - > sec - > grp_sid ?
secdesc_ctr - > sec - > grp_sid :
old_secdesc_ctr - > sec - > grp_sid ;
dacl = secdesc_ctr - > sec - > dacl ?
secdesc_ctr - > sec - > dacl :
old_secdesc_ctr - > sec - > dacl ;
sacl = secdesc_ctr - > sec - > sacl ?
secdesc_ctr - > sec - > sacl :
old_secdesc_ctr - > sec - > sacl ;
/* Make a deep copy of the security descriptor */
2003-09-20 01:57:43 +04:00
psd = make_sec_desc ( mem_ctx , secdesc_ctr - > sec - > revision , secdesc_ctr - > sec - > type ,
2000-11-15 00:56:32 +03:00
owner_sid , group_sid ,
sacl ,
dacl ,
& size ) ;
2001-02-28 03:51:02 +03:00
new_secdesc_ctr = make_sec_desc_buf ( mem_ctx , size , psd ) ;
2000-11-15 00:56:32 +03:00
}
if ( ! new_secdesc_ctr ) {
new_secdesc_ctr = secdesc_ctr ;
}
2000-05-27 13:53:11 +04:00
2000-07-06 11:06:05 +04:00
/* Store the security descriptor in a tdb */
2000-11-15 00:56:32 +03:00
prs_init ( & ps , ( uint32 ) sec_desc_size ( new_secdesc_ctr - > sec ) +
2001-03-10 02:48:58 +03:00
sizeof ( SEC_DESC_BUF ) , mem_ctx , MARSHALL ) ;
2000-07-06 11:06:05 +04:00
2000-11-15 00:56:32 +03:00
if ( ! sec_io_desc_buf ( " nt_printing_setsec " , & new_secdesc_ctr ,
& ps , 1 ) ) {
2001-09-03 14:38:13 +04:00
status = WERR_BADFUNC ;
2000-11-15 00:56:32 +03:00
goto out ;
2000-05-27 13:53:11 +04:00
}
2001-08-10 23:38:53 +04:00
slprintf ( key , sizeof ( key ) - 1 , " SECDESC/%s " , printername ) ;
2000-05-27 13:53:11 +04:00
2001-07-09 22:19:04 +04:00
if ( tdb_prs_store ( tdb_printers , key , & ps ) = = 0 ) {
2001-09-04 11:13:01 +04:00
status = WERR_OK ;
2000-05-27 13:53:11 +04:00
} else {
DEBUG ( 1 , ( " Failed to store secdesc for %s \n " , printername ) ) ;
2001-09-03 14:38:13 +04:00
status = WERR_BADFUNC ;
2000-05-27 13:53:11 +04:00
}
2001-04-09 00:01:51 +04:00
/* Free malloc'ed memory */
2000-07-10 09:08:21 +04:00
2000-11-15 00:56:32 +03:00
out :
2000-11-04 09:36:18 +03:00
2000-11-15 00:56:32 +03:00
prs_mem_free ( & ps ) ;
if ( mem_ctx )
talloc_destroy ( mem_ctx ) ;
2000-05-27 13:53:11 +04:00
return status ;
}
/****************************************************************************
2000-06-01 21:01:34 +04:00
Construct a default security descriptor buffer for a printer .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2001-02-28 03:51:02 +03:00
static SEC_DESC_BUF * construct_default_printer_sdb ( TALLOC_CTX * ctx )
2000-06-01 21:01:34 +04:00
{
2000-12-18 09:02:31 +03:00
SEC_ACE ace [ 3 ] ;
2000-06-07 05:49:23 +04:00
SEC_ACCESS sa ;
SEC_ACL * psa = NULL ;
2000-06-01 21:01:34 +04:00
SEC_DESC_BUF * sdb = NULL ;
2000-06-07 05:49:23 +04:00
SEC_DESC * psd = NULL ;
2000-07-10 09:08:21 +04:00
DOM_SID owner_sid ;
2000-06-01 21:01:34 +04:00
size_t sd_size ;
2000-06-07 05:49:23 +04:00
2000-07-10 09:08:21 +04:00
/* Create an ACE where Everyone is allowed to print */
init_sec_access ( & sa , PRINTER_ACE_PRINT ) ;
2000-08-09 22:40:48 +04:00
init_sec_ace ( & ace [ 0 ] , & global_sid_World , SEC_ACE_TYPE_ACCESS_ALLOWED ,
2000-07-10 09:08:21 +04:00
sa , SEC_ACE_FLAG_CONTAINER_INHERIT ) ;
/* Make the security descriptor owned by the Administrators group
on the PDC of the domain . */
2002-01-26 09:02:28 +03:00
if ( secrets_fetch_domain_sid ( lp_workgroup ( ) , & owner_sid ) ) {
2000-07-17 06:41:38 +04:00
sid_append_rid ( & owner_sid , DOMAIN_USER_RID_ADMIN ) ;
} else {
2002-02-09 07:10:24 +03:00
2002-01-26 01:44:21 +03:00
/* Backup plan - make printer owned by admins.
2002-02-09 07:10:24 +03:00
This should emulate a lanman printer as security
settings can ' t be changed . */
2000-07-17 06:41:38 +04:00
2002-07-15 14:35:28 +04:00
sid_copy ( & owner_sid , get_global_sam_sid ( ) ) ;
2002-01-26 01:44:21 +03:00
sid_append_rid ( & owner_sid , DOMAIN_USER_RID_ADMIN ) ;
2000-07-10 09:08:21 +04:00
}
2000-06-07 05:49:23 +04:00
2000-12-18 09:02:31 +03:00
init_sec_access ( & sa , PRINTER_ACE_FULL_CONTROL ) ;
2000-08-09 22:40:48 +04:00
init_sec_ace ( & ace [ 1 ] , & owner_sid , SEC_ACE_TYPE_ACCESS_ALLOWED ,
2000-12-18 09:02:31 +03:00
sa , SEC_ACE_FLAG_OBJECT_INHERIT |
SEC_ACE_FLAG_INHERIT_ONLY ) ;
init_sec_access ( & sa , PRINTER_ACE_FULL_CONTROL ) ;
init_sec_ace ( & ace [ 2 ] , & owner_sid , SEC_ACE_TYPE_ACCESS_ALLOWED ,
2000-08-09 22:40:48 +04:00
sa , SEC_ACE_FLAG_CONTAINER_INHERIT ) ;
2000-07-10 09:08:21 +04:00
/* The ACL revision number in rpc_secdesc.h differs from the one
created by NT when setting ACE entries in printer
descriptors . NT4 complains about the property being edited by a
NT5 machine . */
2001-02-28 03:51:02 +03:00
if ( ( psa = make_sec_acl ( ctx , NT4_ACL_REVISION , 3 , ace ) ) ! = NULL ) {
2003-09-20 01:57:43 +04:00
psd = make_sec_desc ( ctx , SEC_DESC_REVISION , SEC_DESC_SELF_RELATIVE ,
2000-07-10 09:08:21 +04:00
& owner_sid , NULL ,
NULL , psa , & sd_size ) ;
2000-06-07 05:49:23 +04:00
}
2000-06-01 21:01:34 +04:00
if ( ! psd ) {
2002-02-09 07:10:24 +03:00
DEBUG ( 0 , ( " construct_default_printer_sd: Failed to make SEC_DESC. \n " ) ) ;
2000-06-01 21:01:34 +04:00
return NULL ;
}
2001-02-28 03:51:02 +03:00
sdb = make_sec_desc_buf ( ctx , sd_size , psd ) ;
2000-06-01 21:01:34 +04:00
2000-11-15 00:56:32 +03:00
DEBUG ( 4 , ( " construct_default_printer_sdb: size = %u. \n " ,
2000-07-10 09:08:21 +04:00
( unsigned int ) sd_size ) ) ;
2000-06-07 05:49:23 +04:00
2000-06-01 21:01:34 +04:00
return sdb ;
}
/****************************************************************************
Get a security desc for a printer .
2000-05-27 13:53:11 +04:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2000-06-01 21:01:34 +04:00
2002-07-15 14:35:28 +04:00
BOOL nt_printing_getsec ( TALLOC_CTX * ctx , const char * printername , SEC_DESC_BUF * * secdesc_ctr )
2000-05-27 13:53:11 +04:00
{
prs_struct ps ;
fstring key ;
2001-01-04 22:27:08 +03:00
char * temp ;
2000-05-27 13:53:11 +04:00
2003-02-25 23:53:53 +03:00
if ( strlen ( printername ) > 2 & & ( temp = strchr ( printername + 2 , ' \\ ' ) ) ) {
2001-01-04 22:27:08 +03:00
printername = temp + 1 ;
2003-02-25 23:53:53 +03:00
}
2001-01-04 22:27:08 +03:00
2000-07-17 06:41:38 +04:00
/* Fetch security descriptor from tdb */
2001-08-10 23:38:53 +04:00
slprintf ( key , sizeof ( key ) - 1 , " SECDESC/%s " , printername ) ;
2000-05-27 13:53:11 +04:00
2001-07-09 22:19:04 +04:00
if ( tdb_prs_fetch ( tdb_printers , key , & ps , ctx ) ! = 0 | |
2000-05-27 13:53:11 +04:00
! sec_io_desc_buf ( " nt_printing_getsec " , secdesc_ctr , & ps , 1 ) ) {
2000-06-01 21:01:34 +04:00
2000-05-27 13:53:11 +04:00
DEBUG ( 4 , ( " using default secdesc for %s \n " , printername ) ) ;
2000-06-01 21:01:34 +04:00
2001-02-28 03:51:02 +03:00
if ( ! ( * secdesc_ctr = construct_default_printer_sdb ( ctx ) ) ) {
2000-06-01 21:01:34 +04:00
return False ;
2000-07-27 04:47:19 +04:00
}
2000-06-01 21:01:34 +04:00
2002-02-09 07:10:24 +03:00
/* Save default security descriptor for later */
2001-11-26 06:39:16 +03:00
2002-02-09 07:10:24 +03:00
prs_init ( & ps , ( uint32 ) sec_desc_size ( ( * secdesc_ctr ) - > sec ) +
sizeof ( SEC_DESC_BUF ) , ctx , MARSHALL ) ;
2001-11-26 06:39:16 +03:00
2002-07-15 14:35:28 +04:00
if ( sec_io_desc_buf ( " nt_printing_getsec " , secdesc_ctr , & ps , 1 ) )
2002-02-09 07:10:24 +03:00
tdb_prs_store ( tdb_printers , key , & ps ) ;
2001-11-26 06:39:16 +03:00
2002-02-09 07:10:24 +03:00
prs_mem_free ( & ps ) ;
2001-11-26 06:39:16 +03:00
2000-06-01 21:01:34 +04:00
return True ;
2000-05-27 13:53:11 +04:00
}
2002-02-09 07:10:24 +03:00
/* If security descriptor is owned by S-1-1-0 and winbindd is up,
this security descriptor has been created when winbindd was
2000-07-17 06:41:38 +04:00
down . Take ownership of security descriptor . */
if ( sid_equal ( ( * secdesc_ctr ) - > sec - > owner_sid , & global_sid_World ) ) {
DOM_SID owner_sid ;
/* Change sd owner to workgroup administrator */
2002-01-26 09:02:28 +03:00
if ( secrets_fetch_domain_sid ( lp_workgroup ( ) , & owner_sid ) ) {
2000-07-17 06:41:38 +04:00
SEC_DESC_BUF * new_secdesc_ctr = NULL ;
SEC_DESC * psd = NULL ;
size_t size ;
/* Create new sd */
sid_append_rid ( & owner_sid , DOMAIN_USER_RID_ADMIN ) ;
2003-09-20 01:57:43 +04:00
psd = make_sec_desc ( ctx , ( * secdesc_ctr ) - > sec - > revision , ( * secdesc_ctr ) - > sec - > type ,
2000-07-17 06:41:38 +04:00
& owner_sid ,
( * secdesc_ctr ) - > sec - > grp_sid ,
( * secdesc_ctr ) - > sec - > sacl ,
( * secdesc_ctr ) - > sec - > dacl ,
& size ) ;
2001-02-28 03:51:02 +03:00
new_secdesc_ctr = make_sec_desc_buf ( ctx , size , psd ) ;
2000-07-17 06:41:38 +04:00
/* Swap with other one */
* secdesc_ctr = new_secdesc_ctr ;
/* Set it */
nt_printing_setsec ( printername , * secdesc_ctr ) ;
}
}
2000-12-11 22:24:59 +03:00
if ( DEBUGLEVEL > = 10 ) {
2001-04-28 02:17:10 +04:00
SEC_ACL * the_acl = ( * secdesc_ctr ) - > sec - > dacl ;
2000-12-11 22:24:59 +03:00
int i ;
DEBUG ( 10 , ( " secdesc_ctr for %s has %d aces: \n " ,
2001-04-28 02:17:10 +04:00
printername , the_acl - > num_aces ) ) ;
2000-12-11 22:24:59 +03:00
2001-04-28 02:17:10 +04:00
for ( i = 0 ; i < the_acl - > num_aces ; i + + ) {
2000-12-11 22:24:59 +03:00
fstring sid_str ;
2001-11-30 04:04:15 +03:00
sid_to_string ( sid_str , & the_acl - > ace [ i ] . trustee ) ;
2000-12-11 22:24:59 +03:00
2001-01-04 22:27:08 +03:00
DEBUG ( 10 , ( " %s %d %d 0x%08x \n " , sid_str ,
2001-04-28 02:17:10 +04:00
the_acl - > ace [ i ] . type , the_acl - > ace [ i ] . flags ,
the_acl - > ace [ i ] . info . mask ) ) ;
2000-12-11 22:24:59 +03:00
}
}
2000-05-27 13:53:11 +04:00
prs_mem_free ( & ps ) ;
2000-06-01 21:01:34 +04:00
return True ;
2000-05-27 13:53:11 +04:00
}
2000-02-07 19:17:59 +03:00
/* error code:
0 : everything OK
1 : level not implemented
2 : file doesn ' t exist
3 : can ' t allocate memory
4 : can ' t free memory
5 : non existant struct
*/
/*
A printer and a printer driver are 2 different things .
NT manages them separatelly , Samba does the same .
Why ? Simply because it ' s easier and it makes sense !
Now explanation : You have 3 printers behind your samba server ,
2000-11-15 00:56:32 +03:00
2 of them are the same make and model ( laser A and B ) . But laser B
2000-02-07 19:17:59 +03:00
has an 3000 sheet feeder and laser A doesn ' t such an option .
Your third printer is an old dot - matrix model for the accounting : - ) .
If the / usr / local / samba / lib directory ( default dir ) , you will have
5 files to describe all of this .
3 files for the printers ( 1 by printer ) :
NTprinter_laser A
NTprinter_laser B
NTprinter_accounting
2 files for the drivers ( 1 for the laser and 1 for the dot matrix )
NTdriver_printer model X
NTdriver_printer model Y
2000-11-15 00:56:32 +03:00
jfm : I should use this comment for the text file to explain
2000-02-07 19:17:59 +03:00
same thing for the forms BTW .
Je devrais mettre mes commentaires en francais , ca serait mieux : - )
*/
2001-01-04 22:27:08 +03:00
/* Convert generic access rights to printer object specific access rights.
It turns out that NT4 security descriptors use generic access rights and
NT5 the object specific ones . */
void map_printer_permissions ( SEC_DESC * sd )
{
int i ;
for ( i = 0 ; sd - > dacl & & i < sd - > dacl - > num_aces ; i + + ) {
se_map_generic ( & sd - > dacl - > ace [ i ] . info . mask ,
& printer_generic_mapping ) ;
}
}
2000-08-09 08:19:18 +04:00
/****************************************************************************
2001-01-19 19:57:39 +03:00
Check a user has permissions to perform the given operation . We use the
permission constants defined in include / rpc_spoolss . h to check the various
actions we perform when checking printer access .
2000-09-01 22:49:26 +04:00
PRINTER_ACCESS_ADMINISTER :
print_queue_pause , print_queue_resume , update_printer_sec ,
update_printer , spoolss_addprinterex_level_2 ,
_spoolss_setprinterdata
2000-11-15 00:56:32 +03:00
2000-09-01 22:49:26 +04:00
PRINTER_ACCESS_USE :
print_job_start
2001-01-19 19:57:39 +03:00
JOB_ACCESS_ADMINISTER :
2000-09-01 22:49:26 +04:00
print_job_delete , print_job_pause , print_job_resume ,
print_queue_purge
2000-06-16 12:20:44 +04:00
2000-08-09 08:19:18 +04:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2000-09-01 22:49:26 +04:00
BOOL print_access_check ( struct current_user * user , int snum , int access_type )
2000-06-16 12:20:44 +04:00
{
SEC_DESC_BUF * secdesc = NULL ;
2001-09-04 11:13:01 +04:00
uint32 access_granted ;
NTSTATUS status ;
2000-07-06 11:06:05 +04:00
BOOL result ;
2002-07-15 14:35:28 +04:00
const char * pname ;
2001-02-28 03:51:02 +03:00
TALLOC_CTX * mem_ctx = NULL ;
2000-08-09 08:19:18 +04:00
extern struct current_user current_user ;
2000-07-06 11:10:32 +04:00
2000-09-01 22:49:26 +04:00
/* If user is NULL then use the current_user structure */
2001-09-26 04:05:03 +04:00
if ( ! user )
user = & current_user ;
2000-08-09 08:19:18 +04:00
2000-09-01 22:49:26 +04:00
/* Always allow root or printer admins to do anything */
if ( user - > uid = = 0 | |
2003-02-24 05:47:14 +03:00
user_in_list ( uidtoname ( user - > uid ) , lp_printer_admin ( snum ) , user - > groups , user - > ngroups ) ) {
2000-08-09 08:19:18 +04:00
return True ;
}
2000-06-16 12:20:44 +04:00
2000-08-09 08:19:18 +04:00
/* Get printer name */
2000-09-01 22:49:26 +04:00
2000-07-06 11:06:05 +04:00
pname = PRINTERNAME ( snum ) ;
2000-09-01 22:49:26 +04:00
2000-08-24 03:05:49 +04:00
if ( ! pname | | ! * pname ) {
errno = EACCES ;
return False ;
}
2000-06-16 12:20:44 +04:00
2000-08-09 08:19:18 +04:00
/* Get printer security descriptor */
2000-09-01 22:49:26 +04:00
2002-12-20 23:21:31 +03:00
if ( ! ( mem_ctx = talloc_init ( " print_access_check " ) ) ) {
2001-02-28 03:51:02 +03:00
errno = ENOMEM ;
return False ;
}
nt_printing_getsec ( mem_ctx , pname , & secdesc ) ;
2001-01-19 19:57:39 +03:00
if ( access_type = = JOB_ACCESS_ADMINISTER ) {
SEC_DESC_BUF * parent_secdesc = secdesc ;
/* Create a child security descriptor to check permissions
against . This is because print jobs are child objects
objects of a printer . */
2001-02-28 03:51:02 +03:00
secdesc = se_create_child_secdesc ( mem_ctx , parent_secdesc - > sec , False ) ;
2001-01-19 19:57:39 +03:00
/* Now this is the bit that really confuses me. The access
type needs to be changed from JOB_ACCESS_ADMINISTER to
PRINTER_ACCESS_ADMINISTER for this to work . Something
to do with the child ( job ) object becoming like a
printer ? ? - tpot */
access_type = PRINTER_ACCESS_ADMINISTER ;
}
/* Check access */
2000-12-13 22:55:48 +03:00
2001-01-04 22:27:08 +03:00
map_printer_permissions ( secdesc - > sec ) ;
2001-09-26 04:05:03 +04:00
result = se_access_check ( secdesc - > sec , user - > nt_user_token , access_type ,
2000-07-17 06:41:38 +04:00
& access_granted , & status ) ;
2000-06-16 12:20:44 +04:00
2000-07-06 11:06:05 +04:00
DEBUG ( 4 , ( " access check was %s \n " , result ? " SUCCESS " : " FAILURE " ) ) ;
2000-06-16 12:20:44 +04:00
2001-02-28 03:51:02 +03:00
talloc_destroy ( mem_ctx ) ;
2000-08-24 03:05:49 +04:00
if ( ! result )
errno = EACCES ;
2000-07-06 11:06:05 +04:00
return result ;
2000-06-16 12:20:44 +04:00
}
2000-08-01 04:41:19 +04:00
/****************************************************************************
Check the time parameters allow a print operation .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
BOOL print_time_access_check ( int snum )
{
NT_PRINTER_INFO_LEVEL * printer = NULL ;
BOOL ok = False ;
time_t now = time ( NULL ) ;
struct tm * t ;
uint32 mins ;
2003-02-25 23:53:53 +03:00
if ( ! W_ERROR_IS_OK ( get_a_printer ( NULL , & printer , 2 , lp_servicename ( snum ) ) ) )
2000-08-01 04:41:19 +04:00
return False ;
if ( printer - > info_2 - > starttime = = 0 & & printer - > info_2 - > untiltime = = 0 )
ok = True ;
t = gmtime ( & now ) ;
mins = ( uint32 ) t - > tm_hour * 60 + ( uint32 ) t - > tm_min ;
if ( mins > = printer - > info_2 - > starttime & & mins < = printer - > info_2 - > untiltime )
ok = True ;
free_a_printer ( & printer , 2 ) ;
2000-09-13 06:24:35 +04:00
if ( ! ok )
errno = EACCES ;
2000-08-01 04:41:19 +04:00
return ok ;
}