root/source3/printing/nt_printing.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. make_printer_tdbkey
  2. make_printers_secdesc_tdbkey
  3. upgrade_to_version_3
  4. sec_desc_upg_fn
  5. upgrade_to_version_4
  6. normalize_printers_fn
  7. upgrade_to_version_5
  8. nt_printing_init
  9. driver_unix_convert
  10. traverse_counting_printers
  11. update_c_setprinter
  12. get_c_setprinter
  13. get_builtin_ntforms
  14. get_a_builtin_ntform_by_string
  15. get_ntforms
  16. write_ntforms
  17. add_a_form
  18. delete_a_form
  19. update_a_form
  20. get_ntdrivers
  21. get_short_archi
  22. get_file_version
  23. file_version_is_newer
  24. get_correct_cversion
  25. clean_up_driver_struct_level_3
  26. clean_up_driver_struct_level_6
  27. clean_up_driver_struct
  28. convert_level_6_to_level3
  29. ffmt
  30. move_driver_file_to_download_area
  31. move_driver_to_download_area
  32. add_a_printer_driver_3
  33. add_a_printer_driver_6
  34. get_a_printer_driver_3_default
  35. get_a_printer_driver_3
  36. dump_a_printer_driver
  37. pack_devicemode
  38. pack_values
  39. del_a_printer
  40. update_a_printer_2
  41. construct_nt_devicemode
  42. free_nt_devicemode
  43. free_nt_printer_info_level_2
  44. unpack_devicemode
  45. add_new_printer_key
  46. delete_printer_key
  47. lookup_printerkey
  48. get_printer_subkeys
  49. map_sz_into_ctr
  50. map_dword_into_ctr
  51. map_bool_into_ctr
  52. map_single_multi_sz_into_ctr
  53. map_nt_printer_info2_to_dsspooler
  54. store_printer_guid
  55. nt_printer_publish_ads
  56. nt_printer_unpublish_ads
  57. nt_printer_publish
  58. check_published_printers
  59. is_printer_published
  60. nt_printer_publish
  61. check_published_printers
  62. is_printer_published
  63. delete_all_printer_data
  64. delete_printer_data
  65. add_printer_data
  66. get_printer_data
  67. unpack_values
  68. get_last_from
  69. get_last_to
  70. set_last_from_to
  71. map_to_os2_driver
  72. get_a_printer_2_default
  73. get_a_printer_2
  74. dump_a_printer
  75. rev_changeid
  76. mod_a_printer
  77. set_driver_init_2
  78. set_driver_init
  79. del_driver_init
  80. update_driver_init_2
  81. update_driver_init
  82. convert_driver_init
  83. save_driver_init_2
  84. save_driver_init
  85. get_a_printer_internal
  86. get_a_printer
  87. get_a_printer_search
  88. free_a_printer
  89. add_a_printer_driver
  90. get_a_printer_driver
  91. free_a_printer_driver
  92. printer_driver_in_use
  93. drv_file_in_use
  94. trim_dependent_file
  95. trim_overlap_drv_files
  96. printer_driver_files_in_use
  97. delete_driver_files
  98. delete_printer_driver
  99. nt_printing_setsec
  100. construct_default_printer_sdb
  101. nt_printing_getsec
  102. map_printer_permissions
  103. map_job_permissions
  104. print_access_check
  105. print_time_access_check
  106. get_server_name

   1 /*
   2  *  Unix SMB/CIFS implementation.
   3  *  RPC Pipe client / server routines
   4  *  Copyright (C) Andrew Tridgell              1992-2000,
   5  *  Copyright (C) Jean François Micouleau      1998-2000.
   6  *  Copyright (C) Gerald Carter                2002-2005.
   7  *
   8  *  This program is free software; you can redistribute it and/or modify
   9  *  it under the terms of the GNU General Public License as published by
  10  *  the Free Software Foundation; either version 3 of the License, or
  11  *  (at your option) any later version.
  12  *
  13  *  This program is distributed in the hope that it will be useful,
  14  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
  15  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  16  *  GNU General Public License for more details.
  17  *
  18  *  You should have received a copy of the GNU General Public License
  19  *  along with this program; if not, see <http://www.gnu.org/licenses/>.
  20  */
  21 
  22 #include "includes.h"
  23 
  24 static TDB_CONTEXT *tdb_forms; /* used for forms files */
  25 static TDB_CONTEXT *tdb_drivers; /* used for driver files */
  26 static TDB_CONTEXT *tdb_printers; /* used for printers files */
  27 
  28 #define FORMS_PREFIX "FORMS/"
  29 #define DRIVERS_PREFIX "DRIVERS/"
  30 #define DRIVER_INIT_PREFIX "DRIVER_INIT/"
  31 #define PRINTERS_PREFIX "PRINTERS/"
  32 #define SECDESC_PREFIX "SECDESC/"
  33 #define GLOBAL_C_SETPRINTER "GLOBALS/c_setprinter"
  34 
  35 #define NTDRIVERS_DATABASE_VERSION_1 1
  36 #define NTDRIVERS_DATABASE_VERSION_2 2
  37 #define NTDRIVERS_DATABASE_VERSION_3 3 /* little endian version of v2 */
  38 #define NTDRIVERS_DATABASE_VERSION_4 4 /* fix generic bits in security descriptors */
  39 #define NTDRIVERS_DATABASE_VERSION_5 5 /* normalize keys in ntprinters.tdb */
  40 
  41 /* Map generic permissions to printer object specific permissions */
  42 
  43 const struct generic_mapping printer_generic_mapping = {
  44         PRINTER_READ,
  45         PRINTER_WRITE,
  46         PRINTER_EXECUTE,
  47         PRINTER_ALL_ACCESS
  48 };
  49 
  50 const struct standard_mapping printer_std_mapping = {
  51         PRINTER_READ,
  52         PRINTER_WRITE,
  53         PRINTER_EXECUTE,
  54         PRINTER_ALL_ACCESS
  55 };
  56 
  57 /* Map generic permissions to print server object specific permissions */
  58 
  59 const struct generic_mapping printserver_generic_mapping = {
  60         SERVER_READ,
  61         SERVER_WRITE,
  62         SERVER_EXECUTE,
  63         SERVER_ALL_ACCESS
  64 };
  65 
  66 const struct generic_mapping printserver_std_mapping = {
  67         SERVER_READ,
  68         SERVER_WRITE,
  69         SERVER_EXECUTE,
  70         SERVER_ALL_ACCESS
  71 };
  72 
  73 /* Map generic permissions to job object specific permissions */
  74 
  75 const struct generic_mapping job_generic_mapping = {
  76         JOB_READ,
  77         JOB_WRITE,
  78         JOB_EXECUTE,
  79         JOB_ALL_ACCESS
  80 };
  81 
  82 /* We need one default form to support our default printer. Msoft adds the
  83 forms it wants and in the ORDER it wants them (note: DEVMODE papersize is an
  84 array index). Letter is always first, so (for the current code) additions
  85 always put things in the correct order. */
  86 static const nt_forms_struct default_forms[] = {
  87         {"Letter",0x1,0x34b5c,0x44368,0x0,0x0,0x34b5c,0x44368},
  88         {"Letter Small",0x1,0x34b5c,0x44368,0x0,0x0,0x34b5c,0x44368},
  89         {"Tabloid",0x1,0x44368,0x696b8,0x0,0x0,0x44368,0x696b8},
  90         {"Ledger",0x1,0x696b8,0x44368,0x0,0x0,0x696b8,0x44368},
  91         {"Legal",0x1,0x34b5c,0x56d10,0x0,0x0,0x34b5c,0x56d10},
  92         {"Statement",0x1,0x221b4,0x34b5c,0x0,0x0,0x221b4,0x34b5c},
  93         {"Executive",0x1,0x2cf56,0x411cc,0x0,0x0,0x2cf56,0x411cc},
  94         {"A3",0x1,0x48828,0x668a0,0x0,0x0,0x48828,0x668a0},
  95         {"A4",0x1,0x33450,0x48828,0x0,0x0,0x33450,0x48828},
  96         {"A4 Small",0x1,0x33450,0x48828,0x0,0x0,0x33450,0x48828},
  97         {"A5",0x1,0x24220,0x33450,0x0,0x0,0x24220,0x33450},
  98         {"B4 (JIS)",0x1,0x3ebe8,0x58de0,0x0,0x0,0x3ebe8,0x58de0},
  99         {"B5 (JIS)",0x1,0x2c6f0,0x3ebe8,0x0,0x0,0x2c6f0,0x3ebe8},
 100         {"Folio",0x1,0x34b5c,0x509d8,0x0,0x0,0x34b5c,0x509d8},
 101         {"Quarto",0x1,0x347d8,0x43238,0x0,0x0,0x347d8,0x43238},
 102         {"10x14",0x1,0x3e030,0x56d10,0x0,0x0,0x3e030,0x56d10},
 103         {"11x17",0x1,0x44368,0x696b8,0x0,0x0,0x44368,0x696b8},
 104         {"Note",0x1,0x34b5c,0x44368,0x0,0x0,0x34b5c,0x44368},
 105         {"Envelope #9",0x1,0x18079,0x37091,0x0,0x0,0x18079,0x37091},
 106         {"Envelope #10",0x1,0x19947,0x3ae94,0x0,0x0,0x19947,0x3ae94},
 107         {"Envelope #11",0x1,0x1be7c,0x40565,0x0,0x0,0x1be7c,0x40565},
 108         {"Envelope #12",0x1,0x1d74a,0x44368,0x0,0x0,0x1d74a,0x44368},
 109         {"Envelope #14",0x1,0x1f018,0x47504,0x0,0x0,0x1f018,0x47504},
 110         {"C size sheet",0x1,0x696b8,0x886d0,0x0,0x0,0x696b8,0x886d0},
 111         {"D size sheet",0x1,0x886d0,0xd2d70,0x0,0x0,0x886d0,0xd2d70},
 112         {"E size sheet",0x1,0xd2d70,0x110da0,0x0,0x0,0xd2d70,0x110da0},
 113         {"Envelope DL",0x1,0x1adb0,0x35b60,0x0,0x0,0x1adb0,0x35b60},
 114         {"Envelope C5",0x1,0x278d0,0x37e88,0x0,0x0,0x278d0,0x37e88},
 115         {"Envelope C3",0x1,0x4f1a0,0x6fd10,0x0,0x0,0x4f1a0,0x6fd10},
 116         {"Envelope C4",0x1,0x37e88,0x4f1a0,0x0,0x0,0x37e88,0x4f1a0},
 117         {"Envelope C6",0x1,0x1bd50,0x278d0,0x0,0x0,0x1bd50,0x278d0},
 118         {"Envelope C65",0x1,0x1bd50,0x37e88,0x0,0x0,0x1bd50,0x37e88},
 119         {"Envelope B4",0x1,0x3d090,0x562e8,0x0,0x0,0x3d090,0x562e8},
 120         {"Envelope B5",0x1,0x2af80,0x3d090,0x0,0x0,0x2af80,0x3d090},
 121         {"Envelope B6",0x1,0x2af80,0x1e848,0x0,0x0,0x2af80,0x1e848},
 122         {"Envelope",0x1,0x1adb0,0x38270,0x0,0x0,0x1adb0,0x38270},
 123         {"Envelope Monarch",0x1,0x18079,0x2e824,0x0,0x0,0x18079,0x2e824},
 124         {"6 3/4 Envelope",0x1,0x167ab,0x284ec,0x0,0x0,0x167ab,0x284ec},
 125         {"US Std Fanfold",0x1,0x5c3e1,0x44368,0x0,0x0,0x5c3e1,0x44368},
 126         {"German Std Fanfold",0x1,0x34b5c,0x4a6a0,0x0,0x0,0x34b5c,0x4a6a0},
 127         {"German Legal Fanfold",0x1,0x34b5c,0x509d8,0x0,0x0,0x34b5c,0x509d8},
 128         {"B4 (ISO)",0x1,0x3d090,0x562e8,0x0,0x0,0x3d090,0x562e8},
 129         {"Japanese Postcard",0x1,0x186a0,0x24220,0x0,0x0,0x186a0,0x24220},
 130         {"9x11",0x1,0x37cf8,0x44368,0x0,0x0,0x37cf8,0x44368},
 131         {"10x11",0x1,0x3e030,0x44368,0x0,0x0,0x3e030,0x44368},
 132         {"15x11",0x1,0x5d048,0x44368,0x0,0x0,0x5d048,0x44368},
 133         {"Envelope Invite",0x1,0x35b60,0x35b60,0x0,0x0,0x35b60,0x35b60},
 134         {"Reserved48",0x1,0x1,0x1,0x0,0x0,0x1,0x1},
 135         {"Reserved49",0x1,0x1,0x1,0x0,0x0,0x1,0x1},
 136         {"Letter Extra",0x1,0x3ae94,0x4a6a0,0x0,0x0,0x3ae94,0x4a6a0},
 137         {"Legal Extra",0x1,0x3ae94,0x5d048,0x0,0x0,0x3ae94,0x5d048},
 138         {"Tabloid Extra",0x1,0x4a6a0,0x6f9f0,0x0,0x0,0x4a6a0,0x6f9f0},
 139         {"A4 Extra",0x1,0x397c2,0x4eb16,0x0,0x0,0x397c2,0x4eb16},
 140         {"Letter Transverse",0x1,0x34b5c,0x44368,0x0,0x0,0x34b5c,0x44368},
 141         {"A4 Transverse",0x1,0x33450,0x48828,0x0,0x0,0x33450,0x48828},
 142         {"Letter Extra Transverse",0x1,0x3ae94,0x4a6a0,0x0,0x0,0x3ae94,0x4a6a0},
 143         {"Super A",0x1,0x376b8,0x56ea0,0x0,0x0,0x376b8,0x56ea0},
 144         {"Super B",0x1,0x4a768,0x76e58,0x0,0x0,0x4a768,0x76e58},
 145         {"Letter Plus",0x1,0x34b5c,0x4eb16,0x0,0x0,0x34b5c,0x4eb16},
 146         {"A4 Plus",0x1,0x33450,0x50910,0x0,0x0,0x33450,0x50910},
 147         {"A5 Transverse",0x1,0x24220,0x33450,0x0,0x0,0x24220,0x33450},
 148         {"B5 (JIS) Transverse",0x1,0x2c6f0,0x3ebe8,0x0,0x0,0x2c6f0,0x3ebe8},
 149         {"A3 Extra",0x1,0x4e9d0,0x6ca48,0x0,0x0,0x4e9d0,0x6ca48},
 150         {"A5 Extra",0x1,0x2a7b0,0x395f8,0x0,0x0,0x2a7b0,0x395f8},
 151         {"B5 (ISO) Extra",0x1,0x31128,0x43620,0x0,0x0,0x31128,0x43620},
 152         {"A2",0x1,0x668a0,0x91050,0x0,0x0,0x668a0,0x91050},
 153         {"A3 Transverse",0x1,0x48828,0x668a0,0x0,0x0,0x48828,0x668a0},
 154         {"A3 Extra Transverse",0x1,0x4e9d0,0x6ca48,0x0,0x0,0x4e9d0,0x6ca48},
 155         {"Japanese Double Postcard",0x1,0x30d40,0x24220,0x0,0x0,0x30d40,0x24220},
 156         {"A6",0x1,0x19a28,0x24220,0x0,0x0,0x19a28,0x24220},
 157         {"Japanese Envelope Kaku #2",0x1,0x3a980,0x510e0,0x0,0x0,0x3a980,0x510e0},
 158         {"Japanese Envelope Kaku #3",0x1,0x34bc0,0x43a08,0x0,0x0,0x34bc0,0x43a08},
 159         {"Japanese Envelope Chou #3",0x1,0x1d4c0,0x395f8,0x0,0x0,0x1d4c0,0x395f8},
 160         {"Japanese Envelope Chou #4",0x1,0x15f90,0x320c8,0x0,0x0,0x15f90,0x320c8},
 161         {"Letter Rotated",0x1,0x44368,0x34b5c,0x0,0x0,0x44368,0x34b5c},
 162         {"A3 Rotated",0x1,0x668a0,0x48828,0x0,0x0,0x668a0,0x48828},
 163         {"A4 Rotated",0x1,0x48828,0x33450,0x0,0x0,0x48828,0x33450},
 164         {"A5 Rotated",0x1,0x33450,0x24220,0x0,0x0,0x33450,0x24220},
 165         {"B4 (JIS) Rotated",0x1,0x58de0,0x3ebe8,0x0,0x0,0x58de0,0x3ebe8},
 166         {"B5 (JIS) Rotated",0x1,0x3ebe8,0x2c6f0,0x0,0x0,0x3ebe8,0x2c6f0},
 167         {"Japanese Postcard Rotated",0x1,0x24220,0x186a0,0x0,0x0,0x24220,0x186a0},
 168         {"Double Japan Postcard Rotated",0x1,0x24220,0x30d40,0x0,0x0,0x24220,0x30d40},
 169         {"A6 Rotated",0x1,0x24220,0x19a28,0x0,0x0,0x24220,0x19a28},
 170         {"Japan Envelope Kaku #2 Rotated",0x1,0x510e0,0x3a980,0x0,0x0,0x510e0,0x3a980},
 171         {"Japan Envelope Kaku #3 Rotated",0x1,0x43a08,0x34bc0,0x0,0x0,0x43a08, 0x34bc0},
 172         {"Japan Envelope Chou #3 Rotated",0x1,0x395f8,0x1d4c0,0x0,0x0,0x395f8,0x1d4c0},
 173         {"Japan Envelope Chou #4 Rotated",0x1,0x320c8,0x15f90,0x0,0x0,0x320c8,0x15f90},
 174         {"B6 (JIS)",0x1,0x1f400,0x2c6f0,0x0,0x0,0x1f400,0x2c6f0},
 175         {"B6 (JIS) Rotated",0x1,0x2c6f0,0x1f400,0x0,0x0,0x2c6f0,0x1f400},
 176         {"12x11",0x1,0x4a724,0x443e1,0x0,0x0,0x4a724,0x443e1},
 177         {"Japan Envelope You #4",0x1,0x19a28,0x395f8,0x0,0x0,0x19a28,0x395f8},
 178         {"Japan Envelope You #4 Rotated",0x1,0x395f8,0x19a28,0x0,0x0,0x395f8,0x19a28},
 179         {"PRC 16K",0x1,0x2de60,0x3f7a0,0x0,0x0,0x2de60,0x3f7a0},
 180         {"PRC 32K",0x1,0x1fbd0,0x2cec0,0x0,0x0,0x1fbd0,0x2cec0},
 181         {"PRC 32K(Big)",0x1,0x222e0,0x318f8,0x0,0x0,0x222e0,0x318f8},
 182         {"PRC Envelope #1",0x1,0x18e70,0x28488,0x0,0x0,0x18e70,0x28488},
 183         {"PRC Envelope #2",0x1,0x18e70,0x2af80,0x0,0x0,0x18e70,0x2af80},
 184         {"PRC Envelope #3",0x1,0x1e848,0x2af80,0x0,0x0,0x1e848,0x2af80},
 185         {"PRC Envelope #4",0x1,0x1adb0,0x32c80,0x0,0x0,0x1adb0,0x32c80},
 186         {"PRC Envelope #5",0x1,0x1adb0,0x35b60,0x0,0x0,0x1adb0,0x35b60},
 187         {"PRC Envelope #6",0x1,0x1d4c0,0x38270,0x0,0x0,0x1d4c0,0x38270},
 188         {"PRC Envelope #7",0x1,0x27100,0x38270,0x0,0x0,0x27100,0x38270},
 189         {"PRC Envelope #8",0x1,0x1d4c0,0x4b708,0x0,0x0,0x1d4c0,0x4b708},
 190         {"PRC Envelope #9",0x1,0x37e88,0x4f1a0,0x0,0x0,0x37e88,0x4f1a0},
 191         {"PRC Envelope #10",0x1,0x4f1a0,0x6fd10,0x0,0x0,0x4f1a0,0x6fd10},
 192         {"PRC 16K Rotated",0x1,0x3f7a0,0x2de60,0x0,0x0,0x3f7a0,0x2de60},
 193         {"PRC 32K Rotated",0x1,0x2cec0,0x1fbd0,0x0,0x0,0x2cec0,0x1fbd0},
 194         {"PRC 32K(Big) Rotated",0x1,0x318f8,0x222e0,0x0,0x0,0x318f8,0x222e0},
 195         {"PRC Envelope #1 Rotated",0x1,0x28488,0x18e70,0x0,0x0,0x28488,0x18e70},
 196         {"PRC Envelope #2 Rotated",0x1,0x2af80,0x18e70,0x0,0x0,0x2af80,0x18e70},
 197         {"PRC Envelope #3 Rotated",0x1,0x2af80,0x1e848,0x0,0x0,0x2af80,0x1e848},
 198         {"PRC Envelope #4 Rotated",0x1,0x32c80,0x1adb0,0x0,0x0,0x32c80,0x1adb0},
 199         {"PRC Envelope #5 Rotated",0x1,0x35b60,0x1adb0,0x0,0x0,0x35b60,0x1adb0},
 200         {"PRC Envelope #6 Rotated",0x1,0x38270,0x1d4c0,0x0,0x0,0x38270,0x1d4c0},
 201         {"PRC Envelope #7 Rotated",0x1,0x38270,0x27100,0x0,0x0,0x38270,0x27100},
 202         {"PRC Envelope #8 Rotated",0x1,0x4b708,0x1d4c0,0x0,0x0,0x4b708,0x1d4c0},
 203         {"PRC Envelope #9 Rotated",0x1,0x4f1a0,0x37e88,0x0,0x0,0x4f1a0,0x37e88},
 204         {"PRC Envelope #10 Rotated",0x1,0x6fd10,0x4f1a0,0x0,0x0,0x6fd10,0x4f1a0}
 205 };
 206 
 207 static const struct print_architecture_table_node archi_table[]= {
 208 
 209         {"Windows 4.0",          SPL_ARCH_WIN40,        0 },
 210         {"Windows NT x86",       SPL_ARCH_W32X86,       2 },
 211         {"Windows NT R4000",     SPL_ARCH_W32MIPS,      2 },
 212         {"Windows NT Alpha_AXP", SPL_ARCH_W32ALPHA,     2 },
 213         {"Windows NT PowerPC",   SPL_ARCH_W32PPC,       2 },
 214         {"Windows IA64",         SPL_ARCH_IA64,         3 },
 215         {"Windows x64",          SPL_ARCH_X64,          3 },
 216         {NULL,                   "",            -1 }
 217 };
 218 
 219 
 220 /****************************************************************************
 221  generate a new TDB_DATA key for storing a printer
 222 ****************************************************************************/
 223 
 224 static TDB_DATA make_printer_tdbkey(TALLOC_CTX *ctx, const char *sharename )
     /* [<][>][^][v][top][bottom][index][help] */
 225 {
 226         fstring share;
 227         char *keystr = NULL;
 228         TDB_DATA key;
 229 
 230         fstrcpy(share, sharename);
 231         strlower_m(share);
 232 
 233         keystr = talloc_asprintf(ctx, "%s%s", PRINTERS_PREFIX, share);
 234         key = string_term_tdb_data(keystr ? keystr : "");
 235 
 236         return key;
 237 }
 238 
 239 /****************************************************************************
 240  generate a new TDB_DATA key for storing a printer security descriptor
 241 ****************************************************************************/
 242 
 243 static TDB_DATA make_printers_secdesc_tdbkey(TALLOC_CTX *ctx,
     /* [<][>][^][v][top][bottom][index][help] */
 244                                         const char* sharename  )
 245 {
 246         fstring share;
 247         char *keystr = NULL;
 248         TDB_DATA key;
 249 
 250         fstrcpy(share, sharename );
 251         strlower_m(share);
 252 
 253         keystr = talloc_asprintf(ctx, "%s%s", SECDESC_PREFIX, share);
 254         key = string_term_tdb_data(keystr ? keystr : "");
 255 
 256         return key;
 257 }
 258 
 259 /****************************************************************************
 260 ****************************************************************************/
 261 
 262 static bool upgrade_to_version_3(void)
     /* [<][>][^][v][top][bottom][index][help] */
 263 {
 264         TDB_DATA kbuf, newkey, dbuf;
 265 
 266         DEBUG(0,("upgrade_to_version_3: upgrading print tdb's to version 3\n"));
 267 
 268         for (kbuf = tdb_firstkey(tdb_drivers); kbuf.dptr;
 269                         newkey = tdb_nextkey(tdb_drivers, kbuf), free(kbuf.dptr), kbuf=newkey) {
 270 
 271                 dbuf = tdb_fetch(tdb_drivers, kbuf);
 272 
 273                 if (strncmp((const char *)kbuf.dptr, FORMS_PREFIX, strlen(FORMS_PREFIX)) == 0) {
 274                         DEBUG(0,("upgrade_to_version_3:moving form\n"));
 275                         if (tdb_store(tdb_forms, kbuf, dbuf, TDB_REPLACE) != 0) {
 276                                 SAFE_FREE(dbuf.dptr);
 277                                 DEBUG(0,("upgrade_to_version_3: failed to move form. Error (%s).\n", tdb_errorstr(tdb_forms)));
 278                                 return False;
 279                         }
 280                         if (tdb_delete(tdb_drivers, kbuf) != 0) {
 281                                 SAFE_FREE(dbuf.dptr);
 282                                 DEBUG(0,("upgrade_to_version_3: failed to delete form. Error (%s)\n", tdb_errorstr(tdb_drivers)));
 283                                 return False;
 284                         }
 285                 }
 286 
 287                 if (strncmp((const char *)kbuf.dptr, PRINTERS_PREFIX, strlen(PRINTERS_PREFIX)) == 0) {
 288                         DEBUG(0,("upgrade_to_version_3:moving printer\n"));
 289                         if (tdb_store(tdb_printers, kbuf, dbuf, TDB_REPLACE) != 0) {
 290                                 SAFE_FREE(dbuf.dptr);
 291                                 DEBUG(0,("upgrade_to_version_3: failed to move printer. Error (%s)\n", tdb_errorstr(tdb_printers)));
 292                                 return False;
 293                         }
 294                         if (tdb_delete(tdb_drivers, kbuf) != 0) {
 295                                 SAFE_FREE(dbuf.dptr);
 296                                 DEBUG(0,("upgrade_to_version_3: failed to delete printer. Error (%s)\n", tdb_errorstr(tdb_drivers)));
 297                                 return False;
 298                         }
 299                 }
 300 
 301                 if (strncmp((const char *)kbuf.dptr, SECDESC_PREFIX, strlen(SECDESC_PREFIX)) == 0) {
 302                         DEBUG(0,("upgrade_to_version_3:moving secdesc\n"));
 303                         if (tdb_store(tdb_printers, kbuf, dbuf, TDB_REPLACE) != 0) {
 304                                 SAFE_FREE(dbuf.dptr);
 305                                 DEBUG(0,("upgrade_to_version_3: failed to move secdesc. Error (%s)\n", tdb_errorstr(tdb_printers)));
 306                                 return False;
 307                         }
 308                         if (tdb_delete(tdb_drivers, kbuf) != 0) {
 309                                 SAFE_FREE(dbuf.dptr);
 310                                 DEBUG(0,("upgrade_to_version_3: failed to delete secdesc. Error (%s)\n", tdb_errorstr(tdb_drivers)));
 311                                 return False;
 312                         }
 313                 }
 314 
 315                 SAFE_FREE(dbuf.dptr);
 316         }
 317 
 318         return True;
 319 }
 320 
 321 /*******************************************************************
 322  Fix an issue with security descriptors.  Printer sec_desc must
 323  use more than the generic bits that were previously used
 324  in <= 3.0.14a.  They must also have a owner and group SID assigned.
 325  Otherwise, any printers than have been migrated to a Windows
 326  host using printmig.exe will not be accessible.
 327 *******************************************************************/
 328 
 329 static int sec_desc_upg_fn( TDB_CONTEXT *the_tdb, TDB_DATA key,
     /* [<][>][^][v][top][bottom][index][help] */
 330                             TDB_DATA data, void *state )
 331 {
 332         NTSTATUS status;
 333         SEC_DESC_BUF *sd_orig = NULL;
 334         SEC_DESC_BUF *sd_new, *sd_store;
 335         SEC_DESC *sec, *new_sec;
 336         TALLOC_CTX *ctx = state;
 337         int result, i;
 338         uint32 sd_size;
 339         size_t size_new_sec;
 340 
 341         if (!data.dptr || data.dsize == 0) {
 342                 return 0;
 343         }
 344 
 345         if ( strncmp((const char *) key.dptr, SECDESC_PREFIX, strlen(SECDESC_PREFIX) ) != 0 ) {
 346                 return 0;
 347         }
 348 
 349         /* upgrade the security descriptor */
 350 
 351         status = unmarshall_sec_desc_buf(ctx, data.dptr, data.dsize, &sd_orig);
 352         if (!NT_STATUS_IS_OK(status)) {
 353                 /* delete bad entries */
 354                 DEBUG(0,("sec_desc_upg_fn: Failed to parse original sec_desc for %si.  Deleting....\n",
 355                         (const char *)key.dptr ));
 356                 tdb_delete( tdb_printers, key );
 357                 return 0;
 358         }
 359 
 360         if (!sd_orig) {
 361                 return 0;
 362         }
 363         sec = sd_orig->sd;
 364 
 365         /* is this even valid? */
 366 
 367         if ( !sec->dacl ) {
 368                 return 0;
 369         }
 370 
 371         /* update access masks */
 372 
 373         for ( i=0; i<sec->dacl->num_aces; i++ ) {
 374                 switch ( sec->dacl->aces[i].access_mask ) {
 375                         case (GENERIC_READ_ACCESS | GENERIC_WRITE_ACCESS | GENERIC_EXECUTE_ACCESS):
 376                                 sec->dacl->aces[i].access_mask = PRINTER_ACE_PRINT;
 377                                 break;
 378 
 379                         case GENERIC_ALL_ACCESS:
 380                                 sec->dacl->aces[i].access_mask = PRINTER_ACE_FULL_CONTROL;
 381                                 break;
 382 
 383                         case READ_CONTROL_ACCESS:
 384                                 sec->dacl->aces[i].access_mask = PRINTER_ACE_MANAGE_DOCUMENTS;
 385 
 386                         default:        /* no change */
 387                                 break;
 388                 }
 389         }
 390 
 391         /* create a new SEC_DESC with the appropriate owner and group SIDs */
 392 
 393         new_sec = make_sec_desc( ctx, SEC_DESC_REVISION, SEC_DESC_SELF_RELATIVE,
 394                                  &global_sid_Builtin_Administrators,
 395                                  &global_sid_Builtin_Administrators,
 396                                  NULL, NULL, &size_new_sec );
 397         if (!new_sec) {
 398                 return 0;
 399         }
 400         sd_new = make_sec_desc_buf( ctx, size_new_sec, new_sec );
 401         if (!sd_new) {
 402                 return 0;
 403         }
 404 
 405         if ( !(sd_store = sec_desc_merge( ctx, sd_new, sd_orig )) ) {
 406                 DEBUG(0,("sec_desc_upg_fn: Failed to update sec_desc for %s\n", key.dptr ));
 407                 return 0;
 408         }
 409 
 410         /* store it back */
 411 
 412         sd_size = ndr_size_security_descriptor(sd_store->sd, NULL, 0)
 413                 + sizeof(SEC_DESC_BUF);
 414 
 415         status = marshall_sec_desc_buf(ctx, sd_store, &data.dptr, &data.dsize);
 416         if (!NT_STATUS_IS_OK(status)) {
 417                 DEBUG(0,("sec_desc_upg_fn: Failed to parse new sec_desc for %s\n", key.dptr ));
 418                 return 0;
 419         }
 420 
 421         result = tdb_store( tdb_printers, key, data, TDB_REPLACE );
 422 
 423         /* 0 to continue and non-zero to stop traversal */
 424 
 425         return (result == -1);
 426 }
 427 
 428 /*******************************************************************
 429 *******************************************************************/
 430 
 431 static bool upgrade_to_version_4(void)
     /* [<][>][^][v][top][bottom][index][help] */
 432 {
 433         TALLOC_CTX *ctx;
 434         int result;
 435 
 436         DEBUG(0,("upgrade_to_version_4: upgrading printer security descriptors\n"));
 437 
 438         if ( !(ctx = talloc_init( "upgrade_to_version_4" )) )
 439                 return False;
 440 
 441         result = tdb_traverse( tdb_printers, sec_desc_upg_fn, ctx );
 442 
 443         talloc_destroy( ctx );
 444 
 445         return ( result != -1 );
 446 }
 447 
 448 /*******************************************************************
 449  Fix an issue with security descriptors.  Printer sec_desc must
 450  use more than the generic bits that were previously used
 451  in <= 3.0.14a.  They must also have a owner and group SID assigned.
 452  Otherwise, any printers than have been migrated to a Windows
 453  host using printmig.exe will not be accessible.
 454 *******************************************************************/
 455 
 456 static int normalize_printers_fn( TDB_CONTEXT *the_tdb, TDB_DATA key,
     /* [<][>][^][v][top][bottom][index][help] */
 457                                   TDB_DATA data, void *state )
 458 {
 459         TALLOC_CTX *ctx = talloc_tos();
 460         TDB_DATA new_key;
 461 
 462         if (!data.dptr || data.dsize == 0)
 463                 return 0;
 464 
 465         /* upgrade printer records and security descriptors */
 466 
 467         if ( strncmp((const char *) key.dptr, PRINTERS_PREFIX, strlen(PRINTERS_PREFIX) ) == 0 ) {
 468                 new_key = make_printer_tdbkey(ctx, (const char *)key.dptr+strlen(PRINTERS_PREFIX) );
 469         }
 470         else if ( strncmp((const char *) key.dptr, SECDESC_PREFIX, strlen(SECDESC_PREFIX) ) == 0 ) {
 471                 new_key = make_printers_secdesc_tdbkey(ctx, (const char *)key.dptr+strlen(SECDESC_PREFIX) );
 472         }
 473         else {
 474                 /* ignore this record */
 475                 return 0;
 476         }
 477 
 478         /* delete the original record and store under the normalized key */
 479 
 480         if ( tdb_delete( the_tdb, key ) != 0 ) {
 481                 DEBUG(0,("normalize_printers_fn: tdb_delete for [%s] failed!\n",
 482                         key.dptr));
 483                 return 1;
 484         }
 485 
 486         if ( tdb_store( the_tdb, new_key, data, TDB_REPLACE) != 0 ) {
 487                 DEBUG(0,("normalize_printers_fn: failed to store new record for [%s]!\n",
 488                         key.dptr));
 489                 return 1;
 490         }
 491 
 492         return 0;
 493 }
 494 
 495 /*******************************************************************
 496 *******************************************************************/
 497 
 498 static bool upgrade_to_version_5(void)
     /* [<][>][^][v][top][bottom][index][help] */
 499 {
 500         TALLOC_CTX *ctx;
 501         int result;
 502 
 503         DEBUG(0,("upgrade_to_version_5: normalizing printer keys\n"));
 504 
 505         if ( !(ctx = talloc_init( "upgrade_to_version_5" )) )
 506                 return False;
 507 
 508         result = tdb_traverse( tdb_printers, normalize_printers_fn, NULL );
 509 
 510         talloc_destroy( ctx );
 511 
 512         return ( result != -1 );
 513 }
 514 
 515 /****************************************************************************
 516  Open the NT printing tdbs. Done once before fork().
 517 ****************************************************************************/
 518 
 519 bool nt_printing_init(struct messaging_context *msg_ctx)
     /* [<][>][^][v][top][bottom][index][help] */
 520 {
 521         const char *vstring = "INFO/version";
 522         WERROR win_rc;
 523         int32 vers_id;
 524 
 525         if ( tdb_drivers && tdb_printers && tdb_forms )
 526                 return True;
 527 
 528         if (tdb_drivers)
 529                 tdb_close(tdb_drivers);
 530         tdb_drivers = tdb_open_log(state_path("ntdrivers.tdb"), 0, TDB_DEFAULT, O_RDWR|O_CREAT, 0600);
 531         if (!tdb_drivers) {
 532                 DEBUG(0,("nt_printing_init: Failed to open nt drivers database %s (%s)\n",
 533                         state_path("ntdrivers.tdb"), strerror(errno) ));
 534                 return False;
 535         }
 536 
 537         if (tdb_printers)
 538                 tdb_close(tdb_printers);
 539         tdb_printers = tdb_open_log(state_path("ntprinters.tdb"), 0, TDB_DEFAULT, O_RDWR|O_CREAT, 0600);
 540         if (!tdb_printers) {
 541                 DEBUG(0,("nt_printing_init: Failed to open nt printers database %s (%s)\n",
 542                         state_path("ntprinters.tdb"), strerror(errno) ));
 543                 return False;
 544         }
 545 
 546         if (tdb_forms)
 547                 tdb_close(tdb_forms);
 548         tdb_forms = tdb_open_log(state_path("ntforms.tdb"), 0, TDB_DEFAULT, O_RDWR|O_CREAT, 0600);
 549         if (!tdb_forms) {
 550                 DEBUG(0,("nt_printing_init: Failed to open nt forms database %s (%s)\n",
 551                         state_path("ntforms.tdb"), strerror(errno) ));
 552                 return False;
 553         }
 554 
 555         /* handle a Samba upgrade */
 556 
 557         vers_id = tdb_fetch_int32(tdb_drivers, vstring);
 558         if (vers_id == -1) {
 559                 DEBUG(10, ("Fresh database\n"));
 560                 tdb_store_int32( tdb_drivers, vstring, NTDRIVERS_DATABASE_VERSION_5 );
 561                 vers_id = NTDRIVERS_DATABASE_VERSION_5;
 562         }
 563 
 564         if ( vers_id != NTDRIVERS_DATABASE_VERSION_5 ) {
 565 
 566                 if ((vers_id == NTDRIVERS_DATABASE_VERSION_1) || (IREV(vers_id) == NTDRIVERS_DATABASE_VERSION_1)) {
 567                         if (!upgrade_to_version_3())
 568                                 return False;
 569                         tdb_store_int32(tdb_drivers, vstring, NTDRIVERS_DATABASE_VERSION_3);
 570                         vers_id = NTDRIVERS_DATABASE_VERSION_3;
 571                 }
 572 
 573                 if ((vers_id == NTDRIVERS_DATABASE_VERSION_2) || (IREV(vers_id) == NTDRIVERS_DATABASE_VERSION_2)) {
 574                         /* Written on a bigendian machine with old fetch_int code. Save as le. */
 575                         /* The only upgrade between V2 and V3 is to save the version in little-endian. */
 576                         tdb_store_int32(tdb_drivers, vstring, NTDRIVERS_DATABASE_VERSION_3);
 577                         vers_id = NTDRIVERS_DATABASE_VERSION_3;
 578                 }
 579 
 580                 if (vers_id == NTDRIVERS_DATABASE_VERSION_3 ) {
 581                         if ( !upgrade_to_version_4() )
 582                                 return False;
 583                         tdb_store_int32(tdb_drivers, vstring, NTDRIVERS_DATABASE_VERSION_4);
 584                         vers_id = NTDRIVERS_DATABASE_VERSION_4;
 585                 }
 586 
 587                 if (vers_id == NTDRIVERS_DATABASE_VERSION_4 ) {
 588                         if ( !upgrade_to_version_5() )
 589                                 return False;
 590                         tdb_store_int32(tdb_drivers, vstring, NTDRIVERS_DATABASE_VERSION_5);
 591                         vers_id = NTDRIVERS_DATABASE_VERSION_5;
 592                 }
 593 
 594 
 595                 if ( vers_id != NTDRIVERS_DATABASE_VERSION_5 ) {
 596                         DEBUG(0,("nt_printing_init: Unknown printer database version [%d]\n", vers_id));
 597                         return False;
 598                 }
 599         }
 600 
 601         update_c_setprinter(True);
 602 
 603         /*
 604          * register callback to handle updating printers as new
 605          * drivers are installed
 606          */
 607 
 608         messaging_register(msg_ctx, NULL, MSG_PRINTER_DRVUPGRADE,
 609                            do_drv_upgrade_printer);
 610 
 611         /*
 612          * register callback to handle updating printer data
 613          * when a driver is initialized
 614          */
 615 
 616         messaging_register(msg_ctx, NULL, MSG_PRINTERDATA_INIT_RESET,
 617                            reset_all_printerdata);
 618 
 619         /* of course, none of the message callbacks matter if you don't
 620            tell messages.c that you interested in receiving PRINT_GENERAL
 621            msgs.  This is done in claim_connection() */
 622 
 623 
 624         if ( lp_security() == SEC_ADS ) {
 625                 win_rc = check_published_printers();
 626                 if (!W_ERROR_IS_OK(win_rc))
 627                         DEBUG(0, ("nt_printing_init: error checking published printers: %s\n", win_errstr(win_rc)));
 628         }
 629 
 630         return True;
 631 }
 632 
 633 /*******************************************************************
 634  Function to allow filename parsing "the old way".
 635 ********************************************************************/
 636 
 637 static char *driver_unix_convert(connection_struct *conn,
     /* [<][>][^][v][top][bottom][index][help] */
 638                 const char *old_name,
 639                 SMB_STRUCT_STAT *pst)
 640 {
 641         TALLOC_CTX *ctx = talloc_tos();
 642         char *name = talloc_strdup(ctx, old_name);
 643         char *new_name = NULL;
 644 
 645         if (!name) {
 646                 return NULL;
 647         }
 648         unix_format(name);
 649         name = unix_clean_name(ctx, name);
 650         if (!name) {
 651                 return NULL;
 652         }
 653         trim_string(name,"/","/");
 654         unix_convert(ctx,conn, name, false, &new_name, NULL, pst);
 655         return new_name;
 656 }
 657 
 658 /*******************************************************************
 659  tdb traversal function for counting printers.
 660 ********************************************************************/
 661 
 662 static int traverse_counting_printers(TDB_CONTEXT *t, TDB_DATA key,
     /* [<][>][^][v][top][bottom][index][help] */
 663                                       TDB_DATA data, void *context)
 664 {
 665         int *printer_count = (int*)context;
 666 
 667         if (memcmp(PRINTERS_PREFIX, key.dptr, sizeof(PRINTERS_PREFIX)-1) == 0) {
 668                 (*printer_count)++;
 669                 DEBUG(10,("traverse_counting_printers: printer = [%s]  printer_count = %d\n", key.dptr, *printer_count));
 670         }
 671 
 672         return 0;
 673 }
 674 
 675 /*******************************************************************
 676  Update the spooler global c_setprinter. This variable is initialized
 677  when the parent smbd starts with the number of existing printers. It
 678  is monotonically increased by the current number of printers *after*
 679  each add or delete printer RPC. Only Microsoft knows why... JRR020119
 680 ********************************************************************/
 681 
 682 uint32 update_c_setprinter(bool initialize)
     /* [<][>][^][v][top][bottom][index][help] */
 683 {
 684         int32 c_setprinter;
 685         int32 printer_count = 0;
 686 
 687         tdb_lock_bystring(tdb_printers, GLOBAL_C_SETPRINTER);
 688 
 689         /* Traverse the tdb, counting the printers */
 690         tdb_traverse(tdb_printers, traverse_counting_printers, (void *)&printer_count);
 691 
 692         /* If initializing, set c_setprinter to current printers count
 693          * otherwise, bump it by the current printer count
 694          */
 695         if (!initialize)
 696                 c_setprinter = tdb_fetch_int32(tdb_printers, GLOBAL_C_SETPRINTER) + printer_count;
 697         else
 698                 c_setprinter = printer_count;
 699 
 700         DEBUG(10,("update_c_setprinter: c_setprinter = %u\n", (unsigned int)c_setprinter));
 701         tdb_store_int32(tdb_printers, GLOBAL_C_SETPRINTER, c_setprinter);
 702 
 703         tdb_unlock_bystring(tdb_printers, GLOBAL_C_SETPRINTER);
 704 
 705         return (uint32)c_setprinter;
 706 }
 707 
 708 /*******************************************************************
 709  Get the spooler global c_setprinter, accounting for initialization.
 710 ********************************************************************/
 711 
 712 uint32 get_c_setprinter(void)
     /* [<][>][^][v][top][bottom][index][help] */
 713 {
 714         int32 c_setprinter = tdb_fetch_int32(tdb_printers, GLOBAL_C_SETPRINTER);
 715 
 716         if (c_setprinter == (int32)-1)
 717                 c_setprinter = update_c_setprinter(True);
 718 
 719         DEBUG(10,("get_c_setprinter: c_setprinter = %d\n", c_setprinter));
 720 
 721         return (uint32)c_setprinter;
 722 }
 723 
 724 /****************************************************************************
 725  Get builtin form struct list.
 726 ****************************************************************************/
 727 
 728 int get_builtin_ntforms(nt_forms_struct **list)
     /* [<][>][^][v][top][bottom][index][help] */
 729 {
 730         *list = (nt_forms_struct *)memdup(&default_forms[0], sizeof(default_forms));
 731         if (!*list) {
 732                 return 0;
 733         }
 734         return ARRAY_SIZE(default_forms);
 735 }
 736 
 737 /****************************************************************************
 738  get a builtin form struct
 739 ****************************************************************************/
 740 
 741 bool get_a_builtin_ntform_by_string(const char *form_name, nt_forms_struct *form)
     /* [<][>][^][v][top][bottom][index][help] */
 742 {
 743         int i;
 744         DEBUGADD(6,("Looking for builtin form %s \n", form_name));
 745         for (i=0; i<ARRAY_SIZE(default_forms); i++) {
 746                 if (strequal(form_name,default_forms[i].name)) {
 747                         DEBUGADD(6,("Found builtin form %s \n", form_name));
 748                         memcpy(form,&default_forms[i],sizeof(*form));
 749                         return true;
 750                 }
 751         }
 752 
 753         return false;
 754 }
 755 
 756 /****************************************************************************
 757  get a form struct list.
 758 ****************************************************************************/
 759 
 760 int get_ntforms(nt_forms_struct **list)
     /* [<][>][^][v][top][bottom][index][help] */
 761 {
 762         TDB_DATA kbuf, newkey, dbuf;
 763         nt_forms_struct form;
 764         int ret;
 765         int i;
 766         int n = 0;
 767 
 768         *list = NULL;
 769 
 770         for (kbuf = tdb_firstkey(tdb_forms);
 771              kbuf.dptr;
 772              newkey = tdb_nextkey(tdb_forms, kbuf), free(kbuf.dptr), kbuf=newkey)
 773         {
 774                 if (strncmp((const char *)kbuf.dptr, FORMS_PREFIX, strlen(FORMS_PREFIX)) != 0)
 775                         continue;
 776 
 777                 dbuf = tdb_fetch(tdb_forms, kbuf);
 778                 if (!dbuf.dptr)
 779                         continue;
 780 
 781                 fstrcpy(form.name, (const char *)kbuf.dptr+strlen(FORMS_PREFIX));
 782                 ret = tdb_unpack(dbuf.dptr, dbuf.dsize, "dddddddd",
 783                                  &i, &form.flag, &form.width, &form.length, &form.left,
 784                                  &form.top, &form.right, &form.bottom);
 785                 SAFE_FREE(dbuf.dptr);
 786                 if (ret != dbuf.dsize)
 787                         continue;
 788 
 789                 *list = SMB_REALLOC_ARRAY(*list, nt_forms_struct, n+1);
 790                 if (!*list) {
 791                         DEBUG(0,("get_ntforms: Realloc fail.\n"));
 792                         return 0;
 793                 }
 794                 (*list)[n] = form;
 795                 n++;
 796         }
 797 
 798 
 799         return n;
 800 }
 801 
 802 /****************************************************************************
 803 write a form struct list
 804 ****************************************************************************/
 805 
 806 int write_ntforms(nt_forms_struct **list, int number)
     /* [<][>][^][v][top][bottom][index][help] */
 807 {
 808         TALLOC_CTX *ctx = talloc_tos();
 809         char *buf = NULL;
 810         char *key = NULL;
 811         int len;
 812         TDB_DATA dbuf;
 813         int i;
 814 
 815         for (i=0;i<number;i++) {
 816                 /* save index, so list is rebuilt in correct order */
 817                 len = tdb_pack(NULL, 0, "dddddddd",
 818                                i, (*list)[i].flag, (*list)[i].width, (*list)[i].length,
 819                                (*list)[i].left, (*list)[i].top, (*list)[i].right,
 820                                (*list)[i].bottom);
 821                 if (!len) {
 822                         continue;
 823                 }
 824                 buf = TALLOC_ARRAY(ctx, char, len);
 825                 if (!buf) {
 826                         return 0;
 827                 }
 828                 len = tdb_pack((uint8 *)buf, len, "dddddddd",
 829                                i, (*list)[i].flag, (*list)[i].width, (*list)[i].length,
 830                                (*list)[i].left, (*list)[i].top, (*list)[i].right,
 831                                (*list)[i].bottom);
 832                 key = talloc_asprintf(ctx, "%s%s", FORMS_PREFIX, (*list)[i].name);
 833                 if (!key) {
 834                         return 0;
 835                 }
 836                 dbuf.dsize = len;
 837                 dbuf.dptr = (uint8 *)buf;
 838                 if (tdb_store_bystring(tdb_forms, key, dbuf, TDB_REPLACE) != 0) {
 839                         TALLOC_FREE(key);
 840                         TALLOC_FREE(buf);
 841                         break;
 842                 }
 843                 TALLOC_FREE(key);
 844                 TALLOC_FREE(buf);
 845        }
 846 
 847        return i;
 848 }
 849 
 850 /****************************************************************************
 851 add a form struct at the end of the list
 852 ****************************************************************************/
 853 bool add_a_form(nt_forms_struct **list, struct spoolss_AddFormInfo1 *form, int *count)
     /* [<][>][^][v][top][bottom][index][help] */
 854 {
 855         int n=0;
 856         bool update;
 857 
 858         /*
 859          * NT tries to add forms even when
 860          * they are already in the base
 861          * only update the values if already present
 862          */
 863 
 864         update=False;
 865 
 866         for (n=0; n<*count; n++) {
 867                 if ( strequal((*list)[n].name, form->form_name) ) {
 868                         update=True;
 869                         break;
 870                 }
 871         }
 872 
 873         if (update==False) {
 874                 if((*list=SMB_REALLOC_ARRAY(*list, nt_forms_struct, n+1)) == NULL) {
 875                         DEBUG(0,("add_a_form: failed to enlarge forms list!\n"));
 876                         return False;
 877                 }
 878                 fstrcpy((*list)[n].name, form->form_name);
 879                 (*count)++;
 880         }
 881 
 882         (*list)[n].flag         = form->flags;
 883         (*list)[n].width        = form->size.width;
 884         (*list)[n].length       = form->size.height;
 885         (*list)[n].left         = form->area.left;
 886         (*list)[n].top          = form->area.top;
 887         (*list)[n].right        = form->area.right;
 888         (*list)[n].bottom       = form->area.bottom;
 889 
 890         DEBUG(6,("add_a_form: Successfully %s form [%s]\n",
 891                 update ? "updated" : "added", form->form_name));
 892 
 893         return True;
 894 }
 895 
 896 /****************************************************************************
 897  Delete a named form struct.
 898 ****************************************************************************/
 899 
 900 bool delete_a_form(nt_forms_struct **list, const char *del_name, int *count, WERROR *ret)
     /* [<][>][^][v][top][bottom][index][help] */
 901 {
 902         char *key = NULL;
 903         int n=0;
 904 
 905         *ret = WERR_OK;
 906 
 907         for (n=0; n<*count; n++) {
 908                 if (!strncmp((*list)[n].name, del_name, strlen(del_name))) {
 909                         DEBUG(103, ("delete_a_form, [%s] in list\n", del_name));
 910                         break;
 911                 }
 912         }
 913 
 914         if (n == *count) {
 915                 DEBUG(10,("delete_a_form, [%s] not found\n", del_name));
 916                 *ret = WERR_INVALID_PARAM;
 917                 return False;
 918         }
 919 
 920         if (asprintf(&key, "%s%s", FORMS_PREFIX, (*list)[n].name) < 0) {
 921                 *ret = WERR_NOMEM;
 922                 return false;
 923         }
 924         if (tdb_delete_bystring(tdb_forms, key) != 0) {
 925                 SAFE_FREE(key);
 926                 *ret = WERR_NOMEM;
 927                 return False;
 928         }
 929         SAFE_FREE(key);
 930         return true;
 931 }
 932 
 933 /****************************************************************************
 934  Update a form struct.
 935 ****************************************************************************/
 936 
 937 void update_a_form(nt_forms_struct **list, struct spoolss_AddFormInfo1 *form, int count)
     /* [<][>][^][v][top][bottom][index][help] */
 938 {
 939         int n=0;
 940 
 941         DEBUG(106, ("[%s]\n", form->form_name));
 942         for (n=0; n<count; n++) {
 943                 DEBUGADD(106, ("n [%d]:[%s]\n", n, (*list)[n].name));
 944                 if (!strncmp((*list)[n].name, form->form_name, strlen(form->form_name)))
 945                         break;
 946         }
 947 
 948         if (n==count) return;
 949 
 950         (*list)[n].flag         = form->flags;
 951         (*list)[n].width        = form->size.width;
 952         (*list)[n].length       = form->size.height;
 953         (*list)[n].left         = form->area.left;
 954         (*list)[n].top          = form->area.top;
 955         (*list)[n].right        = form->area.right;
 956         (*list)[n].bottom       = form->area.bottom;
 957 }
 958 
 959 /****************************************************************************
 960  Get the nt drivers list.
 961  Traverse the database and look-up the matching names.
 962 ****************************************************************************/
 963 int get_ntdrivers(fstring **list, const char *architecture, uint32 version)
     /* [<][>][^][v][top][bottom][index][help] */
 964 {
 965         int total=0;
 966         const char *short_archi;
 967         char *key = NULL;
 968         TDB_DATA kbuf, newkey;
 969 
 970         short_archi = get_short_archi(architecture);
 971         if (!short_archi) {
 972                 return 0;
 973         }
 974 
 975         if (asprintf(&key, "%s%s/%d/", DRIVERS_PREFIX,
 976                                 short_archi, version) < 0) {
 977                 return 0;
 978         }
 979 
 980         for (kbuf = tdb_firstkey(tdb_drivers);
 981              kbuf.dptr;
 982              newkey = tdb_nextkey(tdb_drivers, kbuf), free(kbuf.dptr), kbuf=newkey) {
 983 
 984                 if (strncmp((const char *)kbuf.dptr, key, strlen(key)) != 0)
 985                         continue;
 986 
 987                 if((*list = SMB_REALLOC_ARRAY(*list, fstring, total+1)) == NULL) {
 988                         DEBUG(0,("get_ntdrivers: failed to enlarge list!\n"));
 989                         SAFE_FREE(key);
 990                         return -1;
 991                 }
 992 
 993                 fstrcpy((*list)[total], (const char *)kbuf.dptr+strlen(key));
 994                 total++;
 995         }
 996 
 997         SAFE_FREE(key);
 998         return(total);
 999 }
1000 
1001 /****************************************************************************
1002  Function to do the mapping between the long architecture name and
1003  the short one.
1004 ****************************************************************************/
1005 
1006 const char *get_short_archi(const char *long_archi)
     /* [<][>][^][v][top][bottom][index][help] */
1007 {
1008         int i=-1;
1009 
1010         DEBUG(107,("Getting architecture dependant directory\n"));
1011         do {
1012                 i++;
1013         } while ( (archi_table[i].long_archi!=NULL ) &&
1014                   StrCaseCmp(long_archi, archi_table[i].long_archi) );
1015 
1016         if (archi_table[i].long_archi==NULL) {
1017                 DEBUGADD(10,("Unknown architecture [%s] !\n", long_archi));
1018                 return NULL;
1019         }
1020 
1021         /* this might be client code - but shouldn't this be an fstrcpy etc? */
1022 
1023         DEBUGADD(108,("index: [%d]\n", i));
1024         DEBUGADD(108,("long architecture: [%s]\n", archi_table[i].long_archi));
1025         DEBUGADD(108,("short architecture: [%s]\n", archi_table[i].short_archi));
1026 
1027         return archi_table[i].short_archi;
1028 }
1029 
1030 /****************************************************************************
1031  Version information in Microsoft files is held in a VS_VERSION_INFO structure.
1032  There are two case to be covered here: PE (Portable Executable) and NE (New
1033  Executable) files. Both files support the same INFO structure, but PE files
1034  store the signature in unicode, and NE files store it as !unicode.
1035  returns -1 on error, 1 on version info found, and 0 on no version info found.
1036 ****************************************************************************/
1037 
1038 static int get_file_version(files_struct *fsp, char *fname,uint32 *major, uint32 *minor)
     /* [<][>][^][v][top][bottom][index][help] */
1039 {
1040         int     i;
1041         char    *buf = NULL;
1042         ssize_t byte_count;
1043 
1044         if ((buf=(char *)SMB_MALLOC(DOS_HEADER_SIZE)) == NULL) {
1045                 DEBUG(0,("get_file_version: PE file [%s] DOS Header malloc failed bytes = %d\n",
1046                                 fname, DOS_HEADER_SIZE));
1047                 goto error_exit;
1048         }
1049 
1050         if ((byte_count = vfs_read_data(fsp, buf, DOS_HEADER_SIZE)) < DOS_HEADER_SIZE) {
1051                 DEBUG(3,("get_file_version: File [%s] DOS header too short, bytes read = %lu\n",
1052                          fname, (unsigned long)byte_count));
1053                 goto no_version_info;
1054         }
1055 
1056         /* Is this really a DOS header? */
1057         if (SVAL(buf,DOS_HEADER_MAGIC_OFFSET) != DOS_HEADER_MAGIC) {
1058                 DEBUG(6,("get_file_version: File [%s] bad DOS magic = 0x%x\n",
1059                                 fname, SVAL(buf,DOS_HEADER_MAGIC_OFFSET)));
1060                 goto no_version_info;
1061         }
1062 
1063         /* Skip OEM header (if any) and the DOS stub to start of Windows header */
1064         if (SMB_VFS_LSEEK(fsp, SVAL(buf,DOS_HEADER_LFANEW_OFFSET), SEEK_SET) == (SMB_OFF_T)-1) {
1065                 DEBUG(3,("get_file_version: File [%s] too short, errno = %d\n",
1066                                 fname, errno));
1067                 /* Assume this isn't an error... the file just looks sort of like a PE/NE file */
1068                 goto no_version_info;
1069         }
1070 
1071         /* Note: DOS_HEADER_SIZE and NE_HEADER_SIZE are incidentally same */
1072         if ((byte_count = vfs_read_data(fsp, buf, NE_HEADER_SIZE)) < NE_HEADER_SIZE) {
1073                 DEBUG(3,("get_file_version: File [%s] Windows header too short, bytes read = %lu\n",
1074                          fname, (unsigned long)byte_count));
1075                 /* Assume this isn't an error... the file just looks sort of like a PE/NE file */
1076                 goto no_version_info;
1077         }
1078 
1079         /* The header may be a PE (Portable Executable) or an NE (New Executable) */
1080         if (IVAL(buf,PE_HEADER_SIGNATURE_OFFSET) == PE_HEADER_SIGNATURE) {
1081                 unsigned int num_sections;
1082                 unsigned int section_table_bytes;
1083 
1084                 /* Just skip over optional header to get to section table */
1085                 if (SMB_VFS_LSEEK(fsp,
1086                                 SVAL(buf,PE_HEADER_OPTIONAL_HEADER_SIZE)-(NE_HEADER_SIZE-PE_HEADER_SIZE),
1087                                 SEEK_CUR) == (SMB_OFF_T)-1) {
1088                         DEBUG(3,("get_file_version: File [%s] Windows optional header too short, errno = %d\n",
1089                                 fname, errno));
1090                         goto error_exit;
1091                 }
1092 
1093                 /* get the section table */
1094                 num_sections        = SVAL(buf,PE_HEADER_NUMBER_OF_SECTIONS);
1095                 section_table_bytes = num_sections * PE_HEADER_SECT_HEADER_SIZE;
1096                 if (section_table_bytes == 0)
1097                         goto error_exit;
1098 
1099                 SAFE_FREE(buf);
1100                 if ((buf=(char *)SMB_MALLOC(section_table_bytes)) == NULL) {
1101                         DEBUG(0,("get_file_version: PE file [%s] section table malloc failed bytes = %d\n",
1102                                         fname, section_table_bytes));
1103                         goto error_exit;
1104                 }
1105 
1106                 if ((byte_count = vfs_read_data(fsp, buf, section_table_bytes)) < section_table_bytes) {
1107                         DEBUG(3,("get_file_version: PE file [%s] Section header too short, bytes read = %lu\n",
1108                                  fname, (unsigned long)byte_count));
1109                         goto error_exit;
1110                 }
1111 
1112                 /* Iterate the section table looking for the resource section ".rsrc" */
1113                 for (i = 0; i < num_sections; i++) {
1114                         int sec_offset = i * PE_HEADER_SECT_HEADER_SIZE;
1115 
1116                         if (strcmp(".rsrc", &buf[sec_offset+PE_HEADER_SECT_NAME_OFFSET]) == 0) {
1117                                 unsigned int section_pos   = IVAL(buf,sec_offset+PE_HEADER_SECT_PTR_DATA_OFFSET);
1118                                 unsigned int section_bytes = IVAL(buf,sec_offset+PE_HEADER_SECT_SIZE_DATA_OFFSET);
1119 
1120                                 if (section_bytes == 0)
1121                                         goto error_exit;
1122 
1123                                 SAFE_FREE(buf);
1124                                 if ((buf=(char *)SMB_MALLOC(section_bytes)) == NULL) {
1125                                         DEBUG(0,("get_file_version: PE file [%s] version malloc failed bytes = %d\n",
1126                                                         fname, section_bytes));
1127                                         goto error_exit;
1128                                 }
1129 
1130                                 /* Seek to the start of the .rsrc section info */
1131                                 if (SMB_VFS_LSEEK(fsp, section_pos, SEEK_SET) == (SMB_OFF_T)-1) {
1132                                         DEBUG(3,("get_file_version: PE file [%s] too short for section info, errno = %d\n",
1133                                                         fname, errno));
1134                                         goto error_exit;
1135                                 }
1136 
1137                                 if ((byte_count = vfs_read_data(fsp, buf, section_bytes)) < section_bytes) {
1138                                         DEBUG(3,("get_file_version: PE file [%s] .rsrc section too short, bytes read = %lu\n",
1139                                                  fname, (unsigned long)byte_count));
1140                                         goto error_exit;
1141                                 }
1142 
1143                                 if (section_bytes < VS_VERSION_INFO_UNICODE_SIZE)
1144                                         goto error_exit;
1145 
1146                                 for (i=0; i<section_bytes-VS_VERSION_INFO_UNICODE_SIZE; i++) {
1147                                         /* Scan for 1st 3 unicoded bytes followed by word aligned magic value */
1148                                         if (buf[i] == 'V' && buf[i+1] == '\0' && buf[i+2] == 'S') {
1149                                                 /* Align to next long address */
1150                                                 int pos = (i + sizeof(VS_SIGNATURE)*2 + 3) & 0xfffffffc;
1151 
1152                                                 if (IVAL(buf,pos) == VS_MAGIC_VALUE) {
1153                                                         *major = IVAL(buf,pos+VS_MAJOR_OFFSET);
1154                                                         *minor = IVAL(buf,pos+VS_MINOR_OFFSET);
1155 
1156                                                         DEBUG(6,("get_file_version: PE file [%s] Version = %08x:%08x (%d.%d.%d.%d)\n",
1157                                                                           fname, *major, *minor,
1158                                                                           (*major>>16)&0xffff, *major&0xffff,
1159                                                                           (*minor>>16)&0xffff, *minor&0xffff));
1160                                                         SAFE_FREE(buf);
1161                                                         return 1;
1162                                                 }
1163                                         }
1164                                 }
1165                         }
1166                 }
1167 
1168                 /* Version info not found, fall back to origin date/time */
1169                 DEBUG(10,("get_file_version: PE file [%s] has no version info\n", fname));
1170                 SAFE_FREE(buf);
1171                 return 0;
1172 
1173         } else if (SVAL(buf,NE_HEADER_SIGNATURE_OFFSET) == NE_HEADER_SIGNATURE) {
1174                 if (CVAL(buf,NE_HEADER_TARGET_OS_OFFSET) != NE_HEADER_TARGOS_WIN ) {
1175                         DEBUG(3,("get_file_version: NE file [%s] wrong target OS = 0x%x\n",
1176                                         fname, CVAL(buf,NE_HEADER_TARGET_OS_OFFSET)));
1177                         /* At this point, we assume the file is in error. It still could be somthing
1178                          * else besides a NE file, but it unlikely at this point. */
1179                         goto error_exit;
1180                 }
1181 
1182                 /* Allocate a bit more space to speed up things */
1183                 SAFE_FREE(buf);
1184                 if ((buf=(char *)SMB_MALLOC(VS_NE_BUF_SIZE)) == NULL) {
1185                         DEBUG(0,("get_file_version: NE file [%s] malloc failed bytes  = %d\n",
1186                                         fname, PE_HEADER_SIZE));
1187                         goto error_exit;
1188                 }
1189 
1190                 /* This is a HACK! I got tired of trying to sort through the messy
1191                  * 'NE' file format. If anyone wants to clean this up please have at
1192                  * it, but this works. 'NE' files will eventually fade away. JRR */
1193                 while((byte_count = vfs_read_data(fsp, buf, VS_NE_BUF_SIZE)) > 0) {
1194                         /* Cover case that should not occur in a well formed 'NE' .dll file */
1195                         if (byte_count-VS_VERSION_INFO_SIZE <= 0) break;
1196 
1197                         for(i=0; i<byte_count; i++) {
1198                                 /* Fast skip past data that can't possibly match */
1199                                 if (buf[i] != 'V') continue;
1200 
1201                                 /* Potential match data crosses buf boundry, move it to beginning
1202                                  * of buf, and fill the buf with as much as it will hold. */
1203                                 if (i>byte_count-VS_VERSION_INFO_SIZE) {
1204                                         int bc;
1205 
1206                                         memcpy(buf, &buf[i], byte_count-i);
1207                                         if ((bc = vfs_read_data(fsp, &buf[byte_count-i], VS_NE_BUF_SIZE-
1208                                                                    (byte_count-i))) < 0) {
1209 
1210                                                 DEBUG(0,("get_file_version: NE file [%s] Read error, errno=%d\n",
1211                                                                  fname, errno));
1212                                                 goto error_exit;
1213                                         }
1214 
1215                                         byte_count = bc + (byte_count - i);
1216                                         if (byte_count<VS_VERSION_INFO_SIZE) break;
1217 
1218                                         i = 0;
1219                                 }
1220 
1221                                 /* Check that the full signature string and the magic number that
1222                                  * follows exist (not a perfect solution, but the chances that this
1223                                  * occurs in code is, well, remote. Yes I know I'm comparing the 'V'
1224                                  * twice, as it is simpler to read the code. */
1225                                 if (strcmp(&buf[i], VS_SIGNATURE) == 0) {
1226                                         /* Compute skip alignment to next long address */
1227                                         int skip = -(SMB_VFS_LSEEK(fsp, 0, SEEK_CUR) - (byte_count - i) +
1228                                                                  sizeof(VS_SIGNATURE)) & 3;
1229                                         if (IVAL(buf,i+sizeof(VS_SIGNATURE)+skip) != 0xfeef04bd) continue;
1230 
1231                                         *major = IVAL(buf,i+sizeof(VS_SIGNATURE)+skip+VS_MAJOR_OFFSET);
1232                                         *minor = IVAL(buf,i+sizeof(VS_SIGNATURE)+skip+VS_MINOR_OFFSET);
1233                                         DEBUG(6,("get_file_version: NE file [%s] Version = %08x:%08x (%d.%d.%d.%d)\n",
1234                                                           fname, *major, *minor,
1235                                                           (*major>>16)&0xffff, *major&0xffff,
1236                                                           (*minor>>16)&0xffff, *minor&0xffff));
1237                                         SAFE_FREE(buf);
1238                                         return 1;
1239                                 }
1240                         }
1241                 }
1242 
1243                 /* Version info not found, fall back to origin date/time */
1244                 DEBUG(0,("get_file_version: NE file [%s] Version info not found\n", fname));
1245                 SAFE_FREE(buf);
1246                 return 0;
1247 
1248         } else
1249                 /* Assume this isn't an error... the file just looks sort of like a PE/NE file */
1250                 DEBUG(3,("get_file_version: File [%s] unknown file format, signature = 0x%x\n",
1251                                 fname, IVAL(buf,PE_HEADER_SIGNATURE_OFFSET)));
1252 
1253         no_version_info:
1254                 SAFE_FREE(buf);
1255                 return 0;
1256 
1257         error_exit:
1258                 SAFE_FREE(buf);
1259                 return -1;
1260 }
1261 
1262 /****************************************************************************
1263 Drivers for Microsoft systems contain multiple files. Often, multiple drivers
1264 share one or more files. During the MS installation process files are checked
1265 to insure that only a newer version of a shared file is installed over an
1266 older version. There are several possibilities for this comparison. If there
1267 is no previous version, the new one is newer (obviously). If either file is
1268 missing the version info structure, compare the creation date (on Unix use
1269 the modification date). Otherwise chose the numerically larger version number.
1270 ****************************************************************************/
1271 
1272 static int file_version_is_newer(connection_struct *conn, fstring new_file, fstring old_file)
     /* [<][>][^][v][top][bottom][index][help] */
1273 {
1274         bool use_version = true;
1275         char *filepath = NULL;
1276 
1277         uint32 new_major;
1278         uint32 new_minor;
1279         time_t new_create_time;
1280 
1281         uint32 old_major;
1282         uint32 old_minor;
1283         time_t old_create_time;
1284 
1285         files_struct    *fsp = NULL;
1286         SMB_STRUCT_STAT st;
1287         SMB_STRUCT_STAT stat_buf;
1288 
1289         NTSTATUS status;
1290 
1291         SET_STAT_INVALID(st);
1292         SET_STAT_INVALID(stat_buf);
1293         new_create_time = (time_t)0;
1294         old_create_time = (time_t)0;
1295 
1296         /* Get file version info (if available) for previous file (if it exists) */
1297         filepath = driver_unix_convert(conn,old_file,&stat_buf);
1298         if (!filepath) {
1299                 goto error_exit;
1300         }
1301 
1302         status = SMB_VFS_CREATE_FILE(
1303                 conn,                                   /* conn */
1304                 NULL,                                   /* req */
1305                 0,                                      /* root_dir_fid */
1306                 filepath,                               /* fname */
1307                 0,                                      /* create_file_flags */
1308                 FILE_GENERIC_READ,                      /* access_mask */
1309                 FILE_SHARE_READ | FILE_SHARE_WRITE,     /* share_access */
1310                 FILE_OPEN,                              /* create_disposition*/
1311                 0,                                      /* create_options */
1312                 FILE_ATTRIBUTE_NORMAL,                  /* file_attributes */
1313                 INTERNAL_OPEN_ONLY,                     /* oplock_request */
1314                 0,                                      /* allocation_size */
1315                 NULL,                                   /* sd */
1316                 NULL,                                   /* ea_list */
1317                 &fsp,                                   /* result */
1318                 NULL,                                   /* pinfo */
1319                 &stat_buf);                             /* psbuf */
1320 
1321         if (!NT_STATUS_IS_OK(status)) {
1322                 /* Old file not found, so by definition new file is in fact newer */
1323                 DEBUG(10,("file_version_is_newer: Can't open old file [%s], errno = %d\n",
1324                                 filepath, errno));
1325                 return 1;
1326 
1327         } else {
1328                 int ret = get_file_version(fsp, old_file, &old_major, &old_minor);
1329                 if (ret == -1) {
1330                         goto error_exit;
1331                 }
1332 
1333                 if (!ret) {
1334                         DEBUG(6,("file_version_is_newer: Version info not found [%s], use mod time\n",
1335                                          old_file));
1336                         use_version = false;
1337                         if (SMB_VFS_FSTAT(fsp, &st) == -1) {
1338                                  goto error_exit;
1339                         }
1340                         old_create_time = st.st_mtime;
1341                         DEBUGADD(6,("file_version_is_newer: mod time = %ld sec\n",
1342                                 (long)old_create_time));
1343                 }
1344         }
1345         close_file(NULL, fsp, NORMAL_CLOSE);
1346         fsp = NULL;
1347 
1348         /* Get file version info (if available) for new file */
1349         filepath = driver_unix_convert(conn,new_file,&stat_buf);
1350         if (!filepath) {
1351                 goto error_exit;
1352         }
1353 
1354         status = SMB_VFS_CREATE_FILE(
1355                 conn,                                   /* conn */
1356                 NULL,                                   /* req */
1357                 0,                                      /* root_dir_fid */
1358                 filepath,                               /* fname */
1359                 0,                                      /* create_file_flags */
1360                 FILE_GENERIC_READ,                      /* access_mask */
1361                 FILE_SHARE_READ | FILE_SHARE_WRITE,     /* share_access */
1362                 FILE_OPEN,                              /* create_disposition*/
1363                 0,                                      /* create_options */
1364                 FILE_ATTRIBUTE_NORMAL,                  /* file_attributes */
1365                 INTERNAL_OPEN_ONLY,                     /* oplock_request */
1366                 0,                                      /* allocation_size */
1367                 NULL,                                   /* sd */
1368                 NULL,                                   /* ea_list */
1369                 &fsp,                                   /* result */
1370                 NULL,                                   /* pinfo */
1371                 &stat_buf);                             /* psbuf */
1372 
1373         if (!NT_STATUS_IS_OK(status)) {
1374                 /* New file not found, this shouldn't occur if the caller did its job */
1375                 DEBUG(3,("file_version_is_newer: Can't open new file [%s], errno = %d\n",
1376                                 filepath, errno));
1377                 goto error_exit;
1378 
1379         } else {
1380                 int ret = get_file_version(fsp, new_file, &new_major, &new_minor);
1381                 if (ret == -1) {
1382                         goto error_exit;
1383                 }
1384 
1385                 if (!ret) {
1386                         DEBUG(6,("file_version_is_newer: Version info not found [%s], use mod time\n",
1387                                          new_file));
1388                         use_version = false;
1389                         if (SMB_VFS_FSTAT(fsp, &st) == -1) {
1390                                 goto error_exit;
1391                         }
1392                         new_create_time = st.st_mtime;
1393                         DEBUGADD(6,("file_version_is_newer: mod time = %ld sec\n",
1394                                 (long)new_create_time));
1395                 }
1396         }
1397         close_file(NULL, fsp, NORMAL_CLOSE);
1398         fsp = NULL;
1399 
1400         if (use_version && (new_major != old_major || new_minor != old_minor)) {
1401                 /* Compare versions and choose the larger version number */
1402                 if (new_major > old_major ||
1403                         (new_major == old_major && new_minor > old_minor)) {
1404 
1405                         DEBUG(6,("file_version_is_newer: Replacing [%s] with [%s]\n", old_file, new_file));
1406                         return 1;
1407                 }
1408                 else {
1409                         DEBUG(6,("file_version_is_newer: Leaving [%s] unchanged\n", old_file));
1410                         return 0;
1411                 }
1412 
1413         } else {
1414                 /* Compare modification time/dates and choose the newest time/date */
1415                 if (new_create_time > old_create_time) {
1416                         DEBUG(6,("file_version_is_newer: Replacing [%s] with [%s]\n", old_file, new_file));
1417                         return 1;
1418                 }
1419                 else {
1420                         DEBUG(6,("file_version_is_newer: Leaving [%s] unchanged\n", old_file));
1421                         return 0;
1422                 }
1423         }
1424 
1425         error_exit:
1426                 if(fsp)
1427                         close_file(NULL, fsp, NORMAL_CLOSE);
1428                 return -1;
1429 }
1430 
1431 /****************************************************************************
1432 Determine the correct cVersion associated with an architecture and driver
1433 ****************************************************************************/
1434 static uint32 get_correct_cversion(struct pipes_struct *p,
     /* [<][>][^][v][top][bottom][index][help] */
1435                                    const char *architecture,
1436                                    fstring driverpath_in,
1437                                    WERROR *perr)
1438 {
1439         int               cversion;
1440         NTSTATUS          nt_status;
1441         char *driverpath = NULL;
1442         files_struct      *fsp = NULL;
1443         SMB_STRUCT_STAT   st;
1444         connection_struct *conn = NULL;
1445         NTSTATUS status;
1446         char *oldcwd;
1447         fstring printdollar;
1448         int printdollar_snum;
1449 
1450         SET_STAT_INVALID(st);
1451 
1452         *perr = WERR_INVALID_PARAM;
1453 
1454         /* If architecture is Windows 95/98/ME, the version is always 0. */
1455         if (strcmp(architecture, SPL_ARCH_WIN40) == 0) {
1456                 DEBUG(10,("get_correct_cversion: Driver is Win9x, cversion = 0\n"));
1457                 *perr = WERR_OK;
1458                 return 0;
1459         }
1460 
1461         /* If architecture is Windows x64, the version is always 3. */
1462         if (strcmp(architecture, SPL_ARCH_X64) == 0) {
1463                 DEBUG(10,("get_correct_cversion: Driver is x64, cversion = 3\n"));
1464                 *perr = WERR_OK;
1465                 return 3;
1466         }
1467 
1468         fstrcpy(printdollar, "print$");
1469 
1470         printdollar_snum = find_service(printdollar);
1471         if (printdollar_snum == -1) {
1472                 *perr = WERR_NO_SUCH_SHARE;
1473                 return -1;
1474         }
1475 
1476         nt_status = create_conn_struct(talloc_tos(), &conn, printdollar_snum,
1477                                        lp_pathname(printdollar_snum),
1478                                        p->server_info, &oldcwd);
1479         if (!NT_STATUS_IS_OK(nt_status)) {
1480                 DEBUG(0,("get_correct_cversion: create_conn_struct "
1481                          "returned %s\n", nt_errstr(nt_status)));
1482                 *perr = ntstatus_to_werror(nt_status);
1483                 return -1;
1484         }
1485 
1486         /* Open the driver file (Portable Executable format) and determine the
1487          * deriver the cversion. */
1488         driverpath = talloc_asprintf(talloc_tos(),
1489                                         "%s/%s",
1490                                         architecture,
1491                                         driverpath_in);
1492         if (!driverpath) {
1493                 *perr = WERR_NOMEM;
1494                 goto error_exit;
1495         }
1496 
1497         driverpath = driver_unix_convert(conn,driverpath,&st);
1498         if (!driverpath) {
1499                 *perr = WERR_NOMEM;
1500                 goto error_exit;
1501         }
1502 
1503         if (!vfs_file_exist(conn, driverpath, &st)) {
1504                 *perr = WERR_BADFILE;
1505                 goto error_exit;
1506         }
1507 
1508         status = SMB_VFS_CREATE_FILE(
1509                 conn,                                   /* conn */
1510                 NULL,                                   /* req */
1511                 0,                                      /* root_dir_fid */
1512                 driverpath,                             /* fname */
1513                 0,                                      /* create_file_flags */
1514                 FILE_GENERIC_READ,                      /* access_mask */
1515                 FILE_SHARE_READ | FILE_SHARE_WRITE,     /* share_access */
1516                 FILE_OPEN,                              /* create_disposition*/
1517                 0,                                      /* create_options */
1518                 FILE_ATTRIBUTE_NORMAL,                  /* file_attributes */
1519                 INTERNAL_OPEN_ONLY,                     /* oplock_request */
1520                 0,                                      /* allocation_size */
1521                 NULL,                                   /* sd */
1522                 NULL,                                   /* ea_list */
1523                 &fsp,                                   /* result */
1524                 NULL,                                   /* pinfo */
1525                 &st);                                   /* psbuf */
1526 
1527         if (!NT_STATUS_IS_OK(status)) {
1528                 DEBUG(3,("get_correct_cversion: Can't open file [%s], errno = %d\n",
1529                                 driverpath, errno));
1530                 *perr = WERR_ACCESS_DENIED;
1531                 goto error_exit;
1532         } else {
1533                 uint32 major;
1534                 uint32 minor;
1535                 int    ret = get_file_version(fsp, driverpath, &major, &minor);
1536                 if (ret == -1) goto error_exit;
1537 
1538                 if (!ret) {
1539                         DEBUG(6,("get_correct_cversion: Version info not found [%s]\n", driverpath));
1540                         goto error_exit;
1541                 }
1542 
1543                 /*
1544                  * This is a Microsoft'ism. See references in MSDN to VER_FILEVERSION
1545                  * for more details. Version in this case is not just the version of the
1546                  * file, but the version in the sense of kernal mode (2) vs. user mode
1547                  * (3) drivers. Other bits of the version fields are the version info.
1548                  * JRR 010716
1549                 */
1550                 cversion = major & 0x0000ffff;
1551                 switch (cversion) {
1552                         case 2: /* WinNT drivers */
1553                         case 3: /* Win2K drivers */
1554                                 break;
1555 
1556                         default:
1557                                 DEBUG(6,("get_correct_cversion: cversion invalid [%s]  cversion = %d\n",
1558                                         driverpath, cversion));
1559                                 goto error_exit;
1560                 }
1561 
1562                 DEBUG(10,("get_correct_cversion: Version info found [%s]  major = 0x%x  minor = 0x%x\n",
1563                                   driverpath, major, minor));
1564         }
1565 
1566         DEBUG(10,("get_correct_cversion: Driver file [%s] cversion = %d\n",
1567                 driverpath, cversion));
1568 
1569         goto done;
1570 
1571  error_exit:
1572         cversion = -1;
1573  done:
1574         if (fsp != NULL) {
1575                 close_file(NULL, fsp, NORMAL_CLOSE);
1576         }
1577         if (conn != NULL) {
1578                 vfs_ChDir(conn, oldcwd);
1579                 conn_free_internal(conn);
1580         }
1581         if (cversion != -1) {
1582                 *perr = WERR_OK;
1583         }
1584         return cversion;
1585 }
1586 
1587 /****************************************************************************
1588 ****************************************************************************/
1589 static WERROR clean_up_driver_struct_level_3(struct pipes_struct *rpc_pipe,
     /* [<][>][^][v][top][bottom][index][help] */
1590                                              NT_PRINTER_DRIVER_INFO_LEVEL_3 *driver)
1591 {
1592         const char *architecture;
1593         fstring new_name;
1594         char *p;
1595         int i;
1596         WERROR err;
1597 
1598         /* clean up the driver name.
1599          * we can get .\driver.dll
1600          * or worse c:\windows\system\driver.dll !
1601          */
1602         /* using an intermediate string to not have overlaping memcpy()'s */
1603         if ((p = strrchr(driver->driverpath,'\\')) != NULL) {
1604                 fstrcpy(new_name, p+1);
1605                 fstrcpy(driver->driverpath, new_name);
1606         }
1607 
1608         if ((p = strrchr(driver->datafile,'\\')) != NULL) {
1609                 fstrcpy(new_name, p+1);
1610                 fstrcpy(driver->datafile, new_name);
1611         }
1612 
1613         if ((p = strrchr(driver->configfile,'\\')) != NULL) {
1614                 fstrcpy(new_name, p+1);
1615                 fstrcpy(driver->configfile, new_name);
1616         }
1617 
1618         if ((p = strrchr(driver->helpfile,'\\')) != NULL) {
1619                 fstrcpy(new_name, p+1);
1620                 fstrcpy(driver->helpfile, new_name);
1621         }
1622 
1623         if (driver->dependentfiles) {
1624                 for (i=0; *driver->dependentfiles[i]; i++) {
1625                         if ((p = strrchr(driver->dependentfiles[i],'\\')) != NULL) {
1626                                 fstrcpy(new_name, p+1);
1627                                 fstrcpy(driver->dependentfiles[i], new_name);
1628                         }
1629                 }
1630         }
1631 
1632         architecture = get_short_archi(driver->environment);
1633         if (!architecture) {
1634                 return WERR_UNKNOWN_PRINTER_DRIVER;
1635         }
1636 
1637         /* jfm:7/16/2000 the client always sends the cversion=0.
1638          * The server should check which version the driver is by reading
1639          * the PE header of driver->driverpath.
1640          *
1641          * For Windows 95/98 the version is 0 (so the value sent is correct)
1642          * For Windows NT (the architecture doesn't matter)
1643          *      NT 3.1: cversion=0
1644          *      NT 3.5/3.51: cversion=1
1645          *      NT 4: cversion=2
1646          *      NT2K: cversion=3
1647          */
1648         if ((driver->cversion = get_correct_cversion(rpc_pipe, architecture,
1649                                                      driver->driverpath,
1650                                                      &err)) == -1)
1651                 return err;
1652 
1653         return WERR_OK;
1654 }
1655 
1656 /****************************************************************************
1657 ****************************************************************************/
1658 static WERROR clean_up_driver_struct_level_6(struct pipes_struct *rpc_pipe,
     /* [<][>][^][v][top][bottom][index][help] */
1659                                              NT_PRINTER_DRIVER_INFO_LEVEL_6 *driver)
1660 {
1661         const char *architecture;
1662         fstring new_name;
1663         char *p;
1664         int i;
1665         WERROR err;
1666 
1667         /* clean up the driver name.
1668          * we can get .\driver.dll
1669          * or worse c:\windows\system\driver.dll !
1670          */
1671         /* using an intermediate string to not have overlaping memcpy()'s */
1672         if ((p = strrchr(driver->driverpath,'\\')) != NULL) {
1673                 fstrcpy(new_name, p+1);
1674                 fstrcpy(driver->driverpath, new_name);
1675         }
1676 
1677         if ((p = strrchr(driver->datafile,'\\')) != NULL) {
1678                 fstrcpy(new_name, p+1);
1679                 fstrcpy(driver->datafile, new_name);
1680         }
1681 
1682         if ((p = strrchr(driver->configfile,'\\')) != NULL) {
1683                 fstrcpy(new_name, p+1);
1684                 fstrcpy(driver->configfile, new_name);
1685         }
1686 
1687         if ((p = strrchr(driver->helpfile,'\\')) != NULL) {
1688                 fstrcpy(new_name, p+1);
1689                 fstrcpy(driver->helpfile, new_name);
1690         }
1691 
1692         if (driver->dependentfiles) {
1693                 for (i=0; *driver->dependentfiles[i]; i++) {
1694                         if ((p = strrchr(driver->dependentfiles[i],'\\')) != NULL) {
1695                                 fstrcpy(new_name, p+1);
1696                                 fstrcpy(driver->dependentfiles[i], new_name);
1697                         }
1698                 }
1699         }
1700 
1701         architecture = get_short_archi(driver->environment);
1702         if (!architecture) {
1703                 return WERR_UNKNOWN_PRINTER_DRIVER;
1704         }
1705 
1706         /* jfm:7/16/2000 the client always sends the cversion=0.
1707          * The server should check which version the driver is by reading
1708          * the PE header of driver->driverpath.
1709          *
1710          * For Windows 95/98 the version is 0 (so the value sent is correct)
1711          * For Windows NT (the architecture doesn't matter)
1712          *      NT 3.1: cversion=0
1713          *      NT 3.5/3.51: cversion=1
1714          *      NT 4: cversion=2
1715          *      NT2K: cversion=3
1716          */
1717 
1718         if ((driver->version = get_correct_cversion(rpc_pipe, architecture,
1719                                                     driver->driverpath,
1720                                                     &err)) == -1)
1721                         return err;
1722 
1723         return WERR_OK;
1724 }
1725 
1726 /****************************************************************************
1727 ****************************************************************************/
1728 WERROR clean_up_driver_struct(struct pipes_struct *rpc_pipe,
     /* [<][>][^][v][top][bottom][index][help] */
1729                               NT_PRINTER_DRIVER_INFO_LEVEL driver_abstract,
1730                               uint32 level)
1731 {
1732         switch (level) {
1733                 case 3:
1734                 {
1735                         NT_PRINTER_DRIVER_INFO_LEVEL_3 *driver;
1736                         driver=driver_abstract.info_3;
1737                         return clean_up_driver_struct_level_3(rpc_pipe,
1738                                                               driver);
1739                 }
1740                 case 6:
1741                 {
1742                         NT_PRINTER_DRIVER_INFO_LEVEL_6 *driver;
1743                         driver=driver_abstract.info_6;
1744                         return clean_up_driver_struct_level_6(rpc_pipe,
1745                                                               driver);
1746                 }
1747                 default:
1748                         return WERR_INVALID_PARAM;
1749         }
1750 }
1751 
1752 /****************************************************************************
1753  This function sucks and should be replaced. JRA.
1754 ****************************************************************************/
1755 
1756 static void convert_level_6_to_level3(NT_PRINTER_DRIVER_INFO_LEVEL_3 *dst, NT_PRINTER_DRIVER_INFO_LEVEL_6 *src)
     /* [<][>][^][v][top][bottom][index][help] */
1757 {
1758     dst->cversion  = src->version;
1759 
1760     fstrcpy( dst->name, src->name);
1761     fstrcpy( dst->environment, src->environment);
1762     fstrcpy( dst->driverpath, src->driverpath);
1763     fstrcpy( dst->datafile, src->datafile);
1764     fstrcpy( dst->configfile, src->configfile);
1765     fstrcpy( dst->helpfile, src->helpfile);
1766     fstrcpy( dst->monitorname, src->monitorname);
1767     fstrcpy( dst->defaultdatatype, src->defaultdatatype);
1768     dst->dependentfiles = src->dependentfiles;
1769 }
1770 
1771 #if 0 /* Debugging function */
1772 
1773 static char* ffmt(unsigned char *c){
     /* [<][>][^][v][top][bottom][index][help] */
1774         int i;
1775         static char ffmt_str[17];
1776 
1777         for (i=0; i<16; i++) {
1778                 if ((c[i] < ' ') || (c[i] > '~'))
1779                         ffmt_str[i]='.';
1780                 else
1781                         ffmt_str[i]=c[i];
1782         }
1783     ffmt_str[16]='\0';
1784         return ffmt_str;
1785 }
1786 
1787 #endif
1788 
1789 /****************************************************************************
1790 ****************************************************************************/
1791 
1792 static WERROR move_driver_file_to_download_area(TALLOC_CTX *mem_ctx,
     /* [<][>][^][v][top][bottom][index][help] */
1793                                                 connection_struct *conn,
1794                                                 const char *driver_file,
1795                                                 const char *short_architecture,
1796                                                 uint32_t driver_version,
1797                                                 uint32_t version)
1798 {
1799         char *old_name = NULL;
1800         char *new_name = NULL;
1801         SMB_STRUCT_STAT st;
1802         NTSTATUS status;
1803 
1804         old_name = talloc_asprintf(mem_ctx, "%s/%s",
1805                                    short_architecture, driver_file);
1806         W_ERROR_HAVE_NO_MEMORY(old_name);
1807 
1808         new_name = talloc_asprintf(mem_ctx, "%s/%d/%s",
1809                                    short_architecture, driver_version, driver_file);
1810         W_ERROR_HAVE_NO_MEMORY(new_name);
1811 
1812         if (version != -1 && (version = file_version_is_newer(conn, old_name, new_name)) > 0) {
1813 
1814                 old_name = driver_unix_convert(conn, old_name, &st);
1815                 W_ERROR_HAVE_NO_MEMORY(old_name);
1816 
1817                 DEBUG(10,("move_driver_file_to_download_area: copying '%s' to '%s'\n",
1818                         old_name, new_name));
1819 
1820                 status = copy_file(mem_ctx, conn, old_name, new_name,
1821                                    OPENX_FILE_EXISTS_TRUNCATE |
1822                                    OPENX_FILE_CREATE_IF_NOT_EXIST,
1823                                    0, false);
1824 
1825                 if (!NT_STATUS_IS_OK(status)) {
1826                         DEBUG(0,("move_driver_file_to_download_area: Unable to rename [%s] to [%s]: %s\n",
1827                                 old_name, new_name, nt_errstr(status)));
1828                         return WERR_ACCESS_DENIED;
1829                 }
1830         }
1831 
1832         return WERR_OK;
1833 }
1834 
1835 WERROR move_driver_to_download_area(struct pipes_struct *p,
     /* [<][>][^][v][top][bottom][index][help] */
1836                                     NT_PRINTER_DRIVER_INFO_LEVEL driver_abstract,
1837                                     uint32 level, WERROR *perr)
1838 {
1839         NT_PRINTER_DRIVER_INFO_LEVEL_3 *driver;
1840         NT_PRINTER_DRIVER_INFO_LEVEL_3 converted_driver;
1841         const char *short_architecture;
1842         char *new_dir = NULL;
1843         connection_struct *conn = NULL;
1844         NTSTATUS nt_status;
1845         SMB_STRUCT_STAT st;
1846         int i;
1847         TALLOC_CTX *ctx = talloc_tos();
1848         int ver = 0;
1849         char *oldcwd;
1850         fstring printdollar;
1851         int printdollar_snum;
1852 
1853         *perr = WERR_OK;
1854 
1855         switch (level) {
1856         case 3:
1857                 driver = driver_abstract.info_3;
1858                 break;
1859         case 6:
1860                 convert_level_6_to_level3(&converted_driver, driver_abstract.info_6);
1861                 driver = &converted_driver;
1862                 break;
1863         default:
1864                 DEBUG(0,("move_driver_to_download_area: Unknown info level (%u)\n", (unsigned int)level ));
1865                 return WERR_UNKNOWN_LEVEL;
1866         }
1867 
1868         short_architecture = get_short_archi(driver->environment);
1869         if (!short_architecture) {
1870                 return WERR_UNKNOWN_PRINTER_DRIVER;
1871         }
1872 
1873         fstrcpy(printdollar, "print$");
1874 
1875         printdollar_snum = find_service(printdollar);
1876         if (printdollar_snum == -1) {
1877                 *perr = WERR_NO_SUCH_SHARE;
1878                 return WERR_NO_SUCH_SHARE;
1879         }
1880 
1881         nt_status = create_conn_struct(talloc_tos(), &conn, printdollar_snum,
1882                                        lp_pathname(printdollar_snum),
1883                                        p->server_info, &oldcwd);
1884         if (!NT_STATUS_IS_OK(nt_status)) {
1885                 DEBUG(0,("move_driver_to_download_area: create_conn_struct "
1886                          "returned %s\n", nt_errstr(nt_status)));
1887                 *perr = ntstatus_to_werror(nt_status);
1888                 return *perr;
1889         }
1890 
1891         new_dir = talloc_asprintf(ctx,
1892                                 "%s/%d",
1893                                 short_architecture,
1894                                 driver->cversion);
1895         if (!new_dir) {
1896                 *perr = WERR_NOMEM;
1897                 goto err_exit;
1898         }
1899         new_dir = driver_unix_convert(conn,new_dir,&st);
1900         if (!new_dir) {
1901                 *perr = WERR_NOMEM;
1902                 goto err_exit;
1903         }
1904 
1905         DEBUG(5,("Creating first directory: %s\n", new_dir));
1906 
1907         create_directory(conn, NULL, new_dir);
1908 
1909         /* For each driver file, archi\filexxx.yyy, if there is a duplicate file
1910          * listed for this driver which has already been moved, skip it (note:
1911          * drivers may list the same file name several times. Then check if the
1912          * file already exists in archi\cversion\, if so, check that the version
1913          * info (or time stamps if version info is unavailable) is newer (or the
1914          * date is later). If it is, move it to archi\cversion\filexxx.yyy.
1915          * Otherwise, delete the file.
1916          *
1917          * If a file is not moved to archi\cversion\ because of an error, all the
1918          * rest of the 'unmoved' driver files are removed from archi\. If one or
1919          * more of the driver's files was already moved to archi\cversion\, it
1920          * potentially leaves the driver in a partially updated state. Version
1921          * trauma will most likely occur if an client attempts to use any printer
1922          * bound to the driver. Perhaps a rewrite to make sure the moves can be
1923          * done is appropriate... later JRR
1924          */
1925 
1926         DEBUG(5,("Moving files now !\n"));
1927 
1928         if (driver->driverpath && strlen(driver->driverpath)) {
1929 
1930                 *perr = move_driver_file_to_download_area(ctx,
1931                                                           conn,
1932                                                           driver->driverpath,
1933                                                           short_architecture,
1934                                                           driver->cversion,
1935                                                           ver);
1936                 if (!W_ERROR_IS_OK(*perr)) {
1937                         if (W_ERROR_EQUAL(*perr, WERR_ACCESS_DENIED)) {
1938                                 ver = -1;
1939                         }
1940                         goto err_exit;
1941                 }
1942         }
1943 
1944         if (driver->datafile && strlen(driver->datafile)) {
1945                 if (!strequal(driver->datafile, driver->driverpath)) {
1946 
1947                         *perr = move_driver_file_to_download_area(ctx,
1948                                                                   conn,
1949                                                                   driver->datafile,
1950                                                                   short_architecture,
1951                                                                   driver->cversion,
1952                                                                   ver);
1953                         if (!W_ERROR_IS_OK(*perr)) {
1954                                 if (W_ERROR_EQUAL(*perr, WERR_ACCESS_DENIED)) {
1955                                         ver = -1;
1956                                 }
1957                                 goto err_exit;
1958                         }
1959                 }
1960         }
1961 
1962         if (driver->configfile && strlen(driver->configfile)) {
1963                 if (!strequal(driver->configfile, driver->driverpath) &&
1964                     !strequal(driver->configfile, driver->datafile)) {
1965 
1966                         *perr = move_driver_file_to_download_area(ctx,
1967                                                                   conn,
1968                                                                   driver->configfile,
1969                                                                   short_architecture,
1970                                                                   driver->cversion,
1971                                                                   ver);
1972                         if (!W_ERROR_IS_OK(*perr)) {
1973                                 if (W_ERROR_EQUAL(*perr, WERR_ACCESS_DENIED)) {
1974                                         ver = -1;
1975                                 }
1976                                 goto err_exit;
1977                         }
1978                 }
1979         }
1980 
1981         if (driver->helpfile && strlen(driver->helpfile)) {
1982                 if (!strequal(driver->helpfile, driver->driverpath) &&
1983                     !strequal(driver->helpfile, driver->datafile) &&
1984                     !strequal(driver->helpfile, driver->configfile)) {
1985 
1986                         *perr = move_driver_file_to_download_area(ctx,
1987                                                                   conn,
1988                                                                   driver->helpfile,
1989                                                                   short_architecture,
1990                                                                   driver->cversion,
1991                                                                   ver);
1992                         if (!W_ERROR_IS_OK(*perr)) {
1993                                 if (W_ERROR_EQUAL(*perr, WERR_ACCESS_DENIED)) {
1994                                         ver = -1;
1995                                 }
1996                                 goto err_exit;
1997                         }
1998                 }
1999         }
2000 
2001         if (driver->dependentfiles) {
2002                 for (i=0; *driver->dependentfiles[i]; i++) {
2003                         if (!strequal(driver->dependentfiles[i], driver->driverpath) &&
2004                             !strequal(driver->dependentfiles[i], driver->datafile) &&
2005                             !strequal(driver->dependentfiles[i], driver->configfile) &&
2006                             !strequal(driver->dependentfiles[i], driver->helpfile)) {
2007                                 int j;
2008                                 for (j=0; j < i; j++) {
2009                                         if (strequal(driver->dependentfiles[i], driver->dependentfiles[j])) {
2010                                                 goto NextDriver;
2011                                         }
2012                                 }
2013 
2014                                 *perr = move_driver_file_to_download_area(ctx,
2015                                                                           conn,
2016                                                                           driver->dependentfiles[i],
2017                                                                           short_architecture,
2018                                                                           driver->cversion,
2019                                                                           ver);
2020                                 if (!W_ERROR_IS_OK(*perr)) {
2021                                         if (W_ERROR_EQUAL(*perr, WERR_ACCESS_DENIED)) {
2022                                                 ver = -1;
2023                                         }
2024                                         goto err_exit;
2025                                 }
2026                         }
2027                 NextDriver: ;
2028                 }
2029         }
2030 
2031   err_exit:
2032 
2033         if (conn != NULL) {
2034                 vfs_ChDir(conn, oldcwd);
2035                 conn_free_internal(conn);
2036         }
2037 
2038         if (W_ERROR_EQUAL(*perr, WERR_OK)) {
2039                 return WERR_OK;
2040         }
2041         if (ver == -1) {
2042                 return WERR_UNKNOWN_PRINTER_DRIVER;
2043         }
2044         return (*perr);
2045 }
2046 
2047 /****************************************************************************
2048 ****************************************************************************/
2049 
2050 static uint32 add_a_printer_driver_3(NT_PRINTER_DRIVER_INFO_LEVEL_3 *driver)
     /* [<][>][^][v][top][bottom][index][help] */
2051 {
2052         TALLOC_CTX *ctx = talloc_tos();
2053         int len, buflen;
2054         const char *architecture;
2055         char *directory = NULL;
2056         fstring temp_name;
2057         char *key = NULL;
2058         uint8 *buf;
2059         int i, ret;
2060         TDB_DATA dbuf;
2061 
2062         architecture = get_short_archi(driver->environment);
2063         if (!architecture) {
2064                 return (uint32)-1;
2065         }
2066 
2067         /* The names are relative. We store them in the form: \print$\arch\version\driver.xxx
2068          * \\server is added in the rpc server layer.
2069          * It does make sense to NOT store the server's name in the printer TDB.
2070          */
2071 
2072         directory = talloc_asprintf(ctx, "\\print$\\%s\\%d\\",
2073                         architecture, driver->cversion);
2074         if (!directory) {
2075                 return (uint32)-1;
2076         }
2077 
2078         /* .inf files do not always list a file for each of the four standard files.
2079          * Don't prepend a path to a null filename, or client claims:
2080          *   "The server on which the printer resides does not have a suitable
2081          *   <printer driver name> printer driver installed. Click OK if you
2082          *   wish to install the driver on your local machine."
2083          */
2084         if (strlen(driver->driverpath)) {
2085                 fstrcpy(temp_name, driver->driverpath);
2086                 slprintf(driver->driverpath, sizeof(driver->driverpath)-1, "%s%s", directory, temp_name);
2087         }
2088 
2089         if (strlen(driver->datafile)) {
2090                 fstrcpy(temp_name, driver->datafile);
2091                 slprintf(driver->datafile, sizeof(driver->datafile)-1, "%s%s", directory, temp_name);
2092         }
2093 
2094         if (strlen(driver->configfile)) {
2095                 fstrcpy(temp_name, driver->configfile);
2096                 slprintf(driver->configfile, sizeof(driver->configfile)-1, "%s%s", directory, temp_name);
2097         }
2098 
2099         if (strlen(driver->helpfile)) {
2100                 fstrcpy(temp_name, driver->helpfile);
2101                 slprintf(driver->helpfile, sizeof(driver->helpfile)-1, "%s%s", directory, temp_name);
2102         }
2103 
2104         if (driver->dependentfiles) {
2105                 for (i=0; *driver->dependentfiles[i]; i++) {
2106                         fstrcpy(temp_name, driver->dependentfiles[i]);
2107                         slprintf(driver->dependentfiles[i], sizeof(driver->dependentfiles[i])-1, "%s%s", directory, temp_name);
2108                 }
2109         }
2110 
2111         key = talloc_asprintf(ctx, "%s%s/%d/%s", DRIVERS_PREFIX,
2112                         architecture, driver->cversion, driver->name);
2113         if (!key) {
2114                 return (uint32)-1;
2115         }
2116 
2117         DEBUG(5,("add_a_printer_driver_3: Adding driver with key %s\n", key ));
2118 
2119         buf = NULL;
2120         len = buflen = 0;
2121 
2122  again:
2123         len = 0;
2124         len += tdb_pack(buf+len, buflen-len, "dffffffff",
2125                         driver->cversion,
2126                         driver->name,
2127                         driver->environment,
2128                         driver->driverpath,
2129                         driver->datafile,
2130                         driver->configfile,
2131                         driver->helpfile,
2132                         driver->monitorname,
2133                         driver->defaultdatatype);
2134 
2135         if (driver->dependentfiles) {
2136                 for (i=0; *driver->dependentfiles[i]; i++) {
2137                         len += tdb_pack(buf+len, buflen-len, "f",
2138                                         driver->dependentfiles[i]);
2139                 }
2140         }
2141 
2142         if (len != buflen) {
2143                 buf = (uint8 *)SMB_REALLOC(buf, len);
2144                 if (!buf) {
2145                         DEBUG(0,("add_a_printer_driver_3: failed to enlarge buffer\n!"));
2146                         ret = -1;
2147                         goto done;
2148                 }
2149                 buflen = len;
2150                 goto again;
2151         }
2152 
2153         dbuf.dptr = buf;
2154         dbuf.dsize = len;
2155 
2156         ret = tdb_store_bystring(tdb_drivers, key, dbuf, TDB_REPLACE);
2157 
2158 done:
2159         if (ret)
2160                 DEBUG(0,("add_a_printer_driver_3: Adding driver with key %s failed.\n", key ));
2161 
2162         SAFE_FREE(buf);
2163         return ret;
2164 }
2165 
2166 /****************************************************************************
2167 ****************************************************************************/
2168 static uint32 add_a_printer_driver_6(NT_PRINTER_DRIVER_INFO_LEVEL_6 *driver)
     /* [<][>][^][v][top][bottom][index][help] */
2169 {
2170         NT_PRINTER_DRIVER_INFO_LEVEL_3 info3;
2171 
2172         ZERO_STRUCT(info3);
2173         info3.cversion = driver->version;
2174         fstrcpy(info3.name,driver->name);
2175         fstrcpy(info3.environment,driver->environment);
2176         fstrcpy(info3.driverpath,driver->driverpath);
2177         fstrcpy(info3.datafile,driver->datafile);
2178         fstrcpy(info3.configfile,driver->configfile);
2179         fstrcpy(info3.helpfile,driver->helpfile);
2180         fstrcpy(info3.monitorname,driver->monitorname);
2181         fstrcpy(info3.defaultdatatype,driver->defaultdatatype);
2182         info3.dependentfiles = driver->dependentfiles;
2183 
2184         return add_a_printer_driver_3(&info3);
2185 }
2186 
2187 
2188 /****************************************************************************
2189 ****************************************************************************/
2190 static WERROR get_a_printer_driver_3_default(NT_PRINTER_DRIVER_INFO_LEVEL_3 **info_ptr, const char *driver, const char *arch)
     /* [<][>][^][v][top][bottom][index][help] */
2191 {
2192         NT_PRINTER_DRIVER_INFO_LEVEL_3 info;
2193 
2194         ZERO_STRUCT(info);
2195 
2196         fstrcpy(info.name, driver);
2197         fstrcpy(info.defaultdatatype, "RAW");
2198 
2199         fstrcpy(info.driverpath, "");
2200         fstrcpy(info.datafile, "");
2201         fstrcpy(info.configfile, "");
2202         fstrcpy(info.helpfile, "");
2203 
2204         if ((info.dependentfiles= SMB_MALLOC_ARRAY(fstring, 2)) == NULL)
2205                 return WERR_NOMEM;
2206 
2207         memset(info.dependentfiles, '\0', 2*sizeof(fstring));
2208         fstrcpy(info.dependentfiles[0], "");
2209 
2210         *info_ptr = (NT_PRINTER_DRIVER_INFO_LEVEL_3 *)memdup(&info, sizeof(info));
2211         if (!*info_ptr) {
2212                 SAFE_FREE(info.dependentfiles);
2213                 return WERR_NOMEM;
2214         }
2215 
2216         return WERR_OK;
2217 }
2218 
2219 /****************************************************************************
2220 ****************************************************************************/
2221 static WERROR get_a_printer_driver_3(NT_PRINTER_DRIVER_INFO_LEVEL_3 **info_ptr,
     /* [<][>][^][v][top][bottom][index][help] */
2222                                      const char *drivername, const char *arch,
2223                                      uint32_t version)
2224 {
2225         NT_PRINTER_DRIVER_INFO_LEVEL_3 driver;
2226         TDB_DATA dbuf;
2227         const char *architecture;
2228         int len = 0;
2229         int i;
2230         char *key = NULL;
2231 
2232         ZERO_STRUCT(driver);
2233 
2234         architecture = get_short_archi(arch);
2235         if ( !architecture ) {
2236                 return WERR_UNKNOWN_PRINTER_DRIVER;
2237         }
2238 
2239         /* Windows 4.0 (i.e. win9x) should always use a version of 0 */
2240 
2241         if ( strcmp( architecture, SPL_ARCH_WIN40 ) == 0 )
2242                 version = 0;
2243 
2244         DEBUG(8,("get_a_printer_driver_3: [%s%s/%d/%s]\n", DRIVERS_PREFIX, architecture, version, drivername));
2245 
2246         if (asprintf(&key, "%s%s/%d/%s", DRIVERS_PREFIX,
2247                                 architecture, version, drivername) < 0) {
2248                 return WERR_NOMEM;
2249         }
2250 
2251         dbuf = tdb_fetch_bystring(tdb_drivers, key);
2252         if (!dbuf.dptr) {
2253                 SAFE_FREE(key);
2254                 return WERR_UNKNOWN_PRINTER_DRIVER;
2255         }
2256 
2257         len += tdb_unpack(dbuf.dptr, dbuf.dsize, "dffffffff",
2258                           &driver.cversion,
2259                           driver.name,
2260                           driver.environment,
2261                           driver.driverpath,
2262                           driver.datafile,
2263                           driver.configfile,
2264                           driver.helpfile,
2265                           driver.monitorname,
2266                           driver.defaultdatatype);
2267 
2268         i=0;
2269         while (len < dbuf.dsize) {
2270                 driver.dependentfiles = SMB_REALLOC_ARRAY(driver.dependentfiles, fstring, i+2);
2271                 if ( !driver.dependentfiles ) {
2272                         DEBUG(0,("get_a_printer_driver_3: failed to enlarge buffer!\n"));
2273                         break;
2274                 }
2275 
2276                 len += tdb_unpack(dbuf.dptr+len, dbuf.dsize-len, "f",
2277                                   &driver.dependentfiles[i]);
2278                 i++;
2279         }
2280 
2281         if ( driver.dependentfiles )
2282                 fstrcpy( driver.dependentfiles[i], "" );
2283 
2284         SAFE_FREE(dbuf.dptr);
2285         SAFE_FREE(key);
2286 
2287         if (len != dbuf.dsize) {
2288                 SAFE_FREE(driver.dependentfiles);
2289 
2290                 return get_a_printer_driver_3_default(info_ptr, drivername, arch);
2291         }
2292 
2293         *info_ptr = (NT_PRINTER_DRIVER_INFO_LEVEL_3 *)memdup(&driver, sizeof(driver));
2294         if (!*info_ptr) {
2295                 SAFE_FREE(driver.dependentfiles);
2296                 return WERR_NOMEM;
2297         }
2298 
2299         return WERR_OK;
2300 }
2301 
2302 /****************************************************************************
2303  Debugging function, dump at level 6 the struct in the logs.
2304 ****************************************************************************/
2305 
2306 static uint32 dump_a_printer_driver(NT_PRINTER_DRIVER_INFO_LEVEL driver, uint32 level)
     /* [<][>][^][v][top][bottom][index][help] */
2307 {
2308         uint32 result;
2309         NT_PRINTER_DRIVER_INFO_LEVEL_3 *info3;
2310         int i;
2311 
2312         DEBUG(20,("Dumping printer driver at level [%d]\n", level));
2313 
2314         switch (level)
2315         {
2316                 case 3:
2317                 {
2318                         if (driver.info_3 == NULL)
2319                                 result=5;
2320                         else {
2321                                 info3=driver.info_3;
2322 
2323                                 DEBUGADD(20,("version:[%d]\n",         info3->cversion));
2324                                 DEBUGADD(20,("name:[%s]\n",            info3->name));
2325                                 DEBUGADD(20,("environment:[%s]\n",     info3->environment));
2326                                 DEBUGADD(20,("driverpath:[%s]\n",      info3->driverpath));
2327                                 DEBUGADD(20,("datafile:[%s]\n",        info3->datafile));
2328                                 DEBUGADD(20,("configfile:[%s]\n",      info3->configfile));
2329                                 DEBUGADD(20,("helpfile:[%s]\n",        info3->helpfile));
2330                                 DEBUGADD(20,("monitorname:[%s]\n",     info3->monitorname));
2331                                 DEBUGADD(20,("defaultdatatype:[%s]\n", info3->defaultdatatype));
2332 
2333                                 for (i=0; info3->dependentfiles &&
2334                                           *info3->dependentfiles[i]; i++) {
2335                                         DEBUGADD(20,("dependentfile:[%s]\n",
2336                                                       info3->dependentfiles[i]));
2337                                 }
2338                                 result=0;
2339                         }
2340                         break;
2341                 }
2342                 default:
2343                         DEBUGADD(20,("dump_a_printer_driver: Level %u not implemented\n", (unsigned int)level));
2344                         result=1;
2345                         break;
2346         }
2347 
2348         return result;
2349 }
2350 
2351 /****************************************************************************
2352 ****************************************************************************/
2353 int pack_devicemode(NT_DEVICEMODE *nt_devmode, uint8 *buf, int buflen)
     /* [<][>][^][v][top][bottom][index][help] */
2354 {
2355         int len = 0;
2356 
2357         len += tdb_pack(buf+len, buflen-len, "p", nt_devmode);
2358 
2359         if (!nt_devmode)
2360                 return len;
2361 
2362         len += tdb_pack(buf+len, buflen-len, "ffwwwwwwwwwwwwwwwwwwddddddddddddddp",
2363                         nt_devmode->devicename,
2364                         nt_devmode->formname,
2365 
2366                         nt_devmode->specversion,
2367                         nt_devmode->driverversion,
2368                         nt_devmode->size,
2369                         nt_devmode->driverextra,
2370                         nt_devmode->orientation,
2371                         nt_devmode->papersize,
2372                         nt_devmode->paperlength,
2373                         nt_devmode->paperwidth,
2374                         nt_devmode->scale,
2375                         nt_devmode->copies,
2376                         nt_devmode->defaultsource,
2377                         nt_devmode->printquality,
2378                         nt_devmode->color,
2379                         nt_devmode->duplex,
2380                         nt_devmode->yresolution,
2381                         nt_devmode->ttoption,
2382                         nt_devmode->collate,
2383                         nt_devmode->logpixels,
2384 
2385                         nt_devmode->fields,
2386                         nt_devmode->bitsperpel,
2387                         nt_devmode->pelswidth,
2388                         nt_devmode->pelsheight,
2389                         nt_devmode->displayflags,
2390                         nt_devmode->displayfrequency,
2391                         nt_devmode->icmmethod,
2392                         nt_devmode->icmintent,
2393                         nt_devmode->mediatype,
2394                         nt_devmode->dithertype,
2395                         nt_devmode->reserved1,
2396                         nt_devmode->reserved2,
2397                         nt_devmode->panningwidth,
2398                         nt_devmode->panningheight,
2399                         nt_devmode->nt_dev_private);
2400 
2401         if (nt_devmode->nt_dev_private) {
2402                 len += tdb_pack(buf+len, buflen-len, "B",
2403                                 nt_devmode->driverextra,
2404                                 nt_devmode->nt_dev_private);
2405         }
2406 
2407         DEBUG(8,("Packed devicemode [%s]\n", nt_devmode->formname));
2408 
2409         return len;
2410 }
2411 
2412 /****************************************************************************
2413  Pack all values in all printer keys
2414  ***************************************************************************/
2415 
2416 static int pack_values(NT_PRINTER_DATA *data, uint8 *buf, int buflen)
     /* [<][>][^][v][top][bottom][index][help] */
2417 {
2418         int             len = 0;
2419         int             i, j;
2420         REGISTRY_VALUE  *val;
2421         REGVAL_CTR      *val_ctr;
2422         char *path = NULL;
2423         int             num_values;
2424 
2425         if ( !data )
2426                 return 0;
2427 
2428         /* loop over all keys */
2429 
2430         for ( i=0; i<data->num_keys; i++ ) {
2431                 val_ctr = data->keys[i].values;
2432                 num_values = regval_ctr_numvals( val_ctr );
2433 
2434                 /* pack the keyname followed by a empty value */
2435 
2436                 len += tdb_pack(buf+len, buflen-len, "pPdB",
2437                                 &data->keys[i].name,
2438                                 data->keys[i].name,
2439                                 REG_NONE,
2440                                 0,
2441                                 NULL);
2442 
2443                 /* now loop over all values */
2444 
2445                 for ( j=0; j<num_values; j++ ) {
2446                         /* pathname should be stored as <key>\<value> */
2447 
2448                         val = regval_ctr_specific_value( val_ctr, j );
2449                         if (asprintf(&path, "%s\\%s",
2450                                         data->keys[i].name,
2451                                         regval_name(val)) < 0) {
2452                                 return -1;
2453                         }
2454 
2455                         len += tdb_pack(buf+len, buflen-len, "pPdB",
2456                                         val,
2457                                         path,
2458                                         regval_type(val),
2459                                         regval_size(val),
2460                                         regval_data_p(val) );
2461 
2462                         DEBUG(8,("specific: [%s], len: %d\n", regval_name(val), regval_size(val)));
2463                         SAFE_FREE(path);
2464                 }
2465 
2466         }
2467 
2468         /* terminator */
2469 
2470         len += tdb_pack(buf+len, buflen-len, "p", NULL);
2471 
2472         return len;
2473 }
2474 
2475 
2476 /****************************************************************************
2477  Delete a printer - this just deletes the printer info file, any open
2478  handles are not affected.
2479 ****************************************************************************/
2480 
2481 uint32 del_a_printer(const char *sharename)
     /* [<][>][^][v][top][bottom][index][help] */
2482 {
2483         TDB_DATA kbuf;
2484         char *printdb_path = NULL;
2485         TALLOC_CTX *ctx = talloc_tos();
2486 
2487         kbuf = make_printer_tdbkey(ctx, sharename);
2488         tdb_delete(tdb_printers, kbuf);
2489 
2490         kbuf= make_printers_secdesc_tdbkey(ctx, sharename);
2491         tdb_delete(tdb_printers, kbuf);
2492 
2493         close_all_print_db();
2494 
2495         if (geteuid() == 0) {
2496                 if (asprintf(&printdb_path, "%s%s.tdb",
2497                                 cache_path("printing/"),
2498                                 sharename) < 0) {
2499                         return (uint32)-1;
2500                 }
2501                 unlink(printdb_path);
2502                 SAFE_FREE(printdb_path);
2503         }
2504 
2505         return 0;
2506 }
2507 
2508 /****************************************************************************
2509 ****************************************************************************/
2510 static WERROR update_a_printer_2(NT_PRINTER_INFO_LEVEL_2 *info)
     /* [<][>][^][v][top][bottom][index][help] */
2511 {
2512         uint8 *buf;
2513         int buflen, len;
2514         int retlen;
2515         WERROR ret;
2516         TDB_DATA kbuf, dbuf;
2517 
2518         /*
2519          * in addprinter: no servername and the printer is the name
2520          * in setprinter: servername is \\server
2521          *                and printer is \\server\\printer
2522          *
2523          * Samba manages only local printers.
2524          * we currently don't support things like i
2525          * path=\\other_server\printer
2526          *
2527          * We only store the printername, not \\server\printername
2528          */
2529 
2530         if ( info->servername[0] != '\0' ) {
2531                 trim_string(info->printername, info->servername, NULL);
2532                 trim_char(info->printername, '\\', '\0');
2533                 info->servername[0]='\0';
2534         }
2535 
2536         /*
2537          * JFM: one day I'll forget.
2538          * below that's info->portname because that's the SAMBA sharename
2539          * and I made NT 'thinks' it's the portname
2540          * the info->sharename is the thing you can name when you add a printer
2541          * that's the short-name when you create shared printer for 95/98
2542          * So I've made a limitation in SAMBA: you can only have 1 printer model
2543          * behind a SAMBA share.
2544          */
2545 
2546         buf = NULL;
2547         buflen = 0;
2548 
2549  again:
2550         len = 0;
2551         len += tdb_pack(buf+len, buflen-len, "dddddddddddfffffPfffff",
2552                         info->attributes,
2553                         info->priority,
2554                         info->default_priority,
2555                         info->starttime,
2556                         info->untiltime,
2557                         info->status,
2558                         info->cjobs,
2559                         info->averageppm,
2560                         info->changeid,
2561                         info->c_setprinter,
2562                         info->setuptime,
2563                         info->servername,
2564                         info->printername,
2565                         info->sharename,
2566                         info->portname,
2567                         info->drivername,
2568                         info->comment,
2569                         info->location,
2570                         info->sepfile,
2571                         info->printprocessor,
2572                         info->datatype,
2573                         info->parameters);
2574 
2575         len += pack_devicemode(info->devmode, buf+len, buflen-len);
2576         retlen = pack_values( info->data, buf+len, buflen-len );
2577         if (retlen == -1) {
2578                 ret = WERR_NOMEM;
2579                 goto done;
2580         }
2581         len += retlen;
2582 
2583         if (buflen != len) {
2584                 buf = (uint8 *)SMB_REALLOC(buf, len);
2585                 if (!buf) {
2586                         DEBUG(0,("update_a_printer_2: failed to enlarge buffer!\n"));
2587                         ret = WERR_NOMEM;
2588                         goto done;
2589                 }
2590                 buflen = len;
2591                 goto again;
2592         }
2593 
2594         kbuf = make_printer_tdbkey(talloc_tos(), info->sharename );
2595 
2596         dbuf.dptr = buf;
2597         dbuf.dsize = len;
2598 
2599         ret = (tdb_store(tdb_printers, kbuf, dbuf, TDB_REPLACE) == 0? WERR_OK : WERR_NOMEM);
2600 
2601 done:
2602         if (!W_ERROR_IS_OK(ret))
2603                 DEBUG(8, ("error updating printer to tdb on disk\n"));
2604 
2605         SAFE_FREE(buf);
2606 
2607         DEBUG(8,("packed printer [%s] with driver [%s] portname=[%s] len=%d\n",
2608                  info->sharename, info->drivername, info->portname, len));
2609 
2610         return ret;
2611 }
2612 
2613 
2614 /****************************************************************************
2615  Malloc and return an NT devicemode.
2616 ****************************************************************************/
2617 
2618 NT_DEVICEMODE *construct_nt_devicemode(const fstring default_devicename)
     /* [<][>][^][v][top][bottom][index][help] */
2619 {
2620 
2621         char adevice[MAXDEVICENAME];
2622         NT_DEVICEMODE *nt_devmode = SMB_MALLOC_P(NT_DEVICEMODE);
2623 
2624         if (nt_devmode == NULL) {
2625                 DEBUG(0,("construct_nt_devicemode: malloc fail.\n"));
2626                 return NULL;
2627         }
2628 
2629         ZERO_STRUCTP(nt_devmode);
2630 
2631         slprintf(adevice, sizeof(adevice), "%s", default_devicename);
2632         fstrcpy(nt_devmode->devicename, adevice);
2633 
2634         fstrcpy(nt_devmode->formname, "Letter");
2635 
2636         nt_devmode->specversion      = 0x0401;
2637         nt_devmode->driverversion    = 0x0400;
2638         nt_devmode->size             = 0x00DC;
2639         nt_devmode->driverextra      = 0x0000;
2640         nt_devmode->fields           = FORMNAME | TTOPTION | PRINTQUALITY |
2641                                        DEFAULTSOURCE | COPIES | SCALE |
2642                                        PAPERSIZE | ORIENTATION;
2643         nt_devmode->orientation      = 1;
2644         nt_devmode->papersize        = PAPER_LETTER;
2645         nt_devmode->paperlength      = 0;
2646         nt_devmode->paperwidth       = 0;
2647         nt_devmode->scale            = 0x64;
2648         nt_devmode->copies           = 1;
2649         nt_devmode->defaultsource    = BIN_FORMSOURCE;
2650         nt_devmode->printquality     = RES_HIGH;           /* 0x0258 */
2651         nt_devmode->color            = COLOR_MONOCHROME;
2652         nt_devmode->duplex           = DUP_SIMPLEX;
2653         nt_devmode->yresolution      = 0;
2654         nt_devmode->ttoption         = TT_SUBDEV;
2655         nt_devmode->collate          = COLLATE_FALSE;
2656         nt_devmode->icmmethod        = 0;
2657         nt_devmode->icmintent        = 0;
2658         nt_devmode->mediatype        = 0;
2659         nt_devmode->dithertype       = 0;
2660 
2661         /* non utilisés par un driver d'imprimante */
2662         nt_devmode->logpixels        = 0;
2663         nt_devmode->bitsperpel       = 0;
2664         nt_devmode->pelswidth        = 0;
2665         nt_devmode->pelsheight       = 0;
2666         nt_devmode->displayflags     = 0;
2667         nt_devmode->displayfrequency = 0;
2668         nt_devmode->reserved1        = 0;
2669         nt_devmode->reserved2        = 0;
2670         nt_devmode->panningwidth     = 0;
2671         nt_devmode->panningheight    = 0;
2672 
2673         nt_devmode->nt_dev_private = NULL;
2674         return nt_devmode;
2675 }
2676 
2677 /****************************************************************************
2678  Clean up and deallocate a (maybe partially) allocated NT_DEVICEMODE.
2679 ****************************************************************************/
2680 
2681 void free_nt_devicemode(NT_DEVICEMODE **devmode_ptr)
     /* [<][>][^][v][top][bottom][index][help] */
2682 {
2683         NT_DEVICEMODE *nt_devmode = *devmode_ptr;
2684 
2685         if(nt_devmode == NULL)
2686                 return;
2687 
2688         DEBUG(106,("free_nt_devicemode: deleting DEVMODE\n"));
2689 
2690         SAFE_FREE(nt_devmode->nt_dev_private);
2691         SAFE_FREE(*devmode_ptr);
2692 }
2693 
2694 /****************************************************************************
2695  Clean up and deallocate a (maybe partially) allocated NT_PRINTER_INFO_LEVEL_2.
2696 ****************************************************************************/
2697 
2698 static void free_nt_printer_info_level_2(NT_PRINTER_INFO_LEVEL_2 **info_ptr)
     /* [<][>][^][v][top][bottom][index][help] */
2699 {
2700         NT_PRINTER_INFO_LEVEL_2 *info = *info_ptr;
2701 
2702         if ( !info )
2703                 return;
2704 
2705         free_nt_devicemode(&info->devmode);
2706 
2707         TALLOC_FREE( *info_ptr );
2708 }
2709 
2710 
2711 /****************************************************************************
2712 ****************************************************************************/
2713 int unpack_devicemode(NT_DEVICEMODE **nt_devmode, const uint8 *buf, int buflen)
     /* [<][>][^][v][top][bottom][index][help] */
2714 {
2715         int len = 0;
2716         int extra_len = 0;
2717         NT_DEVICEMODE devmode;
2718 
2719         ZERO_STRUCT(devmode);
2720 
2721         len += tdb_unpack(buf+len, buflen-len, "p", nt_devmode);
2722 
2723         if (!*nt_devmode) return len;
2724 
2725         len += tdb_unpack(buf+len, buflen-len, "ffwwwwwwwwwwwwwwwwwwddddddddddddddp",
2726                           devmode.devicename,
2727                           devmode.formname,
2728 
2729                           &devmode.specversion,
2730                           &devmode.driverversion,
2731                           &devmode.size,
2732                           &devmode.driverextra,
2733                           &devmode.orientation,
2734                           &devmode.papersize,
2735                           &devmode.paperlength,
2736                           &devmode.paperwidth,
2737                           &devmode.scale,
2738                           &devmode.copies,
2739                           &devmode.defaultsource,
2740                           &devmode.printquality,
2741                           &devmode.color,
2742                           &devmode.duplex,
2743                           &devmode.yresolution,
2744                           &devmode.ttoption,
2745                           &devmode.collate,
2746                           &devmode.logpixels,
2747 
2748                           &devmode.fields,
2749                           &devmode.bitsperpel,
2750                           &devmode.pelswidth,
2751                           &devmode.pelsheight,
2752                           &devmode.displayflags,
2753                           &devmode.displayfrequency,
2754                           &devmode.icmmethod,
2755                           &devmode.icmintent,
2756                           &devmode.mediatype,
2757                           &devmode.dithertype,
2758                           &devmode.reserved1,
2759                           &devmode.reserved2,
2760                           &devmode.panningwidth,
2761                           &devmode.panningheight,
2762                           &devmode.nt_dev_private);
2763 
2764         if (devmode.nt_dev_private) {
2765                 /* the len in tdb_unpack is an int value and
2766                  * devmode.driverextra is only a short
2767                  */
2768                 len += tdb_unpack(buf+len, buflen-len, "B", &extra_len, &devmode.nt_dev_private);
2769                 devmode.driverextra=(uint16)extra_len;
2770 
2771                 /* check to catch an invalid TDB entry so we don't segfault */
2772                 if (devmode.driverextra == 0) {
2773                         devmode.nt_dev_private = NULL;
2774                 }
2775         }
2776 
2777         *nt_devmode = (NT_DEVICEMODE *)memdup(&devmode, sizeof(devmode));
2778         if (!*nt_devmode) {
2779                 SAFE_FREE(devmode.nt_dev_private);
2780                 return -1;
2781         }
2782 
2783         DEBUG(8,("Unpacked devicemode [%s](%s)\n", devmode.devicename, devmode.formname));
2784         if (devmode.nt_dev_private)
2785                 DEBUG(8,("with a private section of %d bytes\n", devmode.driverextra));
2786 
2787         return len;
2788 }
2789 
2790 /****************************************************************************
2791  Allocate and initialize a new slot.
2792 ***************************************************************************/
2793 
2794 int add_new_printer_key( NT_PRINTER_DATA *data, const char *name )
     /* [<][>][^][v][top][bottom][index][help] */
2795 {
2796         NT_PRINTER_KEY  *d;
2797         int             key_index;
2798 
2799         if ( !name || !data )
2800                 return -1;
2801 
2802         /* allocate another slot in the NT_PRINTER_KEY array */
2803 
2804         if ( !(d = TALLOC_REALLOC_ARRAY( data, data->keys, NT_PRINTER_KEY, data->num_keys+1)) ) {
2805                 DEBUG(0,("add_new_printer_key: Realloc() failed!\n"));
2806                 return -1;
2807         }
2808 
2809         data->keys = d;
2810 
2811         key_index = data->num_keys;
2812 
2813         /* initialze new key */
2814 
2815         data->keys[key_index].name = talloc_strdup( data, name );
2816 
2817         if ( !(data->keys[key_index].values = TALLOC_ZERO_P( data, REGVAL_CTR )) )
2818                 return -1;
2819 
2820         data->num_keys++;
2821 
2822         DEBUG(10,("add_new_printer_key: Inserted new data key [%s]\n", name ));
2823 
2824         return key_index;
2825 }
2826 
2827 /****************************************************************************
2828  search for a registry key name in the existing printer data
2829  ***************************************************************************/
2830 
2831 int delete_printer_key( NT_PRINTER_DATA *data, const char *name )
     /* [<][>][^][v][top][bottom][index][help] */
2832 {
2833         int i;
2834 
2835         for ( i=0; i<data->num_keys; i++ ) {
2836                 if ( strequal( data->keys[i].name, name ) ) {
2837 
2838                         /* cleanup memory */
2839 
2840                         TALLOC_FREE( data->keys[i].name );
2841                         TALLOC_FREE( data->keys[i].values );
2842 
2843                         /* if not the end of the array, move remaining elements down one slot */
2844 
2845                         data->num_keys--;
2846                         if ( data->num_keys && (i < data->num_keys) )
2847                                 memmove( &data->keys[i], &data->keys[i+1], sizeof(NT_PRINTER_KEY)*(data->num_keys-i) );
2848 
2849                         break;
2850                 }
2851         }
2852 
2853 
2854         return data->num_keys;
2855 }
2856 
2857 /****************************************************************************
2858  search for a registry key name in the existing printer data
2859  ***************************************************************************/
2860 
2861 int lookup_printerkey( NT_PRINTER_DATA *data, const char *name )
     /* [<][>][^][v][top][bottom][index][help] */
2862 {
2863         int             key_index = -1;
2864         int             i;
2865 
2866         if ( !data || !name )
2867                 return -1;
2868 
2869         DEBUG(12,("lookup_printerkey: Looking for [%s]\n", name));
2870 
2871         /* loop over all existing keys */
2872 
2873         for ( i=0; i<data->num_keys; i++ ) {
2874                 if ( strequal(data->keys[i].name, name) ) {
2875                         DEBUG(12,("lookup_printerkey: Found [%s]!\n", name));
2876                         key_index = i;
2877                         break;
2878 
2879                 }
2880         }
2881 
2882         return key_index;
2883 }
2884 
2885 /****************************************************************************
2886  ***************************************************************************/
2887 
2888 int get_printer_subkeys( NT_PRINTER_DATA *data, const char* key, fstring **subkeys )
     /* [<][>][^][v][top][bottom][index][help] */
2889 {
2890         int     i, j;
2891         int     key_len;
2892         int     num_subkeys = 0;
2893         char    *p;
2894         fstring *subkeys_ptr = NULL;
2895         fstring subkeyname;
2896 
2897         *subkeys = NULL;
2898 
2899         if ( !data )
2900                 return 0;
2901 
2902         if ( !key )
2903                 return -1;
2904 
2905         /* special case of asking for the top level printer data registry key names */
2906 
2907         if ( strlen(key) == 0 ) {
2908                 for ( i=0; i<data->num_keys; i++ ) {
2909 
2910                         /* found a match, so allocate space and copy the name */
2911 
2912                         if ( !(subkeys_ptr = SMB_REALLOC_ARRAY( subkeys_ptr, fstring, num_subkeys+2)) ) {
2913                                 DEBUG(0,("get_printer_subkeys: Realloc failed for [%d] entries!\n",
2914                                         num_subkeys+1));
2915                                 return -1;
2916                         }
2917 
2918                         fstrcpy( subkeys_ptr[num_subkeys], data->keys[i].name );
2919                         num_subkeys++;
2920                 }
2921 
2922                 goto done;
2923         }
2924 
2925         /* asking for the subkeys of some key */
2926         /* subkey paths are stored in the key name using '\' as the delimiter */
2927 
2928         for ( i=0; i<data->num_keys; i++ ) {
2929                 if ( StrnCaseCmp(data->keys[i].name, key, strlen(key)) == 0 ) {
2930 
2931                         /* if we found the exact key, then break */
2932                         key_len = strlen( key );
2933                         if ( strlen(data->keys[i].name) == key_len )
2934                                 break;
2935 
2936                         /* get subkey path */
2937 
2938                         p = data->keys[i].name + key_len;
2939                         if ( *p == '\\' )
2940                                 p++;
2941                         fstrcpy( subkeyname, p );
2942                         if ( (p = strchr( subkeyname, '\\' )) )
2943                                 *p = '\0';
2944 
2945                         /* don't add a key more than once */
2946 
2947                         for ( j=0; j<num_subkeys; j++ ) {
2948                                 if ( strequal( subkeys_ptr[j], subkeyname ) )
2949                                         break;
2950                         }
2951 
2952                         if ( j != num_subkeys )
2953                                 continue;
2954 
2955                         /* found a match, so allocate space and copy the name */
2956 
2957                         if ( !(subkeys_ptr = SMB_REALLOC_ARRAY( subkeys_ptr, fstring, num_subkeys+2)) ) {
2958                                 DEBUG(0,("get_printer_subkeys: Realloc failed for [%d] entries!\n",
2959                                         num_subkeys+1));
2960                                 return 0;
2961                         }
2962 
2963                         fstrcpy( subkeys_ptr[num_subkeys], subkeyname );
2964                         num_subkeys++;
2965                 }
2966 
2967         }
2968 
2969         /* return error if the key was not found */
2970 
2971         if ( i == data->num_keys ) {
2972                 SAFE_FREE(subkeys_ptr);
2973                 return -1;
2974         }
2975 
2976 done:
2977         /* tag off the end */
2978 
2979         if (num_subkeys)
2980                 fstrcpy(subkeys_ptr[num_subkeys], "" );
2981 
2982         *subkeys = subkeys_ptr;
2983 
2984         return num_subkeys;
2985 }
2986 
2987 #ifdef HAVE_ADS
2988 static void map_sz_into_ctr(REGVAL_CTR *ctr, const char *val_name,
     /* [<][>][^][v][top][bottom][index][help] */
2989                             const char *sz)
2990 {
2991         smb_ucs2_t conv_str[1024];
2992         size_t str_size;
2993 
2994         regval_ctr_delvalue(ctr, val_name);
2995         str_size = push_ucs2(NULL, conv_str, sz, sizeof(conv_str),
2996                              STR_TERMINATE | STR_NOALIGN);
2997         regval_ctr_addvalue(ctr, val_name, REG_SZ,
2998                             (char *) conv_str, str_size);
2999 }
3000 
3001 static void map_dword_into_ctr(REGVAL_CTR *ctr, const char *val_name,
     /* [<][>][^][v][top][bottom][index][help] */
3002                                uint32 dword)
3003 {
3004         regval_ctr_delvalue(ctr, val_name);
3005         regval_ctr_addvalue(ctr, val_name, REG_DWORD,
3006                             (char *) &dword, sizeof(dword));
3007 }
3008 
3009 static void map_bool_into_ctr(REGVAL_CTR *ctr, const char *val_name,
     /* [<][>][^][v][top][bottom][index][help] */
3010                               bool b)
3011 {
3012         uint8 bin_bool = (b ? 1 : 0);
3013         regval_ctr_delvalue(ctr, val_name);
3014         regval_ctr_addvalue(ctr, val_name, REG_BINARY,
3015                             (char *) &bin_bool, sizeof(bin_bool));
3016 }
3017 
3018 static void map_single_multi_sz_into_ctr(REGVAL_CTR *ctr, const char *val_name,
     /* [<][>][^][v][top][bottom][index][help] */
3019                                          const char *multi_sz)
3020 {
3021         smb_ucs2_t *conv_strs = NULL;
3022         size_t str_size;
3023 
3024         /* a multi-sz has to have a null string terminator, i.e., the last
3025            string must be followed by two nulls */
3026         str_size = strlen(multi_sz) + 2;
3027         conv_strs = SMB_CALLOC_ARRAY(smb_ucs2_t, str_size);
3028         if (!conv_strs) {
3029                 return;
3030         }
3031 
3032         /* Change to byte units. */
3033         str_size *= sizeof(smb_ucs2_t);
3034         push_ucs2(NULL, conv_strs, multi_sz, str_size,
3035                   STR_TERMINATE | STR_NOALIGN);
3036 
3037         regval_ctr_delvalue(ctr, val_name);
3038         regval_ctr_addvalue(ctr, val_name, REG_MULTI_SZ,
3039                             (char *) conv_strs, str_size);
3040         SAFE_FREE(conv_strs);
3041 }
3042 
3043 /****************************************************************************
3044  * Map the NT_PRINTER_INFO_LEVEL_2 data into DsSpooler keys for publishing.
3045  *
3046  * @param info2 NT_PRINTER_INFO_LEVEL_2 describing printer - gets modified
3047  * @return bool indicating success or failure
3048  ***************************************************************************/
3049 
3050 static bool map_nt_printer_info2_to_dsspooler(NT_PRINTER_INFO_LEVEL_2 *info2)
     /* [<][>][^][v][top][bottom][index][help] */
3051 {
3052         REGVAL_CTR *ctr = NULL;
3053         fstring longname;
3054         const char *dnssuffix;
3055         char *allocated_string = NULL;
3056         const char *ascii_str;
3057         int i;
3058 
3059         if ((i = lookup_printerkey(info2->data, SPOOL_DSSPOOLER_KEY)) < 0)
3060                 i = add_new_printer_key(info2->data, SPOOL_DSSPOOLER_KEY);
3061         ctr = info2->data->keys[i].values;
3062 
3063         map_sz_into_ctr(ctr, SPOOL_REG_PRINTERNAME, info2->sharename);
3064         map_sz_into_ctr(ctr, SPOOL_REG_SHORTSERVERNAME, global_myname());
3065 
3066         /* we make the assumption that the netbios name is the same
3067            as the DNS name sinc ethe former will be what we used to
3068            join the domain */
3069 
3070         dnssuffix = get_mydnsdomname(talloc_tos());
3071         if (dnssuffix && *dnssuffix) {
3072                 fstr_sprintf( longname, "%s.%s", global_myname(), dnssuffix );
3073         } else {
3074                 fstrcpy( longname, global_myname() );
3075         }
3076 
3077         map_sz_into_ctr(ctr, SPOOL_REG_SERVERNAME, longname);
3078 
3079         if (asprintf(&allocated_string, "\\\\%s\\%s", longname, info2->sharename) == -1) {
3080                 return false;
3081         }
3082         map_sz_into_ctr(ctr, SPOOL_REG_UNCNAME, allocated_string);
3083         SAFE_FREE(allocated_string);
3084 
3085         map_dword_into_ctr(ctr, SPOOL_REG_VERSIONNUMBER, 4);
3086         map_sz_into_ctr(ctr, SPOOL_REG_DRIVERNAME, info2->drivername);
3087         map_sz_into_ctr(ctr, SPOOL_REG_LOCATION, info2->location);
3088         map_sz_into_ctr(ctr, SPOOL_REG_DESCRIPTION, info2->comment);
3089         map_single_multi_sz_into_ctr(ctr, SPOOL_REG_PORTNAME, info2->portname);
3090         map_sz_into_ctr(ctr, SPOOL_REG_PRINTSEPARATORFILE, info2->sepfile);
3091         map_dword_into_ctr(ctr, SPOOL_REG_PRINTSTARTTIME, info2->starttime);
3092         map_dword_into_ctr(ctr, SPOOL_REG_PRINTENDTIME, info2->untiltime);
3093         map_dword_into_ctr(ctr, SPOOL_REG_PRIORITY, info2->priority);
3094 
3095         map_bool_into_ctr(ctr, SPOOL_REG_PRINTKEEPPRINTEDJOBS,
3096                           (info2->attributes &
3097                            PRINTER_ATTRIBUTE_KEEPPRINTEDJOBS));
3098 
3099         switch (info2->attributes & 0x3) {
3100         case 0:
3101                 ascii_str = SPOOL_REGVAL_PRINTWHILESPOOLING;
3102                 break;
3103         case 1:
3104                 ascii_str = SPOOL_REGVAL_PRINTAFTERSPOOLED;
3105                 break;
3106         case 2:
3107                 ascii_str = SPOOL_REGVAL_PRINTDIRECT;
3108                 break;
3109         default:
3110                 ascii_str = "unknown";
3111         }
3112         map_sz_into_ctr(ctr, SPOOL_REG_PRINTSPOOLING, ascii_str);
3113 
3114         return True;
3115 }
3116 
3117 /*****************************************************************
3118  ****************************************************************/
3119 
3120 static void store_printer_guid(NT_PRINTER_INFO_LEVEL_2 *info2,
     /* [<][>][^][v][top][bottom][index][help] */
3121                                struct GUID guid)
3122 {
3123         int i;
3124         REGVAL_CTR *ctr=NULL;
3125         UNISTR2 unistr_guid;
3126 
3127         /* find the DsSpooler key */
3128         if ((i = lookup_printerkey(info2->data, SPOOL_DSSPOOLER_KEY)) < 0)
3129                 i = add_new_printer_key(info2->data, SPOOL_DSSPOOLER_KEY);
3130         ctr = info2->data->keys[i].values;
3131 
3132         regval_ctr_delvalue(ctr, "objectGUID");
3133 
3134         /* We used to store this as a REG_BINARY but that causes
3135            Vista to whine */
3136 
3137         ZERO_STRUCT( unistr_guid );
3138 
3139         init_unistr2( &unistr_guid, GUID_string(talloc_tos(), &guid),
3140                       UNI_STR_TERMINATE );
3141 
3142         regval_ctr_addvalue(ctr, "objectGUID", REG_SZ,
3143                             (char *)unistr_guid.buffer,
3144                             unistr_guid.uni_max_len*2);
3145 
3146 }
3147 
3148 static WERROR nt_printer_publish_ads(ADS_STRUCT *ads,
     /* [<][>][^][v][top][bottom][index][help] */
3149                                      NT_PRINTER_INFO_LEVEL *printer)
3150 {
3151         ADS_STATUS ads_rc;
3152         LDAPMessage *res;
3153         char *prt_dn = NULL, *srv_dn, *srv_cn_0, *srv_cn_escaped, *sharename_escaped;
3154         char *srv_dn_utf8, **srv_cn_utf8;
3155         TALLOC_CTX *ctx;
3156         ADS_MODLIST mods;
3157         const char *attrs[] = {"objectGUID", NULL};
3158         struct GUID guid;
3159         WERROR win_rc = WERR_OK;
3160         size_t converted_size;
3161 
3162         /* build the ads mods */
3163         ctx = talloc_init("nt_printer_publish_ads");
3164         if (ctx == NULL) {
3165                 return WERR_NOMEM;
3166         }
3167 
3168         DEBUG(5, ("publishing printer %s\n", printer->info_2->printername));
3169 
3170         /* figure out where to publish */
3171         ads_find_machine_acct(ads, &res, global_myname());
3172 
3173         /* We use ldap_get_dn here as we need the answer
3174          * in utf8 to call ldap_explode_dn(). JRA. */
3175 
3176         srv_dn_utf8 = ldap_get_dn((LDAP *)ads->ldap.ld, (LDAPMessage *)res);
3177         if (!srv_dn_utf8) {
3178                 TALLOC_FREE(ctx);
3179                 return WERR_SERVER_UNAVAILABLE;
3180         }
3181         ads_msgfree(ads, res);
3182         srv_cn_utf8 = ldap_explode_dn(srv_dn_utf8, 1);
3183         if (!srv_cn_utf8) {
3184                 TALLOC_FREE(ctx);
3185                 ldap_memfree(srv_dn_utf8);
3186                 return WERR_SERVER_UNAVAILABLE;
3187         }
3188         /* Now convert to CH_UNIX. */
3189         if (!pull_utf8_talloc(ctx, &srv_dn, srv_dn_utf8, &converted_size)) {
3190                 TALLOC_FREE(ctx);
3191                 ldap_memfree(srv_dn_utf8);
3192                 ldap_memfree(srv_cn_utf8);
3193                 return WERR_SERVER_UNAVAILABLE;
3194         }
3195         if (!pull_utf8_talloc(ctx, &srv_cn_0, srv_cn_utf8[0], &converted_size)) {
3196                 TALLOC_FREE(ctx);
3197                 ldap_memfree(srv_dn_utf8);
3198                 ldap_memfree(srv_cn_utf8);
3199                 TALLOC_FREE(srv_dn);
3200                 return WERR_SERVER_UNAVAILABLE;
3201         }
3202 
3203         ldap_memfree(srv_dn_utf8);
3204         ldap_memfree(srv_cn_utf8);
3205 
3206         srv_cn_escaped = escape_rdn_val_string_alloc(srv_cn_0);
3207         if (!srv_cn_escaped) {
3208                 TALLOC_FREE(ctx);
3209                 return WERR_SERVER_UNAVAILABLE;
3210         }
3211         sharename_escaped = escape_rdn_val_string_alloc(printer->info_2->sharename);
3212         if (!sharename_escaped) {
3213                 SAFE_FREE(srv_cn_escaped);
3214                 TALLOC_FREE(ctx);
3215                 return WERR_SERVER_UNAVAILABLE;
3216         }
3217 
3218         prt_dn = talloc_asprintf(ctx, "cn=%s-%s,%s", srv_cn_escaped, sharename_escaped, srv_dn);
3219 
3220         SAFE_FREE(srv_cn_escaped);
3221         SAFE_FREE(sharename_escaped);
3222 
3223         mods = ads_init_mods(ctx);
3224 
3225         if (mods == NULL) {
3226                 SAFE_FREE(prt_dn);
3227                 TALLOC_FREE(ctx);
3228                 return WERR_NOMEM;
3229         }
3230 
3231         get_local_printer_publishing_data(ctx, &mods, printer->info_2->data);
3232         ads_mod_str(ctx, &mods, SPOOL_REG_PRINTERNAME,
3233                     printer->info_2->sharename);
3234 
3235         /* publish it */
3236         ads_rc = ads_mod_printer_entry(ads, prt_dn, ctx, &mods);
3237         if (ads_rc.err.rc == LDAP_NO_SUCH_OBJECT) {
3238                 int i;
3239                 for (i=0; mods[i] != 0; i++)
3240                         ;
3241                 mods[i] = (LDAPMod *)-1;
3242                 ads_rc = ads_add_printer_entry(ads, prt_dn, ctx, &mods);
3243         }
3244 
3245         if (!ADS_ERR_OK(ads_rc))
3246                 DEBUG(3, ("error publishing %s: %s\n", printer->info_2->sharename, ads_errstr(ads_rc)));
3247 
3248         /* retreive the guid and store it locally */
3249         if (ADS_ERR_OK(ads_search_dn(ads, &res, prt_dn, attrs))) {
3250                 ZERO_STRUCT(guid);
3251                 ads_pull_guid(ads, res, &guid);
3252                 ads_msgfree(ads, res);
3253                 store_printer_guid(printer->info_2, guid);
3254                 win_rc = mod_a_printer(printer, 2);
3255         }
3256         TALLOC_FREE(ctx);
3257 
3258         return win_rc;
3259 }
3260 
3261 static WERROR nt_printer_unpublish_ads(ADS_STRUCT *ads,
     /* [<][>][^][v][top][bottom][index][help] */
3262                                        NT_PRINTER_INFO_LEVEL *printer)
3263 {
3264         ADS_STATUS ads_rc;
3265         LDAPMessage *res = NULL;
3266         char *prt_dn = NULL;
3267 
3268         DEBUG(5, ("unpublishing printer %s\n", printer->info_2->printername));
3269 
3270         /* remove the printer from the directory */
3271         ads_rc = ads_find_printer_on_server(ads, &res,
3272                             printer->info_2->sharename, global_myname());
3273 
3274         if (ADS_ERR_OK(ads_rc) && res && ads_count_replies(ads, res)) {
3275                 prt_dn = ads_get_dn(ads, talloc_tos(), res);
3276                 if (!prt_dn) {
3277                         ads_msgfree(ads, res);
3278                         return WERR_NOMEM;
3279                 }
3280                 ads_rc = ads_del_dn(ads, prt_dn);
3281                 TALLOC_FREE(prt_dn);
3282         }
3283 
3284         if (res) {
3285                 ads_msgfree(ads, res);
3286         }
3287         return WERR_OK;
3288 }
3289 
3290 /****************************************************************************
3291  * Publish a printer in the directory
3292  *
3293  * @param snum describing printer service
3294  * @return WERROR indicating status of publishing
3295  ***************************************************************************/
3296 
3297 WERROR nt_printer_publish(Printer_entry *print_hnd, int snum, int action)
     /* [<][>][^][v][top][bottom][index][help] */
3298 {
3299         ADS_STATUS ads_rc;
3300         ADS_STRUCT *ads = NULL;
3301         NT_PRINTER_INFO_LEVEL *printer = NULL;
3302         WERROR win_rc;
3303 
3304         win_rc = get_a_printer(print_hnd, &printer, 2, lp_servicename(snum));
3305         if (!W_ERROR_IS_OK(win_rc))
3306                 goto done;
3307 
3308         switch (action) {
3309         case DSPRINT_PUBLISH:
3310         case DSPRINT_UPDATE:
3311                 /* set the DsSpooler info and attributes */
3312                 if (!(map_nt_printer_info2_to_dsspooler(printer->info_2))) {
3313                         win_rc = WERR_NOMEM;
3314                         goto done;
3315                 }
3316 
3317                 printer->info_2->attributes |= PRINTER_ATTRIBUTE_PUBLISHED;
3318                 break;
3319         case DSPRINT_UNPUBLISH:
3320                 printer->info_2->attributes ^= PRINTER_ATTRIBUTE_PUBLISHED;
3321                 break;
3322         default:
3323                 win_rc = WERR_NOT_SUPPORTED;
3324                 goto done;
3325         }
3326 
3327         win_rc = mod_a_printer(printer, 2);
3328         if (!W_ERROR_IS_OK(win_rc)) {
3329                 DEBUG(3, ("err %d saving data\n", W_ERROR_V(win_rc)));
3330                 goto done;
3331         }
3332 
3333         ads = ads_init(lp_realm(), lp_workgroup(), NULL);
3334         if (!ads) {
3335                 DEBUG(3, ("ads_init() failed\n"));
3336                 win_rc = WERR_SERVER_UNAVAILABLE;
3337                 goto done;
3338         }
3339         setenv(KRB5_ENV_CCNAME, "MEMORY:prtpub_cache", 1);
3340         SAFE_FREE(ads->auth.password);
3341         ads->auth.password = secrets_fetch_machine_password(lp_workgroup(),
3342                 NULL, NULL);
3343 
3344         /* ads_connect() will find the DC for us */
3345         ads_rc = ads_connect(ads);
3346         if (!ADS_ERR_OK(ads_rc)) {
3347                 DEBUG(3, ("ads_connect failed: %s\n", ads_errstr(ads_rc)));
3348                 win_rc = WERR_ACCESS_DENIED;
3349                 goto done;
3350         }
3351 
3352         switch (action) {
3353         case DSPRINT_PUBLISH:
3354         case DSPRINT_UPDATE:
3355                 win_rc = nt_printer_publish_ads(ads, printer);
3356                 break;
3357         case DSPRINT_UNPUBLISH:
3358                 win_rc = nt_printer_unpublish_ads(ads, printer);
3359                 break;
3360         }
3361 
3362 done:
3363         free_a_printer(&printer, 2);
3364         ads_destroy(&ads);
3365         return win_rc;
3366 }
3367 
3368 WERROR check_published_printers(void)
     /* [<][>][^][v][top][bottom][index][help] */
3369 {
3370         ADS_STATUS ads_rc;
3371         ADS_STRUCT *ads = NULL;
3372         int snum;
3373         int n_services = lp_numservices();
3374         NT_PRINTER_INFO_LEVEL *printer = NULL;
3375 
3376         ads = ads_init(lp_realm(), lp_workgroup(), NULL);
3377         if (!ads) {
3378                 DEBUG(3, ("ads_init() failed\n"));
3379                 return WERR_SERVER_UNAVAILABLE;
3380         }
3381         setenv(KRB5_ENV_CCNAME, "MEMORY:prtpub_cache", 1);
3382         SAFE_FREE(ads->auth.password);
3383         ads->auth.password = secrets_fetch_machine_password(lp_workgroup(),
3384                 NULL, NULL);
3385 
3386         /* ads_connect() will find the DC for us */
3387         ads_rc = ads_connect(ads);
3388         if (!ADS_ERR_OK(ads_rc)) {
3389                 DEBUG(3, ("ads_connect failed: %s\n", ads_errstr(ads_rc)));
3390                 ads_destroy(&ads);
3391                 ads_kdestroy("MEMORY:prtpub_cache");
3392                 return WERR_ACCESS_DENIED;
3393         }
3394 
3395         for (snum = 0; snum < n_services; snum++) {
3396                 if (!(lp_snum_ok(snum) && lp_print_ok(snum)))
3397                         continue;
3398 
3399                 if (W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2,
3400                                                 lp_servicename(snum))) &&
3401                     (printer->info_2->attributes & PRINTER_ATTRIBUTE_PUBLISHED))
3402                         nt_printer_publish_ads(ads, printer);
3403 
3404                 free_a_printer(&printer, 2);
3405         }
3406 
3407         ads_destroy(&ads);
3408         ads_kdestroy("MEMORY:prtpub_cache");
3409         return WERR_OK;
3410 }
3411 
3412 bool is_printer_published(Printer_entry *print_hnd, int snum,
     /* [<][>][^][v][top][bottom][index][help] */
3413                           struct GUID *guid)
3414 {
3415         NT_PRINTER_INFO_LEVEL *printer = NULL;
3416         REGVAL_CTR *ctr;
3417         REGISTRY_VALUE *guid_val;
3418         WERROR win_rc;
3419         int i;
3420         bool ret = False;
3421 
3422         win_rc = get_a_printer(print_hnd, &printer, 2, lp_servicename(snum));
3423 
3424         if (!W_ERROR_IS_OK(win_rc) ||
3425             !(printer->info_2->attributes & PRINTER_ATTRIBUTE_PUBLISHED) ||
3426             ((i = lookup_printerkey(printer->info_2->data, SPOOL_DSSPOOLER_KEY)) < 0) ||
3427             !(ctr = printer->info_2->data->keys[i].values) ||
3428             !(guid_val = regval_ctr_getvalue(ctr, "objectGUID")))
3429         {
3430                 free_a_printer(&printer, 2);
3431                 return False;
3432         }
3433 
3434         /* fetching printer guids really ought to be a separate function. */
3435 
3436         if ( guid ) {
3437                 fstring guid_str;
3438 
3439                 /* We used to store the guid as REG_BINARY, then swapped
3440                    to REG_SZ for Vista compatibility so check for both */
3441 
3442                 switch ( regval_type(guid_val) ){
3443                 case REG_SZ:
3444                         rpcstr_pull( guid_str, regval_data_p(guid_val),
3445                                      sizeof(guid_str)-1, -1, STR_TERMINATE );
3446                         ret = NT_STATUS_IS_OK(GUID_from_string( guid_str, guid ));
3447                         break;
3448                 case REG_BINARY:
3449                         if ( regval_size(guid_val) != sizeof(struct GUID) ) {
3450                                 ret = False;
3451                                 break;
3452                         }
3453                         memcpy(guid, regval_data_p(guid_val), sizeof(struct GUID));
3454                         break;
3455                 default:
3456                         DEBUG(0,("is_printer_published: GUID value stored as "
3457                                  "invaluid type (%d)\n", regval_type(guid_val) ));
3458                         break;
3459                 }
3460         }
3461 
3462         free_a_printer(&printer, 2);
3463         return ret;
3464 }
3465 #else
3466 WERROR nt_printer_publish(Printer_entry *print_hnd, int snum, int action)
     /* [<][>][^][v][top][bottom][index][help] */
3467 {
3468         return WERR_OK;
3469 }
3470 
3471 WERROR check_published_printers(void)
     /* [<][>][^][v][top][bottom][index][help] */
3472 {
3473         return WERR_OK;
3474 }
3475 
3476 bool is_printer_published(Printer_entry *print_hnd, int snum,
     /* [<][>][^][v][top][bottom][index][help] */
3477                           struct GUID *guid)
3478 {
3479         return False;
3480 }
3481 #endif /* HAVE_ADS */
3482 
3483 /****************************************************************************
3484  ***************************************************************************/
3485 
3486 WERROR delete_all_printer_data( NT_PRINTER_INFO_LEVEL_2 *p2, const char *key )
     /* [<][>][^][v][top][bottom][index][help] */
3487 {
3488         NT_PRINTER_DATA *data;
3489         int             i;
3490         int             removed_keys = 0;
3491         int             empty_slot;
3492 
3493         data = p2->data;
3494         empty_slot = data->num_keys;
3495 
3496         if ( !key )
3497                 return WERR_INVALID_PARAM;
3498 
3499         /* remove all keys */
3500 
3501         if ( !strlen(key) ) {
3502 
3503                 TALLOC_FREE( data );
3504 
3505                 p2->data = NULL;
3506 
3507                 DEBUG(8,("delete_all_printer_data: Removed all Printer Data from printer [%s]\n",
3508                         p2->printername ));
3509 
3510                 return WERR_OK;
3511         }
3512 
3513         /* remove a specific key (and all subkeys) */
3514 
3515         for ( i=0; i<data->num_keys; i++ ) {
3516                 if ( StrnCaseCmp( data->keys[i].name, key, strlen(key)) == 0 ) {
3517                         DEBUG(8,("delete_all_printer_data: Removed all Printer Data from key [%s]\n",
3518                                 data->keys[i].name));
3519 
3520                         TALLOC_FREE( data->keys[i].name );
3521                         TALLOC_FREE( data->keys[i].values );
3522 
3523                         /* mark the slot as empty */
3524 
3525                         ZERO_STRUCTP( &data->keys[i] );
3526                 }
3527         }
3528 
3529         /* find the first empty slot */
3530 
3531         for ( i=0; i<data->num_keys; i++ ) {
3532                 if ( !data->keys[i].name ) {
3533                         empty_slot = i;
3534                         removed_keys++;
3535                         break;
3536                 }
3537         }
3538 
3539         if ( i == data->num_keys )
3540                 /* nothing was removed */
3541                 return WERR_INVALID_PARAM;
3542 
3543         /* move everything down */
3544 
3545         for ( i=empty_slot+1; i<data->num_keys; i++ ) {
3546                 if ( data->keys[i].name ) {
3547                         memcpy( &data->keys[empty_slot], &data->keys[i], sizeof(NT_PRINTER_KEY) );
3548                         ZERO_STRUCTP( &data->keys[i] );
3549                         empty_slot++;
3550                         removed_keys++;
3551                 }
3552         }
3553 
3554         /* update count */
3555 
3556         data->num_keys -= removed_keys;
3557 
3558         /* sanity check to see if anything is left */
3559 
3560         if ( !data->num_keys ) {
3561                 DEBUG(8,("delete_all_printer_data: No keys left for printer [%s]\n", p2->printername ));
3562 
3563                 SAFE_FREE( data->keys );
3564                 ZERO_STRUCTP( data );
3565         }
3566 
3567         return WERR_OK;
3568 }
3569 
3570 /****************************************************************************
3571  ***************************************************************************/
3572 
3573 WERROR delete_printer_data( NT_PRINTER_INFO_LEVEL_2 *p2, const char *key, const char *value )
     /* [<][>][^][v][top][bottom][index][help] */
3574 {
3575         WERROR          result = WERR_OK;
3576         int             key_index;
3577 
3578         /* we must have names on non-zero length */
3579 
3580         if ( !key || !*key|| !value || !*value )
3581                 return WERR_INVALID_NAME;
3582 
3583         /* find the printer key first */
3584 
3585         key_index = lookup_printerkey( p2->data, key );
3586         if ( key_index == -1 )
3587                 return WERR_OK;
3588 
3589         /* make sure the value exists so we can return the correct error code */
3590 
3591         if ( !regval_ctr_getvalue( p2->data->keys[key_index].values, value ) )
3592                 return WERR_BADFILE;
3593 
3594         regval_ctr_delvalue( p2->data->keys[key_index].values, value );
3595 
3596         DEBUG(8,("delete_printer_data: Removed key => [%s], value => [%s]\n",
3597                 key, value ));
3598 
3599         return result;
3600 }
3601 
3602 /****************************************************************************
3603  ***************************************************************************/
3604 
3605 WERROR add_printer_data( NT_PRINTER_INFO_LEVEL_2 *p2, const char *key, const char *value,
     /* [<][>][^][v][top][bottom][index][help] */
3606                            uint32 type, uint8 *data, int real_len )
3607 {
3608         WERROR          result = WERR_OK;
3609         int             key_index;
3610 
3611         /* we must have names on non-zero length */
3612 
3613         if ( !key || !*key|| !value || !*value )
3614                 return WERR_INVALID_NAME;
3615 
3616         /* find the printer key first */
3617 
3618         key_index = lookup_printerkey( p2->data, key );
3619         if ( key_index == -1 )
3620                 key_index = add_new_printer_key( p2->data, key );
3621 
3622         if ( key_index == -1 )
3623                 return WERR_NOMEM;
3624 
3625         regval_ctr_addvalue( p2->data->keys[key_index].values, value,
3626                 type, (const char *)data, real_len );
3627 
3628         DEBUG(8,("add_printer_data: Added key => [%s], value => [%s], type=> [%d], size => [%d]\n",
3629                 key, value, type, real_len  ));
3630 
3631         return result;
3632 }
3633 
3634 /****************************************************************************
3635  ***************************************************************************/
3636 
3637 REGISTRY_VALUE* get_printer_data( NT_PRINTER_INFO_LEVEL_2 *p2, const char *key, const char *value )
     /* [<][>][^][v][top][bottom][index][help] */
3638 {
3639         int             key_index;
3640 
3641         if ( (key_index = lookup_printerkey( p2->data, key )) == -1 )
3642                 return NULL;
3643 
3644         DEBUG(8,("get_printer_data: Attempting to lookup key => [%s], value => [%s]\n",
3645                 key, value ));
3646 
3647         return regval_ctr_getvalue( p2->data->keys[key_index].values, value );
3648 }
3649 
3650 /****************************************************************************
3651  Unpack a list of registry values frem the TDB
3652  ***************************************************************************/
3653 
3654 static int unpack_values(NT_PRINTER_DATA *printer_data, const uint8 *buf, int buflen)
     /* [<][>][^][v][top][bottom][index][help] */
3655 {
3656         int             len = 0;
3657         uint32          type;
3658         fstring string;
3659         const char *valuename = NULL;
3660         const char *keyname = NULL;
3661         char            *str;
3662         int             size;
3663         uint8           *data_p;
3664         REGISTRY_VALUE  *regval_p;
3665         int             key_index;
3666 
3667         /* add the "PrinterDriverData" key first for performance reasons */
3668 
3669         add_new_printer_key( printer_data, SPOOL_PRINTERDATA_KEY );
3670 
3671         /* loop and unpack the rest of the registry values */
3672 
3673         while ( True ) {
3674 
3675                 /* check to see if there are any more registry values */
3676 
3677                 regval_p = NULL;
3678                 len += tdb_unpack(buf+len, buflen-len, "p", &regval_p);
3679                 if ( !regval_p )
3680                         break;
3681 
3682                 /* unpack the next regval */
3683 
3684                 len += tdb_unpack(buf+len, buflen-len, "fdB",
3685                                   string,
3686                                   &type,
3687                                   &size,
3688                                   &data_p);
3689 
3690                 /* lookup for subkey names which have a type of REG_NONE */
3691                 /* there's no data with this entry */
3692 
3693                 if ( type == REG_NONE ) {
3694                         if ( (key_index=lookup_printerkey( printer_data, string)) == -1 )
3695                                 add_new_printer_key( printer_data, string );
3696                         continue;
3697                 }
3698 
3699                 /*
3700                  * break of the keyname from the value name.
3701                  * Valuenames can have embedded '\'s so be careful.
3702                  * only support one level of keys.  See the
3703                  * "Konica Fiery S300 50C-K v1.1. enu" 2k driver.
3704                  * -- jerry
3705                  */
3706 
3707                 str = strchr_m( string, '\\');
3708 
3709                 /* Put in "PrinterDriverData" is no key specified */
3710 
3711                 if ( !str ) {
3712                         keyname = SPOOL_PRINTERDATA_KEY;
3713                         valuename = string;
3714                 }
3715                 else {
3716                         *str = '\0';
3717                         keyname = string;
3718                         valuename = str+1;
3719                 }
3720 
3721                 /* see if we need a new key */
3722 
3723                 if ( (key_index=lookup_printerkey( printer_data, keyname )) == -1 )
3724                         key_index = add_new_printer_key( printer_data, keyname );
3725 
3726                 if ( key_index == -1 ) {
3727                         DEBUG(0,("unpack_values: Failed to allocate a new key [%s]!\n",
3728                                 keyname));
3729                         break;
3730                 }
3731 
3732                 DEBUG(8,("specific: [%s:%s], len: %d\n", keyname, valuename, size));
3733 
3734                 /* Vista doesn't like unknown REG_BINARY values in DsSpooler.
3735                    Thanks to Martin Zielinski for the hint. */
3736 
3737                 if ( type == REG_BINARY &&
3738                      strequal( keyname, SPOOL_DSSPOOLER_KEY ) &&
3739                      strequal( valuename, "objectGUID" ) )
3740                 {
3741                         struct GUID guid;
3742                         UNISTR2 unistr_guid;
3743 
3744                         ZERO_STRUCT( unistr_guid );
3745 
3746                         /* convert the GUID to a UNICODE string */
3747 
3748                         memcpy( &guid, data_p, sizeof(struct GUID) );
3749 
3750                         init_unistr2( &unistr_guid,
3751                                       GUID_string(talloc_tos(), &guid),
3752                                       UNI_STR_TERMINATE );
3753 
3754                         regval_ctr_addvalue( printer_data->keys[key_index].values,
3755                                              valuename, REG_SZ,
3756                                              (const char *)unistr_guid.buffer,
3757                                              unistr_guid.uni_str_len*2 );
3758 
3759                 } else {
3760                         /* add the value */
3761 
3762                         regval_ctr_addvalue( printer_data->keys[key_index].values,
3763                                              valuename, type, (const char *)data_p,
3764                                              size );
3765                 }
3766 
3767                 SAFE_FREE(data_p); /* 'B' option to tdbpack does a malloc() */
3768 
3769         }
3770 
3771         return len;
3772 }
3773 
3774 /****************************************************************************
3775  ***************************************************************************/
3776 
3777 static char *last_from;
3778 static char *last_to;
3779 
3780 static const char *get_last_from(void)
     /* [<][>][^][v][top][bottom][index][help] */
3781 {
3782         if (!last_from) {
3783                 return "";
3784         }
3785         return last_from;
3786 }
3787 
3788 static const char *get_last_to(void)
     /* [<][>][^][v][top][bottom][index][help] */
3789 {
3790         if (!last_to) {
3791                 return "";
3792         }
3793         return last_to;
3794 }
3795 
3796 static bool set_last_from_to(const char *from, const char *to)
     /* [<][>][^][v][top][bottom][index][help] */
3797 {
3798         char *orig_from = last_from;
3799         char *orig_to = last_to;
3800 
3801         last_from = SMB_STRDUP(from);
3802         last_to = SMB_STRDUP(to);
3803 
3804         SAFE_FREE(orig_from);
3805         SAFE_FREE(orig_to);
3806 
3807         if (!last_from || !last_to) {
3808                 SAFE_FREE(last_from);
3809                 SAFE_FREE(last_to);
3810                 return false;
3811         }
3812         return true;
3813 }
3814 
3815 static void map_to_os2_driver(fstring drivername)
     /* [<][>][^][v][top][bottom][index][help] */
3816 {
3817         char *mapfile = lp_os2_driver_map();
3818         char **lines = NULL;
3819         int numlines = 0;
3820         int i;
3821 
3822         if (!strlen(drivername))
3823                 return;
3824 
3825         if (!*mapfile)
3826                 return;
3827 
3828         if (strequal(drivername,get_last_from())) {
3829                 DEBUG(3,("Mapped Windows driver %s to OS/2 driver %s\n",
3830                         drivername,get_last_to()));
3831                 fstrcpy(drivername,get_last_to());
3832                 return;
3833         }
3834 
3835         lines = file_lines_load(mapfile, &numlines,0,NULL);
3836         if (numlines == 0 || lines == NULL) {
3837                 DEBUG(0,("No entries in OS/2 driver map %s\n",mapfile));
3838                 TALLOC_FREE(lines);
3839                 return;
3840         }
3841 
3842         DEBUG(4,("Scanning OS/2 driver map %s\n",mapfile));
3843 
3844         for( i = 0; i < numlines; i++) {
3845                 char *nt_name = lines[i];
3846                 char *os2_name = strchr(nt_name,'=');
3847 
3848                 if (!os2_name)
3849                         continue;
3850 
3851                 *os2_name++ = 0;
3852 
3853                 while (isspace(*nt_name))
3854                         nt_name++;
3855 
3856                 if (!*nt_name || strchr("#;",*nt_name))
3857                         continue;
3858 
3859                 {
3860                         int l = strlen(nt_name);
3861                         while (l && isspace(nt_name[l-1])) {
3862                                 nt_name[l-1] = 0;
3863                                 l--;
3864                         }
3865                 }
3866 
3867                 while (isspace(*os2_name))
3868                         os2_name++;
3869 
3870                 {
3871                         int l = strlen(os2_name);
3872                         while (l && isspace(os2_name[l-1])) {
3873                                 os2_name[l-1] = 0;
3874                                 l--;
3875                         }
3876                 }
3877 
3878                 if (strequal(nt_name,drivername)) {
3879                         DEBUG(3,("Mapped windows driver %s to os2 driver%s\n",drivername,os2_name));
3880                         set_last_from_to(drivername,os2_name);
3881                         fstrcpy(drivername,os2_name);
3882                         TALLOC_FREE(lines);
3883                         return;
3884                 }
3885         }
3886 
3887         TALLOC_FREE(lines);
3888 }
3889 
3890 /****************************************************************************
3891  Get a default printer info 2 struct.
3892 ****************************************************************************/
3893 
3894 static WERROR get_a_printer_2_default(NT_PRINTER_INFO_LEVEL_2 *info,
     /* [<][>][^][v][top][bottom][index][help] */
3895                                 const char *servername,
3896                                 const char* sharename,
3897                                 bool get_loc_com)
3898 {
3899         int snum = lp_servicenumber(sharename);
3900 
3901         slprintf(info->servername, sizeof(info->servername)-1, "\\\\%s", servername);
3902         slprintf(info->printername, sizeof(info->printername)-1, "\\\\%s\\%s",
3903                 servername, sharename);
3904         fstrcpy(info->sharename, sharename);
3905         fstrcpy(info->portname, SAMBA_PRINTER_PORT_NAME);
3906 
3907         /* by setting the driver name to an empty string, a local NT admin
3908            can now run the **local** APW to install a local printer driver
3909            for a Samba shared printer in 2.2.  Without this, drivers **must** be
3910            installed on the Samba server for NT clients --jerry */
3911 #if 0   /* JERRY --do not uncomment-- */
3912         if (!*info->drivername)
3913                 fstrcpy(info->drivername, "NO DRIVER AVAILABLE FOR THIS PRINTER");
3914 #endif
3915 
3916 
3917         DEBUG(10,("get_a_printer_2_default: driver name set to [%s]\n", info->drivername));
3918 
3919         strlcpy(info->comment, "", sizeof(info->comment));
3920         fstrcpy(info->printprocessor, "winprint");
3921         fstrcpy(info->datatype, "RAW");
3922 
3923 #ifdef HAVE_CUPS
3924         if (get_loc_com && (enum printing_types)lp_printing(snum) == PRINT_CUPS ) {
3925                 /* Pull the location and comment strings from cups if we don't
3926                    already have one */
3927                 if ( !strlen(info->location) || !strlen(info->comment) )
3928                         cups_pull_comment_location( info );
3929         }
3930 #endif
3931 
3932         info->attributes = PRINTER_ATTRIBUTE_SAMBA;
3933 
3934         info->starttime = 0; /* Minutes since 12:00am GMT */
3935         info->untiltime = 0; /* Minutes since 12:00am GMT */
3936         info->priority = 1;
3937         info->default_priority = 1;
3938         info->setuptime = (uint32)time(NULL);
3939 
3940         /*
3941          * I changed this as I think it is better to have a generic
3942          * DEVMODE than to crash Win2k explorer.exe   --jerry
3943          * See the HP Deskjet 990c Win2k drivers for an example.
3944          *
3945          * However the default devmode appears to cause problems
3946          * with the HP CLJ 8500 PCL driver.  Hence the addition of
3947          * the "default devmode" parameter   --jerry 22/01/2002
3948          */
3949 
3950         if (lp_default_devmode(snum)) {
3951                 if ((info->devmode = construct_nt_devicemode(info->printername)) == NULL) {
3952                         goto fail;
3953                 }
3954         } else {
3955                 info->devmode = NULL;
3956         }
3957 
3958         if (!nt_printing_getsec(info, sharename, &info->secdesc_buf)) {
3959                 goto fail;
3960         }
3961 
3962         return WERR_OK;
3963 
3964 fail:
3965         if (info->devmode)
3966                 free_nt_devicemode(&info->devmode);
3967 
3968         return WERR_ACCESS_DENIED;
3969 }
3970 
3971 /****************************************************************************
3972 ****************************************************************************/
3973 
3974 static WERROR get_a_printer_2(NT_PRINTER_INFO_LEVEL_2 *info,
     /* [<][>][^][v][top][bottom][index][help] */
3975                                 const char *servername,
3976                                 const char *sharename,
3977                                 bool get_loc_com)
3978 {
3979         int len = 0;
3980         int snum = lp_servicenumber(sharename);
3981         TDB_DATA kbuf, dbuf;
3982         fstring printername;
3983         char adevice[MAXDEVICENAME];
3984         char *comment = NULL;
3985 
3986         kbuf = make_printer_tdbkey(talloc_tos(), sharename);
3987 
3988         dbuf = tdb_fetch(tdb_printers, kbuf);
3989         if (!dbuf.dptr) {
3990                 return get_a_printer_2_default(info, servername,
3991                                         sharename, get_loc_com);
3992         }
3993 
3994         len += tdb_unpack(dbuf.dptr+len, dbuf.dsize-len, "dddddddddddfffffPfffff",
3995                         &info->attributes,
3996                         &info->priority,
3997                         &info->default_priority,
3998                         &info->starttime,
3999                         &info->untiltime,
4000                         &info->status,
4001                         &info->cjobs,
4002                         &info->averageppm,
4003                         &info->changeid,
4004                         &info->c_setprinter,
4005                         &info->setuptime,
4006                         info->servername,
4007                         info->printername,
4008                         info->sharename,
4009                         info->portname,
4010                         info->drivername,
4011                         &comment,
4012                         info->location,
4013                         info->sepfile,
4014                         info->printprocessor,
4015                         info->datatype,
4016                         info->parameters);
4017 
4018         if (comment) {
4019                 strlcpy(info->comment, comment, sizeof(info->comment));
4020                 SAFE_FREE(comment);
4021         }
4022 
4023         /* Samba has to have shared raw drivers. */
4024         info->attributes |= PRINTER_ATTRIBUTE_SAMBA;
4025         info->attributes &= ~PRINTER_ATTRIBUTE_NOT_SAMBA;
4026 
4027         /* Restore the stripped strings. */
4028         slprintf(info->servername, sizeof(info->servername)-1, "\\\\%s", servername);
4029 
4030         if ( lp_force_printername(snum) ) {
4031                 slprintf(printername, sizeof(printername)-1, "\\\\%s\\%s", servername, sharename );
4032         } else {
4033                 slprintf(printername, sizeof(printername)-1, "\\\\%s\\%s", servername, info->printername);
4034         }
4035 
4036         fstrcpy(info->printername, printername);
4037 
4038 #ifdef HAVE_CUPS
4039         if (get_loc_com && (enum printing_types)lp_printing(snum) == PRINT_CUPS ) {
4040                 /* Pull the location and comment strings from cups if we don't
4041                    already have one */
4042                 if ( !strlen(info->location) || !strlen(info->comment) )
4043                         cups_pull_comment_location( info );
4044         }
4045 #endif
4046 
4047         len += unpack_devicemode(&info->devmode,dbuf.dptr+len, dbuf.dsize-len);
4048 
4049         /*
4050          * Some client drivers freak out if there is a NULL devmode
4051          * (probably the driver is not checking before accessing
4052          * the devmode pointer)   --jerry
4053          *
4054          * See comments in get_a_printer_2_default()
4055          */
4056 
4057         if (lp_default_devmode(snum) && !info->devmode) {
4058                 DEBUG(8,("get_a_printer_2: Constructing a default device mode for [%s]\n",
4059                         printername));
4060                 info->devmode = construct_nt_devicemode(printername);
4061         }
4062 
4063         slprintf( adevice, sizeof(adevice), "%s", info->printername );
4064         if (info->devmode) {
4065                 fstrcpy(info->devmode->devicename, adevice);
4066         }
4067 
4068         if ( !(info->data = TALLOC_ZERO_P( info, NT_PRINTER_DATA )) ) {
4069                 DEBUG(0,("unpack_values: talloc() failed!\n"));
4070                 SAFE_FREE(dbuf.dptr);
4071                 return WERR_NOMEM;
4072         }
4073         len += unpack_values( info->data, dbuf.dptr+len, dbuf.dsize-len );
4074 
4075         /* This will get the current RPC talloc context, but we should be
4076            passing this as a parameter... fixme... JRA ! */
4077 
4078         if (!nt_printing_getsec(info, sharename, &info->secdesc_buf)) {
4079                 SAFE_FREE(dbuf.dptr);
4080                 return WERR_NOMEM;
4081         }
4082 
4083         /* Fix for OS/2 drivers. */
4084 
4085         if (get_remote_arch() == RA_OS2) {
4086                 map_to_os2_driver(info->drivername);
4087         }
4088 
4089         SAFE_FREE(dbuf.dptr);
4090 
4091         DEBUG(9,("Unpacked printer [%s] name [%s] running driver [%s]\n",
4092                  sharename, info->printername, info->drivername));
4093 
4094         return WERR_OK;
4095 }
4096 
4097 /****************************************************************************
4098  Debugging function, dump at level 6 the struct in the logs.
4099 ****************************************************************************/
4100 static uint32 dump_a_printer(NT_PRINTER_INFO_LEVEL *printer, uint32 level)
     /* [<][>][^][v][top][bottom][index][help] */
4101 {
4102         uint32 result;
4103         NT_PRINTER_INFO_LEVEL_2 *info2;
4104 
4105         DEBUG(106,("Dumping printer at level [%d]\n", level));
4106 
4107         switch (level) {
4108                 case 2:
4109                 {
4110                         if (printer->info_2 == NULL)
4111                                 result=5;
4112                         else
4113                         {
4114                                 info2=printer->info_2;
4115 
4116                                 DEBUGADD(106,("attributes:[%d]\n", info2->attributes));
4117                                 DEBUGADD(106,("priority:[%d]\n", info2->priority));
4118                                 DEBUGADD(106,("default_priority:[%d]\n", info2->default_priority));
4119                                 DEBUGADD(106,("starttime:[%d]\n", info2->starttime));
4120                                 DEBUGADD(106,("untiltime:[%d]\n", info2->untiltime));
4121                                 DEBUGADD(106,("status:[%d]\n", info2->status));
4122                                 DEBUGADD(106,("cjobs:[%d]\n", info2->cjobs));
4123                                 DEBUGADD(106,("averageppm:[%d]\n", info2->averageppm));
4124                                 DEBUGADD(106,("changeid:[%d]\n", info2->changeid));
4125                                 DEBUGADD(106,("c_setprinter:[%d]\n", info2->c_setprinter));
4126                                 DEBUGADD(106,("setuptime:[%d]\n", info2->setuptime));
4127 
4128                                 DEBUGADD(106,("servername:[%s]\n", info2->servername));
4129                                 DEBUGADD(106,("printername:[%s]\n", info2->printername));
4130                                 DEBUGADD(106,("sharename:[%s]\n", info2->sharename));
4131                                 DEBUGADD(106,("portname:[%s]\n", info2->portname));
4132                                 DEBUGADD(106,("drivername:[%s]\n", info2->drivername));
4133                                 DEBUGADD(106,("comment:[%s]\n", info2->comment));
4134                                 DEBUGADD(106,("location:[%s]\n", info2->location));
4135                                 DEBUGADD(106,("sepfile:[%s]\n", info2->sepfile));
4136                                 DEBUGADD(106,("printprocessor:[%s]\n", info2->printprocessor));
4137                                 DEBUGADD(106,("datatype:[%s]\n", info2->datatype));
4138                                 DEBUGADD(106,("parameters:[%s]\n", info2->parameters));
4139                                 result=0;
4140                         }
4141                         break;
4142                 }
4143                 default:
4144                         DEBUGADD(106,("dump_a_printer: Level %u not implemented\n", (unsigned int)level ));
4145                         result=1;
4146                         break;
4147         }
4148 
4149         return result;
4150 }
4151 
4152 /****************************************************************************
4153  Update the changeid time.
4154  This is SO NASTY as some drivers need this to change, others need it
4155  static. This value will change every second, and I must hope that this
4156  is enough..... DON'T CHANGE THIS CODE WITHOUT A TEST MATRIX THE SIZE OF
4157  UTAH ! JRA.
4158 ****************************************************************************/
4159 
4160 static uint32 rev_changeid(void)
     /* [<][>][^][v][top][bottom][index][help] */
4161 {
4162         struct timeval tv;
4163 
4164         get_process_uptime(&tv);
4165 
4166 #if 1   /* JERRY */
4167         /* Return changeid as msec since spooler restart */
4168         return tv.tv_sec * 1000 + tv.tv_usec / 1000;
4169 #else
4170         /*
4171          * This setting seems to work well but is too untested
4172          * to replace the above calculation.  Left in for experiementation
4173          * of the reader            --jerry (Tue Mar 12 09:15:05 CST 2002)
4174          */
4175         return tv.tv_sec * 10 + tv.tv_usec / 100000;
4176 #endif
4177 }
4178 
4179 
4180 /*
4181  * The function below are the high level ones.
4182  * only those ones must be called from the spoolss code.
4183  * JFM.
4184  */
4185 
4186 /****************************************************************************
4187  Modify a printer. This is called from SETPRINTERDATA/DELETEPRINTERDATA.
4188 ****************************************************************************/
4189 
4190 WERROR mod_a_printer(NT_PRINTER_INFO_LEVEL *printer, uint32 level)
     /* [<][>][^][v][top][bottom][index][help] */
4191 {
4192         WERROR result;
4193 
4194         dump_a_printer(printer, level);
4195 
4196         switch (level) {
4197                 case 2:
4198                 {
4199                         /*
4200                          * Update the changestamp.  Emperical tests show that the
4201                          * ChangeID is always updated,but c_setprinter is
4202                          *  global spooler variable (not per printer).
4203                          */
4204 
4205                         /* ChangeID **must** be increasing over the lifetime
4206                            of client's spoolss service in order for the
4207                            client's cache to show updates */
4208 
4209                         printer->info_2->changeid = rev_changeid();
4210 
4211                         /*
4212                          * Because one day someone will ask:
4213                          * NT->NT       An admin connection to a remote
4214                          *              printer show changes imeediately in
4215                          *              the properities dialog
4216                          *
4217                          *              A non-admin connection will only show the
4218                          *              changes after viewing the properites page
4219                          *              2 times.  Seems to be related to a
4220                          *              race condition in the client between the spooler
4221                          *              updating the local cache and the Explorer.exe GUI
4222                          *              actually displaying the properties.
4223                          *
4224                          *              This is fixed in Win2k.  admin/non-admin
4225                          *              connections both display changes immediately.
4226                          *
4227                          * 14/12/01     --jerry
4228                          */
4229 
4230                         result=update_a_printer_2(printer->info_2);
4231                         break;
4232                 }
4233                 default:
4234                         result=WERR_UNKNOWN_LEVEL;
4235                         break;
4236         }
4237 
4238         return result;
4239 }
4240 
4241 /****************************************************************************
4242  Initialize printer devmode & data with previously saved driver init values.
4243 ****************************************************************************/
4244 
4245 static bool set_driver_init_2( NT_PRINTER_INFO_LEVEL_2 *info_ptr )
     /* [<][>][^][v][top][bottom][index][help] */
4246 {
4247         int                     len = 0;
4248         char *key = NULL;
4249         TDB_DATA                dbuf;
4250         NT_PRINTER_INFO_LEVEL_2 info;
4251 
4252 
4253         ZERO_STRUCT(info);
4254 
4255         /*
4256          * Delete any printer data 'values' already set. When called for driver
4257          * replace, there will generally be some, but during an add printer, there
4258          * should not be any (if there are delete them).
4259          */
4260 
4261         if ( info_ptr->data )
4262                 delete_all_printer_data( info_ptr, "" );
4263 
4264         if (asprintf(&key, "%s%s", DRIVER_INIT_PREFIX,
4265                                 info_ptr->drivername) < 0) {
4266                 return false;
4267         }
4268 
4269         dbuf = tdb_fetch_bystring(tdb_drivers, key);
4270         if (!dbuf.dptr) {
4271                 /*
4272                  * When changing to a driver that has no init info in the tdb, remove
4273                  * the previous drivers init info and leave the new on blank.
4274                  */
4275                 free_nt_devicemode(&info_ptr->devmode);
4276                 SAFE_FREE(key);
4277                 return false;
4278         }
4279 
4280         SAFE_FREE(key);
4281         /*
4282          * Get the saved DEVMODE..
4283          */
4284 
4285         len += unpack_devicemode(&info.devmode,dbuf.dptr+len, dbuf.dsize-len);
4286 
4287         /*
4288          * The saved DEVMODE contains the devicename from the printer used during
4289          * the initialization save. Change it to reflect the new printer.
4290          */
4291 
4292         if ( info.devmode ) {
4293                 ZERO_STRUCT(info.devmode->devicename);
4294                 fstrcpy(info.devmode->devicename, info_ptr->printername);
4295         }
4296 
4297         /*
4298          * NT/2k does not change out the entire DeviceMode of a printer
4299          * when changing the driver.  Only the driverextra, private, &
4300          * driverversion fields.   --jerry  (Thu Mar 14 08:58:43 CST 2002)
4301          *
4302          * Later examination revealed that Windows NT/2k does reset the
4303          * the printer's device mode, bit **only** when you change a
4304          * property of the device mode such as the page orientation.
4305          * --jerry
4306          */
4307 
4308 
4309         /* Bind the saved DEVMODE to the new the printer */
4310 
4311         free_nt_devicemode(&info_ptr->devmode);
4312         info_ptr->devmode = info.devmode;
4313 
4314         DEBUG(10,("set_driver_init_2: Set printer [%s] init %s DEVMODE for driver [%s]\n",
4315                 info_ptr->printername, info_ptr->devmode?"VALID":"NULL", info_ptr->drivername));
4316 
4317         /* Add the printer data 'values' to the new printer */
4318 
4319         if ( !(info_ptr->data = TALLOC_ZERO_P( info_ptr, NT_PRINTER_DATA )) ) {
4320                 DEBUG(0,("set_driver_init_2: talloc() failed!\n"));
4321                 return False;
4322         }
4323 
4324         len += unpack_values( info_ptr->data, dbuf.dptr+len, dbuf.dsize-len );
4325 
4326         SAFE_FREE(dbuf.dptr);
4327 
4328         return true;
4329 }
4330 
4331 /****************************************************************************
4332  Initialize printer devmode & data with previously saved driver init values.
4333  When a printer is created using AddPrinter, the drivername bound to the
4334  printer is used to lookup previously saved driver initialization info, which
4335  is bound to the new printer.
4336 ****************************************************************************/
4337 
4338 bool set_driver_init(NT_PRINTER_INFO_LEVEL *printer, uint32 level)
     /* [<][>][^][v][top][bottom][index][help] */
4339 {
4340         bool result = False;
4341 
4342         switch (level) {
4343                 case 2:
4344                         result = set_driver_init_2(printer->info_2);
4345                         break;
4346 
4347                 default:
4348                         DEBUG(0,("set_driver_init: Programmer's error!  Unknown driver_init level [%d]\n",
4349                                 level));
4350                         break;
4351         }
4352 
4353         return result;
4354 }
4355 
4356 /****************************************************************************
4357  Delete driver init data stored for a specified driver
4358 ****************************************************************************/
4359 
4360 bool del_driver_init(const char *drivername)
     /* [<][>][^][v][top][bottom][index][help] */
4361 {
4362         char *key;
4363         bool ret;
4364 
4365         if (!drivername || !*drivername) {
4366                 DEBUG(3,("del_driver_init: No drivername specified!\n"));
4367                 return false;
4368         }
4369 
4370         if (asprintf(&key, "%s%s", DRIVER_INIT_PREFIX, drivername) < 0) {
4371                 return false;
4372         }
4373 
4374         DEBUG(6,("del_driver_init: Removing driver init data for [%s]\n",
4375                                 drivername));
4376 
4377         ret = (tdb_delete_bystring(tdb_drivers, key) == 0);
4378         SAFE_FREE(key);
4379         return ret;
4380 }
4381 
4382 /****************************************************************************
4383  Pack up the DEVMODE and values for a printer into a 'driver init' entry
4384  in the tdb. Note: this is different from the driver entry and the printer
4385  entry. There should be a single driver init entry for each driver regardless
4386  of whether it was installed from NT or 2K. Technically, they should be
4387  different, but they work out to the same struct.
4388 ****************************************************************************/
4389 
4390 static uint32 update_driver_init_2(NT_PRINTER_INFO_LEVEL_2 *info)
     /* [<][>][^][v][top][bottom][index][help] */
4391 {
4392         char *key = NULL;
4393         uint8 *buf;
4394         int buflen, len, ret;
4395         int retlen;
4396         TDB_DATA dbuf;
4397 
4398         buf = NULL;
4399         buflen = 0;
4400 
4401  again:
4402         len = 0;
4403         len += pack_devicemode(info->devmode, buf+len, buflen-len);
4404 
4405         retlen = pack_values( info->data, buf+len, buflen-len );
4406         if (retlen == -1) {
4407                 ret = -1;
4408                 goto done;
4409         }
4410         len += retlen;
4411 
4412         if (buflen < len) {
4413                 buf = (uint8 *)SMB_REALLOC(buf, len);
4414                 if (!buf) {
4415                         DEBUG(0, ("update_driver_init_2: failed to enlarge buffer!\n"));
4416                         ret = -1;
4417                         goto done;
4418                 }
4419                 buflen = len;
4420                 goto again;
4421         }
4422 
4423         SAFE_FREE(key);
4424         if (asprintf(&key, "%s%s", DRIVER_INIT_PREFIX, info->drivername) < 0) {
4425                 ret = (uint32)-1;
4426                 goto done;
4427         }
4428 
4429         dbuf.dptr = buf;
4430         dbuf.dsize = len;
4431 
4432         ret = tdb_store_bystring(tdb_drivers, key, dbuf, TDB_REPLACE);
4433 
4434 done:
4435         if (ret == -1)
4436                 DEBUG(8, ("update_driver_init_2: error updating printer init to tdb on disk\n"));
4437 
4438         SAFE_FREE(buf);
4439 
4440         DEBUG(10,("update_driver_init_2: Saved printer [%s] init DEVMODE & values for driver [%s]\n",
4441                  info->sharename, info->drivername));
4442 
4443         return ret;
4444 }
4445 
4446 /****************************************************************************
4447  Update (i.e. save) the driver init info (DEVMODE and values) for a printer
4448 ****************************************************************************/
4449 
4450 static uint32 update_driver_init(NT_PRINTER_INFO_LEVEL *printer, uint32 level)
     /* [<][>][^][v][top][bottom][index][help] */
4451 {
4452         uint32 result;
4453 
4454         dump_a_printer(printer, level);
4455 
4456         switch (level) {
4457                 case 2:
4458                         result = update_driver_init_2(printer->info_2);
4459                         break;
4460                 default:
4461                         result = 1;
4462                         break;
4463         }
4464 
4465         return result;
4466 }
4467 
4468 /****************************************************************************
4469  Convert the printer data value, a REG_BINARY array, into an initialization
4470  DEVMODE. Note: the array must be parsed as if it was a DEVMODE in an rpc...
4471  got to keep the endians happy :).
4472 ****************************************************************************/
4473 
4474 static bool convert_driver_init(TALLOC_CTX *mem_ctx, NT_DEVICEMODE *nt_devmode,
     /* [<][>][^][v][top][bottom][index][help] */
4475                                 const uint8_t *data, uint32_t data_len)
4476 {
4477         struct spoolss_DeviceMode devmode;
4478         enum ndr_err_code ndr_err;
4479         DATA_BLOB blob;
4480 
4481         ZERO_STRUCT(devmode);
4482 
4483         blob = data_blob_const(data, data_len);
4484 
4485         ndr_err = ndr_pull_struct_blob(&blob, mem_ctx, NULL, &devmode,
4486                         (ndr_pull_flags_fn_t)ndr_pull_spoolss_DeviceMode);
4487         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
4488                 DEBUG(10,("convert_driver_init: error parsing spoolss_DeviceMode\n"));
4489                 return false;
4490         }
4491 
4492         return convert_devicemode("", &devmode, &nt_devmode);
4493 }
4494 
4495 /****************************************************************************
4496  Set the DRIVER_INIT info in the tdb. Requires Win32 client code that:
4497 
4498  1. Use the driver's config DLL to this UNC printername and:
4499     a. Call DrvPrintEvent with PRINTER_EVENT_INITIALIZE
4500     b. Call DrvConvertDevMode with CDM_DRIVER_DEFAULT to get default DEVMODE
4501  2. Call SetPrinterData with the 'magic' key and the DEVMODE as data.
4502 
4503  The last step triggers saving the "driver initialization" information for
4504  this printer into the tdb. Later, new printers that use this driver will
4505  have this initialization information bound to them. This simulates the
4506  driver initialization, as if it had run on the Samba server (as it would
4507  have done on NT).
4508 
4509  The Win32 client side code requirement sucks! But until we can run arbitrary
4510  Win32 printer driver code on any Unix that Samba runs on, we are stuck with it.
4511 
4512  It would have been easier to use SetPrinter because all the UNMARSHALLING of
4513  the DEVMODE is done there, but 2K/XP clients do not set the DEVMODE... think
4514  about it and you will realize why.  JRR 010720
4515 ****************************************************************************/
4516 
4517 static WERROR save_driver_init_2(NT_PRINTER_INFO_LEVEL *printer, uint8 *data, uint32 data_len )
     /* [<][>][^][v][top][bottom][index][help] */
4518 {
4519         WERROR        status       = WERR_OK;
4520         TALLOC_CTX    *ctx         = NULL;
4521         NT_DEVICEMODE *nt_devmode  = NULL;
4522         NT_DEVICEMODE *tmp_devmode = printer->info_2->devmode;
4523 
4524         /*
4525          * When the DEVMODE is already set on the printer, don't try to unpack it.
4526          */
4527         DEBUG(8,("save_driver_init_2: Enter...\n"));
4528 
4529         if ( !printer->info_2->devmode && data_len ) {
4530                 /*
4531                  * Set devmode on printer info, so entire printer initialization can be
4532                  * saved to tdb.
4533                  */
4534 
4535                 if ((ctx = talloc_init("save_driver_init_2")) == NULL)
4536                         return WERR_NOMEM;
4537 
4538                 if ((nt_devmode = SMB_MALLOC_P(NT_DEVICEMODE)) == NULL) {
4539                         status = WERR_NOMEM;
4540                         goto done;
4541                 }
4542 
4543                 ZERO_STRUCTP(nt_devmode);
4544 
4545                 /*
4546                  * The DEVMODE is held in the 'data' component of the param in raw binary.
4547                  * Convert it to to a devmode structure
4548                  */
4549                 if ( !convert_driver_init( ctx, nt_devmode, data, data_len )) {
4550                         DEBUG(10,("save_driver_init_2: error converting DEVMODE\n"));
4551                         status = WERR_INVALID_PARAM;
4552                         goto done;
4553                 }
4554 
4555                 printer->info_2->devmode = nt_devmode;
4556         }
4557 
4558         /*
4559          * Pack up and add (or update) the DEVMODE and any current printer data to
4560          * a 'driver init' element in the tdb
4561          *
4562          */
4563 
4564         if ( update_driver_init(printer, 2) != 0 ) {
4565                 DEBUG(10,("save_driver_init_2: error updating DEVMODE\n"));
4566                 status = WERR_NOMEM;
4567                 goto done;
4568         }
4569 
4570         /*
4571          * If driver initialization info was successfully saved, set the current
4572          * printer to match it. This allows initialization of the current printer
4573          * as well as the driver.
4574          */
4575         status = mod_a_printer(printer, 2);
4576         if (!W_ERROR_IS_OK(status)) {
4577                 DEBUG(10,("save_driver_init_2: error setting DEVMODE on printer [%s]\n",
4578                                   printer->info_2->printername));
4579         }
4580 
4581   done:
4582         talloc_destroy(ctx);
4583         free_nt_devicemode( &nt_devmode );
4584 
4585         printer->info_2->devmode = tmp_devmode;
4586 
4587         return status;
4588 }
4589 
4590 /****************************************************************************
4591  Update the driver init info (DEVMODE and specifics) for a printer
4592 ****************************************************************************/
4593 
4594 WERROR save_driver_init(NT_PRINTER_INFO_LEVEL *printer, uint32 level, uint8 *data, uint32 data_len)
     /* [<][>][^][v][top][bottom][index][help] */
4595 {
4596         WERROR status = WERR_OK;
4597 
4598         switch (level) {
4599                 case 2:
4600                         status = save_driver_init_2( printer, data, data_len );
4601                         break;
4602                 default:
4603                         status = WERR_UNKNOWN_LEVEL;
4604                         break;
4605         }
4606 
4607         return status;
4608 }
4609 
4610 /****************************************************************************
4611  Get a NT_PRINTER_INFO_LEVEL struct. It returns malloced memory.
4612 
4613  Previously the code had a memory allocation problem because it always
4614  used the TALLOC_CTX from the Printer_entry*.   This context lasts
4615  as a long as the original handle is open.  So if the client made a lot
4616  of getprinter[data]() calls, the memory usage would climb.  Now we use
4617  a short lived TALLOC_CTX for printer_info_2 objects returned.  We
4618  still use the Printer_entry->ctx for maintaining the cache copy though
4619  since that object must live as long as the handle by definition.
4620                                                     --jerry
4621 
4622 ****************************************************************************/
4623 
4624 static WERROR get_a_printer_internal( Printer_entry *print_hnd, NT_PRINTER_INFO_LEVEL **pp_printer, uint32 level,
     /* [<][>][^][v][top][bottom][index][help] */
4625                         const char *sharename, bool get_loc_com)
4626 {
4627         WERROR result;
4628         fstring servername;
4629 
4630         DEBUG(10,("get_a_printer: [%s] level %u\n", sharename, (unsigned int)level));
4631 
4632         if ( !(*pp_printer = TALLOC_ZERO_P(NULL, NT_PRINTER_INFO_LEVEL)) ) {
4633                 DEBUG(0,("get_a_printer: talloc() fail.\n"));
4634                 return WERR_NOMEM;
4635         }
4636 
4637         switch (level) {
4638                 case 2:
4639                         if ( !((*pp_printer)->info_2 = TALLOC_ZERO_P(*pp_printer, NT_PRINTER_INFO_LEVEL_2)) ) {
4640                                 DEBUG(0,("get_a_printer: talloc() fail.\n"));
4641                                 TALLOC_FREE( *pp_printer );
4642                                 return WERR_NOMEM;
4643                         }
4644 
4645                         if ( print_hnd )
4646                                 fstrcpy( servername, print_hnd->servername );
4647                         else {
4648                                 fstrcpy( servername, "%L" );
4649                                 standard_sub_basic( "", "", servername,
4650                                                     sizeof(servername)-1 );
4651                         }
4652 
4653                         result = get_a_printer_2( (*pp_printer)->info_2,
4654                                         servername, sharename, get_loc_com);
4655 
4656                         /* we have a new printer now.  Save it with this handle */
4657 
4658                         if ( !W_ERROR_IS_OK(result) ) {
4659                                 TALLOC_FREE( *pp_printer );
4660                                 DEBUG(10,("get_a_printer: [%s] level %u returning %s\n",
4661                                         sharename, (unsigned int)level, win_errstr(result)));
4662                                 return result;
4663                         }
4664 
4665                         dump_a_printer( *pp_printer, level);
4666 
4667                         break;
4668 
4669                 default:
4670                         TALLOC_FREE( *pp_printer );
4671                         return WERR_UNKNOWN_LEVEL;
4672         }
4673 
4674         return WERR_OK;
4675 }
4676 
4677 WERROR get_a_printer( Printer_entry *print_hnd,
     /* [<][>][^][v][top][bottom][index][help] */
4678                         NT_PRINTER_INFO_LEVEL **pp_printer,
4679                         uint32 level,
4680                         const char *sharename)
4681 {
4682         return get_a_printer_internal(print_hnd, pp_printer, level,
4683                                         sharename, true);
4684 }
4685 
4686 WERROR get_a_printer_search( Printer_entry *print_hnd,
     /* [<][>][^][v][top][bottom][index][help] */
4687                         NT_PRINTER_INFO_LEVEL **pp_printer,
4688                         uint32 level,
4689                         const char *sharename)
4690 {
4691         return get_a_printer_internal(print_hnd, pp_printer, level,
4692                                         sharename, false);
4693 }
4694 
4695 /****************************************************************************
4696  Deletes a NT_PRINTER_INFO_LEVEL struct.
4697 ****************************************************************************/
4698 
4699 uint32 free_a_printer(NT_PRINTER_INFO_LEVEL **pp_printer, uint32 level)
     /* [<][>][^][v][top][bottom][index][help] */
4700 {
4701         NT_PRINTER_INFO_LEVEL *printer = *pp_printer;
4702 
4703         if ( !printer )
4704                 return 0;
4705 
4706         switch (level) {
4707                 case 2:
4708                         if ( printer->info_2 )
4709                                 free_nt_printer_info_level_2(&printer->info_2);
4710                         break;
4711 
4712                 default:
4713                         DEBUG(0,("free_a_printer: unknown level! [%d]\n", level ));
4714                         return 1;
4715         }
4716 
4717         TALLOC_FREE(*pp_printer);
4718 
4719         return 0;
4720 }
4721 
4722 /****************************************************************************
4723 ****************************************************************************/
4724 uint32 add_a_printer_driver(NT_PRINTER_DRIVER_INFO_LEVEL driver, uint32 level)
     /* [<][>][^][v][top][bottom][index][help] */
4725 {
4726         uint32 result;
4727         DEBUG(104,("adding a printer at level [%d]\n", level));
4728         dump_a_printer_driver(driver, level);
4729 
4730         switch (level) {
4731                 case 3:
4732                         result=add_a_printer_driver_3(driver.info_3);
4733                         break;
4734 
4735                 case 6:
4736                         result=add_a_printer_driver_6(driver.info_6);
4737                         break;
4738 
4739                 default:
4740                         result=1;
4741                         break;
4742         }
4743 
4744         return result;
4745 }
4746 /****************************************************************************
4747 ****************************************************************************/
4748 
4749 WERROR get_a_printer_driver(NT_PRINTER_DRIVER_INFO_LEVEL *driver, uint32_t level,
     /* [<][>][^][v][top][bottom][index][help] */
4750                             const char *drivername, const char *architecture,
4751                             uint32_t version)
4752 {
4753         WERROR result;
4754 
4755         switch (level) {
4756                 case 3:
4757                         /* Sometime we just want any version of the driver */
4758 
4759                         if ( version == DRIVER_ANY_VERSION ) {
4760                                 /* look for Win2k first and then for NT4 */
4761                                 result = get_a_printer_driver_3(&driver->info_3, drivername,
4762                                                 architecture, 3);
4763 
4764                                 if ( !W_ERROR_IS_OK(result) ) {
4765                                         result = get_a_printer_driver_3( &driver->info_3,
4766                                                         drivername, architecture, 2 );
4767                                 }
4768                         } else {
4769                                 result = get_a_printer_driver_3(&driver->info_3, drivername,
4770                                         architecture, version);
4771                         }
4772                         break;
4773 
4774                 default:
4775                         result=W_ERROR(1);
4776                         break;
4777         }
4778 
4779         if (W_ERROR_IS_OK(result))
4780                 dump_a_printer_driver(*driver, level);
4781 
4782         return result;
4783 }
4784 
4785 /****************************************************************************
4786 ****************************************************************************/
4787 uint32 free_a_printer_driver(NT_PRINTER_DRIVER_INFO_LEVEL driver, uint32 level)
     /* [<][>][^][v][top][bottom][index][help] */
4788 {
4789         uint32 result;
4790 
4791         switch (level) {
4792                 case 3:
4793                 {
4794                         NT_PRINTER_DRIVER_INFO_LEVEL_3 *info3;
4795                         if (driver.info_3 != NULL)
4796                         {
4797                                 info3=driver.info_3;
4798                                 SAFE_FREE(info3->dependentfiles);
4799                                 ZERO_STRUCTP(info3);
4800                                 SAFE_FREE(info3);
4801                                 result=0;
4802                         } else {
4803                                 result=4;
4804                         }
4805                         break;
4806                 }
4807                 case 6:
4808                 {
4809                         NT_PRINTER_DRIVER_INFO_LEVEL_6 *info6;
4810                         if (driver.info_6 != NULL) {
4811                                 info6=driver.info_6;
4812                                 SAFE_FREE(info6->dependentfiles);
4813                                 SAFE_FREE(info6->previousnames);
4814                                 ZERO_STRUCTP(info6);
4815                                 SAFE_FREE(info6);
4816                                 result=0;
4817                         } else {
4818                                 result=4;
4819                         }
4820                         break;
4821                 }
4822                 default:
4823                         result=1;
4824                         break;
4825         }
4826         return result;
4827 }
4828 
4829 
4830 /****************************************************************************
4831   Determine whether or not a particular driver is currently assigned
4832   to a printer
4833 ****************************************************************************/
4834 
4835 bool printer_driver_in_use ( NT_PRINTER_DRIVER_INFO_LEVEL_3 *info_3 )
     /* [<][>][^][v][top][bottom][index][help] */
4836 {
4837         int snum;
4838         int n_services = lp_numservices();
4839         NT_PRINTER_INFO_LEVEL *printer = NULL;
4840         bool in_use = False;
4841 
4842         if ( !info_3 )
4843                 return False;
4844 
4845         DEBUG(10,("printer_driver_in_use: Beginning search through ntprinters.tdb...\n"));
4846 
4847         /* loop through the printers.tdb and check for the drivername */
4848 
4849         for (snum=0; snum<n_services && !in_use; snum++) {
4850                 if ( !(lp_snum_ok(snum) && lp_print_ok(snum) ) )
4851                         continue;
4852 
4853                 if ( !W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, lp_servicename(snum))) )
4854                         continue;
4855 
4856                 if ( strequal(info_3->name, printer->info_2->drivername) )
4857                         in_use = True;
4858 
4859                 free_a_printer( &printer, 2 );
4860         }
4861 
4862         DEBUG(10,("printer_driver_in_use: Completed search through ntprinters.tdb...\n"));
4863 
4864         if ( in_use ) {
4865                 NT_PRINTER_DRIVER_INFO_LEVEL d;
4866                 WERROR werr;
4867 
4868                 DEBUG(5,("printer_driver_in_use: driver \"%s\" is currently in use\n", info_3->name));
4869 
4870                 /* we can still remove the driver if there is one of
4871                    "Windows NT x86" version 2 or 3 left */
4872 
4873                 if ( !strequal( "Windows NT x86", info_3->environment ) ) {
4874                         werr = get_a_printer_driver( &d, 3, info_3->name, "Windows NT x86", DRIVER_ANY_VERSION );
4875                 }
4876                 else {
4877                         switch ( info_3->cversion ) {
4878                         case 2:
4879                                 werr = get_a_printer_driver( &d, 3, info_3->name, "Windows NT x86", 3 );
4880                                 break;
4881                         case 3:
4882                                 werr = get_a_printer_driver( &d, 3, info_3->name, "Windows NT x86", 2 );
4883                                 break;
4884                         default:
4885                                 DEBUG(0,("printer_driver_in_use: ERROR! unknown driver version (%d)\n",
4886                                         info_3->cversion));
4887                                 werr = WERR_UNKNOWN_PRINTER_DRIVER;
4888                                 break;
4889                         }
4890                 }
4891 
4892                 /* now check the error code */
4893 
4894                 if ( W_ERROR_IS_OK(werr) ) {
4895                         /* it's ok to remove the driver, we have other architctures left */
4896                         in_use = False;
4897                         free_a_printer_driver( d, 3 );
4898                 }
4899         }
4900 
4901         /* report that the driver is not in use by default */
4902 
4903         return in_use;
4904 }
4905 
4906 
4907 /**********************************************************************
4908  Check to see if a ogiven file is in use by *info
4909  *********************************************************************/
4910 
4911 static bool drv_file_in_use( char* file, NT_PRINTER_DRIVER_INFO_LEVEL_3 *info )
     /* [<][>][^][v][top][bottom][index][help] */
4912 {
4913         int i = 0;
4914 
4915         if ( !info )
4916                 return False;
4917 
4918         /* mz: skip files that are in the list but already deleted */
4919         if (!file || !file[0]) {
4920                 return false;
4921         }
4922 
4923         if ( strequal(file, info->driverpath) )
4924                 return True;
4925 
4926         if ( strequal(file, info->datafile) )
4927                 return True;
4928 
4929         if ( strequal(file, info->configfile) )
4930                 return True;
4931 
4932         if ( strequal(file, info->helpfile) )
4933                 return True;
4934 
4935         /* see of there are any dependent files to examine */
4936 
4937         if ( !info->dependentfiles )
4938                 return False;
4939 
4940         while ( *info->dependentfiles[i] ) {
4941                 if ( strequal(file, info->dependentfiles[i]) )
4942                         return True;
4943                 i++;
4944         }
4945 
4946         return False;
4947 
4948 }
4949 
4950 /**********************************************************************
4951  Utility function to remove the dependent file pointed to by the
4952  input parameter from the list
4953  *********************************************************************/
4954 
4955 static void trim_dependent_file( fstring files[], int idx )
     /* [<][>][^][v][top][bottom][index][help] */
4956 {
4957 
4958         /* bump everything down a slot */
4959 
4960         while( *files[idx+1] ) {
4961                 fstrcpy( files[idx], files[idx+1] );
4962                 idx++;
4963         }
4964 
4965         *files[idx] = '\0';
4966 
4967         return;
4968 }
4969 
4970 /**********************************************************************
4971  Check if any of the files used by src are also used by drv
4972  *********************************************************************/
4973 
4974 static bool trim_overlap_drv_files( NT_PRINTER_DRIVER_INFO_LEVEL_3 *src,
     /* [<][>][^][v][top][bottom][index][help] */
4975                                        NT_PRINTER_DRIVER_INFO_LEVEL_3 *drv )
4976 {
4977         bool    in_use = False;
4978         int     i = 0;
4979 
4980         if ( !src || !drv )
4981                 return False;
4982 
4983         /* check each file.  Remove it from the src structure if it overlaps */
4984 
4985         if ( drv_file_in_use(src->driverpath, drv) ) {
4986                 in_use = True;
4987                 DEBUG(10,("Removing driverfile [%s] from list\n", src->driverpath));
4988                 fstrcpy( src->driverpath, "" );
4989         }
4990 
4991         if ( drv_file_in_use(src->datafile, drv) ) {
4992                 in_use = True;
4993                 DEBUG(10,("Removing datafile [%s] from list\n", src->datafile));
4994                 fstrcpy( src->datafile, "" );
4995         }
4996 
4997         if ( drv_file_in_use(src->configfile, drv) ) {
4998                 in_use = True;
4999                 DEBUG(10,("Removing configfile [%s] from list\n", src->configfile));
5000                 fstrcpy( src->configfile, "" );
5001         }
5002 
5003         if ( drv_file_in_use(src->helpfile, drv) ) {
5004                 in_use = True;
5005                 DEBUG(10,("Removing helpfile [%s] from list\n", src->helpfile));
5006                 fstrcpy( src->helpfile, "" );
5007         }
5008 
5009         /* are there any dependentfiles to examine? */
5010 
5011         if ( !src->dependentfiles )
5012                 return in_use;
5013 
5014         while ( *src->dependentfiles[i] ) {
5015                 if ( drv_file_in_use(src->dependentfiles[i], drv) ) {
5016                         in_use = True;
5017                         DEBUG(10,("Removing [%s] from dependent file list\n", src->dependentfiles[i]));
5018                         trim_dependent_file( src->dependentfiles, i );
5019                 } else
5020                         i++;
5021         }
5022 
5023         return in_use;
5024 }
5025 
5026 /****************************************************************************
5027   Determine whether or not a particular driver files are currently being
5028   used by any other driver.
5029 
5030   Return value is True if any files were in use by other drivers
5031   and False otherwise.
5032 
5033   Upon return, *info has been modified to only contain the driver files
5034   which are not in use
5035 
5036   Fix from mz:
5037 
5038   This needs to check all drivers to ensure that all files in use
5039   have been removed from *info, not just the ones in the first
5040   match.
5041 ****************************************************************************/
5042 
5043 bool printer_driver_files_in_use ( NT_PRINTER_DRIVER_INFO_LEVEL_3 *info )
     /* [<][>][^][v][top][bottom][index][help] */
5044 {
5045         int                             i;
5046         int                             ndrivers;
5047         uint32                          version;
5048         fstring                         *list = NULL;
5049         NT_PRINTER_DRIVER_INFO_LEVEL    driver;
5050         bool in_use = false;
5051 
5052         if ( !info )
5053                 return False;
5054 
5055         version = info->cversion;
5056 
5057         /* loop over all driver versions */
5058 
5059         DEBUG(5,("printer_driver_files_in_use: Beginning search through ntdrivers.tdb...\n"));
5060 
5061         /* get the list of drivers */
5062 
5063         list = NULL;
5064         ndrivers = get_ntdrivers(&list, info->environment, version);
5065 
5066         DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n",
5067                 ndrivers, info->environment, version));
5068 
5069         /* check each driver for overlap in files */
5070 
5071         for (i=0; i<ndrivers; i++) {
5072                 DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
5073 
5074                 ZERO_STRUCT(driver);
5075 
5076                 if ( !W_ERROR_IS_OK(get_a_printer_driver(&driver, 3, list[i], info->environment, version)) ) {
5077                         SAFE_FREE(list);
5078                         return True;
5079                 }
5080 
5081                 /* check if d2 uses any files from d1 */
5082                 /* only if this is a different driver than the one being deleted */
5083 
5084                 if ( !strequal(info->name, driver.info_3->name) ) {
5085                         if ( trim_overlap_drv_files(info, driver.info_3) ) {
5086                                 /* mz: Do not instantly return -
5087                                  * we need to ensure this file isn't
5088                                  * also in use by other drivers. */
5089                                 in_use = true;
5090                         }
5091                 }
5092 
5093                 free_a_printer_driver(driver, 3);
5094         }
5095 
5096         SAFE_FREE(list);
5097 
5098         DEBUG(5,("printer_driver_files_in_use: Completed search through ntdrivers.tdb...\n"));
5099 
5100         driver.info_3 = info;
5101 
5102         if ( DEBUGLEVEL >= 20 )
5103                 dump_a_printer_driver( driver, 3 );
5104 
5105         return in_use;
5106 }
5107 
5108 /****************************************************************************
5109   Actually delete the driver files.  Make sure that
5110   printer_driver_files_in_use() return False before calling
5111   this.
5112 ****************************************************************************/
5113 
5114 static bool delete_driver_files(struct pipes_struct *rpc_pipe,
     /* [<][>][^][v][top][bottom][index][help] */
5115                                 NT_PRINTER_DRIVER_INFO_LEVEL_3 *info_3)
5116 {
5117         int i = 0;
5118         char *s;
5119         const char *file;
5120         connection_struct *conn;
5121         NTSTATUS nt_status;
5122         SMB_STRUCT_STAT  st;
5123         char *oldcwd;
5124         fstring printdollar;
5125         int printdollar_snum;
5126         bool ret = false;
5127 
5128         if ( !info_3 )
5129                 return False;
5130 
5131         DEBUG(6,("delete_driver_files: deleting driver [%s] - version [%d]\n", info_3->name, info_3->cversion));
5132 
5133         fstrcpy(printdollar, "print$");
5134 
5135         printdollar_snum = find_service(printdollar);
5136         if (printdollar_snum == -1) {
5137                 return false;
5138         }
5139 
5140         nt_status = create_conn_struct(talloc_tos(), &conn, printdollar_snum,
5141                                        lp_pathname(printdollar_snum),
5142                                        rpc_pipe->server_info, &oldcwd);
5143         if (!NT_STATUS_IS_OK(nt_status)) {
5144                 DEBUG(0,("delete_driver_files: create_conn_struct "
5145                          "returned %s\n", nt_errstr(nt_status)));
5146                 return false;
5147         }
5148 
5149         if ( !CAN_WRITE(conn) ) {
5150                 DEBUG(3,("delete_driver_files: Cannot delete print driver when [print$] is read-only\n"));
5151                 goto fail;
5152         }
5153 
5154         /* now delete the files; must strip the '\print$' string from
5155            fron of path                                                */
5156 
5157         if ( *info_3->driverpath ) {
5158                 if ( (s = strchr( &info_3->driverpath[1], '\\' )) != NULL ) {
5159                         file = s;
5160                         driver_unix_convert(conn,file,&st);
5161                         DEBUG(10,("deleting driverfile [%s]\n", s));
5162                         unlink_internals(conn, NULL, 0, file, False);
5163                 }
5164         }
5165 
5166         if ( *info_3->configfile ) {
5167                 if ( (s = strchr( &info_3->configfile[1], '\\' )) != NULL ) {
5168                         file = s;
5169                         driver_unix_convert(conn,file,&st);
5170                         DEBUG(10,("deleting configfile [%s]\n", s));
5171                         unlink_internals(conn, NULL, 0, file, False);
5172                 }
5173         }
5174 
5175         if ( *info_3->datafile ) {
5176                 if ( (s = strchr( &info_3->datafile[1], '\\' )) != NULL ) {
5177                         file = s;
5178                         driver_unix_convert(conn,file,&st);
5179                         DEBUG(10,("deleting datafile [%s]\n", s));
5180                         unlink_internals(conn, NULL, 0, file, False);
5181                 }
5182         }
5183 
5184         if ( *info_3->helpfile ) {
5185                 if ( (s = strchr( &info_3->helpfile[1], '\\' )) != NULL ) {
5186                         file = s;
5187                         driver_unix_convert(conn,file,&st);
5188                         DEBUG(10,("deleting helpfile [%s]\n", s));
5189                         unlink_internals(conn, NULL, 0, file, False);
5190                 }
5191         }
5192 
5193         /* check if we are done removing files */
5194 
5195         if ( info_3->dependentfiles ) {
5196                 while ( info_3->dependentfiles[i][0] ) {
5197                         char *p;
5198 
5199                         /* bypass the "\print$" portion of the path */
5200 
5201                         if ( (p = strchr( info_3->dependentfiles[i]+1, '\\' )) != NULL ) {
5202                                 file = p;
5203                                 driver_unix_convert(conn,file,&st);
5204                                 DEBUG(10,("deleting dependent file [%s]\n", file));
5205                                 unlink_internals(conn, NULL, 0, file, False);
5206                         }
5207 
5208                         i++;
5209                 }
5210         }
5211 
5212         goto done;
5213  fail:
5214         ret = false;
5215  done:
5216         if (conn != NULL) {
5217                 vfs_ChDir(conn, oldcwd);
5218                 conn_free_internal(conn);
5219         }
5220         return ret;
5221 }
5222 
5223 /****************************************************************************
5224  Remove a printer driver from the TDB.  This assumes that the the driver was
5225  previously looked up.
5226  ***************************************************************************/
5227 
5228 WERROR delete_printer_driver(struct pipes_struct *rpc_pipe,
     /* [<][>][^][v][top][bottom][index][help] */
5229                              NT_PRINTER_DRIVER_INFO_LEVEL_3 *info_3,
5230                              uint32 version, bool delete_files )
5231 {
5232         char *key = NULL;
5233         const char     *arch;
5234         TDB_DATA        dbuf;
5235         NT_PRINTER_DRIVER_INFO_LEVEL    ctr;
5236 
5237         /* delete the tdb data first */
5238 
5239         arch = get_short_archi(info_3->environment);
5240         if (!arch) {
5241                 return WERR_UNKNOWN_PRINTER_DRIVER;
5242         }
5243         if (asprintf(&key, "%s%s/%d/%s", DRIVERS_PREFIX,
5244                         arch, version, info_3->name) < 0) {
5245                 return WERR_NOMEM;
5246         }
5247 
5248         DEBUG(5,("delete_printer_driver: key = [%s] delete_files = %s\n",
5249                 key, delete_files ? "TRUE" : "FALSE" ));
5250 
5251         ctr.info_3 = info_3;
5252         dump_a_printer_driver( ctr, 3 );
5253 
5254         /* check if the driver actually exists for this environment */
5255 
5256         dbuf = tdb_fetch_bystring( tdb_drivers, key );
5257         if ( !dbuf.dptr ) {
5258                 DEBUG(8,("delete_printer_driver: Driver unknown [%s]\n", key));
5259                 SAFE_FREE(key);
5260                 return WERR_UNKNOWN_PRINTER_DRIVER;
5261         }
5262 
5263         SAFE_FREE( dbuf.dptr );
5264 
5265         /* ok... the driver exists so the delete should return success */
5266 
5267         if (tdb_delete_bystring(tdb_drivers, key) == -1) {
5268                 DEBUG (0,("delete_printer_driver: fail to delete %s!\n", key));
5269                 SAFE_FREE(key);
5270                 return WERR_ACCESS_DENIED;
5271         }
5272 
5273         /*
5274          * now delete any associated files if delete_files == True
5275          * even if this part failes, we return succes because the
5276          * driver doesn not exist any more
5277          */
5278 
5279         if ( delete_files )
5280                 delete_driver_files(rpc_pipe, info_3);
5281 
5282         DEBUG(5,("delete_printer_driver: driver delete successful [%s]\n", key));
5283         SAFE_FREE(key);
5284 
5285         return WERR_OK;
5286 }
5287 
5288 /****************************************************************************
5289  Store a security desc for a printer.
5290 ****************************************************************************/
5291 
5292 WERROR nt_printing_setsec(const char *sharename, SEC_DESC_BUF *secdesc_ctr)
     /* [<][>][^][v][top][bottom][index][help] */
5293 {
5294         SEC_DESC_BUF *new_secdesc_ctr = NULL;
5295         SEC_DESC_BUF *old_secdesc_ctr = NULL;
5296         TALLOC_CTX *mem_ctx = NULL;
5297         TDB_DATA kbuf;
5298         TDB_DATA dbuf;
5299         DATA_BLOB blob;
5300         WERROR status;
5301         NTSTATUS nt_status;
5302 
5303         mem_ctx = talloc_init("nt_printing_setsec");
5304         if (mem_ctx == NULL)
5305                 return WERR_NOMEM;
5306 
5307         /* The old owner and group sids of the security descriptor are not
5308            present when new ACEs are added or removed by changing printer
5309            permissions through NT.  If they are NULL in the new security
5310            descriptor then copy them over from the old one. */
5311 
5312         if (!secdesc_ctr->sd->owner_sid || !secdesc_ctr->sd->group_sid) {
5313                 DOM_SID *owner_sid, *group_sid;
5314                 SEC_ACL *dacl, *sacl;
5315                 SEC_DESC *psd = NULL;
5316                 size_t size;
5317 
5318                 if (!nt_printing_getsec(mem_ctx, sharename, &old_secdesc_ctr)) {
5319                         status = WERR_NOMEM;
5320                         goto out;
5321                 }
5322 
5323                 /* Pick out correct owner and group sids */
5324 
5325                 owner_sid = secdesc_ctr->sd->owner_sid ?
5326                         secdesc_ctr->sd->owner_sid :
5327                         old_secdesc_ctr->sd->owner_sid;
5328 
5329                 group_sid = secdesc_ctr->sd->group_sid ?
5330                         secdesc_ctr->sd->group_sid :
5331                         old_secdesc_ctr->sd->group_sid;
5332 
5333                 dacl = secdesc_ctr->sd->dacl ?
5334                         secdesc_ctr->sd->dacl :
5335                         old_secdesc_ctr->sd->dacl;
5336 
5337                 sacl = secdesc_ctr->sd->sacl ?
5338                         secdesc_ctr->sd->sacl :
5339                         old_secdesc_ctr->sd->sacl;
5340 
5341                 /* Make a deep copy of the security descriptor */
5342 
5343                 psd = make_sec_desc(mem_ctx, secdesc_ctr->sd->revision, secdesc_ctr->sd->type,
5344                                     owner_sid, group_sid,
5345                                     sacl,
5346                                     dacl,
5347                                     &size);
5348 
5349                 if (!psd) {
5350                         status = WERR_NOMEM;
5351                         goto out;
5352                 }
5353 
5354                 new_secdesc_ctr = make_sec_desc_buf(mem_ctx, size, psd);
5355         }
5356 
5357         if (!new_secdesc_ctr) {
5358                 new_secdesc_ctr = secdesc_ctr;
5359         }
5360 
5361         /* Store the security descriptor in a tdb */
5362 
5363         nt_status = marshall_sec_desc_buf(mem_ctx, new_secdesc_ctr,
5364                                           &blob.data, &blob.length);
5365         if (!NT_STATUS_IS_OK(nt_status)) {
5366                 status = ntstatus_to_werror(nt_status);
5367                 goto out;
5368         }
5369 
5370         kbuf = make_printers_secdesc_tdbkey(mem_ctx, sharename );
5371 
5372         dbuf.dptr = (unsigned char *)blob.data;
5373         dbuf.dsize = blob.length;
5374 
5375         if (tdb_trans_store(tdb_printers, kbuf, dbuf, TDB_REPLACE)==0) {
5376                 status = WERR_OK;
5377         } else {
5378                 DEBUG(1,("Failed to store secdesc for %s\n", sharename));
5379                 status = WERR_BADFUNC;
5380         }
5381 
5382         /* Free malloc'ed memory */
5383         talloc_free(blob.data);
5384 
5385  out:
5386 
5387         if (mem_ctx)
5388                 talloc_destroy(mem_ctx);
5389         return status;
5390 }
5391 
5392 /****************************************************************************
5393  Construct a default security descriptor buffer for a printer.
5394 ****************************************************************************/
5395 
5396 static SEC_DESC_BUF *construct_default_printer_sdb(TALLOC_CTX *ctx)
     /* [<][>][^][v][top][bottom][index][help] */
5397 {
5398         SEC_ACE ace[5]; /* max number of ace entries */
5399         int i = 0;
5400         uint32_t sa;
5401         SEC_ACL *psa = NULL;
5402         SEC_DESC_BUF *sdb = NULL;
5403         SEC_DESC *psd = NULL;
5404         DOM_SID adm_sid;
5405         size_t sd_size;
5406 
5407         /* Create an ACE where Everyone is allowed to print */
5408 
5409         sa = PRINTER_ACE_PRINT;
5410         init_sec_ace(&ace[i++], &global_sid_World, SEC_ACE_TYPE_ACCESS_ALLOWED,
5411                      sa, SEC_ACE_FLAG_CONTAINER_INHERIT);
5412 
5413         /* Add the domain admins group if we are a DC */
5414 
5415         if ( IS_DC ) {
5416                 DOM_SID domadmins_sid;
5417 
5418                 sid_copy(&domadmins_sid, get_global_sam_sid());
5419                 sid_append_rid(&domadmins_sid, DOMAIN_GROUP_RID_ADMINS);
5420 
5421                 sa = PRINTER_ACE_FULL_CONTROL;
5422                 init_sec_ace(&ace[i++], &domadmins_sid,
5423                         SEC_ACE_TYPE_ACCESS_ALLOWED, sa,
5424                         SEC_ACE_FLAG_OBJECT_INHERIT | SEC_ACE_FLAG_INHERIT_ONLY);
5425                 init_sec_ace(&ace[i++], &domadmins_sid, SEC_ACE_TYPE_ACCESS_ALLOWED,
5426                         sa, SEC_ACE_FLAG_CONTAINER_INHERIT);
5427         }
5428         else if (secrets_fetch_domain_sid(lp_workgroup(), &adm_sid)) {
5429                 sid_append_rid(&adm_sid, DOMAIN_USER_RID_ADMIN);
5430 
5431                 sa = PRINTER_ACE_FULL_CONTROL;
5432                 init_sec_ace(&ace[i++], &adm_sid,
5433                         SEC_ACE_TYPE_ACCESS_ALLOWED, sa,
5434                         SEC_ACE_FLAG_OBJECT_INHERIT | SEC_ACE_FLAG_INHERIT_ONLY);
5435                 init_sec_ace(&ace[i++], &adm_sid, SEC_ACE_TYPE_ACCESS_ALLOWED,
5436                         sa, SEC_ACE_FLAG_CONTAINER_INHERIT);
5437         }
5438 
5439         /* add BUILTIN\Administrators as FULL CONTROL */
5440 
5441         sa = PRINTER_ACE_FULL_CONTROL;
5442         init_sec_ace(&ace[i++], &global_sid_Builtin_Administrators,
5443                 SEC_ACE_TYPE_ACCESS_ALLOWED, sa,
5444                 SEC_ACE_FLAG_OBJECT_INHERIT | SEC_ACE_FLAG_INHERIT_ONLY);
5445         init_sec_ace(&ace[i++], &global_sid_Builtin_Administrators,
5446                 SEC_ACE_TYPE_ACCESS_ALLOWED,
5447                 sa, SEC_ACE_FLAG_CONTAINER_INHERIT);
5448 
5449         /* Make the security descriptor owned by the BUILTIN\Administrators */
5450 
5451         /* The ACL revision number in rpc_secdesc.h differs from the one
5452            created by NT when setting ACE entries in printer
5453            descriptors.  NT4 complains about the property being edited by a
5454            NT5 machine. */
5455 
5456         if ((psa = make_sec_acl(ctx, NT4_ACL_REVISION, i, ace)) != NULL) {
5457                 psd = make_sec_desc(ctx, SEC_DESC_REVISION, SEC_DESC_SELF_RELATIVE,
5458                         &global_sid_Builtin_Administrators,
5459                         &global_sid_Builtin_Administrators,
5460                         NULL, psa, &sd_size);
5461         }
5462 
5463         if (!psd) {
5464                 DEBUG(0,("construct_default_printer_sd: Failed to make SEC_DESC.\n"));
5465                 return NULL;
5466         }
5467 
5468         sdb = make_sec_desc_buf(ctx, sd_size, psd);
5469 
5470         DEBUG(4,("construct_default_printer_sdb: size = %u.\n",
5471                  (unsigned int)sd_size));
5472 
5473         return sdb;
5474 }
5475 
5476 /****************************************************************************
5477  Get a security desc for a printer.
5478 ****************************************************************************/
5479 
5480 bool nt_printing_getsec(TALLOC_CTX *ctx, const char *sharename, SEC_DESC_BUF **secdesc_ctr)
     /* [<][>][^][v][top][bottom][index][help] */
5481 {
5482         TDB_DATA kbuf;
5483         TDB_DATA dbuf;
5484         DATA_BLOB blob;
5485         char *temp;
5486         NTSTATUS status;
5487 
5488         if (strlen(sharename) > 2 && (temp = strchr(sharename + 2, '\\'))) {
5489                 sharename = temp + 1;
5490         }
5491 
5492         /* Fetch security descriptor from tdb */
5493 
5494         kbuf = make_printers_secdesc_tdbkey(ctx, sharename);
5495 
5496         dbuf = tdb_fetch(tdb_printers, kbuf);
5497         if (dbuf.dptr) {
5498 
5499                 status = unmarshall_sec_desc_buf(ctx, dbuf.dptr, dbuf.dsize,
5500                                                  secdesc_ctr);
5501                 SAFE_FREE(dbuf.dptr);
5502 
5503                 if (NT_STATUS_IS_OK(status)) {
5504                         return true;
5505                 }
5506         }
5507 
5508         *secdesc_ctr = construct_default_printer_sdb(ctx);
5509         if (!*secdesc_ctr) {
5510                 return false;
5511         }
5512 
5513         status = marshall_sec_desc_buf(ctx, *secdesc_ctr,
5514                                        &blob.data, &blob.length);
5515         if (NT_STATUS_IS_OK(status)) {
5516                 dbuf.dptr = (unsigned char *)blob.data;
5517                 dbuf.dsize = blob.length;
5518                 tdb_trans_store(tdb_printers, kbuf, dbuf, TDB_REPLACE);
5519                 talloc_free(blob.data);
5520         }
5521 
5522         /* If security descriptor is owned by S-1-1-0 and winbindd is up,
5523            this security descriptor has been created when winbindd was
5524            down.  Take ownership of security descriptor. */
5525 
5526         if (sid_equal((*secdesc_ctr)->sd->owner_sid, &global_sid_World)) {
5527                 DOM_SID owner_sid;
5528 
5529                 /* Change sd owner to workgroup administrator */
5530 
5531                 if (secrets_fetch_domain_sid(lp_workgroup(), &owner_sid)) {
5532                         SEC_DESC_BUF *new_secdesc_ctr = NULL;
5533                         SEC_DESC *psd = NULL;
5534                         size_t size;
5535 
5536                         /* Create new sd */
5537 
5538                         sid_append_rid(&owner_sid, DOMAIN_USER_RID_ADMIN);
5539 
5540                         psd = make_sec_desc(ctx, (*secdesc_ctr)->sd->revision, (*secdesc_ctr)->sd->type,
5541                                             &owner_sid,
5542                                             (*secdesc_ctr)->sd->group_sid,
5543                                             (*secdesc_ctr)->sd->sacl,
5544                                             (*secdesc_ctr)->sd->dacl,
5545                                             &size);
5546 
5547                         if (!psd) {
5548                                 return False;
5549                         }
5550 
5551                         new_secdesc_ctr = make_sec_desc_buf(ctx, size, psd);
5552                         if (!new_secdesc_ctr) {
5553                                 return False;
5554                         }
5555 
5556                         /* Swap with other one */
5557 
5558                         *secdesc_ctr = new_secdesc_ctr;
5559 
5560                         /* Set it */
5561 
5562                         nt_printing_setsec(sharename, *secdesc_ctr);
5563                 }
5564         }
5565 
5566         if (DEBUGLEVEL >= 10) {
5567                 SEC_ACL *the_acl = (*secdesc_ctr)->sd->dacl;
5568                 int i;
5569 
5570                 DEBUG(10, ("secdesc_ctr for %s has %d aces:\n",
5571                            sharename, the_acl->num_aces));
5572 
5573                 for (i = 0; i < the_acl->num_aces; i++) {
5574                         DEBUG(10, ("%s %d %d 0x%08x\n",
5575                                    sid_string_dbg(&the_acl->aces[i].trustee),
5576                                    the_acl->aces[i].type, the_acl->aces[i].flags,
5577                                    the_acl->aces[i].access_mask));
5578                 }
5579         }
5580 
5581         return True;
5582 }
5583 
5584 /* error code:
5585         0: everything OK
5586         1: level not implemented
5587         2: file doesn't exist
5588         3: can't allocate memory
5589         4: can't free memory
5590         5: non existant struct
5591 */
5592 
5593 /*
5594         A printer and a printer driver are 2 different things.
5595         NT manages them separatelly, Samba does the same.
5596         Why ? Simply because it's easier and it makes sense !
5597 
5598         Now explanation: You have 3 printers behind your samba server,
5599         2 of them are the same make and model (laser A and B). But laser B
5600         has an 3000 sheet feeder and laser A doesn't such an option.
5601         Your third printer is an old dot-matrix model for the accounting :-).
5602 
5603         If the /usr/local/samba/lib directory (default dir), you will have
5604         5 files to describe all of this.
5605 
5606         3 files for the printers (1 by printer):
5607                 NTprinter_laser A
5608                 NTprinter_laser B
5609                 NTprinter_accounting
5610         2 files for the drivers (1 for the laser and 1 for the dot matrix)
5611                 NTdriver_printer model X
5612                 NTdriver_printer model Y
5613 
5614 jfm: I should use this comment for the text file to explain
5615         same thing for the forms BTW.
5616         Je devrais mettre mes commentaires en francais, ca serait mieux :-)
5617 
5618 */
5619 
5620 /* Convert generic access rights to printer object specific access rights.
5621    It turns out that NT4 security descriptors use generic access rights and
5622    NT5 the object specific ones. */
5623 
5624 void map_printer_permissions(SEC_DESC *sd)
     /* [<][>][^][v][top][bottom][index][help] */
5625 {
5626         int i;
5627 
5628         for (i = 0; sd->dacl && i < sd->dacl->num_aces; i++) {
5629                 se_map_generic(&sd->dacl->aces[i].access_mask,
5630                                &printer_generic_mapping);
5631         }
5632 }
5633 
5634 void map_job_permissions(SEC_DESC *sd)
     /* [<][>][^][v][top][bottom][index][help] */
5635 {
5636         int i;
5637 
5638         for (i = 0; sd->dacl && i < sd->dacl->num_aces; i++) {
5639                 se_map_generic(&sd->dacl->aces[i].access_mask,
5640                                &job_generic_mapping);
5641         }
5642 }
5643 
5644 
5645 /****************************************************************************
5646  Check a user has permissions to perform the given operation.  We use the
5647  permission constants defined in include/rpc_spoolss.h to check the various
5648  actions we perform when checking printer access.
5649 
5650    PRINTER_ACCESS_ADMINISTER:
5651        print_queue_pause, print_queue_resume, update_printer_sec,
5652        update_printer, spoolss_addprinterex_level_2,
5653        _spoolss_setprinterdata
5654 
5655    PRINTER_ACCESS_USE:
5656        print_job_start
5657 
5658    JOB_ACCESS_ADMINISTER:
5659        print_job_delete, print_job_pause, print_job_resume,
5660        print_queue_purge
5661 
5662   Try access control in the following order (for performance reasons):
5663     1)  root ans SE_PRINT_OPERATOR can do anything (easy check)
5664     2)  check security descriptor (bit comparisons in memory)
5665     3)  "printer admins" (may result in numerous calls to winbind)
5666 
5667  ****************************************************************************/
5668 bool print_access_check(struct auth_serversupplied_info *server_info, int snum,
     /* [<][>][^][v][top][bottom][index][help] */
5669                         int access_type)
5670 {
5671         SEC_DESC_BUF *secdesc = NULL;
5672         uint32 access_granted;
5673         NTSTATUS status;
5674         const char *pname;
5675         TALLOC_CTX *mem_ctx = NULL;
5676         SE_PRIV se_printop = SE_PRINT_OPERATOR;
5677 
5678         /* If user is NULL then use the current_user structure */
5679 
5680         /* Always allow root or SE_PRINT_OPERATROR to do anything */
5681 
5682         if (server_info->utok.uid == sec_initial_uid()
5683             || user_has_privileges(server_info->ptok, &se_printop ) ) {
5684                 return True;
5685         }
5686 
5687         /* Get printer name */
5688 
5689         pname = PRINTERNAME(snum);
5690 
5691         if (!pname || !*pname) {
5692                 errno = EACCES;
5693                 return False;
5694         }
5695 
5696         /* Get printer security descriptor */
5697 
5698         if(!(mem_ctx = talloc_init("print_access_check"))) {
5699                 errno = ENOMEM;
5700                 return False;
5701         }
5702 
5703         if (!nt_printing_getsec(mem_ctx, pname, &secdesc)) {
5704                 talloc_destroy(mem_ctx);
5705                 errno = ENOMEM;
5706                 return False;
5707         }
5708 
5709         if (access_type == JOB_ACCESS_ADMINISTER) {
5710                 SEC_DESC_BUF *parent_secdesc = secdesc;
5711 
5712                 /* Create a child security descriptor to check permissions
5713                    against.  This is because print jobs are child objects
5714                    objects of a printer. */
5715 
5716                 status = se_create_child_secdesc_buf(mem_ctx, &secdesc, parent_secdesc->sd, False);
5717 
5718                 if (!NT_STATUS_IS_OK(status)) {
5719                         talloc_destroy(mem_ctx);
5720                         errno = map_errno_from_nt_status(status);
5721                         return False;
5722                 }
5723 
5724                 map_job_permissions(secdesc->sd);
5725         } else {
5726                 map_printer_permissions(secdesc->sd);
5727         }
5728 
5729         /* Check access */
5730         status = se_access_check(secdesc->sd, server_info->ptok, access_type,
5731                                  &access_granted);
5732 
5733         DEBUG(4, ("access check was %s\n", NT_STATUS_IS_OK(status) ? "SUCCESS" : "FAILURE"));
5734 
5735         /* see if we need to try the printer admin list */
5736 
5737         if ((access_granted == 0) &&
5738             (token_contains_name_in_list(uidtoname(server_info->utok.uid),
5739                                          NULL, NULL, server_info->ptok,
5740                                          lp_printer_admin(snum)))) {
5741                 talloc_destroy(mem_ctx);
5742                 return True;
5743         }
5744 
5745         talloc_destroy(mem_ctx);
5746 
5747         if (!NT_STATUS_IS_OK(status)) {
5748                 errno = EACCES;
5749         }
5750 
5751         return NT_STATUS_IS_OK(status);
5752 }
5753 
5754 /****************************************************************************
5755  Check the time parameters allow a print operation.
5756 *****************************************************************************/
5757 
5758 bool print_time_access_check(const char *servicename)
     /* [<][>][^][v][top][bottom][index][help] */
5759 {
5760         NT_PRINTER_INFO_LEVEL *printer = NULL;
5761         bool ok = False;
5762         time_t now = time(NULL);
5763         struct tm *t;
5764         uint32 mins;
5765 
5766         if (!W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, servicename)))
5767                 return False;
5768 
5769         if (printer->info_2->starttime == 0 && printer->info_2->untiltime == 0)
5770                 ok = True;
5771 
5772         t = gmtime(&now);
5773         mins = (uint32)t->tm_hour*60 + (uint32)t->tm_min;
5774 
5775         if (mins >= printer->info_2->starttime && mins <= printer->info_2->untiltime)
5776                 ok = True;
5777 
5778         free_a_printer(&printer, 2);
5779 
5780         if (!ok)
5781                 errno = EACCES;
5782 
5783         return ok;
5784 }
5785 
5786 /****************************************************************************
5787  Fill in the servername sent in the _spoolss_open_printer_ex() call
5788 ****************************************************************************/
5789 
5790 char* get_server_name( Printer_entry *printer )
     /* [<][>][^][v][top][bottom][index][help] */
5791 {
5792         return printer->servername;
5793 }
5794 
5795 

/* [<][>][^][v][top][bottom][index][help] */