root/source3/rpc_server/srv_spoolss_nt.c

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

DEFINITIONS

This source file includes following definitions.
  1. canon_servername
  2. nt_printj_status
  3. nt_printq_status
  4. srv_spoolss_replycloseprinter
  5. printer_entry_destructor
  6. find_printer_index_by_hnd
  7. close_printer_handle
  8. delete_printer_hook
  9. delete_printer_handle
  10. get_printer_snum
  11. set_printer_hnd_printertype
  12. set_printer_hnd_name
  13. open_printer_hnd
  14. is_monitoring_event_flags
  15. is_monitoring_event
  16. init_systemtime_buffer
  17. notify_one_value
  18. notify_string
  19. notify_system_time
  20. notify_msg_ctr_init
  21. notify_msg_ctr_destroy
  22. notify_ctr_getctx
  23. notify_ctr_getgroup
  24. notify_msg_ctr_numgroups
  25. notify_msg_ctr_addmsg
  26. send_notify2_changes
  27. notify2_unpack_msg
  28. receive_notify2_message_list
  29. srv_spoolss_drv_upgrade_printer
  30. do_drv_upgrade_printer
  31. update_monitored_printq_cache
  32. srv_spoolss_reset_printerdata
  33. reset_all_printerdata
  34. _spoolss_OpenPrinter
  35. convert_devicemode
  36. _spoolss_OpenPrinterEx
  37. printer_info2_to_nt_printer_info2
  38. convert_printer_info
  39. string_array_to_fstring_array
  40. driver_info3_to_nt_driver_info3
  41. driver_info6_to_nt_driver_info6
  42. convert_printer_driver_info
  43. _spoolss_enddocprinter_internal
  44. _spoolss_ClosePrinter
  45. _spoolss_DeletePrinter
  46. get_version_id
  47. _spoolss_DeletePrinterDriver
  48. _spoolss_DeletePrinterDriverEx
  49. delete_printer_dataex
  50. set_printer_dataex
  51. getprinterdata_printer_server
  52. _spoolss_GetPrinterData
  53. spoolss_connect_to_client
  54. srv_spoolss_replyopenprinter
  55. dup_spoolss_NotifyOption
  56. _spoolss_RemoteFindFirstPrinterChangeNotifyEx
  57. spoolss_notify_server_name
  58. spoolss_notify_printer_name
  59. spoolss_notify_share_name
  60. spoolss_notify_port_name
  61. spoolss_notify_driver_name
  62. spoolss_notify_comment
  63. spoolss_notify_location
  64. spoolss_notify_devmode
  65. spoolss_notify_sepfile
  66. spoolss_notify_print_processor
  67. spoolss_notify_parameters
  68. spoolss_notify_datatype
  69. spoolss_notify_security_desc
  70. spoolss_notify_attributes
  71. spoolss_notify_priority
  72. spoolss_notify_default_priority
  73. spoolss_notify_start_time
  74. spoolss_notify_until_time
  75. spoolss_notify_status
  76. spoolss_notify_cjobs
  77. spoolss_notify_average_ppm
  78. spoolss_notify_username
  79. spoolss_notify_job_status
  80. spoolss_notify_job_name
  81. spoolss_notify_job_status_string
  82. spoolss_notify_job_time
  83. spoolss_notify_job_size
  84. spoolss_notify_total_pages
  85. spoolss_notify_pages_printed
  86. spoolss_notify_job_position
  87. spoolss_notify_submitted_time
  88. variable_type_of_notify_info_data
  89. search_notify
  90. construct_info_data
  91. construct_notify_printer_info
  92. construct_notify_jobs_info
  93. printserver_notify_info
  94. printer_notify_info
  95. _spoolss_RouterRefreshPrinterChangeNotify
  96. construct_printer_info0
  97. convert_nt_devicemode
  98. construct_dev_mode
  99. construct_printer_info3
  100. construct_printer_info4
  101. construct_printer_info5
  102. construct_printer_info6
  103. construct_printer_info7
  104. construct_printer_info8
  105. construct_printer_info1
  106. construct_printer_info2
  107. snum_is_shared_printer
  108. enum_all_printers_info_level
  109. enumprinters_level0
  110. enum_all_printers_info_1
  111. enum_all_printers_info_1_local
  112. enum_all_printers_info_1_name
  113. enum_all_printers_info_1_network
  114. enum_all_printers_info_2
  115. enumprinters_level1
  116. enumprinters_level2
  117. enumprinters_level4
  118. enumprinters_level5
  119. _spoolss_EnumPrinters
  120. _spoolss_GetPrinter
  121. string_array_from_driver_info
  122. fill_printer_driver_info1
  123. fill_printer_driver_info2
  124. fill_printer_driver_info3
  125. fill_printer_driver_info4
  126. fill_printer_driver_info5
  127. fill_printer_driver_info6
  128. fill_spoolss_DriverFileInfo
  129. spoolss_DriverFileInfo_from_driver
  130. fill_printer_driver_info101
  131. construct_printer_driver_info_1
  132. construct_printer_driver_info_2
  133. construct_printer_driver_info_3
  134. construct_printer_driver_info_6
  135. construct_printer_driver_info_101
  136. _spoolss_GetPrinterDriver2
  137. _spoolss_StartPagePrinter
  138. _spoolss_EndPagePrinter
  139. _spoolss_StartDocPrinter
  140. _spoolss_EndDocPrinter
  141. _spoolss_WritePrinter
  142. control_printer
  143. _spoolss_AbortPrinter
  144. update_printer_sec
  145. check_printer_ok
  146. add_port_hook
  147. add_printer_hook
  148. update_printer
  149. publish_or_unpublish_printer
  150. _spoolss_SetPrinter
  151. _spoolss_FindClosePrinterNotify
  152. _spoolss_AddJob
  153. fill_job_info1
  154. fill_job_info2
  155. enumjobs_level1
  156. enumjobs_level2
  157. _spoolss_EnumJobs
  158. _spoolss_ScheduleJob
  159. _spoolss_SetJob
  160. enumprinterdrivers_level
  161. enumprinterdrivers_level1
  162. enumprinterdrivers_level2
  163. enumprinterdrivers_level3
  164. enumprinterdrivers_level4
  165. enumprinterdrivers_level5
  166. enumprinterdrivers_level6
  167. _spoolss_EnumPrinterDrivers
  168. fill_form_info_1
  169. spoolss_enumforms_level1
  170. _spoolss_EnumForms
  171. find_form_byname
  172. _spoolss_GetForm
  173. fill_port_1
  174. fill_port_2
  175. enumports_hook
  176. enumports_level_1
  177. enumports_level_2
  178. _spoolss_EnumPorts
  179. spoolss_addprinterex_level_2
  180. _spoolss_AddPrinterEx
  181. _spoolss_AddPrinterDriver
  182. _spoolss_AddPrinterDriverEx
  183. compose_spoolss_server_path
  184. getprinterdriverdir_level_1
  185. _spoolss_GetPrinterDriverDirectory
  186. _spoolss_EnumPrinterData
  187. _spoolss_SetPrinterData
  188. _spoolss_ResetPrinter
  189. _spoolss_DeletePrinterData
  190. _spoolss_AddForm
  191. _spoolss_DeleteForm
  192. _spoolss_SetForm
  193. fill_print_processor1
  194. enumprintprocessors_level_1
  195. _spoolss_EnumPrintProcessors
  196. fill_printprocdatatype1
  197. enumprintprocdatatypes_level_1
  198. _spoolss_EnumPrintProcDataTypes
  199. fill_monitor_1
  200. fill_monitor_2
  201. enumprintmonitors_level_1
  202. enumprintmonitors_level_2
  203. _spoolss_EnumMonitors
  204. getjob_level_1
  205. getjob_level_2
  206. _spoolss_GetJob
  207. _spoolss_GetPrinterDataEx
  208. _spoolss_SetPrinterDataEx
  209. _spoolss_DeletePrinterDataEx
  210. _spoolss_EnumPrinterKey
  211. _spoolss_DeletePrinterKey
  212. registry_value_to_printer_enum_value
  213. _spoolss_EnumPrinterDataEx
  214. getprintprocessordirectory_level_1
  215. _spoolss_GetPrintProcessorDirectory
  216. push_monitorui_buf
  217. xcvtcp_monitorui
  218. pull_port_data_1
  219. pull_port_data_2
  220. xcvtcp_addport
  221. process_xcvtcp_command
  222. xcvlocal_monitorui
  223. process_xcvlocal_command
  224. _spoolss_XcvData
  225. _spoolss_AddPrintProcessor
  226. _spoolss_AddPort
  227. _spoolss_AddPrinter
  228. _spoolss_GetPrinterDriver
  229. _spoolss_ReadPrinter
  230. _spoolss_WaitForPrinterChange
  231. _spoolss_ConfigurePort
  232. _spoolss_DeletePort
  233. _spoolss_CreatePrinterIC
  234. _spoolss_PlayGDIScriptOnPrinterIC
  235. _spoolss_DeletePrinterIC
  236. _spoolss_AddPrinterConnection
  237. _spoolss_DeletePrinterConnection
  238. _spoolss_PrinterMessageBox
  239. _spoolss_AddMonitor
  240. _spoolss_DeleteMonitor
  241. _spoolss_DeletePrintProcessor
  242. _spoolss_AddPrintProvidor
  243. _spoolss_DeletePrintProvidor
  244. _spoolss_FindFirstPrinterChangeNotification
  245. _spoolss_FindNextPrinterChangeNotification
  246. _spoolss_RouterFindFirstPrinterChangeNotificationOld
  247. _spoolss_ReplyOpenPrinter
  248. _spoolss_RouterReplyPrinter
  249. _spoolss_ReplyClosePrinter
  250. _spoolss_AddPortEx
  251. _spoolss_RouterFindFirstPrinterChangeNotification
  252. _spoolss_SpoolerInit
  253. _spoolss_ResetPrinterEx
  254. _spoolss_RouterReplyPrinterEx
  255. _spoolss_44
  256. _spoolss_47
  257. _spoolss_4a
  258. _spoolss_4b
  259. _spoolss_4c
  260. _spoolss_53
  261. _spoolss_55
  262. _spoolss_56
  263. _spoolss_57
  264. _spoolss_5a
  265. _spoolss_5b
  266. _spoolss_5c
  267. _spoolss_5d
  268. _spoolss_5e
  269. _spoolss_5f

   1 /*
   2  *  Unix SMB/CIFS implementation.
   3  *  RPC Pipe client / server routines
   4  *  Copyright (C) Andrew Tridgell              1992-2000,
   5  *  Copyright (C) Luke Kenneth Casson Leighton 1996-2000,
   6  *  Copyright (C) Jean François Micouleau      1998-2000,
   7  *  Copyright (C) Jeremy Allison               2001-2002,
   8  *  Copyright (C) Gerald Carter                2000-2004,
   9  *  Copyright (C) Tim Potter                   2001-2002.
  10  *  Copyright (C) Guenther Deschner                 2009.
  11  *
  12  *  This program is free software; you can redistribute it and/or modify
  13  *  it under the terms of the GNU General Public License as published by
  14  *  the Free Software Foundation; either version 3 of the License, or
  15  *  (at your option) any later version.
  16  *
  17  *  This program is distributed in the hope that it will be useful,
  18  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
  19  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  20  *  GNU General Public License for more details.
  21  *
  22  *  You should have received a copy of the GNU General Public License
  23  *  along with this program; if not, see <http://www.gnu.org/licenses/>.
  24  */
  25 
  26 /* Since the SPOOLSS rpc routines are basically DOS 16-bit calls wrapped
  27    up, all the errors returned are DOS errors, not NT status codes. */
  28 
  29 #include "includes.h"
  30 
  31 /* macros stolen from s4 spoolss server */
  32 #define SPOOLSS_BUFFER_UNION(fn,ic,info,level) \
  33         ((info)?ndr_size_##fn(info, level, ic, 0):0)
  34 
  35 #define SPOOLSS_BUFFER_UNION_ARRAY(mem_ctx,fn,ic,info,level,count) \
  36         ((info)?ndr_size_##fn##_info(mem_ctx, ic, level, count, info):0)
  37 
  38 #define SPOOLSS_BUFFER_ARRAY(mem_ctx,fn,ic,info,count) \
  39         ((info)?ndr_size_##fn##_info(mem_ctx, ic, count, info):0)
  40 
  41 #define SPOOLSS_BUFFER_OK(val_true,val_false) ((r->in.offered >= *r->out.needed)?val_true:val_false)
  42 
  43 
  44 extern userdom_struct current_user_info;
  45 
  46 #undef DBGC_CLASS
  47 #define DBGC_CLASS DBGC_RPC_SRV
  48 
  49 #ifndef MAX_OPEN_PRINTER_EXS
  50 #define MAX_OPEN_PRINTER_EXS 50
  51 #endif
  52 
  53 #define MAGIC_DISPLAY_FREQUENCY 0xfade2bad
  54 #define PHANTOM_DEVMODE_KEY "_p_f_a_n_t_0_m_"
  55 
  56 static Printer_entry *printers_list;
  57 
  58 typedef struct _counter_printer_0 {
  59         struct _counter_printer_0 *next;
  60         struct _counter_printer_0 *prev;
  61 
  62         int snum;
  63         uint32_t counter;
  64 } counter_printer_0;
  65 
  66 static counter_printer_0 *counter_list;
  67 
  68 static struct rpc_pipe_client *notify_cli_pipe; /* print notify back-channel pipe handle*/
  69 static uint32_t smb_connections = 0;
  70 
  71 
  72 /* in printing/nt_printing.c */
  73 
  74 extern struct standard_mapping printer_std_mapping, printserver_std_mapping;
  75 
  76 /* API table for Xcv Monitor functions */
  77 
  78 struct xcv_api_table {
  79         const char *name;
  80         WERROR(*fn) (TALLOC_CTX *mem_ctx, NT_USER_TOKEN *token, DATA_BLOB *in, DATA_BLOB *out, uint32_t *needed);
  81 };
  82 
  83 /********************************************************************
  84  * Canonicalize servername.
  85  ********************************************************************/
  86 
  87 static const char *canon_servername(const char *servername)
     /* [<][>][^][v][top][bottom][index][help] */
  88 {
  89         const char *pservername = servername;
  90         while (*pservername == '\\') {
  91                 pservername++;
  92         }
  93         return pservername;
  94 }
  95 
  96 /* translate between internal status numbers and NT status numbers */
  97 static int nt_printj_status(int v)
     /* [<][>][^][v][top][bottom][index][help] */
  98 {
  99         switch (v) {
 100         case LPQ_QUEUED:
 101                 return 0;
 102         case LPQ_PAUSED:
 103                 return JOB_STATUS_PAUSED;
 104         case LPQ_SPOOLING:
 105                 return JOB_STATUS_SPOOLING;
 106         case LPQ_PRINTING:
 107                 return JOB_STATUS_PRINTING;
 108         case LPQ_ERROR:
 109                 return JOB_STATUS_ERROR;
 110         case LPQ_DELETING:
 111                 return JOB_STATUS_DELETING;
 112         case LPQ_OFFLINE:
 113                 return JOB_STATUS_OFFLINE;
 114         case LPQ_PAPEROUT:
 115                 return JOB_STATUS_PAPEROUT;
 116         case LPQ_PRINTED:
 117                 return JOB_STATUS_PRINTED;
 118         case LPQ_DELETED:
 119                 return JOB_STATUS_DELETED;
 120         case LPQ_BLOCKED:
 121                 return JOB_STATUS_BLOCKED_DEVQ;
 122         case LPQ_USER_INTERVENTION:
 123                 return JOB_STATUS_USER_INTERVENTION;
 124         }
 125         return 0;
 126 }
 127 
 128 static int nt_printq_status(int v)
     /* [<][>][^][v][top][bottom][index][help] */
 129 {
 130         switch (v) {
 131         case LPQ_PAUSED:
 132                 return PRINTER_STATUS_PAUSED;
 133         case LPQ_QUEUED:
 134         case LPQ_SPOOLING:
 135         case LPQ_PRINTING:
 136                 return 0;
 137         }
 138         return 0;
 139 }
 140 
 141 /***************************************************************************
 142  Disconnect from the client
 143 ****************************************************************************/
 144 
 145 static void srv_spoolss_replycloseprinter(int snum, struct policy_handle *handle)
     /* [<][>][^][v][top][bottom][index][help] */
 146 {
 147         WERROR result;
 148         NTSTATUS status;
 149 
 150         /*
 151          * Tell the specific printing tdb we no longer want messages for this printer
 152          * by deregistering our PID.
 153          */
 154 
 155         if (!print_notify_deregister_pid(snum))
 156                 DEBUG(0,("print_notify_register_pid: Failed to register our pid for printer %s\n", lp_const_servicename(snum) ));
 157 
 158         /* weird if the test succeds !!! */
 159         if (smb_connections==0) {
 160                 DEBUG(0,("srv_spoolss_replycloseprinter:Trying to close non-existant notify backchannel !\n"));
 161                 return;
 162         }
 163 
 164         status = rpccli_spoolss_ReplyClosePrinter(notify_cli_pipe, talloc_tos(),
 165                                                   handle,
 166                                                   &result);
 167         if (!NT_STATUS_IS_OK(status) || !W_ERROR_IS_OK(result))
 168                 DEBUG(0,("srv_spoolss_replycloseprinter: reply_close_printer failed [%s].\n",
 169                         win_errstr(result)));
 170 
 171         /* if it's the last connection, deconnect the IPC$ share */
 172         if (smb_connections==1) {
 173 
 174                 cli_shutdown( rpc_pipe_np_smb_conn(notify_cli_pipe) );
 175                 notify_cli_pipe = NULL; /* The above call shuts downn the pipe also. */
 176 
 177                 messaging_deregister(smbd_messaging_context(),
 178                                      MSG_PRINTER_NOTIFY2, NULL);
 179 
 180                 /* Tell the connections db we're no longer interested in
 181                  * printer notify messages. */
 182 
 183                 register_message_flags(false, FLAG_MSG_PRINT_NOTIFY);
 184         }
 185 
 186         smb_connections--;
 187 }
 188 
 189 /****************************************************************************
 190  Functions to free a printer entry datastruct.
 191 ****************************************************************************/
 192 
 193 static int printer_entry_destructor(Printer_entry *Printer)
     /* [<][>][^][v][top][bottom][index][help] */
 194 {
 195         if (Printer->notify.client_connected == true) {
 196                 int snum = -1;
 197 
 198                 if ( Printer->printer_type == SPLHND_SERVER) {
 199                         snum = -1;
 200                         srv_spoolss_replycloseprinter(snum, &Printer->notify.client_hnd);
 201                 } else if (Printer->printer_type == SPLHND_PRINTER) {
 202                         snum = print_queue_snum(Printer->sharename);
 203                         if (snum != -1)
 204                                 srv_spoolss_replycloseprinter(snum,
 205                                                 &Printer->notify.client_hnd);
 206                 }
 207         }
 208 
 209         Printer->notify.flags=0;
 210         Printer->notify.options=0;
 211         Printer->notify.localmachine[0]='\0';
 212         Printer->notify.printerlocal=0;
 213         TALLOC_FREE(Printer->notify.option);
 214         Printer->notify.client_connected = false;
 215 
 216         free_nt_devicemode( &Printer->nt_devmode );
 217         free_a_printer( &Printer->printer_info, 2 );
 218 
 219         /* Remove from the internal list. */
 220         DLIST_REMOVE(printers_list, Printer);
 221         return 0;
 222 }
 223 
 224 /****************************************************************************
 225   find printer index by handle
 226 ****************************************************************************/
 227 
 228 static Printer_entry *find_printer_index_by_hnd(pipes_struct *p,
     /* [<][>][^][v][top][bottom][index][help] */
 229                                                 struct policy_handle *hnd)
 230 {
 231         Printer_entry *find_printer = NULL;
 232 
 233         if(!find_policy_by_hnd(p,hnd,(void **)(void *)&find_printer)) {
 234                 DEBUG(2,("find_printer_index_by_hnd: Printer handle not found: "));
 235                 return NULL;
 236         }
 237 
 238         return find_printer;
 239 }
 240 
 241 /****************************************************************************
 242  Close printer index by handle.
 243 ****************************************************************************/
 244 
 245 static bool close_printer_handle(pipes_struct *p, struct policy_handle *hnd)
     /* [<][>][^][v][top][bottom][index][help] */
 246 {
 247         Printer_entry *Printer = find_printer_index_by_hnd(p, hnd);
 248 
 249         if (!Printer) {
 250                 DEBUG(2,("close_printer_handle: Invalid handle (%s:%u:%u)\n",
 251                         OUR_HANDLE(hnd)));
 252                 return false;
 253         }
 254 
 255         close_policy_hnd(p, hnd);
 256 
 257         return true;
 258 }
 259 
 260 /****************************************************************************
 261  Delete a printer given a handle.
 262 ****************************************************************************/
 263 
 264 WERROR delete_printer_hook(TALLOC_CTX *ctx, NT_USER_TOKEN *token, const char *sharename )
     /* [<][>][^][v][top][bottom][index][help] */
 265 {
 266         char *cmd = lp_deleteprinter_cmd();
 267         char *command = NULL;
 268         int ret;
 269         SE_PRIV se_printop = SE_PRINT_OPERATOR;
 270         bool is_print_op = false;
 271 
 272         /* can't fail if we don't try */
 273 
 274         if ( !*cmd )
 275                 return WERR_OK;
 276 
 277         command = talloc_asprintf(ctx,
 278                         "%s \"%s\"",
 279                         cmd, sharename);
 280         if (!command) {
 281                 return WERR_NOMEM;
 282         }
 283         if ( token )
 284                 is_print_op = user_has_privileges( token, &se_printop );
 285 
 286         DEBUG(10,("Running [%s]\n", command));
 287 
 288         /********** BEGIN SePrintOperatorPrivlege BLOCK **********/
 289 
 290         if ( is_print_op )
 291                 become_root();
 292 
 293         if ( (ret = smbrun(command, NULL)) == 0 ) {
 294                 /* Tell everyone we updated smb.conf. */
 295                 message_send_all(smbd_messaging_context(),
 296                                  MSG_SMB_CONF_UPDATED, NULL, 0, NULL);
 297         }
 298 
 299         if ( is_print_op )
 300                 unbecome_root();
 301 
 302         /********** END SePrintOperatorPrivlege BLOCK **********/
 303 
 304         DEBUGADD(10,("returned [%d]\n", ret));
 305 
 306         TALLOC_FREE(command);
 307 
 308         if (ret != 0)
 309                 return WERR_BADFID; /* What to return here? */
 310 
 311         /* go ahead and re-read the services immediately */
 312         become_root();
 313         reload_services(false);
 314         unbecome_root();
 315 
 316         if ( lp_servicenumber( sharename )  < 0 )
 317                 return WERR_ACCESS_DENIED;
 318 
 319         return WERR_OK;
 320 }
 321 
 322 /****************************************************************************
 323  Delete a printer given a handle.
 324 ****************************************************************************/
 325 
 326 static WERROR delete_printer_handle(pipes_struct *p, struct policy_handle *hnd)
     /* [<][>][^][v][top][bottom][index][help] */
 327 {
 328         Printer_entry *Printer = find_printer_index_by_hnd(p, hnd);
 329 
 330         if (!Printer) {
 331                 DEBUG(2,("delete_printer_handle: Invalid handle (%s:%u:%u)\n",
 332                         OUR_HANDLE(hnd)));
 333                 return WERR_BADFID;
 334         }
 335 
 336         /*
 337          * It turns out that Windows allows delete printer on a handle
 338          * opened by an admin user, then used on a pipe handle created
 339          * by an anonymous user..... but they're working on security.... riiight !
 340          * JRA.
 341          */
 342 
 343         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
 344                 DEBUG(3, ("delete_printer_handle: denied by handle\n"));
 345                 return WERR_ACCESS_DENIED;
 346         }
 347 
 348         /* this does not need a become root since the access check has been
 349            done on the handle already */
 350 
 351         if (del_a_printer( Printer->sharename ) != 0) {
 352                 DEBUG(3,("Error deleting printer %s\n", Printer->sharename));
 353                 return WERR_BADFID;
 354         }
 355 
 356         return delete_printer_hook(p->mem_ctx, p->server_info->ptok,
 357                                    Printer->sharename );
 358 }
 359 
 360 /****************************************************************************
 361  Return the snum of a printer corresponding to an handle.
 362 ****************************************************************************/
 363 
 364 static bool get_printer_snum(pipes_struct *p, struct policy_handle *hnd,
     /* [<][>][^][v][top][bottom][index][help] */
 365                              int *number, struct share_params **params)
 366 {
 367         Printer_entry *Printer = find_printer_index_by_hnd(p, hnd);
 368 
 369         if (!Printer) {
 370                 DEBUG(2,("get_printer_snum: Invalid handle (%s:%u:%u)\n",
 371                         OUR_HANDLE(hnd)));
 372                 return false;
 373         }
 374 
 375         switch (Printer->printer_type) {
 376                 case SPLHND_PRINTER:
 377                         DEBUG(4,("short name:%s\n", Printer->sharename));
 378                         *number = print_queue_snum(Printer->sharename);
 379                         return (*number != -1);
 380                 case SPLHND_SERVER:
 381                         return false;
 382                 default:
 383                         return false;
 384         }
 385 }
 386 
 387 /****************************************************************************
 388  Set printer handle type.
 389  Check if it's \\server or \\server\printer
 390 ****************************************************************************/
 391 
 392 static bool set_printer_hnd_printertype(Printer_entry *Printer, const char *handlename)
     /* [<][>][^][v][top][bottom][index][help] */
 393 {
 394         DEBUG(3,("Setting printer type=%s\n", handlename));
 395 
 396         if ( strlen(handlename) < 3 ) {
 397                 DEBUGADD(4,("A print server must have at least 1 char ! %s\n", handlename));
 398                 return false;
 399         }
 400 
 401         /* it's a print server */
 402         if (*handlename=='\\' && *(handlename+1)=='\\' && !strchr_m(handlename+2, '\\')) {
 403                 DEBUGADD(4,("Printer is a print server\n"));
 404                 Printer->printer_type = SPLHND_SERVER;
 405         }
 406         /* it's a printer (set_printer_hnd_name() will handle port monitors */
 407         else {
 408                 DEBUGADD(4,("Printer is a printer\n"));
 409                 Printer->printer_type = SPLHND_PRINTER;
 410         }
 411 
 412         return true;
 413 }
 414 
 415 /****************************************************************************
 416  Set printer handle name..  Accept names like \\server, \\server\printer,
 417  \\server\SHARE, & "\\server\,XcvMonitor Standard TCP/IP Port"    See
 418  the MSDN docs regarding OpenPrinter() for details on the XcvData() and
 419  XcvDataPort() interface.
 420 ****************************************************************************/
 421 
 422 static bool set_printer_hnd_name(Printer_entry *Printer, const char *handlename)
     /* [<][>][^][v][top][bottom][index][help] */
 423 {
 424         int snum;
 425         int n_services=lp_numservices();
 426         char *aprinter, *printername;
 427         const char *servername;
 428         fstring sname;
 429         bool found = false;
 430         NT_PRINTER_INFO_LEVEL *printer = NULL;
 431         WERROR result;
 432 
 433         DEBUG(4,("Setting printer name=%s (len=%lu)\n", handlename,
 434                 (unsigned long)strlen(handlename)));
 435 
 436         aprinter = CONST_DISCARD(char *, handlename);
 437         if ( *handlename == '\\' ) {
 438                 servername = canon_servername(handlename);
 439                 if ( (aprinter = strchr_m( servername, '\\' )) != NULL ) {
 440                         *aprinter = '\0';
 441                         aprinter++;
 442                 }
 443         } else {
 444                 servername = global_myname();
 445         }
 446 
 447         /* save the servername to fill in replies on this handle */
 448 
 449         if ( !is_myname_or_ipaddr( servername ) )
 450                 return false;
 451 
 452         fstrcpy( Printer->servername, servername );
 453 
 454         if ( Printer->printer_type == SPLHND_SERVER )
 455                 return true;
 456 
 457         if ( Printer->printer_type != SPLHND_PRINTER )
 458                 return false;
 459 
 460         DEBUGADD(5, ("searching for [%s]\n", aprinter ));
 461 
 462         /* check for the Port Monitor Interface */
 463 
 464         if ( strequal( aprinter, SPL_XCV_MONITOR_TCPMON ) ) {
 465                 Printer->printer_type = SPLHND_PORTMON_TCP;
 466                 fstrcpy(sname, SPL_XCV_MONITOR_TCPMON);
 467                 found = true;
 468         }
 469         else if ( strequal( aprinter, SPL_XCV_MONITOR_LOCALMON ) ) {
 470                 Printer->printer_type = SPLHND_PORTMON_LOCAL;
 471                 fstrcpy(sname, SPL_XCV_MONITOR_LOCALMON);
 472                 found = true;
 473         }
 474 
 475         /* Search all sharenames first as this is easier than pulling
 476            the printer_info_2 off of disk. Don't use find_service() since
 477            that calls out to map_username() */
 478 
 479         /* do another loop to look for printernames */
 480 
 481         for (snum=0; !found && snum<n_services; snum++) {
 482 
 483                 /* no point going on if this is not a printer */
 484 
 485                 if ( !(lp_snum_ok(snum) && lp_print_ok(snum)) )
 486                         continue;
 487 
 488                 fstrcpy(sname, lp_servicename(snum));
 489                 if ( strequal( aprinter, sname ) ) {
 490                         found = true;
 491                         break;
 492                 }
 493 
 494                 /* no point looking up the printer object if
 495                    we aren't allowing printername != sharename */
 496 
 497                 if ( lp_force_printername(snum) )
 498                         continue;
 499 
 500                 fstrcpy(sname, lp_servicename(snum));
 501 
 502                 printer = NULL;
 503 
 504                 /* This call doesn't fill in the location or comment from
 505                  * a CUPS server for efficiency with large numbers of printers.
 506                  * JRA.
 507                  */
 508 
 509                 result = get_a_printer_search( NULL, &printer, 2, sname );
 510                 if ( !W_ERROR_IS_OK(result) ) {
 511                         DEBUG(0,("set_printer_hnd_name: failed to lookup printer [%s] -- result [%s]\n",
 512                                 sname, win_errstr(result)));
 513                         continue;
 514                 }
 515 
 516                 /* printername is always returned as \\server\printername */
 517                 if ( !(printername = strchr_m(&printer->info_2->printername[2], '\\')) ) {
 518                         DEBUG(0,("set_printer_hnd_name: info2->printername in wrong format! [%s]\n",
 519                                 printer->info_2->printername));
 520                         free_a_printer( &printer, 2);
 521                         continue;
 522                 }
 523 
 524                 printername++;
 525 
 526                 if ( strequal(printername, aprinter) ) {
 527                         free_a_printer( &printer, 2);
 528                         found = true;
 529                         break;
 530                 }
 531 
 532                 DEBUGADD(10, ("printername: %s\n", printername));
 533 
 534                 free_a_printer( &printer, 2);
 535         }
 536 
 537         free_a_printer( &printer, 2);
 538 
 539         if ( !found ) {
 540                 DEBUGADD(4,("Printer not found\n"));
 541                 return false;
 542         }
 543 
 544         DEBUGADD(4,("set_printer_hnd_name: Printer found: %s -> %s\n", aprinter, sname));
 545 
 546         fstrcpy(Printer->sharename, sname);
 547 
 548         return true;
 549 }
 550 
 551 /****************************************************************************
 552  Find first available printer slot. creates a printer handle for you.
 553  ****************************************************************************/
 554 
 555 static bool open_printer_hnd(pipes_struct *p, struct policy_handle *hnd,
     /* [<][>][^][v][top][bottom][index][help] */
 556                              const char *name, uint32_t access_granted)
 557 {
 558         Printer_entry *new_printer;
 559 
 560         DEBUG(10,("open_printer_hnd: name [%s]\n", name));
 561 
 562         new_printer = TALLOC_ZERO_P(NULL, Printer_entry);
 563         if (new_printer == NULL) {
 564                 return false;
 565         }
 566         talloc_set_destructor(new_printer, printer_entry_destructor);
 567 
 568         if (!create_policy_hnd(p, hnd, new_printer)) {
 569                 TALLOC_FREE(new_printer);
 570                 return false;
 571         }
 572 
 573         /* Add to the internal list. */
 574         DLIST_ADD(printers_list, new_printer);
 575 
 576         new_printer->notify.option=NULL;
 577 
 578         if (!set_printer_hnd_printertype(new_printer, name)) {
 579                 close_printer_handle(p, hnd);
 580                 return false;
 581         }
 582 
 583         if (!set_printer_hnd_name(new_printer, name)) {
 584                 close_printer_handle(p, hnd);
 585                 return false;
 586         }
 587 
 588         new_printer->access_granted = access_granted;
 589 
 590         DEBUG(5, ("%d printer handles active\n", (int)p->pipe_handles->count ));
 591 
 592         return true;
 593 }
 594 
 595 /***************************************************************************
 596  check to see if the client motify handle is monitoring the notification
 597  given by (notify_type, notify_field).
 598  **************************************************************************/
 599 
 600 static bool is_monitoring_event_flags(uint32_t flags, uint16_t notify_type,
     /* [<][>][^][v][top][bottom][index][help] */
 601                                       uint16_t notify_field)
 602 {
 603         return true;
 604 }
 605 
 606 static bool is_monitoring_event(Printer_entry *p, uint16_t notify_type,
     /* [<][>][^][v][top][bottom][index][help] */
 607                                 uint16_t notify_field)
 608 {
 609         struct spoolss_NotifyOption *option = p->notify.option;
 610         uint32_t i, j;
 611 
 612         /*
 613          * Flags should always be zero when the change notify
 614          * is registered by the client's spooler.  A user Win32 app
 615          * might use the flags though instead of the NOTIFY_OPTION_INFO
 616          * --jerry
 617          */
 618 
 619         if (!option) {
 620                 return false;
 621         }
 622 
 623         if (p->notify.flags)
 624                 return is_monitoring_event_flags(
 625                         p->notify.flags, notify_type, notify_field);
 626 
 627         for (i = 0; i < option->count; i++) {
 628 
 629                 /* Check match for notify_type */
 630 
 631                 if (option->types[i].type != notify_type)
 632                         continue;
 633 
 634                 /* Check match for field */
 635 
 636                 for (j = 0; j < option->types[i].count; j++) {
 637                         if (option->types[i].fields[j].field == notify_field) {
 638                                 return true;
 639                         }
 640                 }
 641         }
 642 
 643         DEBUG(10, ("Open handle for \\\\%s\\%s is not monitoring 0x%02x/0x%02x\n",
 644                    p->servername, p->sharename, notify_type, notify_field));
 645 
 646         return false;
 647 }
 648 
 649 #define SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(_data, _integer) \
 650         _data->data.integer[0] = _integer; \
 651         _data->data.integer[1] = 0;
 652 
 653 
 654 #define SETUP_SPOOLSS_NOTIFY_DATA_STRING(_data, _p) \
 655         _data->data.string.string = talloc_strdup(mem_ctx, _p); \
 656         if (!_data->data.string.string) {\
 657                 _data->data.string.size = 0; \
 658         } \
 659         _data->data.string.size = strlen_m_term(_p) * 2;
 660 
 661 #define SETUP_SPOOLSS_NOTIFY_DATA_DEVMODE(_data, _devmode) \
 662         _data->data.devmode.devmode = _devmode;
 663 
 664 #define SETUP_SPOOLSS_NOTIFY_DATA_SECDESC(_data, _size, _sd) \
 665         _data->data.sd.sd = dup_sec_desc(mem_ctx, _sd); \
 666         if (!_data->data.sd.sd) { \
 667                 _data->data.sd.sd_size = 0; \
 668         } \
 669         _data->data.sd.sd_size = _size;
 670 
 671 static void init_systemtime_buffer(TALLOC_CTX *mem_ctx,
     /* [<][>][^][v][top][bottom][index][help] */
 672                                    struct tm *t,
 673                                    const char **pp,
 674                                    uint32_t *plen)
 675 {
 676         struct spoolss_Time st;
 677         uint32_t len = 16;
 678         char *p;
 679 
 680         if (!init_systemtime(&st, t)) {
 681                 return;
 682         }
 683 
 684         p = talloc_array(mem_ctx, char, len);
 685         if (!p) {
 686                 return;
 687         }
 688 
 689         /*
 690          * Systemtime must be linearized as a set of UINT16's.
 691          * Fix from Benjamin (Bj) Kuit bj@it.uts.edu.au
 692          */
 693 
 694         SSVAL(p, 0, st.year);
 695         SSVAL(p, 2, st.month);
 696         SSVAL(p, 4, st.day_of_week);
 697         SSVAL(p, 6, st.day);
 698         SSVAL(p, 8, st.hour);
 699         SSVAL(p, 10, st.minute);
 700         SSVAL(p, 12, st.second);
 701         SSVAL(p, 14, st.millisecond);
 702 
 703         *pp = p;
 704         *plen = len;
 705 }
 706 
 707 /* Convert a notification message to a struct spoolss_Notify */
 708 
 709 static void notify_one_value(struct spoolss_notify_msg *msg,
     /* [<][>][^][v][top][bottom][index][help] */
 710                              struct spoolss_Notify *data,
 711                              TALLOC_CTX *mem_ctx)
 712 {
 713         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, msg->notify.value[0]);
 714 }
 715 
 716 static void notify_string(struct spoolss_notify_msg *msg,
     /* [<][>][^][v][top][bottom][index][help] */
 717                           struct spoolss_Notify *data,
 718                           TALLOC_CTX *mem_ctx)
 719 {
 720         /* The length of the message includes the trailing \0 */
 721 
 722         data->data.string.size = msg->len * 2;
 723         data->data.string.string = talloc_strdup(mem_ctx, msg->notify.data);
 724         if (!data->data.string.string) {
 725                 data->data.string.size = 0;
 726                 return;
 727         }
 728 }
 729 
 730 static void notify_system_time(struct spoolss_notify_msg *msg,
     /* [<][>][^][v][top][bottom][index][help] */
 731                                struct spoolss_Notify *data,
 732                                TALLOC_CTX *mem_ctx)
 733 {
 734         data->data.string.string = NULL;
 735         data->data.string.size = 0;
 736 
 737         if (msg->len != sizeof(time_t)) {
 738                 DEBUG(5, ("notify_system_time: received wrong sized message (%d)\n",
 739                           msg->len));
 740                 return;
 741         }
 742 
 743         init_systemtime_buffer(mem_ctx, gmtime((time_t *)msg->notify.data),
 744                                &data->data.string.string,
 745                                &data->data.string.size);
 746 }
 747 
 748 struct notify2_message_table {
 749         const char *name;
 750         void (*fn)(struct spoolss_notify_msg *msg,
 751                    struct spoolss_Notify *data, TALLOC_CTX *mem_ctx);
 752 };
 753 
 754 static struct notify2_message_table printer_notify_table[] = {
 755         /* 0x00 */ { "PRINTER_NOTIFY_FIELD_SERVER_NAME", notify_string },
 756         /* 0x01 */ { "PRINTER_NOTIFY_FIELD_PRINTER_NAME", notify_string },
 757         /* 0x02 */ { "PRINTER_NOTIFY_FIELD_SHARE_NAME", notify_string },
 758         /* 0x03 */ { "PRINTER_NOTIFY_FIELD_PORT_NAME", notify_string },
 759         /* 0x04 */ { "PRINTER_NOTIFY_FIELD_DRIVER_NAME", notify_string },
 760         /* 0x05 */ { "PRINTER_NOTIFY_FIELD_COMMENT", notify_string },
 761         /* 0x06 */ { "PRINTER_NOTIFY_FIELD_LOCATION", notify_string },
 762         /* 0x07 */ { "PRINTER_NOTIFY_FIELD_DEVMODE", NULL },
 763         /* 0x08 */ { "PRINTER_NOTIFY_FIELD_SEPFILE", notify_string },
 764         /* 0x09 */ { "PRINTER_NOTIFY_FIELD_PRINT_PROCESSOR", notify_string },
 765         /* 0x0a */ { "PRINTER_NOTIFY_FIELD_PARAMETERS", NULL },
 766         /* 0x0b */ { "PRINTER_NOTIFY_FIELD_DATATYPE", notify_string },
 767         /* 0x0c */ { "PRINTER_NOTIFY_FIELD_SECURITY_DESCRIPTOR", NULL },
 768         /* 0x0d */ { "PRINTER_NOTIFY_FIELD_ATTRIBUTES", notify_one_value },
 769         /* 0x0e */ { "PRINTER_NOTIFY_FIELD_PRIORITY", notify_one_value },
 770         /* 0x0f */ { "PRINTER_NOTIFY_FIELD_DEFAULT_PRIORITY", NULL },
 771         /* 0x10 */ { "PRINTER_NOTIFY_FIELD_START_TIME", NULL },
 772         /* 0x11 */ { "PRINTER_NOTIFY_FIELD_UNTIL_TIME", NULL },
 773         /* 0x12 */ { "PRINTER_NOTIFY_FIELD_STATUS", notify_one_value },
 774 };
 775 
 776 static struct notify2_message_table job_notify_table[] = {
 777         /* 0x00 */ { "JOB_NOTIFY_FIELD_PRINTER_NAME", NULL },
 778         /* 0x01 */ { "JOB_NOTIFY_FIELD_MACHINE_NAME", NULL },
 779         /* 0x02 */ { "JOB_NOTIFY_FIELD_PORT_NAME", NULL },
 780         /* 0x03 */ { "JOB_NOTIFY_FIELD_USER_NAME", notify_string },
 781         /* 0x04 */ { "JOB_NOTIFY_FIELD_NOTIFY_NAME", NULL },
 782         /* 0x05 */ { "JOB_NOTIFY_FIELD_DATATYPE", NULL },
 783         /* 0x06 */ { "JOB_NOTIFY_FIELD_PRINT_PROCESSOR", NULL },
 784         /* 0x07 */ { "JOB_NOTIFY_FIELD_PARAMETERS", NULL },
 785         /* 0x08 */ { "JOB_NOTIFY_FIELD_DRIVER_NAME", NULL },
 786         /* 0x09 */ { "JOB_NOTIFY_FIELD_DEVMODE", NULL },
 787         /* 0x0a */ { "JOB_NOTIFY_FIELD_STATUS", notify_one_value },
 788         /* 0x0b */ { "JOB_NOTIFY_FIELD_STATUS_STRING", NULL },
 789         /* 0x0c */ { "JOB_NOTIFY_FIELD_SECURITY_DESCRIPTOR", NULL },
 790         /* 0x0d */ { "JOB_NOTIFY_FIELD_DOCUMENT", notify_string },
 791         /* 0x0e */ { "JOB_NOTIFY_FIELD_PRIORITY", NULL },
 792         /* 0x0f */ { "JOB_NOTIFY_FIELD_POSITION", NULL },
 793         /* 0x10 */ { "JOB_NOTIFY_FIELD_SUBMITTED", notify_system_time },
 794         /* 0x11 */ { "JOB_NOTIFY_FIELD_START_TIME", NULL },
 795         /* 0x12 */ { "JOB_NOTIFY_FIELD_UNTIL_TIME", NULL },
 796         /* 0x13 */ { "JOB_NOTIFY_FIELD_TIME", NULL },
 797         /* 0x14 */ { "JOB_NOTIFY_FIELD_TOTAL_PAGES", notify_one_value },
 798         /* 0x15 */ { "JOB_NOTIFY_FIELD_PAGES_PRINTED", NULL },
 799         /* 0x16 */ { "JOB_NOTIFY_FIELD_TOTAL_BYTES", notify_one_value },
 800         /* 0x17 */ { "JOB_NOTIFY_FIELD_BYTES_PRINTED", NULL },
 801 };
 802 
 803 
 804 /***********************************************************************
 805  Allocate talloc context for container object
 806  **********************************************************************/
 807 
 808 static void notify_msg_ctr_init( SPOOLSS_NOTIFY_MSG_CTR *ctr )
     /* [<][>][^][v][top][bottom][index][help] */
 809 {
 810         if ( !ctr )
 811                 return;
 812 
 813         ctr->ctx = talloc_init("notify_msg_ctr_init %p", ctr);
 814 
 815         return;
 816 }
 817 
 818 /***********************************************************************
 819  release all allocated memory and zero out structure
 820  **********************************************************************/
 821 
 822 static void notify_msg_ctr_destroy( SPOOLSS_NOTIFY_MSG_CTR *ctr )
     /* [<][>][^][v][top][bottom][index][help] */
 823 {
 824         if ( !ctr )
 825                 return;
 826 
 827         if ( ctr->ctx )
 828                 talloc_destroy(ctr->ctx);
 829 
 830         ZERO_STRUCTP(ctr);
 831 
 832         return;
 833 }
 834 
 835 /***********************************************************************
 836  **********************************************************************/
 837 
 838 static TALLOC_CTX* notify_ctr_getctx( SPOOLSS_NOTIFY_MSG_CTR *ctr )
     /* [<][>][^][v][top][bottom][index][help] */
 839 {
 840         if ( !ctr )
 841                 return NULL;
 842 
 843         return ctr->ctx;
 844 }
 845 
 846 /***********************************************************************
 847  **********************************************************************/
 848 
 849 static SPOOLSS_NOTIFY_MSG_GROUP* notify_ctr_getgroup( SPOOLSS_NOTIFY_MSG_CTR *ctr, uint32_t idx )
     /* [<][>][^][v][top][bottom][index][help] */
 850 {
 851         if ( !ctr || !ctr->msg_groups )
 852                 return NULL;
 853 
 854         if ( idx >= ctr->num_groups )
 855                 return NULL;
 856 
 857         return &ctr->msg_groups[idx];
 858 
 859 }
 860 
 861 /***********************************************************************
 862  How many groups of change messages do we have ?
 863  **********************************************************************/
 864 
 865 static int notify_msg_ctr_numgroups( SPOOLSS_NOTIFY_MSG_CTR *ctr )
     /* [<][>][^][v][top][bottom][index][help] */
 866 {
 867         if ( !ctr )
 868                 return 0;
 869 
 870         return ctr->num_groups;
 871 }
 872 
 873 /***********************************************************************
 874  Add a SPOOLSS_NOTIFY_MSG_CTR to the correct group
 875  **********************************************************************/
 876 
 877 static int notify_msg_ctr_addmsg( SPOOLSS_NOTIFY_MSG_CTR *ctr, SPOOLSS_NOTIFY_MSG *msg )
     /* [<][>][^][v][top][bottom][index][help] */
 878 {
 879         SPOOLSS_NOTIFY_MSG_GROUP        *groups = NULL;
 880         SPOOLSS_NOTIFY_MSG_GROUP        *msg_grp = NULL;
 881         SPOOLSS_NOTIFY_MSG              *msg_list = NULL;
 882         int                             i, new_slot;
 883 
 884         if ( !ctr || !msg )
 885                 return 0;
 886 
 887         /* loop over all groups looking for a matching printer name */
 888 
 889         for ( i=0; i<ctr->num_groups; i++ ) {
 890                 if ( strcmp(ctr->msg_groups[i].printername, msg->printer) == 0 )
 891                         break;
 892         }
 893 
 894         /* add a new group? */
 895 
 896         if ( i == ctr->num_groups ) {
 897                 ctr->num_groups++;
 898 
 899                 if ( !(groups = TALLOC_REALLOC_ARRAY( ctr->ctx, ctr->msg_groups, SPOOLSS_NOTIFY_MSG_GROUP, ctr->num_groups)) ) {
 900                         DEBUG(0,("notify_msg_ctr_addmsg: talloc_realloc() failed!\n"));
 901                         return 0;
 902                 }
 903                 ctr->msg_groups = groups;
 904 
 905                 /* clear the new entry and set the printer name */
 906 
 907                 ZERO_STRUCT( ctr->msg_groups[ctr->num_groups-1] );
 908                 fstrcpy( ctr->msg_groups[ctr->num_groups-1].printername, msg->printer );
 909         }
 910 
 911         /* add the change messages; 'i' is the correct index now regardless */
 912 
 913         msg_grp = &ctr->msg_groups[i];
 914 
 915         msg_grp->num_msgs++;
 916 
 917         if ( !(msg_list = TALLOC_REALLOC_ARRAY( ctr->ctx, msg_grp->msgs, SPOOLSS_NOTIFY_MSG, msg_grp->num_msgs )) ) {
 918                 DEBUG(0,("notify_msg_ctr_addmsg: talloc_realloc() failed for new message [%d]!\n", msg_grp->num_msgs));
 919                 return 0;
 920         }
 921         msg_grp->msgs = msg_list;
 922 
 923         new_slot = msg_grp->num_msgs-1;
 924         memcpy( &msg_grp->msgs[new_slot], msg, sizeof(SPOOLSS_NOTIFY_MSG) );
 925 
 926         /* need to allocate own copy of data */
 927 
 928         if ( msg->len != 0 )
 929                 msg_grp->msgs[new_slot].notify.data = (char *)
 930                         TALLOC_MEMDUP( ctr->ctx, msg->notify.data, msg->len );
 931 
 932         return ctr->num_groups;
 933 }
 934 
 935 /***********************************************************************
 936  Send a change notication message on all handles which have a call
 937  back registered
 938  **********************************************************************/
 939 
 940 static void send_notify2_changes( SPOOLSS_NOTIFY_MSG_CTR *ctr, uint32_t idx )
     /* [<][>][^][v][top][bottom][index][help] */
 941 {
 942         Printer_entry            *p;
 943         TALLOC_CTX               *mem_ctx = notify_ctr_getctx( ctr );
 944         SPOOLSS_NOTIFY_MSG_GROUP *msg_group = notify_ctr_getgroup( ctr, idx );
 945         SPOOLSS_NOTIFY_MSG       *messages;
 946         int                      sending_msg_count;
 947 
 948         if ( !msg_group ) {
 949                 DEBUG(5,("send_notify2_changes() called with no msg group!\n"));
 950                 return;
 951         }
 952 
 953         messages = msg_group->msgs;
 954 
 955         if ( !messages ) {
 956                 DEBUG(5,("send_notify2_changes() called with no messages!\n"));
 957                 return;
 958         }
 959 
 960         DEBUG(8,("send_notify2_changes: Enter...[%s]\n", msg_group->printername));
 961 
 962         /* loop over all printers */
 963 
 964         for (p = printers_list; p; p = p->next) {
 965                 struct spoolss_Notify *notifies;
 966                 uint32_t count = 0;
 967                 uint32_t id;
 968                 int     i;
 969 
 970                 /* Is there notification on this handle? */
 971 
 972                 if ( !p->notify.client_connected )
 973                         continue;
 974 
 975                 DEBUG(10,("Client connected! [\\\\%s\\%s]\n", p->servername, p->sharename));
 976 
 977                 /* For this printer?  Print servers always receive
 978                    notifications. */
 979 
 980                 if ( ( p->printer_type == SPLHND_PRINTER )  &&
 981                     ( !strequal(msg_group->printername, p->sharename) ) )
 982                         continue;
 983 
 984                 DEBUG(10,("Our printer\n"));
 985 
 986                 /* allocate the max entries possible */
 987 
 988                 notifies = TALLOC_ZERO_ARRAY(mem_ctx, struct spoolss_Notify, msg_group->num_msgs);
 989                 if (!notifies) {
 990                         return;
 991                 }
 992 
 993                 /* build the array of change notifications */
 994 
 995                 sending_msg_count = 0;
 996 
 997                 for ( i=0; i<msg_group->num_msgs; i++ ) {
 998                         SPOOLSS_NOTIFY_MSG      *msg = &messages[i];
 999 
1000                         /* Are we monitoring this event? */
1001 
1002                         if (!is_monitoring_event(p, msg->type, msg->field))
1003                                 continue;
1004 
1005                         sending_msg_count++;
1006 
1007 
1008                         DEBUG(10,("process_notify2_message: Sending message type [0x%x] field [0x%2x] for printer [%s]\n",
1009                                 msg->type, msg->field, p->sharename));
1010 
1011                         /*
1012                          * if the is a printer notification handle and not a job notification
1013                          * type, then set the id to 0.  Other wise just use what was specified
1014                          * in the message.
1015                          *
1016                          * When registering change notification on a print server handle
1017                          * we always need to send back the id (snum) matching the printer
1018                          * for which the change took place.  For change notify registered
1019                          * on a printer handle, this does not matter and the id should be 0.
1020                          *
1021                          * --jerry
1022                          */
1023 
1024                         if ( ( p->printer_type == SPLHND_PRINTER ) && ( msg->type == PRINTER_NOTIFY_TYPE ) )
1025                                 id = 0;
1026                         else
1027                                 id = msg->id;
1028 
1029 
1030                         /* Convert unix jobid to smb jobid */
1031 
1032                         if (msg->flags & SPOOLSS_NOTIFY_MSG_UNIX_JOBID) {
1033                                 id = sysjob_to_jobid(msg->id);
1034 
1035                                 if (id == -1) {
1036                                         DEBUG(3, ("no such unix jobid %d\n", msg->id));
1037                                         goto done;
1038                                 }
1039                         }
1040 
1041                         construct_info_data( &notifies[count], msg->type, msg->field, id );
1042 
1043                         switch(msg->type) {
1044                         case PRINTER_NOTIFY_TYPE:
1045                                 if ( printer_notify_table[msg->field].fn )
1046                                         printer_notify_table[msg->field].fn(msg, &notifies[count], mem_ctx);
1047                                 break;
1048 
1049                         case JOB_NOTIFY_TYPE:
1050                                 if ( job_notify_table[msg->field].fn )
1051                                         job_notify_table[msg->field].fn(msg, &notifies[count], mem_ctx);
1052                                 break;
1053 
1054                         default:
1055                                 DEBUG(5, ("Unknown notification type %d\n", msg->type));
1056                                 goto done;
1057                         }
1058 
1059                         count++;
1060                 }
1061 
1062                 if ( sending_msg_count ) {
1063                         NTSTATUS status;
1064                         WERROR werr;
1065                         union spoolss_ReplyPrinterInfo info;
1066                         struct spoolss_NotifyInfo info0;
1067                         uint32_t reply_result;
1068 
1069                         info0.version   = 0x2;
1070                         info0.flags     = count ? 0x00020000 /* ??? */ : PRINTER_NOTIFY_INFO_DISCARDED;
1071                         info0.count     = count;
1072                         info0.notifies  = notifies;
1073 
1074                         info.info0 = &info0;
1075 
1076                         status = rpccli_spoolss_RouterReplyPrinterEx(notify_cli_pipe, mem_ctx,
1077                                                                      &p->notify.client_hnd,
1078                                                                      p->notify.change, /* color */
1079                                                                      p->notify.flags,
1080                                                                      &reply_result,
1081                                                                      0, /* reply_type, must be 0 */
1082                                                                      info,
1083                                                                      &werr);
1084                         if (!NT_STATUS_IS_OK(status) || !W_ERROR_IS_OK(werr)) {
1085                                 DEBUG(1,("RouterReplyPrinterEx to client: %s failed: %s\n",
1086                                         notify_cli_pipe->srv_name_slash,
1087                                         win_errstr(werr)));
1088                         }
1089                         switch (reply_result) {
1090                                 case 0:
1091                                         break;
1092                                 case PRINTER_NOTIFY_INFO_DISCARDED:
1093                                 case PRINTER_NOTIFY_INFO_DISCARDNOTED:
1094                                 case PRINTER_NOTIFY_INFO_COLOR_MISMATCH:
1095                                         break;
1096                                 default:
1097                                         break;
1098                         }
1099                 }
1100         }
1101 
1102 done:
1103         DEBUG(8,("send_notify2_changes: Exit...\n"));
1104         return;
1105 }
1106 
1107 /***********************************************************************
1108  **********************************************************************/
1109 
1110 static bool notify2_unpack_msg( SPOOLSS_NOTIFY_MSG *msg, struct timeval *tv, void *buf, size_t len )
     /* [<][>][^][v][top][bottom][index][help] */
1111 {
1112 
1113         uint32_t tv_sec, tv_usec;
1114         size_t offset = 0;
1115 
1116         /* Unpack message */
1117 
1118         offset += tdb_unpack((uint8_t *)buf + offset, len - offset, "f",
1119                              msg->printer);
1120 
1121         offset += tdb_unpack((uint8_t *)buf + offset, len - offset, "ddddddd",
1122                                 &tv_sec, &tv_usec,
1123                                 &msg->type, &msg->field, &msg->id, &msg->len, &msg->flags);
1124 
1125         if (msg->len == 0)
1126                 tdb_unpack((uint8_t *)buf + offset, len - offset, "dd",
1127                            &msg->notify.value[0], &msg->notify.value[1]);
1128         else
1129                 tdb_unpack((uint8_t *)buf + offset, len - offset, "B",
1130                            &msg->len, &msg->notify.data);
1131 
1132         DEBUG(3, ("notify2_unpack_msg: got NOTIFY2 message for printer %s, jobid %u type %d, field 0x%02x, flags 0x%04x\n",
1133                   msg->printer, (unsigned int)msg->id, msg->type, msg->field, msg->flags));
1134 
1135         tv->tv_sec = tv_sec;
1136         tv->tv_usec = tv_usec;
1137 
1138         if (msg->len == 0)
1139                 DEBUG(3, ("notify2_unpack_msg: value1 = %d, value2 = %d\n", msg->notify.value[0],
1140                           msg->notify.value[1]));
1141         else
1142                 dump_data(3, (uint8_t *)msg->notify.data, msg->len);
1143 
1144         return true;
1145 }
1146 
1147 /********************************************************************
1148  Receive a notify2 message list
1149  ********************************************************************/
1150 
1151 static void receive_notify2_message_list(struct messaging_context *msg,
     /* [<][>][^][v][top][bottom][index][help] */
1152                                          void *private_data,
1153                                          uint32_t msg_type,
1154                                          struct server_id server_id,
1155                                          DATA_BLOB *data)
1156 {
1157         size_t                  msg_count, i;
1158         char                    *buf = (char *)data->data;
1159         char                    *msg_ptr;
1160         size_t                  msg_len;
1161         SPOOLSS_NOTIFY_MSG      notify;
1162         SPOOLSS_NOTIFY_MSG_CTR  messages;
1163         int                     num_groups;
1164 
1165         if (data->length < 4) {
1166                 DEBUG(0,("receive_notify2_message_list: bad message format (len < 4)!\n"));
1167                 return;
1168         }
1169 
1170         msg_count = IVAL(buf, 0);
1171         msg_ptr = buf + 4;
1172 
1173         DEBUG(5, ("receive_notify2_message_list: got %lu messages in list\n", (unsigned long)msg_count));
1174 
1175         if (msg_count == 0) {
1176                 DEBUG(0,("receive_notify2_message_list: bad message format (msg_count == 0) !\n"));
1177                 return;
1178         }
1179 
1180         /* initialize the container */
1181 
1182         ZERO_STRUCT( messages );
1183         notify_msg_ctr_init( &messages );
1184 
1185         /*
1186          * build message groups for each printer identified
1187          * in a change_notify msg.  Remember that a PCN message
1188          * includes the handle returned for the srv_spoolss_replyopenprinter()
1189          * call.  Therefore messages are grouped according to printer handle.
1190          */
1191 
1192         for ( i=0; i<msg_count; i++ ) {
1193                 struct timeval msg_tv;
1194 
1195                 if (msg_ptr + 4 - buf > data->length) {
1196                         DEBUG(0,("receive_notify2_message_list: bad message format (len > buf_size) !\n"));
1197                         return;
1198                 }
1199 
1200                 msg_len = IVAL(msg_ptr,0);
1201                 msg_ptr += 4;
1202 
1203                 if (msg_ptr + msg_len - buf > data->length) {
1204                         DEBUG(0,("receive_notify2_message_list: bad message format (bad len) !\n"));
1205                         return;
1206                 }
1207 
1208                 /* unpack messages */
1209 
1210                 ZERO_STRUCT( notify );
1211                 notify2_unpack_msg( &notify, &msg_tv, msg_ptr, msg_len );
1212                 msg_ptr += msg_len;
1213 
1214                 /* add to correct list in container */
1215 
1216                 notify_msg_ctr_addmsg( &messages, &notify );
1217 
1218                 /* free memory that might have been allocated by notify2_unpack_msg() */
1219 
1220                 if ( notify.len != 0 )
1221                         SAFE_FREE( notify.notify.data );
1222         }
1223 
1224         /* process each group of messages */
1225 
1226         num_groups = notify_msg_ctr_numgroups( &messages );
1227         for ( i=0; i<num_groups; i++ )
1228                 send_notify2_changes( &messages, i );
1229 
1230 
1231         /* cleanup */
1232 
1233         DEBUG(10,("receive_notify2_message_list: processed %u messages\n",
1234                 (uint32_t)msg_count ));
1235 
1236         notify_msg_ctr_destroy( &messages );
1237 
1238         return;
1239 }
1240 
1241 /********************************************************************
1242  Send a message to ourself about new driver being installed
1243  so we can upgrade the information for each printer bound to this
1244  driver
1245  ********************************************************************/
1246 
1247 static bool srv_spoolss_drv_upgrade_printer(const char *drivername)
     /* [<][>][^][v][top][bottom][index][help] */
1248 {
1249         int len = strlen(drivername);
1250 
1251         if (!len)
1252                 return false;
1253 
1254         DEBUG(10,("srv_spoolss_drv_upgrade_printer: Sending message about driver upgrade [%s]\n",
1255                 drivername));
1256 
1257         messaging_send_buf(smbd_messaging_context(), procid_self(),
1258                            MSG_PRINTER_DRVUPGRADE,
1259                            (uint8_t *)drivername, len+1);
1260 
1261         return true;
1262 }
1263 
1264 /**********************************************************************
1265  callback to receive a MSG_PRINTER_DRVUPGRADE message and interate
1266  over all printers, upgrading ones as necessary
1267  **********************************************************************/
1268 
1269 void do_drv_upgrade_printer(struct messaging_context *msg,
     /* [<][>][^][v][top][bottom][index][help] */
1270                             void *private_data,
1271                             uint32_t msg_type,
1272                             struct server_id server_id,
1273                             DATA_BLOB *data)
1274 {
1275         fstring drivername;
1276         int snum;
1277         int n_services = lp_numservices();
1278         size_t len;
1279 
1280         len = MIN(data->length,sizeof(drivername)-1);
1281         strncpy(drivername, (const char *)data->data, len);
1282 
1283         DEBUG(10,("do_drv_upgrade_printer: Got message for new driver [%s]\n", drivername ));
1284 
1285         /* Iterate the printer list */
1286 
1287         for (snum=0; snum<n_services; snum++)
1288         {
1289                 if (lp_snum_ok(snum) && lp_print_ok(snum) )
1290                 {
1291                         WERROR result;
1292                         NT_PRINTER_INFO_LEVEL *printer = NULL;
1293 
1294                         result = get_a_printer(NULL, &printer, 2, lp_const_servicename(snum));
1295                         if (!W_ERROR_IS_OK(result))
1296                                 continue;
1297 
1298                         if (printer && printer->info_2 && !strcmp(drivername, printer->info_2->drivername))
1299                         {
1300                                 DEBUG(6,("Updating printer [%s]\n", printer->info_2->printername));
1301 
1302                                 /* all we care about currently is the change_id */
1303 
1304                                 result = mod_a_printer(printer, 2);
1305                                 if (!W_ERROR_IS_OK(result)) {
1306                                         DEBUG(3,("do_drv_upgrade_printer: mod_a_printer() failed with status [%s]\n",
1307                                                 win_errstr(result)));
1308                                 }
1309                         }
1310 
1311                         free_a_printer(&printer, 2);
1312                 }
1313         }
1314 
1315         /* all done */
1316 }
1317 
1318 /********************************************************************
1319  Update the cache for all printq's with a registered client
1320  connection
1321  ********************************************************************/
1322 
1323 void update_monitored_printq_cache( void )
     /* [<][>][^][v][top][bottom][index][help] */
1324 {
1325         Printer_entry *printer = printers_list;
1326         int snum;
1327 
1328         /* loop through all printers and update the cache where
1329            client_connected == true */
1330         while ( printer )
1331         {
1332                 if ( (printer->printer_type == SPLHND_PRINTER)
1333                         && printer->notify.client_connected )
1334                 {
1335                         snum = print_queue_snum(printer->sharename);
1336                         print_queue_status( snum, NULL, NULL );
1337                 }
1338 
1339                 printer = printer->next;
1340         }
1341 
1342         return;
1343 }
1344 /********************************************************************
1345  Send a message to ourself about new driver being installed
1346  so we can upgrade the information for each printer bound to this
1347  driver
1348  ********************************************************************/
1349 
1350 static bool srv_spoolss_reset_printerdata(char* drivername)
     /* [<][>][^][v][top][bottom][index][help] */
1351 {
1352         int len = strlen(drivername);
1353 
1354         if (!len)
1355                 return false;
1356 
1357         DEBUG(10,("srv_spoolss_reset_printerdata: Sending message about resetting printerdata [%s]\n",
1358                 drivername));
1359 
1360         messaging_send_buf(smbd_messaging_context(), procid_self(),
1361                            MSG_PRINTERDATA_INIT_RESET,
1362                            (uint8_t *)drivername, len+1);
1363 
1364         return true;
1365 }
1366 
1367 /**********************************************************************
1368  callback to receive a MSG_PRINTERDATA_INIT_RESET message and interate
1369  over all printers, resetting printer data as neessary
1370  **********************************************************************/
1371 
1372 void reset_all_printerdata(struct messaging_context *msg,
     /* [<][>][^][v][top][bottom][index][help] */
1373                            void *private_data,
1374                            uint32_t msg_type,
1375                            struct server_id server_id,
1376                            DATA_BLOB *data)
1377 {
1378         fstring drivername;
1379         int snum;
1380         int n_services = lp_numservices();
1381         size_t len;
1382 
1383         len = MIN( data->length, sizeof(drivername)-1 );
1384         strncpy( drivername, (const char *)data->data, len );
1385 
1386         DEBUG(10,("reset_all_printerdata: Got message for new driver [%s]\n", drivername ));
1387 
1388         /* Iterate the printer list */
1389 
1390         for ( snum=0; snum<n_services; snum++ )
1391         {
1392                 if ( lp_snum_ok(snum) && lp_print_ok(snum) )
1393                 {
1394                         WERROR result;
1395                         NT_PRINTER_INFO_LEVEL *printer = NULL;
1396 
1397                         result = get_a_printer( NULL, &printer, 2, lp_const_servicename(snum) );
1398                         if ( !W_ERROR_IS_OK(result) )
1399                                 continue;
1400 
1401                         /*
1402                          * if the printer is bound to the driver,
1403                          * then reset to the new driver initdata
1404                          */
1405 
1406                         if ( printer && printer->info_2 && !strcmp(drivername, printer->info_2->drivername) )
1407                         {
1408                                 DEBUG(6,("reset_all_printerdata: Updating printer [%s]\n", printer->info_2->printername));
1409 
1410                                 if ( !set_driver_init(printer, 2) ) {
1411                                         DEBUG(5,("reset_all_printerdata: Error resetting printer data for printer [%s], driver [%s]!\n",
1412                                                 printer->info_2->printername, printer->info_2->drivername));
1413                                 }
1414 
1415                                 result = mod_a_printer( printer, 2 );
1416                                 if ( !W_ERROR_IS_OK(result) ) {
1417                                         DEBUG(3,("reset_all_printerdata: mod_a_printer() failed!  (%s)\n",
1418                                                 get_dos_error_msg(result)));
1419                                 }
1420                         }
1421 
1422                         free_a_printer( &printer, 2 );
1423                 }
1424         }
1425 
1426         /* all done */
1427 
1428         return;
1429 }
1430 
1431 /****************************************************************
1432  _spoolss_OpenPrinter
1433 ****************************************************************/
1434 
1435 WERROR _spoolss_OpenPrinter(pipes_struct *p,
     /* [<][>][^][v][top][bottom][index][help] */
1436                             struct spoolss_OpenPrinter *r)
1437 {
1438         struct spoolss_OpenPrinterEx e;
1439         WERROR werr;
1440 
1441         ZERO_STRUCT(e.in.userlevel);
1442 
1443         e.in.printername        = r->in.printername;
1444         e.in.datatype           = r->in.datatype;
1445         e.in.devmode_ctr        = r->in.devmode_ctr;
1446         e.in.access_mask        = r->in.access_mask;
1447         e.in.level              = 0;
1448 
1449         e.out.handle            = r->out.handle;
1450 
1451         werr = _spoolss_OpenPrinterEx(p, &e);
1452 
1453         if (W_ERROR_EQUAL(werr, WERR_INVALID_PARAM)) {
1454                 /* OpenPrinterEx returns this for a bad
1455                  * printer name. We must return WERR_INVALID_PRINTER_NAME
1456                  * instead.
1457                  */
1458                 werr = WERR_INVALID_PRINTER_NAME;
1459         }
1460 
1461         return werr;
1462 }
1463 
1464 /********************************************************************
1465  ********************************************************************/
1466 
1467 bool convert_devicemode(const char *printername,
     /* [<][>][^][v][top][bottom][index][help] */
1468                         const struct spoolss_DeviceMode *devmode,
1469                         NT_DEVICEMODE **pp_nt_devmode)
1470 {
1471         NT_DEVICEMODE *nt_devmode = *pp_nt_devmode;
1472 
1473         /*
1474          * Ensure nt_devmode is a valid pointer
1475          * as we will be overwriting it.
1476          */
1477 
1478         if (nt_devmode == NULL) {
1479                 DEBUG(5, ("convert_devicemode: allocating a generic devmode\n"));
1480                 if ((nt_devmode = construct_nt_devicemode(printername)) == NULL)
1481                         return false;
1482         }
1483 
1484         rpcstr_push(nt_devmode->devicename, devmode->devicename, 31, 0);
1485         rpcstr_push(nt_devmode->formname, devmode->formname, 31, 0);
1486 
1487         nt_devmode->specversion         = devmode->specversion;
1488         nt_devmode->driverversion       = devmode->driverversion;
1489         nt_devmode->size                = devmode->size;
1490         nt_devmode->fields              = devmode->fields;
1491         nt_devmode->orientation         = devmode->orientation;
1492         nt_devmode->papersize           = devmode->papersize;
1493         nt_devmode->paperlength         = devmode->paperlength;
1494         nt_devmode->paperwidth          = devmode->paperwidth;
1495         nt_devmode->scale               = devmode->scale;
1496         nt_devmode->copies              = devmode->copies;
1497         nt_devmode->defaultsource       = devmode->defaultsource;
1498         nt_devmode->printquality        = devmode->printquality;
1499         nt_devmode->color               = devmode->color;
1500         nt_devmode->duplex              = devmode->duplex;
1501         nt_devmode->yresolution         = devmode->yresolution;
1502         nt_devmode->ttoption            = devmode->ttoption;
1503         nt_devmode->collate             = devmode->collate;
1504 
1505         nt_devmode->logpixels           = devmode->logpixels;
1506         nt_devmode->bitsperpel          = devmode->bitsperpel;
1507         nt_devmode->pelswidth           = devmode->pelswidth;
1508         nt_devmode->pelsheight          = devmode->pelsheight;
1509         nt_devmode->displayflags        = devmode->displayflags;
1510         nt_devmode->displayfrequency    = devmode->displayfrequency;
1511         nt_devmode->icmmethod           = devmode->icmmethod;
1512         nt_devmode->icmintent           = devmode->icmintent;
1513         nt_devmode->mediatype           = devmode->mediatype;
1514         nt_devmode->dithertype          = devmode->dithertype;
1515         nt_devmode->reserved1           = devmode->reserved1;
1516         nt_devmode->reserved2           = devmode->reserved2;
1517         nt_devmode->panningwidth        = devmode->panningwidth;
1518         nt_devmode->panningheight       = devmode->panningheight;
1519 
1520         /*
1521          * Only change private and driverextra if the incoming devmode
1522          * has a new one. JRA.
1523          */
1524 
1525         if ((devmode->__driverextra_length != 0) && (devmode->driverextra_data.data != NULL)) {
1526                 SAFE_FREE(nt_devmode->nt_dev_private);
1527                 nt_devmode->driverextra = devmode->__driverextra_length;
1528                 if((nt_devmode->nt_dev_private = SMB_MALLOC_ARRAY(uint8_t, nt_devmode->driverextra)) == NULL)
1529                         return false;
1530                 memcpy(nt_devmode->nt_dev_private, devmode->driverextra_data.data, nt_devmode->driverextra);
1531         }
1532 
1533         *pp_nt_devmode = nt_devmode;
1534 
1535         return true;
1536 }
1537 
1538 /****************************************************************
1539  _spoolss_OpenPrinterEx
1540 ****************************************************************/
1541 
1542 WERROR _spoolss_OpenPrinterEx(pipes_struct *p,
     /* [<][>][^][v][top][bottom][index][help] */
1543                               struct spoolss_OpenPrinterEx *r)
1544 {
1545         int snum;
1546         Printer_entry *Printer=NULL;
1547 
1548         if (!r->in.printername) {
1549                 return WERR_INVALID_PARAM;
1550         }
1551 
1552         /* some sanity check because you can open a printer or a print server */
1553         /* aka: \\server\printer or \\server */
1554 
1555         DEBUGADD(3,("checking name: %s\n", r->in.printername));
1556 
1557         if (!open_printer_hnd(p, r->out.handle, r->in.printername, 0)) {
1558                 ZERO_STRUCTP(r->out.handle);
1559                 return WERR_INVALID_PARAM;
1560         }
1561 
1562         Printer = find_printer_index_by_hnd(p, r->out.handle);
1563         if ( !Printer ) {
1564                 DEBUG(0,("_spoolss_OpenPrinterEx: logic error.  Can't find printer "
1565                         "handle we created for printer %s\n", r->in.printername));
1566                 close_printer_handle(p, r->out.handle);
1567                 ZERO_STRUCTP(r->out.handle);
1568                 return WERR_INVALID_PARAM;
1569         }
1570 
1571         /*
1572          * First case: the user is opening the print server:
1573          *
1574          * Disallow MS AddPrinterWizard if parameter disables it. A Win2k
1575          * client 1st tries an OpenPrinterEx with access==0, MUST be allowed.
1576          *
1577          * Then both Win2k and WinNT clients try an OpenPrinterEx with
1578          * SERVER_ALL_ACCESS, which we allow only if the user is root (uid=0)
1579          * or if the user is listed in the smb.conf printer admin parameter.
1580          *
1581          * Then they try OpenPrinterEx with SERVER_READ which we allow. This lets the
1582          * client view printer folder, but does not show the MSAPW.
1583          *
1584          * Note: this test needs code to check access rights here too. Jeremy
1585          * could you look at this?
1586          *
1587          * Second case: the user is opening a printer:
1588          * NT doesn't let us connect to a printer if the connecting user
1589          * doesn't have print permission.
1590          *
1591          * Third case: user is opening a Port Monitor
1592          * access checks same as opening a handle to the print server.
1593          */
1594 
1595         switch (Printer->printer_type )
1596         {
1597         case SPLHND_SERVER:
1598         case SPLHND_PORTMON_TCP:
1599         case SPLHND_PORTMON_LOCAL:
1600                 /* Printserver handles use global struct... */
1601 
1602                 snum = -1;
1603 
1604                 /* Map standard access rights to object specific access rights */
1605 
1606                 se_map_standard(&r->in.access_mask,
1607                                 &printserver_std_mapping);
1608 
1609                 /* Deny any object specific bits that don't apply to print
1610                    servers (i.e printer and job specific bits) */
1611 
1612                 r->in.access_mask &= SPECIFIC_RIGHTS_MASK;
1613 
1614                 if (r->in.access_mask &
1615                     ~(SERVER_ACCESS_ADMINISTER | SERVER_ACCESS_ENUMERATE)) {
1616                         DEBUG(3, ("access DENIED for non-printserver bits\n"));
1617                         close_printer_handle(p, r->out.handle);
1618                         ZERO_STRUCTP(r->out.handle);
1619                         return WERR_ACCESS_DENIED;
1620                 }
1621 
1622                 /* Allow admin access */
1623 
1624                 if ( r->in.access_mask & SERVER_ACCESS_ADMINISTER )
1625                 {
1626                         SE_PRIV se_printop = SE_PRINT_OPERATOR;
1627 
1628                         if (!lp_ms_add_printer_wizard()) {
1629                                 close_printer_handle(p, r->out.handle);
1630                                 ZERO_STRUCTP(r->out.handle);
1631                                 return WERR_ACCESS_DENIED;
1632                         }
1633 
1634                         /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
1635                            and not a printer admin, then fail */
1636 
1637                         if ((p->server_info->utok.uid != sec_initial_uid()) &&
1638                             !user_has_privileges(p->server_info->ptok,
1639                                                  &se_printop ) &&
1640                             !token_contains_name_in_list(
1641                                     uidtoname(p->server_info->utok.uid),
1642                                     NULL, NULL,
1643                                     p->server_info->ptok,
1644                                     lp_printer_admin(snum))) {
1645                                 close_printer_handle(p, r->out.handle);
1646                                 ZERO_STRUCTP(r->out.handle);
1647                                 return WERR_ACCESS_DENIED;
1648                         }
1649 
1650                         r->in.access_mask = SERVER_ACCESS_ADMINISTER;
1651                 }
1652                 else
1653                 {
1654                         r->in.access_mask = SERVER_ACCESS_ENUMERATE;
1655                 }
1656 
1657                 DEBUG(4,("Setting print server access = %s\n", (r->in.access_mask == SERVER_ACCESS_ADMINISTER)
1658                         ? "SERVER_ACCESS_ADMINISTER" : "SERVER_ACCESS_ENUMERATE" ));
1659 
1660                 /* We fall through to return WERR_OK */
1661                 break;
1662 
1663         case SPLHND_PRINTER:
1664                 /* NT doesn't let us connect to a printer if the connecting user
1665                    doesn't have print permission.  */
1666 
1667                 if (!get_printer_snum(p, r->out.handle, &snum, NULL)) {
1668                         close_printer_handle(p, r->out.handle);
1669                         ZERO_STRUCTP(r->out.handle);
1670                         return WERR_BADFID;
1671                 }
1672 
1673                 se_map_standard(&r->in.access_mask, &printer_std_mapping);
1674 
1675                 /* map an empty access mask to the minimum access mask */
1676                 if (r->in.access_mask == 0x0)
1677                         r->in.access_mask = PRINTER_ACCESS_USE;
1678 
1679                 /*
1680                  * If we are not serving the printer driver for this printer,
1681                  * map PRINTER_ACCESS_ADMINISTER to PRINTER_ACCESS_USE.  This
1682                  * will keep NT clients happy  --jerry
1683                  */
1684 
1685                 if (lp_use_client_driver(snum)
1686                         && (r->in.access_mask & PRINTER_ACCESS_ADMINISTER))
1687                 {
1688                         r->in.access_mask = PRINTER_ACCESS_USE;
1689                 }
1690 
1691                 /* check smb.conf parameters and the the sec_desc */
1692 
1693                 if ( !check_access(get_client_fd(), lp_hostsallow(snum), lp_hostsdeny(snum)) ) {
1694                         DEBUG(3, ("access DENIED (hosts allow/deny) for printer open\n"));
1695                         ZERO_STRUCTP(r->out.handle);
1696                         return WERR_ACCESS_DENIED;
1697                 }
1698 
1699                 if (!user_ok_token(uidtoname(p->server_info->utok.uid), NULL,
1700                                    p->server_info->ptok, snum) ||
1701                     !print_access_check(p->server_info, snum,
1702                                         r->in.access_mask)) {
1703                         DEBUG(3, ("access DENIED for printer open\n"));
1704                         close_printer_handle(p, r->out.handle);
1705                         ZERO_STRUCTP(r->out.handle);
1706                         return WERR_ACCESS_DENIED;
1707                 }
1708 
1709                 if ((r->in.access_mask & SPECIFIC_RIGHTS_MASK)& ~(PRINTER_ACCESS_ADMINISTER|PRINTER_ACCESS_USE)) {
1710                         DEBUG(3, ("access DENIED for printer open - unknown bits\n"));
1711                         close_printer_handle(p, r->out.handle);
1712                         ZERO_STRUCTP(r->out.handle);
1713                         return WERR_ACCESS_DENIED;
1714                 }
1715 
1716                 if (r->in.access_mask & PRINTER_ACCESS_ADMINISTER)
1717                         r->in.access_mask = PRINTER_ACCESS_ADMINISTER;
1718                 else
1719                         r->in.access_mask = PRINTER_ACCESS_USE;
1720 
1721                 DEBUG(4,("Setting printer access = %s\n", (r->in.access_mask == PRINTER_ACCESS_ADMINISTER)
1722                         ? "PRINTER_ACCESS_ADMINISTER" : "PRINTER_ACCESS_USE" ));
1723 
1724                 break;
1725 
1726         default:
1727                 /* sanity check to prevent programmer error */
1728                 ZERO_STRUCTP(r->out.handle);
1729                 return WERR_BADFID;
1730         }
1731 
1732         Printer->access_granted = r->in.access_mask;
1733 
1734         /*
1735          * If the client sent a devmode in the OpenPrinter() call, then
1736          * save it here in case we get a job submission on this handle
1737          */
1738 
1739          if ((Printer->printer_type != SPLHND_SERVER) &&
1740              r->in.devmode_ctr.devmode) {
1741                 convert_devicemode(Printer->sharename,
1742                                    r->in.devmode_ctr.devmode,
1743                                    &Printer->nt_devmode);
1744          }
1745 
1746 #if 0   /* JERRY -- I'm doubtful this is really effective */
1747         /* HACK ALERT!!! Sleep for 1/3 of a second to try trigger a LAN/WAN
1748            optimization in Windows 2000 clients  --jerry */
1749 
1750         if ( (r->in.access_mask == PRINTER_ACCESS_ADMINISTER)
1751                 && (RA_WIN2K == get_remote_arch()) )
1752         {
1753                 DEBUG(10,("_spoolss_OpenPrinterEx: Enabling LAN/WAN hack for Win2k clients.\n"));
1754                 sys_usleep( 500000 );
1755         }
1756 #endif
1757 
1758         return WERR_OK;
1759 }
1760 
1761 /****************************************************************************
1762 ****************************************************************************/
1763 
1764 static bool printer_info2_to_nt_printer_info2(struct spoolss_SetPrinterInfo2 *r,
     /* [<][>][^][v][top][bottom][index][help] */
1765                                               NT_PRINTER_INFO_LEVEL_2 *d)
1766 {
1767         DEBUG(7,("printer_info2_to_nt_printer_info2\n"));
1768 
1769         if (!r || !d) {
1770                 return false;
1771         }
1772 
1773         d->attributes           = r->attributes;
1774         d->priority             = r->priority;
1775         d->default_priority     = r->defaultpriority;
1776         d->starttime            = r->starttime;
1777         d->untiltime            = r->untiltime;
1778         d->status               = r->status;
1779         d->cjobs                = r->cjobs;
1780 
1781         fstrcpy(d->servername,  r->servername);
1782         fstrcpy(d->printername, r->printername);
1783         fstrcpy(d->sharename,   r->sharename);
1784         fstrcpy(d->portname,    r->portname);
1785         fstrcpy(d->drivername,  r->drivername);
1786         slprintf(d->comment, sizeof(d->comment)-1, "%s", r->comment);
1787         fstrcpy(d->location,    r->location);
1788         fstrcpy(d->sepfile,     r->sepfile);
1789         fstrcpy(d->printprocessor, r->printprocessor);
1790         fstrcpy(d->datatype,    r->datatype);
1791         fstrcpy(d->parameters,  r->parameters);
1792 
1793         return true;
1794 }
1795 
1796 /****************************************************************************
1797 ****************************************************************************/
1798 
1799 static bool convert_printer_info(struct spoolss_SetPrinterInfoCtr *info_ctr,
     /* [<][>][^][v][top][bottom][index][help] */
1800                                  NT_PRINTER_INFO_LEVEL *printer)
1801 {
1802         bool ret;
1803 
1804         switch (info_ctr->level) {
1805         case 2:
1806                 /* allocate memory if needed.  Messy because
1807                    convert_printer_info is used to update an existing
1808                    printer or build a new one */
1809 
1810                 if (!printer->info_2) {
1811                         printer->info_2 = TALLOC_ZERO_P(printer, NT_PRINTER_INFO_LEVEL_2);
1812                         if (!printer->info_2) {
1813                                 DEBUG(0,("convert_printer_info: "
1814                                         "talloc() failed!\n"));
1815                                 return false;
1816                         }
1817                 }
1818 
1819                 ret = printer_info2_to_nt_printer_info2(info_ctr->info.info2,
1820                                                         printer->info_2);
1821                 printer->info_2->setuptime = time(NULL);
1822                 return ret;
1823         }
1824 
1825         return false;
1826 }
1827 
1828 /*******************************************************************
1829 ********************************************************************/
1830 
1831 static bool string_array_to_fstring_array(const char **sarray, fstring **farray)
     /* [<][>][^][v][top][bottom][index][help] */
1832 {
1833         int i;
1834 
1835         if (!sarray) {
1836                 *farray = NULL;
1837                 return true;
1838         }
1839 
1840         *farray = SMB_MALLOC_ARRAY(fstring, 1);
1841         if (!*farray) {
1842                 return false;
1843         }
1844 
1845         for (i=0; sarray[i] != NULL; i++) {
1846                 *farray = SMB_REALLOC_ARRAY(*farray, fstring, i+2);
1847                 if (!*farray) {
1848                         return false;
1849                 }
1850                 fstrcpy((*farray)[i], sarray[i]);
1851         }
1852 
1853         fstrcpy((*farray)[i], "");
1854 
1855         return true;
1856 }
1857 
1858 /*******************************************************************
1859 ********************************************************************/
1860 
1861 static bool driver_info3_to_nt_driver_info3(struct spoolss_AddDriverInfo3 *r,
     /* [<][>][^][v][top][bottom][index][help] */
1862                                             NT_PRINTER_DRIVER_INFO_LEVEL_3 **p)
1863 {
1864         NT_PRINTER_DRIVER_INFO_LEVEL_3 *d;
1865 
1866         DEBUG(7,("driver_info3_to_nt_driver_info3: Converting from UNICODE to ASCII\n"));
1867 
1868         if (*p == NULL) {
1869                 *p = SMB_MALLOC_P(NT_PRINTER_DRIVER_INFO_LEVEL_3);
1870                 if (*p == NULL) {
1871                         return false;
1872                 }
1873                 ZERO_STRUCTP(*p);
1874         }
1875 
1876         d = *p;
1877 
1878         d->cversion =                   r->version;
1879 
1880         fstrcpy(d->name,                r->driver_name);
1881         fstrcpy(d->environment,         r->architecture);
1882         fstrcpy(d->driverpath,          r->driver_path);
1883         fstrcpy(d->datafile,            r->data_file);
1884         fstrcpy(d->configfile,          r->config_file);
1885         fstrcpy(d->helpfile,            r->help_file);
1886         fstrcpy(d->monitorname,         r->monitor_name);
1887         fstrcpy(d->defaultdatatype,     r->default_datatype);
1888 
1889         DEBUGADD(8,( "version:         %d\n", d->cversion));
1890         DEBUGADD(8,( "name:            %s\n", d->name));
1891         DEBUGADD(8,( "environment:     %s\n", d->environment));
1892         DEBUGADD(8,( "driverpath:      %s\n", d->driverpath));
1893         DEBUGADD(8,( "datafile:        %s\n", d->datafile));
1894         DEBUGADD(8,( "configfile:      %s\n", d->configfile));
1895         DEBUGADD(8,( "helpfile:        %s\n", d->helpfile));
1896         DEBUGADD(8,( "monitorname:     %s\n", d->monitorname));
1897         DEBUGADD(8,( "defaultdatatype: %s\n", d->defaultdatatype));
1898 
1899         if (r->dependent_files) {
1900                 if (!string_array_to_fstring_array(r->dependent_files->string,
1901                                                    &d->dependentfiles)) {
1902                         SAFE_FREE(*p);
1903                         return false;
1904                 }
1905         }
1906 
1907         return true;
1908 }
1909 
1910 /*******************************************************************
1911 ********************************************************************/
1912 
1913 static bool driver_info6_to_nt_driver_info6(struct spoolss_AddDriverInfo6 *r,
     /* [<][>][^][v][top][bottom][index][help] */
1914                                             NT_PRINTER_DRIVER_INFO_LEVEL_6 **p)
1915 {
1916         NT_PRINTER_DRIVER_INFO_LEVEL_6 *d;
1917 
1918         DEBUG(7,("driver_info6_to_nt_driver_info6: Converting from UNICODE to ASCII\n"));
1919 
1920         if (*p == NULL) {
1921                 *p = SMB_MALLOC_P(NT_PRINTER_DRIVER_INFO_LEVEL_6);
1922                 if (*p == NULL) {
1923                         return false;
1924                 }
1925                 ZERO_STRUCTP(*p);
1926         }
1927 
1928         d = *p;
1929 
1930         d->version =                    r->version;
1931 
1932         fstrcpy(d->name,                r->driver_name);
1933         fstrcpy(d->environment,         r->architecture);
1934         fstrcpy(d->driverpath,          r->driver_path);
1935         fstrcpy(d->datafile,            r->data_file);
1936         fstrcpy(d->configfile,          r->config_file);
1937         fstrcpy(d->helpfile,            r->help_file);
1938         fstrcpy(d->monitorname,         r->monitor_name);
1939         fstrcpy(d->defaultdatatype,     r->default_datatype);
1940 
1941         DEBUGADD(8,( "version:         %d\n", d->version));
1942         DEBUGADD(8,( "name:            %s\n", d->name));
1943         DEBUGADD(8,( "environment:     %s\n", d->environment));
1944         DEBUGADD(8,( "driverpath:      %s\n", d->driverpath));
1945         DEBUGADD(8,( "datafile:        %s\n", d->datafile));
1946         DEBUGADD(8,( "configfile:      %s\n", d->configfile));
1947         DEBUGADD(8,( "helpfile:        %s\n", d->helpfile));
1948         DEBUGADD(8,( "monitorname:     %s\n", d->monitorname));
1949         DEBUGADD(8,( "defaultdatatype: %s\n", d->defaultdatatype));
1950 
1951         if (r->dependent_files) {
1952                 if (!string_array_to_fstring_array(r->dependent_files->string,
1953                                                    &d->dependentfiles)) {
1954                         goto error;
1955                 }
1956         }
1957 
1958         if (r->previous_names) {
1959                 if (!string_array_to_fstring_array(r->previous_names->string,
1960                                                    &d->previousnames)) {
1961                         goto error;
1962                 }
1963         }
1964 
1965         return true;
1966 
1967  error:
1968         SAFE_FREE(*p);
1969         return false;
1970 }
1971 
1972 /********************************************************************
1973  ********************************************************************/
1974 
1975 static bool convert_printer_driver_info(const struct spoolss_AddDriverInfoCtr *r,
     /* [<][>][^][v][top][bottom][index][help] */
1976                                         NT_PRINTER_DRIVER_INFO_LEVEL *printer,
1977                                         uint32_t level)
1978 {
1979         switch (level) {
1980         case 3:
1981                 printer->info_3 = NULL;
1982                 if (!driver_info3_to_nt_driver_info3(r->info.info3, &printer->info_3)) {
1983                         return false;
1984                 }
1985                 break;
1986         case 6:
1987                 printer->info_6 = NULL;
1988                 if (!driver_info6_to_nt_driver_info6(r->info.info6, &printer->info_6)) {
1989                         return false;
1990                 }
1991                 break;
1992         default:
1993                 return false;
1994         }
1995 
1996         return true;
1997 }
1998 
1999 /********************************************************************
2000  * _spoolss_enddocprinter_internal.
2001  ********************************************************************/
2002 
2003 static WERROR _spoolss_enddocprinter_internal(pipes_struct *p,
     /* [<][>][^][v][top][bottom][index][help] */
2004                                               struct policy_handle *handle)
2005 {
2006         Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
2007         int snum;
2008 
2009         if (!Printer) {
2010                 DEBUG(2,("_spoolss_enddocprinter_internal: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
2011                 return WERR_BADFID;
2012         }
2013 
2014         if (!get_printer_snum(p, handle, &snum, NULL))
2015                 return WERR_BADFID;
2016 
2017         Printer->document_started = false;
2018         print_job_end(snum, Printer->jobid,NORMAL_CLOSE);
2019         /* error codes unhandled so far ... */
2020 
2021         return WERR_OK;
2022 }
2023 
2024 /****************************************************************
2025  _spoolss_ClosePrinter
2026 ****************************************************************/
2027 
2028 WERROR _spoolss_ClosePrinter(pipes_struct *p,
     /* [<][>][^][v][top][bottom][index][help] */
2029                              struct spoolss_ClosePrinter *r)
2030 {
2031         Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
2032 
2033         if (Printer && Printer->document_started)
2034                 _spoolss_enddocprinter_internal(p, r->in.handle);          /* print job was not closed */
2035 
2036         if (!close_printer_handle(p, r->in.handle))
2037                 return WERR_BADFID;
2038 
2039         /* clear the returned printer handle.  Observed behavior
2040            from Win2k server.  Don't think this really matters.
2041            Previous code just copied the value of the closed
2042            handle.    --jerry */
2043 
2044         ZERO_STRUCTP(r->out.handle);
2045 
2046         return WERR_OK;
2047 }
2048 
2049 /****************************************************************
2050  _spoolss_DeletePrinter
2051 ****************************************************************/
2052 
2053 WERROR _spoolss_DeletePrinter(pipes_struct *p,
     /* [<][>][^][v][top][bottom][index][help] */
2054                               struct spoolss_DeletePrinter *r)
2055 {
2056         Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
2057         WERROR result;
2058 
2059         if (Printer && Printer->document_started)
2060                 _spoolss_enddocprinter_internal(p, r->in.handle);  /* print job was not closed */
2061 
2062         result = delete_printer_handle(p, r->in.handle);
2063 
2064         update_c_setprinter(false);
2065 
2066         return result;
2067 }
2068 
2069 /*******************************************************************
2070  * static function to lookup the version id corresponding to an
2071  * long architecture string
2072  ******************************************************************/
2073 
2074 static int get_version_id(const char *arch)
     /* [<][>][^][v][top][bottom][index][help] */
2075 {
2076         int i;
2077         struct print_architecture_table_node archi_table[]= {
2078 
2079                 {"Windows 4.0",          "WIN40",       0 },
2080                 {"Windows NT x86",       "W32X86",      2 },
2081                 {"Windows NT R4000",     "W32MIPS",     2 },
2082                 {"Windows NT Alpha_AXP", "W32ALPHA",    2 },
2083                 {"Windows NT PowerPC",   "W32PPC",      2 },
2084                 {"Windows IA64",         "IA64",        3 },
2085                 {"Windows x64",          "x64",         3 },
2086                 {NULL,                   "",            -1 }
2087         };
2088 
2089         for (i=0; archi_table[i].long_archi != NULL; i++)
2090         {
2091                 if (strcmp(arch, archi_table[i].long_archi) == 0)
2092                         return (archi_table[i].version);
2093         }
2094 
2095         return -1;
2096 }
2097 
2098 /****************************************************************
2099  _spoolss_DeletePrinterDriver
2100 ****************************************************************/
2101 
2102 WERROR _spoolss_DeletePrinterDriver(pipes_struct *p,
     /* [<][>][^][v][top][bottom][index][help] */
2103                                     struct spoolss_DeletePrinterDriver *r)
2104 {
2105         NT_PRINTER_DRIVER_INFO_LEVEL    info;
2106         NT_PRINTER_DRIVER_INFO_LEVEL    info_win2k;
2107         int                             version;
2108         WERROR                          status;
2109         WERROR                          status_win2k = WERR_ACCESS_DENIED;
2110         SE_PRIV                         se_printop = SE_PRINT_OPERATOR;
2111 
2112         /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
2113            and not a printer admin, then fail */
2114 
2115         if ( (p->server_info->utok.uid != sec_initial_uid())
2116                 && !user_has_privileges(p->server_info->ptok, &se_printop )
2117                 && !token_contains_name_in_list(
2118                         uidtoname(p->server_info->utok.uid), NULL,
2119                         NULL, p->server_info->ptok,
2120                         lp_printer_admin(-1)) )
2121         {
2122                 return WERR_ACCESS_DENIED;
2123         }
2124 
2125         /* check that we have a valid driver name first */
2126 
2127         if ((version = get_version_id(r->in.architecture)) == -1)
2128                 return WERR_INVALID_ENVIRONMENT;
2129 
2130         ZERO_STRUCT(info);
2131         ZERO_STRUCT(info_win2k);
2132 
2133         if (!W_ERROR_IS_OK(get_a_printer_driver(&info, 3, r->in.driver,
2134                                                 r->in.architecture,
2135                                                 version)))
2136         {
2137                 /* try for Win2k driver if "Windows NT x86" */
2138 
2139                 if ( version == 2 ) {
2140                         version = 3;
2141                         if (!W_ERROR_IS_OK(get_a_printer_driver(&info, 3,
2142                                                                 r->in.driver,
2143                                                                 r->in.architecture,
2144                                                                 version))) {
2145                                 status = WERR_UNKNOWN_PRINTER_DRIVER;
2146                                 goto done;
2147                         }
2148                 }
2149                 /* otherwise it was a failure */
2150                 else {
2151                         status = WERR_UNKNOWN_PRINTER_DRIVER;
2152                         goto done;
2153                 }
2154 
2155         }
2156 
2157         if (printer_driver_in_use(info.info_3)) {
2158                 status = WERR_PRINTER_DRIVER_IN_USE;
2159                 goto done;
2160         }
2161 
2162         if ( version == 2 )
2163         {
2164                 if (W_ERROR_IS_OK(get_a_printer_driver(&info_win2k, 3,
2165                                                        r->in.driver,
2166                                                        r->in.architecture, 3)))
2167                 {
2168                         /* if we get to here, we now have 2 driver info structures to remove */
2169                         /* remove the Win2k driver first*/
2170 
2171                         status_win2k = delete_printer_driver(
2172                                 p, info_win2k.info_3, 3, false);
2173                         free_a_printer_driver( info_win2k, 3 );
2174 
2175                         /* this should not have failed---if it did, report to client */
2176                         if ( !W_ERROR_IS_OK(status_win2k) )
2177                         {
2178                                 status = status_win2k;
2179                                 goto done;
2180                         }
2181                 }
2182         }
2183 
2184         status = delete_printer_driver(p, info.info_3, version, false);
2185 
2186         /* if at least one of the deletes succeeded return OK */
2187 
2188         if ( W_ERROR_IS_OK(status) || W_ERROR_IS_OK(status_win2k) )
2189                 status = WERR_OK;
2190 
2191 done:
2192         free_a_printer_driver( info, 3 );
2193 
2194         return status;
2195 }
2196 
2197 /****************************************************************
2198  _spoolss_DeletePrinterDriverEx
2199 ****************************************************************/
2200 
2201 WERROR _spoolss_DeletePrinterDriverEx(pipes_struct *p,
     /* [<][>][^][v][top][bottom][index][help] */
2202                                       struct spoolss_DeletePrinterDriverEx *r)
2203 {
2204         NT_PRINTER_DRIVER_INFO_LEVEL    info;
2205         NT_PRINTER_DRIVER_INFO_LEVEL    info_win2k;
2206         int                             version;
2207         bool                            delete_files;
2208         WERROR                          status;
2209         WERROR                          status_win2k = WERR_ACCESS_DENIED;
2210         SE_PRIV                         se_printop = SE_PRINT_OPERATOR;
2211 
2212         /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
2213            and not a printer admin, then fail */
2214 
2215         if ( (p->server_info->utok.uid != sec_initial_uid())
2216                 && !user_has_privileges(p->server_info->ptok, &se_printop )
2217                 && !token_contains_name_in_list(
2218                         uidtoname(p->server_info->utok.uid), NULL, NULL,
2219                         p->server_info->ptok, lp_printer_admin(-1)) )
2220         {
2221                 return WERR_ACCESS_DENIED;
2222         }
2223 
2224         /* check that we have a valid driver name first */
2225         if ((version = get_version_id(r->in.architecture)) == -1) {
2226                 /* this is what NT returns */
2227                 return WERR_INVALID_ENVIRONMENT;
2228         }
2229 
2230         if (r->in.delete_flags & DPD_DELETE_SPECIFIC_VERSION)
2231                 version = r->in.version;
2232 
2233         ZERO_STRUCT(info);
2234         ZERO_STRUCT(info_win2k);
2235 
2236         status = get_a_printer_driver(&info, 3, r->in.driver,
2237                                       r->in.architecture, version);
2238 
2239         if ( !W_ERROR_IS_OK(status) )
2240         {
2241                 /*
2242                  * if the client asked for a specific version,
2243                  * or this is something other than Windows NT x86,
2244                  * then we've failed
2245                  */
2246 
2247                 if ( (r->in.delete_flags & DPD_DELETE_SPECIFIC_VERSION) || (version !=2) )
2248                         goto done;
2249 
2250                 /* try for Win2k driver if "Windows NT x86" */
2251 
2252                 version = 3;
2253                 if (!W_ERROR_IS_OK(get_a_printer_driver(&info, 3, r->in.driver,
2254                                                         r->in.architecture,
2255                                                         version))) {
2256                         status = WERR_UNKNOWN_PRINTER_DRIVER;
2257                         goto done;
2258                 }
2259         }
2260 
2261         if ( printer_driver_in_use(info.info_3) ) {
2262                 status = WERR_PRINTER_DRIVER_IN_USE;
2263                 goto done;
2264         }
2265 
2266         /*
2267          * we have a couple of cases to consider.
2268          * (1) Are any files in use?  If so and DPD_DELTE_ALL_FILE is set,
2269          *     then the delete should fail if **any** files overlap with
2270          *     other drivers
2271          * (2) If DPD_DELTE_UNUSED_FILES is sert, then delete all
2272          *     non-overlapping files
2273          * (3) If neither DPD_DELTE_ALL_FILE nor DPD_DELTE_ALL_FILES
2274          *     is set, the do not delete any files
2275          * Refer to MSDN docs on DeletePrinterDriverEx() for details.
2276          */
2277 
2278         delete_files = r->in.delete_flags & (DPD_DELETE_ALL_FILES|DPD_DELETE_UNUSED_FILES);
2279 
2280         /* fail if any files are in use and DPD_DELETE_ALL_FILES is set */
2281 
2282         if ( delete_files && printer_driver_files_in_use(info.info_3) & (r->in.delete_flags & DPD_DELETE_ALL_FILES) ) {
2283                 /* no idea of the correct error here */
2284                 status = WERR_ACCESS_DENIED;
2285                 goto done;
2286         }
2287 
2288 
2289         /* also check for W32X86/3 if necessary; maybe we already have? */
2290 
2291         if ( (version == 2) && ((r->in.delete_flags & DPD_DELETE_SPECIFIC_VERSION) != DPD_DELETE_SPECIFIC_VERSION)  ) {
2292                 if (W_ERROR_IS_OK(get_a_printer_driver(&info_win2k, 3,
2293                                                        r->in.driver,
2294                                                        r->in.architecture, 3)))
2295                 {
2296 
2297                         if ( delete_files && printer_driver_files_in_use(info_win2k.info_3) & (r->in.delete_flags & DPD_DELETE_ALL_FILES) ) {
2298                                 /* no idea of the correct error here */
2299                                 free_a_printer_driver( info_win2k, 3 );
2300                                 status = WERR_ACCESS_DENIED;
2301                                 goto done;
2302                         }
2303 
2304                         /* if we get to here, we now have 2 driver info structures to remove */
2305                         /* remove the Win2k driver first*/
2306 
2307                         status_win2k = delete_printer_driver(
2308                                 p, info_win2k.info_3, 3, delete_files);
2309                         free_a_printer_driver( info_win2k, 3 );
2310 
2311                         /* this should not have failed---if it did, report to client */
2312 
2313                         if ( !W_ERROR_IS_OK(status_win2k) )
2314                                 goto done;
2315                 }
2316         }
2317 
2318         status = delete_printer_driver(p, info.info_3, version, delete_files);
2319 
2320         if ( W_ERROR_IS_OK(status) || W_ERROR_IS_OK(status_win2k) )
2321                 status = WERR_OK;
2322 done:
2323         free_a_printer_driver( info, 3 );
2324 
2325         return status;
2326 }
2327 
2328 
2329 /****************************************************************************
2330  Internal routine for removing printerdata
2331  ***************************************************************************/
2332 
2333 static WERROR delete_printer_dataex( NT_PRINTER_INFO_LEVEL *printer, const char *key, const char *value )
     /* [<][>][^][v][top][bottom][index][help] */
2334 {
2335         return delete_printer_data( printer->info_2, key, value );
2336 }
2337 
2338 /****************************************************************************
2339  Internal routine for storing printerdata
2340  ***************************************************************************/
2341 
2342 WERROR set_printer_dataex(NT_PRINTER_INFO_LEVEL *printer,
     /* [<][>][^][v][top][bottom][index][help] */
2343                           const char *key, const char *value,
2344                           uint32_t type, uint8_t *data, int real_len)
2345 {
2346         /* the registry objects enforce uniqueness based on value name */
2347 
2348         return add_printer_data( printer->info_2, key, value, type, data, real_len );
2349 }
2350 
2351 /********************************************************************
2352  GetPrinterData on a printer server Handle.
2353 ********************************************************************/
2354 
2355 static WERROR getprinterdata_printer_server(TALLOC_CTX *mem_ctx,
     /* [<][>][^][v][top][bottom][index][help] */
2356                                             const char *value,
2357                                             enum winreg_Type *type,
2358                                             union spoolss_PrinterData *data)
2359 {
2360         DEBUG(8,("getprinterdata_printer_server:%s\n", value));
2361 
2362         if (!StrCaseCmp(value, "W3SvcInstalled")) {
2363                 *type = REG_DWORD;
2364                 data->value = 0x00;
2365                 return WERR_OK;
2366         }
2367 
2368         if (!StrCaseCmp(value, "BeepEnabled")) {
2369                 *type = REG_DWORD;
2370                 data->value = 0x00;
2371                 return WERR_OK;
2372         }
2373 
2374         if (!StrCaseCmp(value, "EventLog")) {
2375                 *type = REG_DWORD;
2376                 /* formally was 0x1b */
2377                 data->value = 0x00;
2378                 return WERR_OK;
2379         }
2380 
2381         if (!StrCaseCmp(value, "NetPopup")) {
2382                 *type = REG_DWORD;
2383                 data->value = 0x00;
2384                 return WERR_OK;
2385         }
2386 
2387         if (!StrCaseCmp(value, "MajorVersion")) {
2388                 *type = REG_DWORD;
2389 
2390                 /* Windows NT 4.0 seems to not allow uploading of drivers
2391                    to a server that reports 0x3 as the MajorVersion.
2392                    need to investigate more how Win2k gets around this .
2393                    -- jerry */
2394 
2395                 if (RA_WINNT == get_remote_arch()) {
2396                         data->value = 0x02;
2397                 } else {
2398                         data->value = 0x03;
2399                 }
2400 
2401                 return WERR_OK;
2402         }
2403 
2404         if (!StrCaseCmp(value, "MinorVersion")) {
2405                 *type = REG_DWORD;
2406                 data->value = 0x00;
2407                 return WERR_OK;
2408         }
2409 
2410         /* REG_BINARY
2411          *  uint32_t size        = 0x114
2412          *  uint32_t major       = 5
2413          *  uint32_t minor       = [0|1]
2414          *  uint32_t build       = [2195|2600]
2415          *  extra unicode string = e.g. "Service Pack 3"
2416          */
2417         if (!StrCaseCmp(value, "OSVersion")) {
2418                 DATA_BLOB blob;
2419                 enum ndr_err_code ndr_err;
2420                 struct spoolss_OSVersion os;
2421 
2422                 os.major                = 5;    /* Windows 2000 == 5.0 */
2423                 os.minor                = 0;
2424                 os.build                = 2195; /* build */
2425                 os.extra_string         = "";   /* leave extra string empty */
2426 
2427                 ndr_err = ndr_push_struct_blob(&blob, mem_ctx, NULL, &os,
2428                         (ndr_push_flags_fn_t)ndr_push_spoolss_OSVersion);
2429                 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
2430                         return WERR_GENERAL_FAILURE;
2431                 }
2432 
2433                 *type = REG_BINARY;
2434                 data->binary = blob;
2435 
2436                 return WERR_OK;
2437         }
2438 
2439 
2440         if (!StrCaseCmp(value, "DefaultSpoolDirectory")) {
2441                 *type = REG_SZ;
2442 
2443                 data->string = talloc_strdup(mem_ctx, "C:\\PRINTERS");
2444                 W_ERROR_HAVE_NO_MEMORY(data->string);
2445 
2446                 return WERR_OK;
2447         }
2448 
2449         if (!StrCaseCmp(value, "Architecture")) {
2450                 *type = REG_SZ;
2451 
2452                 data->string = talloc_strdup(mem_ctx, "Windows NT x86");
2453                 W_ERROR_HAVE_NO_MEMORY(data->string);
2454 
2455                 return WERR_OK;
2456         }
2457 
2458         if (!StrCaseCmp(value, "DsPresent")) {
2459                 *type = REG_DWORD;
2460 
2461                 /* only show the publish check box if we are a
2462                    member of a AD domain */
2463 
2464                 if (lp_security() == SEC_ADS) {
2465                         data->value = 0x01;
2466                 } else {
2467                         data->value = 0x00;
2468                 }
2469                 return WERR_OK;
2470         }
2471 
2472         if (!StrCaseCmp(value, "DNSMachineName")) {
2473                 const char *hostname = get_mydnsfullname();
2474 
2475                 if (!hostname) {
2476                         return WERR_BADFILE;
2477                 }
2478 
2479                 *type = REG_SZ;
2480                 data->string = talloc_strdup(mem_ctx, hostname);
2481                 W_ERROR_HAVE_NO_MEMORY(data->string);
2482 
2483                 return WERR_OK;
2484         }
2485 
2486         return WERR_INVALID_PARAM;
2487 }
2488 
2489 /****************************************************************
2490  _spoolss_GetPrinterData
2491 ****************************************************************/
2492 
2493 WERROR _spoolss_GetPrinterData(pipes_struct *p,
     /* [<][>][^][v][top][bottom][index][help] */
2494                                struct spoolss_GetPrinterData *r)
2495 {
2496         WERROR result;
2497         Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
2498         NT_PRINTER_INFO_LEVEL *printer = NULL;
2499         int snum = 0;
2500 
2501         /*
2502          * Reminder: when it's a string, the length is in BYTES
2503          * even if UNICODE is negociated.
2504          *
2505          * JFM, 4/19/1999
2506          */
2507 
2508         /* in case of problem, return some default values */
2509 
2510         *r->out.needed  = 0;
2511         *r->out.type    = 0;
2512 
2513         DEBUG(4,("_spoolss_GetPrinterData\n"));
2514 
2515         if (!Printer) {
2516                 DEBUG(2,("_spoolss_GetPrinterData: Invalid handle (%s:%u:%u).\n",
2517                         OUR_HANDLE(r->in.handle)));
2518                 result = WERR_BADFID;
2519                 goto done;
2520         }
2521 
2522         if (Printer->printer_type == SPLHND_SERVER) {
2523                 result = getprinterdata_printer_server(p->mem_ctx,
2524                                                        r->in.value_name,
2525                                                        r->out.type,
2526                                                        r->out.data);
2527         } else {
2528                 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
2529                         result = WERR_BADFID;
2530                         goto done;
2531                 }
2532 
2533                 result = get_a_printer(Printer, &printer, 2, lp_servicename(snum));
2534                 if (!W_ERROR_IS_OK(result)) {
2535                         goto done;
2536                 }
2537 
2538                 /* XP sends this and wants to change id value from the PRINTER_INFO_0 */
2539 
2540                 if (strequal(r->in.value_name, "ChangeId")) {
2541                         *r->out.type = REG_DWORD;
2542                         r->out.data->value = printer->info_2->changeid;
2543                         result = WERR_OK;
2544                 } else {
2545                         REGISTRY_VALUE *v;
2546                         DATA_BLOB blob;
2547 
2548                         v = get_printer_data(printer->info_2,
2549                                              SPOOL_PRINTERDATA_KEY,
2550                                              r->in.value_name);
2551                         if (!v) {
2552                                 result = WERR_BADFILE;
2553                                 goto done;
2554                         }
2555 
2556                         *r->out.type = v->type;
2557 
2558                         blob = data_blob_const(v->data_p, v->size);
2559 
2560                         result = pull_spoolss_PrinterData(p->mem_ctx, &blob,
2561                                                           r->out.data,
2562                                                           *r->out.type);
2563                 }
2564         }
2565 
2566  done:
2567         /* cleanup & exit */
2568 
2569         if (printer) {
2570                 free_a_printer(&printer, 2);
2571         }
2572 
2573         if (!W_ERROR_IS_OK(result)) {
2574                 return result;
2575         }
2576 
2577         *r->out.needed  = ndr_size_spoolss_PrinterData(r->out.data, *r->out.type, NULL, 0);
2578         *r->out.type    = SPOOLSS_BUFFER_OK(*r->out.type, REG_NONE);
2579         r->out.data     = SPOOLSS_BUFFER_OK(r->out.data, r->out.data);
2580 
2581         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_MORE_DATA);
2582 }
2583 
2584 /*********************************************************
2585  Connect to the client machine.
2586 **********************************************************/
2587 
2588 static bool spoolss_connect_to_client(struct rpc_pipe_client **pp_pipe,
     /* [<][>][^][v][top][bottom][index][help] */
2589                         struct sockaddr_storage *client_ss, const char *remote_machine)
2590 {
2591         NTSTATUS ret;
2592         struct cli_state *the_cli;
2593         struct sockaddr_storage rm_addr;
2594 
2595         if ( is_zero_addr((struct sockaddr *)client_ss) ) {
2596                 if ( !resolve_name( remote_machine, &rm_addr, 0x20) ) {
2597                         DEBUG(2,("spoolss_connect_to_client: Can't resolve address for %s\n", remote_machine));
2598                         return false;
2599                 }
2600 
2601                 if (ismyaddr((struct sockaddr *)&rm_addr)) {
2602                         DEBUG(0,("spoolss_connect_to_client: Machine %s is one of our addresses. Cannot add to ourselves.\n", remote_machine));
2603                         return false;
2604                 }
2605         } else {
2606                 char addr[INET6_ADDRSTRLEN];
2607                 rm_addr = *client_ss;
2608                 print_sockaddr(addr, sizeof(addr), &rm_addr);
2609                 DEBUG(5,("spoolss_connect_to_client: Using address %s (no name resolution necessary)\n",
2610                         addr));
2611         }
2612 
2613         /* setup the connection */
2614 
2615         ret = cli_full_connection( &the_cli, global_myname(), remote_machine,
2616                 &rm_addr, 0, "IPC$", "IPC",
2617                 "", /* username */
2618                 "", /* domain */
2619                 "", /* password */
2620                 0, lp_client_signing(), NULL );
2621 
2622         if ( !NT_STATUS_IS_OK( ret ) ) {
2623                 DEBUG(2,("spoolss_connect_to_client: connection to [%s] failed!\n",
2624                         remote_machine ));
2625                 return false;
2626         }
2627 
2628         if ( the_cli->protocol != PROTOCOL_NT1 ) {
2629                 DEBUG(0,("spoolss_connect_to_client: machine %s didn't negotiate NT protocol.\n", remote_machine));
2630                 cli_shutdown(the_cli);
2631                 return false;
2632         }
2633 
2634         /*
2635          * Ok - we have an anonymous connection to the IPC$ share.
2636          * Now start the NT Domain stuff :-).
2637          */
2638 
2639         ret = cli_rpc_pipe_open_noauth(the_cli, &ndr_table_spoolss.syntax_id, pp_pipe);
2640         if (!NT_STATUS_IS_OK(ret)) {
2641                 DEBUG(2,("spoolss_connect_to_client: unable to open the spoolss pipe on machine %s. Error was : %s.\n",
2642                         remote_machine, nt_errstr(ret)));
2643                 cli_shutdown(the_cli);
2644                 return false;
2645         }
2646 
2647         return true;
2648 }
2649 
2650 /***************************************************************************
2651  Connect to the client.
2652 ****************************************************************************/
2653 
2654 static bool srv_spoolss_replyopenprinter(int snum, const char *printer,
     /* [<][>][^][v][top][bottom][index][help] */
2655                                         uint32_t localprinter, uint32_t type,
2656                                         struct policy_handle *handle,
2657                                         struct sockaddr_storage *client_ss)
2658 {
2659         WERROR result;
2660         NTSTATUS status;
2661 
2662         /*
2663          * If it's the first connection, contact the client
2664          * and connect to the IPC$ share anonymously
2665          */
2666         if (smb_connections==0) {
2667                 fstring unix_printer;
2668 
2669                 fstrcpy(unix_printer, printer+2); /* the +2 is to strip the leading 2 backslashs */
2670 
2671                 if ( !spoolss_connect_to_client( &notify_cli_pipe, client_ss, unix_printer ))
2672                         return false;
2673 
2674                 messaging_register(smbd_messaging_context(), NULL,
2675                                    MSG_PRINTER_NOTIFY2,
2676                                    receive_notify2_message_list);
2677                 /* Tell the connections db we're now interested in printer
2678                  * notify messages. */
2679                 register_message_flags(true, FLAG_MSG_PRINT_NOTIFY);
2680         }
2681 
2682         /*
2683          * Tell the specific printing tdb we want messages for this printer
2684          * by registering our PID.
2685          */
2686 
2687         if (!print_notify_register_pid(snum))
2688                 DEBUG(0,("print_notify_register_pid: Failed to register our pid for printer %s\n", printer ));
2689 
2690         smb_connections++;
2691 
2692         status = rpccli_spoolss_ReplyOpenPrinter(notify_cli_pipe, talloc_tos(),
2693                                                  printer,
2694                                                  localprinter,
2695                                                  type,
2696                                                  0,
2697                                                  NULL,
2698                                                  handle,
2699                                                  &result);
2700         if (!NT_STATUS_IS_OK(status) || !W_ERROR_IS_OK(result))
2701                 DEBUG(5,("srv_spoolss_reply_open_printer: Client RPC returned [%s]\n",
2702                         win_errstr(result)));
2703 
2704         return (W_ERROR_IS_OK(result));
2705 }
2706 
2707 /****************************************************************
2708  ****************************************************************/
2709 
2710 static struct spoolss_NotifyOption *dup_spoolss_NotifyOption(TALLOC_CTX *mem_ctx,
     /* [<][>][^][v][top][bottom][index][help] */
2711                                                              const struct spoolss_NotifyOption *r)
2712 {
2713         struct spoolss_NotifyOption *option;
2714         uint32_t i,k;
2715 
2716         if (!r) {
2717                 return NULL;
2718         }
2719 
2720         option = talloc_zero(mem_ctx, struct spoolss_NotifyOption);
2721         if (!option) {
2722                 return NULL;
2723         }
2724 
2725         *option = *r;
2726 
2727         if (!option->count) {
2728                 return option;
2729         }
2730 
2731         option->types = talloc_zero_array(option,
2732                 struct spoolss_NotifyOptionType, option->count);
2733         if (!option->types) {
2734                 talloc_free(option);
2735                 return NULL;
2736         }
2737 
2738         for (i=0; i < option->count; i++) {
2739                 option->types[i] = r->types[i];
2740 
2741                 if (option->types[i].count) {
2742                         option->types[i].fields = talloc_zero_array(option,
2743                                 union spoolss_Field, option->types[i].count);
2744                         if (!option->types[i].fields) {
2745                                 talloc_free(option);
2746                                 return NULL;
2747                         }
2748                         for (k=0; k<option->types[i].count; k++) {
2749                                 option->types[i].fields[k] =
2750                                         r->types[i].fields[k];
2751                         }
2752                 }
2753         }
2754 
2755         return option;
2756 }
2757 
2758 /****************************************************************
2759  * _spoolss_RemoteFindFirstPrinterChangeNotifyEx
2760  *
2761  * before replying OK: status=0 a rpc call is made to the workstation
2762  * asking ReplyOpenPrinter
2763  *
2764  * in fact ReplyOpenPrinter is the changenotify equivalent on the spoolss pipe
2765  * called from api_spoolss_rffpcnex
2766 ****************************************************************/
2767 
2768 WERROR _spoolss_RemoteFindFirstPrinterChangeNotifyEx(pipes_struct *p,
     /* [<][>][^][v][top][bottom][index][help] */
2769                                                      struct spoolss_RemoteFindFirstPrinterChangeNotifyEx *r)
2770 {
2771         int snum = -1;
2772         struct spoolss_NotifyOption *option = r->in.notify_options;
2773         struct sockaddr_storage client_ss;
2774 
2775         /* store the notify value in the printer struct */
2776 
2777         Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
2778 
2779         if (!Printer) {
2780                 DEBUG(2,("_spoolss_RemoteFindFirstPrinterChangeNotifyEx: "
2781                         "Invalid handle (%s:%u:%u).\n",
2782                         OUR_HANDLE(r->in.handle)));
2783                 return WERR_BADFID;
2784         }
2785 
2786         Printer->notify.flags           = r->in.flags;
2787         Printer->notify.options         = r->in.options;
2788         Printer->notify.printerlocal    = r->in.printer_local;
2789 
2790         TALLOC_FREE(Printer->notify.option);
2791         Printer->notify.option = dup_spoolss_NotifyOption(Printer, option);
2792 
2793         fstrcpy(Printer->notify.localmachine, r->in.local_machine);
2794 
2795         /* Connect to the client machine and send a ReplyOpenPrinter */
2796 
2797         if ( Printer->printer_type == SPLHND_SERVER)
2798                 snum = -1;
2799         else if ( (Printer->printer_type == SPLHND_PRINTER) &&
2800                         !get_printer_snum(p, r->in.handle, &snum, NULL) )
2801                 return WERR_BADFID;
2802 
2803         if (!interpret_string_addr(&client_ss, p->client_address,
2804                                    AI_NUMERICHOST)) {
2805                 return WERR_SERVER_UNAVAILABLE;
2806         }
2807 
2808         if(!srv_spoolss_replyopenprinter(snum, Printer->notify.localmachine,
2809                                         Printer->notify.printerlocal, 1,
2810                                         &Printer->notify.client_hnd, &client_ss))
2811                 return WERR_SERVER_UNAVAILABLE;
2812 
2813         Printer->notify.client_connected = true;
2814 
2815         return WERR_OK;
2816 }
2817 
2818 /*******************************************************************
2819  * fill a notify_info_data with the servername
2820  ********************************************************************/
2821 
2822 void spoolss_notify_server_name(int snum,
     /* [<][>][^][v][top][bottom][index][help] */
2823                                        struct spoolss_Notify *data,
2824                                        print_queue_struct *queue,
2825                                        NT_PRINTER_INFO_LEVEL *printer,
2826                                        TALLOC_CTX *mem_ctx)
2827 {
2828         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, printer->info_2->servername);
2829 }
2830 
2831 /*******************************************************************
2832  * fill a notify_info_data with the printername (not including the servername).
2833  ********************************************************************/
2834 
2835 void spoolss_notify_printer_name(int snum,
     /* [<][>][^][v][top][bottom][index][help] */
2836                                         struct spoolss_Notify *data,
2837                                         print_queue_struct *queue,
2838                                         NT_PRINTER_INFO_LEVEL *printer,
2839                                         TALLOC_CTX *mem_ctx)
2840 {
2841         /* the notify name should not contain the \\server\ part */
2842         char *p = strrchr(printer->info_2->printername, '\\');
2843 
2844         if (!p) {
2845                 p = printer->info_2->printername;
2846         } else {
2847                 p++;
2848         }
2849 
2850         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, p);
2851 }
2852 
2853 /*******************************************************************
2854  * fill a notify_info_data with the servicename
2855  ********************************************************************/
2856 
2857 void spoolss_notify_share_name(int snum,
     /* [<][>][^][v][top][bottom][index][help] */
2858                                       struct spoolss_Notify *data,
2859                                       print_queue_struct *queue,
2860                                       NT_PRINTER_INFO_LEVEL *printer,
2861                                       TALLOC_CTX *mem_ctx)
2862 {
2863         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, lp_servicename(snum));
2864 }
2865 
2866 /*******************************************************************
2867  * fill a notify_info_data with the port name
2868  ********************************************************************/
2869 
2870 void spoolss_notify_port_name(int snum,
     /* [<][>][^][v][top][bottom][index][help] */
2871                                      struct spoolss_Notify *data,
2872                                      print_queue_struct *queue,
2873                                      NT_PRINTER_INFO_LEVEL *printer,
2874                                      TALLOC_CTX *mem_ctx)
2875 {
2876         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, printer->info_2->portname);
2877 }
2878 
2879 /*******************************************************************
2880  * fill a notify_info_data with the printername
2881  * but it doesn't exist, have to see what to do
2882  ********************************************************************/
2883 
2884 void spoolss_notify_driver_name(int snum,
     /* [<][>][^][v][top][bottom][index][help] */
2885                                        struct spoolss_Notify *data,
2886                                        print_queue_struct *queue,
2887                                        NT_PRINTER_INFO_LEVEL *printer,
2888                                        TALLOC_CTX *mem_ctx)
2889 {
2890         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, printer->info_2->drivername);
2891 }
2892 
2893 /*******************************************************************
2894  * fill a notify_info_data with the comment
2895  ********************************************************************/
2896 
2897 void spoolss_notify_comment(int snum,
     /* [<][>][^][v][top][bottom][index][help] */
2898                                    struct spoolss_Notify *data,
2899                                    print_queue_struct *queue,
2900                                    NT_PRINTER_INFO_LEVEL *printer,
2901                                    TALLOC_CTX *mem_ctx)
2902 {
2903         char *p;
2904 
2905         if (*printer->info_2->comment == '\0') {
2906                 p = lp_comment(snum);
2907         } else {
2908                 p = printer->info_2->comment;
2909         }
2910 
2911         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, printer->info_2->comment);
2912 }
2913 
2914 /*******************************************************************
2915  * fill a notify_info_data with the comment
2916  * location = "Room 1, floor 2, building 3"
2917  ********************************************************************/
2918 
2919 void spoolss_notify_location(int snum,
     /* [<][>][^][v][top][bottom][index][help] */
2920                                     struct spoolss_Notify *data,
2921                                     print_queue_struct *queue,
2922                                     NT_PRINTER_INFO_LEVEL *printer,
2923                                     TALLOC_CTX *mem_ctx)
2924 {
2925         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, printer->info_2->location);
2926 }
2927 
2928 /*******************************************************************
2929  * fill a notify_info_data with the device mode
2930  * jfm:xxxx don't to it for know but that's a real problem !!!
2931  ********************************************************************/
2932 
2933 static void spoolss_notify_devmode(int snum,
     /* [<][>][^][v][top][bottom][index][help] */
2934                                    struct spoolss_Notify *data,
2935                                    print_queue_struct *queue,
2936                                    NT_PRINTER_INFO_LEVEL *printer,
2937                                    TALLOC_CTX *mem_ctx)
2938 {
2939         /* for a dummy implementation we have to zero the fields */
2940         SETUP_SPOOLSS_NOTIFY_DATA_DEVMODE(data, NULL);
2941 }
2942 
2943 /*******************************************************************
2944  * fill a notify_info_data with the separator file name
2945  ********************************************************************/
2946 
2947 void spoolss_notify_sepfile(int snum,
     /* [<][>][^][v][top][bottom][index][help] */
2948                                    struct spoolss_Notify *data,
2949                                    print_queue_struct *queue,
2950                                    NT_PRINTER_INFO_LEVEL *printer,
2951                                    TALLOC_CTX *mem_ctx)
2952 {
2953         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, printer->info_2->sepfile);
2954 }
2955 
2956 /*******************************************************************
2957  * fill a notify_info_data with the print processor
2958  * jfm:xxxx return always winprint to indicate we don't do anything to it
2959  ********************************************************************/
2960 
2961 void spoolss_notify_print_processor(int snum,
     /* [<][>][^][v][top][bottom][index][help] */
2962                                            struct spoolss_Notify *data,
2963                                            print_queue_struct *queue,
2964                                            NT_PRINTER_INFO_LEVEL *printer,
2965                                            TALLOC_CTX *mem_ctx)
2966 {
2967         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, printer->info_2->printprocessor);
2968 }
2969 
2970 /*******************************************************************
2971  * fill a notify_info_data with the print processor options
2972  * jfm:xxxx send an empty string
2973  ********************************************************************/
2974 
2975 void spoolss_notify_parameters(int snum,
     /* [<][>][^][v][top][bottom][index][help] */
2976                                       struct spoolss_Notify *data,
2977                                       print_queue_struct *queue,
2978                                       NT_PRINTER_INFO_LEVEL *printer,
2979                                       TALLOC_CTX *mem_ctx)
2980 {
2981         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, printer->info_2->parameters);
2982 }
2983 
2984 /*******************************************************************
2985  * fill a notify_info_data with the data type
2986  * jfm:xxxx always send RAW as data type
2987  ********************************************************************/
2988 
2989 void spoolss_notify_datatype(int snum,
     /* [<][>][^][v][top][bottom][index][help] */
2990                                     struct spoolss_Notify *data,
2991                                     print_queue_struct *queue,
2992                                     NT_PRINTER_INFO_LEVEL *printer,
2993                                     TALLOC_CTX *mem_ctx)
2994 {
2995         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, printer->info_2->datatype);
2996 }
2997 
2998 /*******************************************************************
2999  * fill a notify_info_data with the security descriptor
3000  * jfm:xxxx send an null pointer to say no security desc
3001  * have to implement security before !
3002  ********************************************************************/
3003 
3004 static void spoolss_notify_security_desc(int snum,
     /* [<][>][^][v][top][bottom][index][help] */
3005                                          struct spoolss_Notify *data,
3006                                          print_queue_struct *queue,
3007                                          NT_PRINTER_INFO_LEVEL *printer,
3008                                          TALLOC_CTX *mem_ctx)
3009 {
3010         SETUP_SPOOLSS_NOTIFY_DATA_SECDESC(data,
3011                                           printer->info_2->secdesc_buf->sd_size,
3012                                           printer->info_2->secdesc_buf->sd);
3013 }
3014 
3015 /*******************************************************************
3016  * fill a notify_info_data with the attributes
3017  * jfm:xxxx a samba printer is always shared
3018  ********************************************************************/
3019 
3020 void spoolss_notify_attributes(int snum,
     /* [<][>][^][v][top][bottom][index][help] */
3021                                       struct spoolss_Notify *data,
3022                                       print_queue_struct *queue,
3023                                       NT_PRINTER_INFO_LEVEL *printer,
3024                                       TALLOC_CTX *mem_ctx)
3025 {
3026         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, printer->info_2->attributes);
3027 }
3028 
3029 /*******************************************************************
3030  * fill a notify_info_data with the priority
3031  ********************************************************************/
3032 
3033 static void spoolss_notify_priority(int snum,
     /* [<][>][^][v][top][bottom][index][help] */
3034                                     struct spoolss_Notify *data,
3035                                     print_queue_struct *queue,
3036                                     NT_PRINTER_INFO_LEVEL *printer,
3037                                     TALLOC_CTX *mem_ctx)
3038 {
3039         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, printer->info_2->priority);
3040 }
3041 
3042 /*******************************************************************
3043  * fill a notify_info_data with the default priority
3044  ********************************************************************/
3045 
3046 static void spoolss_notify_default_priority(int snum,
     /* [<][>][^][v][top][bottom][index][help] */
3047                                             struct spoolss_Notify *data,
3048                                             print_queue_struct *queue,
3049                                             NT_PRINTER_INFO_LEVEL *printer,
3050                                             TALLOC_CTX *mem_ctx)
3051 {
3052         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, printer->info_2->default_priority);
3053 }
3054 
3055 /*******************************************************************
3056  * fill a notify_info_data with the start time
3057  ********************************************************************/
3058 
3059 static void spoolss_notify_start_time(int snum,
     /* [<][>][^][v][top][bottom][index][help] */
3060                                       struct spoolss_Notify *data,
3061                                       print_queue_struct *queue,
3062                                       NT_PRINTER_INFO_LEVEL *printer,
3063                                       TALLOC_CTX *mem_ctx)
3064 {
3065         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, printer->info_2->starttime);
3066 }
3067 
3068 /*******************************************************************
3069  * fill a notify_info_data with the until time
3070  ********************************************************************/
3071 
3072 static void spoolss_notify_until_time(int snum,
     /* [<][>][^][v][top][bottom][index][help] */
3073                                       struct spoolss_Notify *data,
3074                                       print_queue_struct *queue,
3075                                       NT_PRINTER_INFO_LEVEL *printer,
3076                                       TALLOC_CTX *mem_ctx)
3077 {
3078         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, printer->info_2->untiltime);
3079 }
3080 
3081 /*******************************************************************
3082  * fill a notify_info_data with the status
3083  ********************************************************************/
3084 
3085 static void spoolss_notify_status(int snum,
     /* [<][>][^][v][top][bottom][index][help] */
3086                                   struct spoolss_Notify *data,
3087                                   print_queue_struct *queue,
3088                                   NT_PRINTER_INFO_LEVEL *printer,
3089                                   TALLOC_CTX *mem_ctx)
3090 {
3091         print_status_struct status;
3092 
3093         print_queue_length(snum, &status);
3094         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, status.status);
3095 }
3096 
3097 /*******************************************************************
3098  * fill a notify_info_data with the number of jobs queued
3099  ********************************************************************/
3100 
3101 void spoolss_notify_cjobs(int snum,
     /* [<][>][^][v][top][bottom][index][help] */
3102                                  struct spoolss_Notify *data,
3103                                  print_queue_struct *queue,
3104                                  NT_PRINTER_INFO_LEVEL *printer,
3105                                  TALLOC_CTX *mem_ctx)
3106 {
3107         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, print_queue_length(snum, NULL));
3108 }
3109 
3110 /*******************************************************************
3111  * fill a notify_info_data with the average ppm
3112  ********************************************************************/
3113 
3114 static void spoolss_notify_average_ppm(int snum,
     /* [<][>][^][v][top][bottom][index][help] */
3115                                        struct spoolss_Notify *data,
3116                                        print_queue_struct *queue,
3117                                        NT_PRINTER_INFO_LEVEL *printer,
3118                                        TALLOC_CTX *mem_ctx)
3119 {
3120         /* always respond 8 pages per minutes */
3121         /* a little hard ! */
3122         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, printer->info_2->averageppm);
3123 }
3124 
3125 /*******************************************************************
3126  * fill a notify_info_data with username
3127  ********************************************************************/
3128 
3129 static void spoolss_notify_username(int snum,
     /* [<][>][^][v][top][bottom][index][help] */
3130                                     struct spoolss_Notify *data,
3131                                     print_queue_struct *queue,
3132                                     NT_PRINTER_INFO_LEVEL *printer,
3133                                     TALLOC_CTX *mem_ctx)
3134 {
3135         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, queue->fs_user);
3136 }
3137 
3138 /*******************************************************************
3139  * fill a notify_info_data with job status
3140  ********************************************************************/
3141 
3142 static void spoolss_notify_job_status(int snum,
     /* [<][>][^][v][top][bottom][index][help] */
3143                                       struct spoolss_Notify *data,
3144                                       print_queue_struct *queue,
3145                                       NT_PRINTER_INFO_LEVEL *printer,
3146                                       TALLOC_CTX *mem_ctx)
3147 {
3148         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, nt_printj_status(queue->status));
3149 }
3150 
3151 /*******************************************************************
3152  * fill a notify_info_data with job name
3153  ********************************************************************/
3154 
3155 static void spoolss_notify_job_name(int snum,
     /* [<][>][^][v][top][bottom][index][help] */
3156                                     struct spoolss_Notify *data,
3157                                     print_queue_struct *queue,
3158                                     NT_PRINTER_INFO_LEVEL *printer,
3159                                     TALLOC_CTX *mem_ctx)
3160 {
3161         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, queue->fs_file);
3162 }
3163 
3164 /*******************************************************************
3165  * fill a notify_info_data with job status
3166  ********************************************************************/
3167 
3168 static void spoolss_notify_job_status_string(int snum,
     /* [<][>][^][v][top][bottom][index][help] */
3169                                              struct spoolss_Notify *data,
3170                                              print_queue_struct *queue,
3171                                              NT_PRINTER_INFO_LEVEL *printer,
3172                                              TALLOC_CTX *mem_ctx)
3173 {
3174         /*
3175          * Now we're returning job status codes we just return a "" here. JRA.
3176          */
3177 
3178         const char *p = "";
3179 
3180 #if 0 /* NO LONGER NEEDED - JRA. 02/22/2001 */
3181         p = "unknown";
3182 
3183         switch (queue->status) {
3184         case LPQ_QUEUED:
3185                 p = "Queued";
3186                 break;
3187         case LPQ_PAUSED:
3188                 p = "";    /* NT provides the paused string */
3189                 break;
3190         case LPQ_SPOOLING:
3191                 p = "Spooling";
3192                 break;
3193         case LPQ_PRINTING:
3194                 p = "Printing";
3195                 break;
3196         }
3197 #endif /* NO LONGER NEEDED. */
3198 
3199         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, p);
3200 }
3201 
3202 /*******************************************************************
3203  * fill a notify_info_data with job time
3204  ********************************************************************/
3205 
3206 static void spoolss_notify_job_time(int snum,
     /* [<][>][^][v][top][bottom][index][help] */
3207                                     struct spoolss_Notify *data,
3208                                     print_queue_struct *queue,
3209                                     NT_PRINTER_INFO_LEVEL *printer,
3210                                     TALLOC_CTX *mem_ctx)
3211 {
3212         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, 0);
3213 }
3214 
3215 /*******************************************************************
3216  * fill a notify_info_data with job size
3217  ********************************************************************/
3218 
3219 static void spoolss_notify_job_size(int snum,
     /* [<][>][^][v][top][bottom][index][help] */
3220                                     struct spoolss_Notify *data,
3221                                     print_queue_struct *queue,
3222                                     NT_PRINTER_INFO_LEVEL *printer,
3223                                     TALLOC_CTX *mem_ctx)
3224 {
3225         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, queue->size);
3226 }
3227 
3228 /*******************************************************************
3229  * fill a notify_info_data with page info
3230  ********************************************************************/
3231 static void spoolss_notify_total_pages(int snum,
     /* [<][>][^][v][top][bottom][index][help] */
3232                                 struct spoolss_Notify *data,
3233                                 print_queue_struct *queue,
3234                                 NT_PRINTER_INFO_LEVEL *printer,
3235                                 TALLOC_CTX *mem_ctx)
3236 {
3237         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, queue->page_count);
3238 }
3239 
3240 /*******************************************************************
3241  * fill a notify_info_data with pages printed info.
3242  ********************************************************************/
3243 static void spoolss_notify_pages_printed(int snum,
     /* [<][>][^][v][top][bottom][index][help] */
3244                                 struct spoolss_Notify *data,
3245                                 print_queue_struct *queue,
3246                                 NT_PRINTER_INFO_LEVEL *printer,
3247                                 TALLOC_CTX *mem_ctx)
3248 {
3249         /* Add code when back-end tracks this */
3250         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, 0);
3251 }
3252 
3253 /*******************************************************************
3254  Fill a notify_info_data with job position.
3255  ********************************************************************/
3256 
3257 static void spoolss_notify_job_position(int snum,
     /* [<][>][^][v][top][bottom][index][help] */
3258                                         struct spoolss_Notify *data,
3259                                         print_queue_struct *queue,
3260                                         NT_PRINTER_INFO_LEVEL *printer,
3261                                         TALLOC_CTX *mem_ctx)
3262 {
3263         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, queue->job);
3264 }
3265 
3266 /*******************************************************************
3267  Fill a notify_info_data with submitted time.
3268  ********************************************************************/
3269 
3270 static void spoolss_notify_submitted_time(int snum,
     /* [<][>][^][v][top][bottom][index][help] */
3271                                           struct spoolss_Notify *data,
3272                                           print_queue_struct *queue,
3273                                           NT_PRINTER_INFO_LEVEL *printer,
3274                                           TALLOC_CTX *mem_ctx)
3275 {
3276         data->data.string.string = NULL;
3277         data->data.string.size = 0;
3278 
3279         init_systemtime_buffer(mem_ctx, gmtime(&queue->time),
3280                                &data->data.string.string,
3281                                &data->data.string.size);
3282 
3283 }
3284 
3285 struct s_notify_info_data_table
3286 {
3287         enum spoolss_NotifyType type;
3288         uint16_t field;
3289         const char *name;
3290         enum spoolss_NotifyTable variable_type;
3291         void (*fn) (int snum, struct spoolss_Notify *data,
3292                     print_queue_struct *queue,
3293                     NT_PRINTER_INFO_LEVEL *printer, TALLOC_CTX *mem_ctx);
3294 };
3295 
3296 /* A table describing the various print notification constants and
3297    whether the notification data is a pointer to a variable sized
3298    buffer, a one value uint32_t or a two value uint32_t. */
3299 
3300 static const struct s_notify_info_data_table notify_info_data_table[] =
3301 {
3302 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_SERVER_NAME,         "PRINTER_NOTIFY_FIELD_SERVER_NAME",         NOTIFY_TABLE_STRING,   spoolss_notify_server_name },
3303 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PRINTER_NAME,        "PRINTER_NOTIFY_FIELD_PRINTER_NAME",        NOTIFY_TABLE_STRING,   spoolss_notify_printer_name },
3304 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_SHARE_NAME,          "PRINTER_NOTIFY_FIELD_SHARE_NAME",          NOTIFY_TABLE_STRING,   spoolss_notify_share_name },
3305 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PORT_NAME,           "PRINTER_NOTIFY_FIELD_PORT_NAME",           NOTIFY_TABLE_STRING,   spoolss_notify_port_name },
3306 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_DRIVER_NAME,         "PRINTER_NOTIFY_FIELD_DRIVER_NAME",         NOTIFY_TABLE_STRING,   spoolss_notify_driver_name },
3307 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_COMMENT,             "PRINTER_NOTIFY_FIELD_COMMENT",             NOTIFY_TABLE_STRING,   spoolss_notify_comment },
3308 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_LOCATION,            "PRINTER_NOTIFY_FIELD_LOCATION",            NOTIFY_TABLE_STRING,   spoolss_notify_location },
3309 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_DEVMODE,             "PRINTER_NOTIFY_FIELD_DEVMODE",             NOTIFY_TABLE_DEVMODE,  spoolss_notify_devmode },
3310 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_SEPFILE,             "PRINTER_NOTIFY_FIELD_SEPFILE",             NOTIFY_TABLE_STRING,   spoolss_notify_sepfile },
3311 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PRINT_PROCESSOR,     "PRINTER_NOTIFY_FIELD_PRINT_PROCESSOR",     NOTIFY_TABLE_STRING,   spoolss_notify_print_processor },
3312 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PARAMETERS,          "PRINTER_NOTIFY_FIELD_PARAMETERS",          NOTIFY_TABLE_STRING,   spoolss_notify_parameters },
3313 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_DATATYPE,            "PRINTER_NOTIFY_FIELD_DATATYPE",            NOTIFY_TABLE_STRING,   spoolss_notify_datatype },
3314 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_SECURITY_DESCRIPTOR, "PRINTER_NOTIFY_FIELD_SECURITY_DESCRIPTOR", NOTIFY_TABLE_SECURITYDESCRIPTOR,   spoolss_notify_security_desc },
3315 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_ATTRIBUTES,          "PRINTER_NOTIFY_FIELD_ATTRIBUTES",          NOTIFY_TABLE_DWORD,    spoolss_notify_attributes },
3316 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PRIORITY,            "PRINTER_NOTIFY_FIELD_PRIORITY",            NOTIFY_TABLE_DWORD,    spoolss_notify_priority },
3317 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_DEFAULT_PRIORITY,    "PRINTER_NOTIFY_FIELD_DEFAULT_PRIORITY",    NOTIFY_TABLE_DWORD,    spoolss_notify_default_priority },
3318 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_START_TIME,          "PRINTER_NOTIFY_FIELD_START_TIME",          NOTIFY_TABLE_DWORD,    spoolss_notify_start_time },
3319 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_UNTIL_TIME,          "PRINTER_NOTIFY_FIELD_UNTIL_TIME",          NOTIFY_TABLE_DWORD,    spoolss_notify_until_time },
3320 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_STATUS,              "PRINTER_NOTIFY_FIELD_STATUS",              NOTIFY_TABLE_DWORD,    spoolss_notify_status },
3321 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_STATUS_STRING,       "PRINTER_NOTIFY_FIELD_STATUS_STRING",       NOTIFY_TABLE_STRING,   NULL },
3322 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_CJOBS,               "PRINTER_NOTIFY_FIELD_CJOBS",               NOTIFY_TABLE_DWORD,    spoolss_notify_cjobs },
3323 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_AVERAGE_PPM,         "PRINTER_NOTIFY_FIELD_AVERAGE_PPM",         NOTIFY_TABLE_DWORD,    spoolss_notify_average_ppm },
3324 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_TOTAL_PAGES,         "PRINTER_NOTIFY_FIELD_TOTAL_PAGES",         NOTIFY_TABLE_DWORD,    NULL },
3325 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PAGES_PRINTED,       "PRINTER_NOTIFY_FIELD_PAGES_PRINTED",       NOTIFY_TABLE_DWORD,    NULL },
3326 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_TOTAL_BYTES,         "PRINTER_NOTIFY_FIELD_TOTAL_BYTES",         NOTIFY_TABLE_DWORD,    NULL },
3327 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_BYTES_PRINTED,       "PRINTER_NOTIFY_FIELD_BYTES_PRINTED",       NOTIFY_TABLE_DWORD,    NULL },
3328 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_PRINTER_NAME,            "JOB_NOTIFY_FIELD_PRINTER_NAME",            NOTIFY_TABLE_STRING,   spoolss_notify_printer_name },
3329 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_MACHINE_NAME,            "JOB_NOTIFY_FIELD_MACHINE_NAME",            NOTIFY_TABLE_STRING,   spoolss_notify_server_name },
3330 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_PORT_NAME,               "JOB_NOTIFY_FIELD_PORT_NAME",               NOTIFY_TABLE_STRING,   spoolss_notify_port_name },
3331 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_USER_NAME,               "JOB_NOTIFY_FIELD_USER_NAME",               NOTIFY_TABLE_STRING,   spoolss_notify_username },
3332 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_NOTIFY_NAME,             "JOB_NOTIFY_FIELD_NOTIFY_NAME",             NOTIFY_TABLE_STRING,   spoolss_notify_username },
3333 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_DATATYPE,                "JOB_NOTIFY_FIELD_DATATYPE",                NOTIFY_TABLE_STRING,   spoolss_notify_datatype },
3334 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_PRINT_PROCESSOR,         "JOB_NOTIFY_FIELD_PRINT_PROCESSOR",         NOTIFY_TABLE_STRING,   spoolss_notify_print_processor },
3335 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_PARAMETERS,              "JOB_NOTIFY_FIELD_PARAMETERS",              NOTIFY_TABLE_STRING,   spoolss_notify_parameters },
3336 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_DRIVER_NAME,             "JOB_NOTIFY_FIELD_DRIVER_NAME",             NOTIFY_TABLE_STRING,   spoolss_notify_driver_name },
3337 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_DEVMODE,                 "JOB_NOTIFY_FIELD_DEVMODE",                 NOTIFY_TABLE_DEVMODE,  spoolss_notify_devmode },
3338 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_STATUS,                  "JOB_NOTIFY_FIELD_STATUS",                  NOTIFY_TABLE_DWORD,    spoolss_notify_job_status },
3339 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_STATUS_STRING,           "JOB_NOTIFY_FIELD_STATUS_STRING",           NOTIFY_TABLE_STRING,   spoolss_notify_job_status_string },
3340 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_SECURITY_DESCRIPTOR,     "JOB_NOTIFY_FIELD_SECURITY_DESCRIPTOR",     NOTIFY_TABLE_SECURITYDESCRIPTOR,   NULL },
3341 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_DOCUMENT,                "JOB_NOTIFY_FIELD_DOCUMENT",                NOTIFY_TABLE_STRING,   spoolss_notify_job_name },
3342 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_PRIORITY,                "JOB_NOTIFY_FIELD_PRIORITY",                NOTIFY_TABLE_DWORD,    spoolss_notify_priority },
3343 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_POSITION,                "JOB_NOTIFY_FIELD_POSITION",                NOTIFY_TABLE_DWORD,    spoolss_notify_job_position },
3344 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_SUBMITTED,               "JOB_NOTIFY_FIELD_SUBMITTED",               NOTIFY_TABLE_TIME,     spoolss_notify_submitted_time },
3345 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_START_TIME,              "JOB_NOTIFY_FIELD_START_TIME",              NOTIFY_TABLE_DWORD,    spoolss_notify_start_time },
3346 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_UNTIL_TIME,              "JOB_NOTIFY_FIELD_UNTIL_TIME",              NOTIFY_TABLE_DWORD,    spoolss_notify_until_time },
3347 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_TIME,                    "JOB_NOTIFY_FIELD_TIME",                    NOTIFY_TABLE_DWORD,    spoolss_notify_job_time },
3348 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_TOTAL_PAGES,             "JOB_NOTIFY_FIELD_TOTAL_PAGES",             NOTIFY_TABLE_DWORD,    spoolss_notify_total_pages },
3349 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_PAGES_PRINTED,           "JOB_NOTIFY_FIELD_PAGES_PRINTED",           NOTIFY_TABLE_DWORD,    spoolss_notify_pages_printed },
3350 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_TOTAL_BYTES,             "JOB_NOTIFY_FIELD_TOTAL_BYTES",             NOTIFY_TABLE_DWORD,    spoolss_notify_job_size },
3351 };
3352 
3353 /*******************************************************************
3354  Return the variable_type of info_data structure.
3355 ********************************************************************/
3356 
3357 static uint32_t variable_type_of_notify_info_data(enum spoolss_NotifyType type,
     /* [<][>][^][v][top][bottom][index][help] */
3358                                                   uint16_t field)
3359 {
3360         int i=0;
3361 
3362         for (i = 0; i < ARRAY_SIZE(notify_info_data_table); i++) {
3363                 if ( (notify_info_data_table[i].type == type) &&
3364                      (notify_info_data_table[i].field == field) ) {
3365                         return notify_info_data_table[i].variable_type;
3366                 }
3367         }
3368 
3369         DEBUG(5, ("invalid notify data type %d/%d\n", type, field));
3370 
3371         return 0;
3372 }
3373 
3374 /****************************************************************************
3375 ****************************************************************************/
3376 
3377 static bool search_notify(enum spoolss_NotifyType type,
     /* [<][>][^][v][top][bottom][index][help] */
3378                           uint16_t field,
3379                           int *value)
3380 {
3381         int i;
3382 
3383         for (i = 0; i < ARRAY_SIZE(notify_info_data_table); i++) {
3384                 if (notify_info_data_table[i].type == type &&
3385                     notify_info_data_table[i].field == field &&
3386                     notify_info_data_table[i].fn != NULL) {
3387                         *value = i;
3388                         return true;
3389                 }
3390         }
3391 
3392         return false;
3393 }
3394 
3395 /****************************************************************************
3396 ****************************************************************************/
3397 
3398 void construct_info_data(struct spoolss_Notify *info_data,
     /* [<][>][^][v][top][bottom][index][help] */
3399                          enum spoolss_NotifyType type,
3400                          uint16_t field,
3401                          int id)
3402 {
3403         info_data->type                 = type;
3404         info_data->field.field          = field;
3405         info_data->variable_type        = variable_type_of_notify_info_data(type, field);
3406         info_data->job_id               = id;
3407 }
3408 
3409 /*******************************************************************
3410  *
3411  * fill a notify_info struct with info asked
3412  *
3413  ********************************************************************/
3414 
3415 static bool construct_notify_printer_info(Printer_entry *print_hnd,
     /* [<][>][^][v][top][bottom][index][help] */
3416                                           struct spoolss_NotifyInfo *info,
3417                                           int snum,
3418                                           const struct spoolss_NotifyOptionType *option_type,
3419                                           uint32_t id,
3420                                           TALLOC_CTX *mem_ctx)
3421 {
3422         int field_num,j;
3423         enum spoolss_NotifyType type;
3424         uint16_t field;
3425 
3426         struct spoolss_Notify *current_data;
3427         NT_PRINTER_INFO_LEVEL *printer = NULL;
3428         print_queue_struct *queue=NULL;
3429 
3430         type = option_type->type;
3431 
3432         DEBUG(4,("construct_notify_printer_info: Notify type: [%s], number of notify info: [%d] on printer: [%s]\n",
3433                 (type == PRINTER_NOTIFY_TYPE ? "PRINTER_NOTIFY_TYPE" : "JOB_NOTIFY_TYPE"),
3434                 option_type->count, lp_servicename(snum)));
3435 
3436         if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &printer, 2, lp_const_servicename(snum))))
3437                 return false;
3438 
3439         for(field_num=0; field_num < option_type->count; field_num++) {
3440                 field = option_type->fields[field_num].field;
3441 
3442                 DEBUG(4,("construct_notify_printer_info: notify [%d]: type [%x], field [%x]\n", field_num, type, field));
3443 
3444                 if (!search_notify(type, field, &j) )
3445                         continue;
3446 
3447                 info->notifies = TALLOC_REALLOC_ARRAY(info, info->notifies,
3448                                                       struct spoolss_Notify,
3449                                                       info->count + 1);
3450                 if (info->notifies == NULL) {
3451                         DEBUG(2,("construct_notify_printer_info: failed to enlarge buffer info->data!\n"));
3452                         free_a_printer(&printer, 2);
3453                         return false;
3454                 }
3455 
3456                 current_data = &info->notifies[info->count];
3457 
3458                 construct_info_data(current_data, type, field, id);
3459 
3460                 DEBUG(10,("construct_notify_printer_info: calling [%s]  snum=%d  printername=[%s])\n",
3461                                 notify_info_data_table[j].name, snum, printer->info_2->printername ));
3462 
3463                 notify_info_data_table[j].fn(snum, current_data, queue,
3464                                              printer, mem_ctx);
3465 
3466                 info->count++;
3467         }
3468 
3469         free_a_printer(&printer, 2);
3470         return true;
3471 }
3472 
3473 /*******************************************************************
3474  *
3475  * fill a notify_info struct with info asked
3476  *
3477  ********************************************************************/
3478 
3479 static bool construct_notify_jobs_info(print_queue_struct *queue,
     /* [<][>][^][v][top][bottom][index][help] */
3480                                        struct spoolss_NotifyInfo *info,
3481                                        NT_PRINTER_INFO_LEVEL *printer,
3482                                        int snum,
3483                                        const struct spoolss_NotifyOptionType *option_type,
3484                                        uint32_t id,
3485                                        TALLOC_CTX *mem_ctx)
3486 {
3487         int field_num,j;
3488         enum spoolss_NotifyType type;
3489         uint16_t field;
3490         struct spoolss_Notify *current_data;
3491 
3492         DEBUG(4,("construct_notify_jobs_info\n"));
3493 
3494         type = option_type->type;
3495 
3496         DEBUGADD(4,("Notify type: [%s], number of notify info: [%d]\n",
3497                 (type == PRINTER_NOTIFY_TYPE ? "PRINTER_NOTIFY_TYPE" : "JOB_NOTIFY_TYPE"),
3498                 option_type->count));
3499 
3500         for(field_num=0; field_num<option_type->count; field_num++) {
3501                 field = option_type->fields[field_num].field;
3502 
3503                 if (!search_notify(type, field, &j) )
3504                         continue;
3505 
3506                 info->notifies = TALLOC_REALLOC_ARRAY(info, info->notifies,
3507                                                       struct spoolss_Notify,
3508                                                       info->count + 1);
3509                 if (info->notifies == NULL) {
3510                         DEBUG(2,("construct_notify_jobs_info: failed to enlarg buffer info->data!\n"));
3511                         return false;
3512                 }
3513 
3514                 current_data=&(info->notifies[info->count]);
3515 
3516                 construct_info_data(current_data, type, field, id);
3517                 notify_info_data_table[j].fn(snum, current_data, queue,
3518                                              printer, mem_ctx);
3519                 info->count++;
3520         }
3521 
3522         return true;
3523 }
3524 
3525 /*
3526  * JFM: The enumeration is not that simple, it's even non obvious.
3527  *
3528  * let's take an example: I want to monitor the PRINTER SERVER for
3529  * the printer's name and the number of jobs currently queued.
3530  * So in the NOTIFY_OPTION, I have one NOTIFY_OPTION_TYPE structure.
3531  * Its type is PRINTER_NOTIFY_TYPE and it has 2 fields NAME and CJOBS.
3532  *
3533  * I have 3 printers on the back of my server.
3534  *
3535  * Now the response is a NOTIFY_INFO structure, with 6 NOTIFY_INFO_DATA
3536  * structures.
3537  *   Number     Data                    Id
3538  *      1       printer 1 name          1
3539  *      2       printer 1 cjob          1
3540  *      3       printer 2 name          2
3541  *      4       printer 2 cjob          2
3542  *      5       printer 3 name          3
3543  *      6       printer 3 name          3
3544  *
3545  * that's the print server case, the printer case is even worse.
3546  */
3547 
3548 /*******************************************************************
3549  *
3550  * enumerate all printers on the printserver
3551  * fill a notify_info struct with info asked
3552  *
3553  ********************************************************************/
3554 
3555 static WERROR printserver_notify_info(pipes_struct *p,
     /* [<][>][^][v][top][bottom][index][help] */
3556                                       struct policy_handle *hnd,
3557                                       struct spoolss_NotifyInfo *info,
3558                                       TALLOC_CTX *mem_ctx)
3559 {
3560         int snum;
3561         Printer_entry *Printer = find_printer_index_by_hnd(p, hnd);
3562         int n_services=lp_numservices();
3563         int i;
3564         struct spoolss_NotifyOption *option;
3565         struct spoolss_NotifyOptionType option_type;
3566 
3567         DEBUG(4,("printserver_notify_info\n"));
3568 
3569         if (!Printer)
3570                 return WERR_BADFID;
3571 
3572         option = Printer->notify.option;
3573 
3574         info->version   = 2;
3575         info->notifies  = NULL;
3576         info->count     = 0;
3577 
3578         /* a bug in xp sp2 rc2 causes it to send a fnpcn request without
3579            sending a ffpcn() request first */
3580 
3581         if ( !option )
3582                 return WERR_BADFID;
3583 
3584         for (i=0; i<option->count; i++) {
3585                 option_type = option->types[i];
3586 
3587                 if (option_type.type != PRINTER_NOTIFY_TYPE)
3588                         continue;
3589 
3590                 for (snum=0; snum<n_services; snum++)
3591                 {
3592                         if ( lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) )
3593                                 construct_notify_printer_info ( Printer, info, snum, &option_type, snum, mem_ctx );
3594                 }
3595         }
3596 
3597 #if 0
3598         /*
3599          * Debugging information, don't delete.
3600          */
3601 
3602         DEBUG(1,("dumping the NOTIFY_INFO\n"));
3603         DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
3604         DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3605 
3606         for (i=0; i<info->count; i++) {
3607                 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3608                 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
3609                 info->data[i].id, info->data[i].size, info->data[i].enc_type));
3610         }
3611 #endif
3612 
3613         return WERR_OK;
3614 }
3615 
3616 /*******************************************************************
3617  *
3618  * fill a notify_info struct with info asked
3619  *
3620  ********************************************************************/
3621 
3622 static WERROR printer_notify_info(pipes_struct *p, struct policy_handle *hnd,
     /* [<][>][^][v][top][bottom][index][help] */
3623                                   struct spoolss_NotifyInfo *info,
3624                                   TALLOC_CTX *mem_ctx)
3625 {
3626         int snum;
3627         Printer_entry *Printer = find_printer_index_by_hnd(p, hnd);
3628         int i;
3629         uint32_t id;
3630         struct spoolss_NotifyOption *option;
3631         struct spoolss_NotifyOptionType option_type;
3632         int count,j;
3633         print_queue_struct *queue=NULL;
3634         print_status_struct status;
3635 
3636         DEBUG(4,("printer_notify_info\n"));
3637 
3638         if (!Printer)
3639                 return WERR_BADFID;
3640 
3641         option = Printer->notify.option;
3642         id = 0x0;
3643 
3644         info->version   = 2;
3645         info->notifies  = NULL;
3646         info->count     = 0;
3647 
3648         /* a bug in xp sp2 rc2 causes it to send a fnpcn request without
3649            sending a ffpcn() request first */
3650 
3651         if ( !option )
3652                 return WERR_BADFID;
3653 
3654         get_printer_snum(p, hnd, &snum, NULL);
3655 
3656         for (i=0; i<option->count; i++) {
3657                 option_type = option->types[i];
3658 
3659                 switch (option_type.type) {
3660                 case PRINTER_NOTIFY_TYPE:
3661                         if(construct_notify_printer_info(Printer, info, snum,
3662                                                          &option_type, id,
3663                                                          mem_ctx))
3664                                 id--;
3665                         break;
3666 
3667                 case JOB_NOTIFY_TYPE: {
3668                         NT_PRINTER_INFO_LEVEL *printer = NULL;
3669 
3670                         count = print_queue_status(snum, &queue, &status);
3671 
3672                         if (!W_ERROR_IS_OK(get_a_printer(Printer, &printer, 2, lp_const_servicename(snum))))
3673                                 goto done;
3674 
3675                         for (j=0; j<count; j++) {
3676                                 construct_notify_jobs_info(&queue[j], info,
3677                                                            printer, snum,
3678                                                            &option_type,
3679                                                            queue[j].job,
3680                                                            mem_ctx);
3681                         }
3682 
3683                         free_a_printer(&printer, 2);
3684 
3685                 done:
3686                         SAFE_FREE(queue);
3687                         break;
3688                 }
3689                 }
3690         }
3691 
3692         /*
3693          * Debugging information, don't delete.
3694          */
3695         /*
3696         DEBUG(1,("dumping the NOTIFY_INFO\n"));
3697         DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
3698         DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3699 
3700         for (i=0; i<info->count; i++) {
3701                 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3702                 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
3703                 info->data[i].id, info->data[i].size, info->data[i].enc_type));
3704         }
3705         */
3706         return WERR_OK;
3707 }
3708 
3709 /****************************************************************
3710  _spoolss_RouterRefreshPrinterChangeNotify
3711 ****************************************************************/
3712 
3713 WERROR _spoolss_RouterRefreshPrinterChangeNotify(pipes_struct *p,
     /* [<][>][^][v][top][bottom][index][help] */
3714                                                  struct spoolss_RouterRefreshPrinterChangeNotify *r)
3715 {
3716         struct spoolss_NotifyInfo *info;
3717 
3718         Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
3719         WERROR result = WERR_BADFID;
3720 
3721         /* we always have a spoolss_NotifyInfo struct */
3722         info = talloc_zero(p->mem_ctx, struct spoolss_NotifyInfo);
3723         if (!info) {
3724                 result = WERR_NOMEM;
3725                 goto done;
3726         }
3727 
3728         *r->out.info = info;
3729 
3730         if (!Printer) {
3731                 DEBUG(2,("_spoolss_RouterRefreshPrinterChangeNotify: "
3732                         "Invalid handle (%s:%u:%u).\n",
3733                         OUR_HANDLE(r->in.handle)));
3734                 goto done;
3735         }
3736 
3737         DEBUG(4,("Printer type %x\n",Printer->printer_type));
3738 
3739         /*
3740          *      We are now using the change value, and
3741          *      I should check for PRINTER_NOTIFY_OPTIONS_REFRESH but as
3742          *      I don't have a global notification system, I'm sending back all the
3743          *      informations even when _NOTHING_ has changed.
3744          */
3745 
3746         /* We need to keep track of the change value to send back in
3747            RRPCN replies otherwise our updates are ignored. */
3748 
3749         Printer->notify.fnpcn = true;
3750 
3751         if (Printer->notify.client_connected) {
3752                 DEBUG(10,("_spoolss_RouterRefreshPrinterChangeNotify: "
3753                         "Saving change value in request [%x]\n",
3754                         r->in.change_low));
3755                 Printer->notify.change = r->in.change_low;
3756         }
3757 
3758         /* just ignore the spoolss_NotifyOption */
3759 
3760         switch (Printer->printer_type) {
3761                 case SPLHND_SERVER:
3762                         result = printserver_notify_info(p, r->in.handle,
3763                                                          info, p->mem_ctx);
3764                         break;
3765 
3766                 case SPLHND_PRINTER:
3767                         result = printer_notify_info(p, r->in.handle,
3768                                                      info, p->mem_ctx);
3769                         break;
3770         }
3771 
3772         Printer->notify.fnpcn = false;
3773 
3774 done:
3775         return result;
3776 }
3777 
3778 /********************************************************************
3779  * construct_printer_info_0
3780  * fill a printer_info_0 struct
3781  ********************************************************************/
3782 
3783 static WERROR construct_printer_info0(TALLOC_CTX *mem_ctx,
     /* [<][>][^][v][top][bottom][index][help] */
3784                                       const NT_PRINTER_INFO_LEVEL *ntprinter,
3785                                       struct spoolss_PrinterInfo0 *r,
3786                                       int snum)
3787 {
3788         int count;
3789         counter_printer_0 *session_counter;
3790         time_t setuptime;
3791         print_status_struct status;
3792 
3793         r->printername          = talloc_strdup(mem_ctx, ntprinter->info_2->printername);
3794         W_ERROR_HAVE_NO_MEMORY(r->printername);
3795 
3796         r->servername           = talloc_strdup(mem_ctx, ntprinter->info_2->servername);
3797         W_ERROR_HAVE_NO_MEMORY(r->servername);
3798 
3799         count = print_queue_length(snum, &status);
3800 
3801         /* check if we already have a counter for this printer */
3802         for (session_counter = counter_list; session_counter; session_counter = session_counter->next) {
3803                 if (session_counter->snum == snum)
3804                         break;
3805         }
3806 
3807         /* it's the first time, add it to the list */
3808         if (session_counter == NULL) {
3809                 session_counter = SMB_MALLOC_P(counter_printer_0);
3810                 W_ERROR_HAVE_NO_MEMORY(session_counter);
3811                 ZERO_STRUCTP(session_counter);
3812                 session_counter->snum           = snum;
3813                 session_counter->counter        = 0;
3814                 DLIST_ADD(counter_list, session_counter);
3815         }
3816 
3817         /* increment it */
3818         session_counter->counter++;
3819 
3820         r->cjobs                        = count;
3821         r->total_jobs                   = 0;
3822         r->total_bytes                  = 0;
3823 
3824         setuptime = (time_t)ntprinter->info_2->setuptime;
3825 
3826         init_systemtime(&r->time, gmtime(&setuptime));
3827 
3828         /* JFM:
3829          * the global_counter should be stored in a TDB as it's common to all the clients
3830          * and should be zeroed on samba startup
3831          */
3832         r->global_counter               = session_counter->counter;
3833         r->total_pages                  = 0;
3834         /* in 2.2 we reported ourselves as 0x0004 and 0x0565 */
3835         r->version                      = 0x0005;       /* NT 5 */
3836         r->free_build                   = 0x0893;       /* build 2195 */
3837         r->spooling                     = 0;
3838         r->max_spooling                 = 0;
3839         r->session_counter              = session_counter->counter;
3840         r->num_error_out_of_paper       = 0x0;
3841         r->num_error_not_ready          = 0x0;          /* number of print failure */
3842         r->job_error                    = 0x0;
3843         r->number_of_processors         = 0x1;
3844         r->processor_type               = PROCESSOR_INTEL_PENTIUM; /* 586 Pentium ? */
3845         r->high_part_total_bytes        = 0x0;
3846         r->change_id                    = ntprinter->info_2->changeid; /* ChangeID in milliseconds*/
3847         r->last_error                   = WERR_OK;
3848         r->status                       = nt_printq_status(status.status);
3849         r->enumerate_network_printers   = 0x0;
3850         r->c_setprinter                 = get_c_setprinter(); /* monotonically increasing sum of delta printer counts */
3851         r->processor_architecture       = 0x0;
3852         r->processor_level              = 0x6;          /* 6  ???*/
3853         r->ref_ic                       = 0;
3854         r->reserved2                    = 0;
3855         r->reserved3                    = 0;
3856 
3857         return WERR_OK;
3858 }
3859 
3860 /****************************************************************************
3861  Convert an NT_DEVICEMODE to a spoolss_DeviceMode structure.  Both pointers
3862  should be valid upon entry
3863 ****************************************************************************/
3864 
3865 static WERROR convert_nt_devicemode(TALLOC_CTX *mem_ctx,
     /* [<][>][^][v][top][bottom][index][help] */
3866                                     struct spoolss_DeviceMode *r,
3867                                     const NT_DEVICEMODE *ntdevmode)
3868 {
3869         if (!r || !ntdevmode) {
3870                 return WERR_INVALID_PARAM;
3871         }
3872 
3873         r->devicename           = talloc_strdup(mem_ctx, ntdevmode->devicename);
3874         W_ERROR_HAVE_NO_MEMORY(r->devicename);
3875 
3876         r->specversion          = ntdevmode->specversion;
3877         r->driverversion        = ntdevmode->driverversion;
3878         r->size                 = ntdevmode->size;
3879         r->__driverextra_length = ntdevmode->driverextra;
3880         r->fields               = ntdevmode->fields;
3881 
3882         r->orientation          = ntdevmode->orientation;
3883         r->papersize            = ntdevmode->papersize;
3884         r->paperlength          = ntdevmode->paperlength;
3885         r->paperwidth           = ntdevmode->paperwidth;
3886         r->scale                = ntdevmode->scale;
3887         r->copies               = ntdevmode->copies;
3888         r->defaultsource        = ntdevmode->defaultsource;
3889         r->printquality         = ntdevmode->printquality;
3890         r->color                = ntdevmode->color;
3891         r->duplex               = ntdevmode->duplex;
3892         r->yresolution          = ntdevmode->yresolution;
3893         r->ttoption             = ntdevmode->ttoption;
3894         r->collate              = ntdevmode->collate;
3895 
3896         r->formname             = talloc_strdup(mem_ctx, ntdevmode->formname);
3897         W_ERROR_HAVE_NO_MEMORY(r->formname);
3898 
3899         /* all 0 below are values that have not been set in the old parsing/copy
3900          * function, maybe they should... - gd */
3901 
3902         r->logpixels            = 0;
3903         r->bitsperpel           = 0;
3904         r->pelswidth            = 0;
3905         r->pelsheight           = 0;
3906         r->displayflags         = 0;
3907         r->displayfrequency     = 0;
3908         r->icmmethod            = ntdevmode->icmmethod;
3909         r->icmintent            = ntdevmode->icmintent;
3910         r->mediatype            = ntdevmode->mediatype;
3911         r->dithertype           = ntdevmode->dithertype;
3912         r->reserved1            = 0;
3913         r->reserved2            = 0;
3914         r->panningwidth         = 0;
3915         r->panningheight        = 0;
3916 
3917         if (ntdevmode->nt_dev_private != NULL) {
3918                 r->driverextra_data = data_blob_talloc(mem_ctx,
3919                         ntdevmode->nt_dev_private,
3920                         ntdevmode->driverextra);
3921                 W_ERROR_HAVE_NO_MEMORY(r->driverextra_data.data);
3922         }
3923 
3924         return WERR_OK;
3925 }
3926 
3927 
3928 /****************************************************************************
3929  Create a spoolss_DeviceMode struct. Returns talloced memory.
3930 ****************************************************************************/
3931 
3932 struct spoolss_DeviceMode *construct_dev_mode(TALLOC_CTX *mem_ctx,
     /* [<][>][^][v][top][bottom][index][help] */
3933                                               const char *servicename)
3934 {
3935         WERROR result;
3936         NT_PRINTER_INFO_LEVEL   *printer = NULL;
3937         struct spoolss_DeviceMode *devmode = NULL;
3938 
3939         DEBUG(7,("construct_dev_mode\n"));
3940 
3941         DEBUGADD(8,("getting printer characteristics\n"));
3942 
3943         if (!W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, servicename)))
3944                 return NULL;
3945 
3946         if (!printer->info_2->devmode) {
3947                 DEBUG(5, ("BONG! There was no device mode!\n"));
3948                 goto done;
3949         }
3950 
3951         devmode = TALLOC_ZERO_P(mem_ctx, struct spoolss_DeviceMode);
3952         if (!devmode) {
3953                 DEBUG(2,("construct_dev_mode: talloc fail.\n"));
3954                 goto done;
3955         }
3956 
3957         DEBUGADD(8,("loading DEVICEMODE\n"));
3958 
3959         result = convert_nt_devicemode(mem_ctx, devmode, printer->info_2->devmode);
3960         if (!W_ERROR_IS_OK(result)) {
3961                 TALLOC_FREE(devmode);
3962         }
3963 
3964 done:
3965         free_a_printer(&printer,2);
3966 
3967         return devmode;
3968 }
3969 
3970 /********************************************************************
3971  * construct_printer_info3
3972  * fill a spoolss_PrinterInfo3 struct
3973  ********************************************************************/
3974 
3975 static WERROR construct_printer_info3(TALLOC_CTX *mem_ctx,
     /* [<][>][^][v][top][bottom][index][help] */
3976                                       const NT_PRINTER_INFO_LEVEL *ntprinter,
3977                                       struct spoolss_PrinterInfo3 *r,
3978                                       int snum)
3979 {
3980         /* These are the components of the SD we are returning. */
3981 
3982         if (ntprinter->info_2->secdesc_buf && ntprinter->info_2->secdesc_buf->sd_size != 0) {
3983                 /* don't use talloc_steal() here unless you do a deep steal of all
3984                    the SEC_DESC members */
3985 
3986                 r->secdesc = dup_sec_desc(mem_ctx,
3987                                           ntprinter->info_2->secdesc_buf->sd);
3988                 W_ERROR_HAVE_NO_MEMORY(r->secdesc);
3989         }
3990 
3991         return WERR_OK;
3992 }
3993 
3994 /********************************************************************
3995  * construct_printer_info4
3996  * fill a spoolss_PrinterInfo4 struct
3997  ********************************************************************/
3998 
3999 static WERROR construct_printer_info4(TALLOC_CTX *mem_ctx,
     /* [<][>][^][v][top][bottom][index][help] */
4000                                       const NT_PRINTER_INFO_LEVEL *ntprinter,
4001                                       struct spoolss_PrinterInfo4 *r,
4002                                       int snum)
4003 {
4004         r->printername  = talloc_strdup(mem_ctx, ntprinter->info_2->printername);
4005         W_ERROR_HAVE_NO_MEMORY(r->printername);
4006         r->servername   = talloc_strdup(mem_ctx, ntprinter->info_2->servername);
4007         W_ERROR_HAVE_NO_MEMORY(r->servername);
4008 
4009         r->attributes   = ntprinter->info_2->attributes;
4010 
4011         return WERR_OK;
4012 }
4013 
4014 /********************************************************************
4015  * construct_printer_info5
4016  * fill a spoolss_PrinterInfo5 struct
4017  ********************************************************************/
4018 
4019 static WERROR construct_printer_info5(TALLOC_CTX *mem_ctx,
     /* [<][>][^][v][top][bottom][index][help] */
4020                                       const NT_PRINTER_INFO_LEVEL *ntprinter,
4021                                       struct spoolss_PrinterInfo5 *r,
4022                                       int snum)
4023 {
4024         r->printername  = talloc_strdup(mem_ctx, ntprinter->info_2->printername);
4025         W_ERROR_HAVE_NO_MEMORY(r->printername);
4026         r->portname     = talloc_strdup(mem_ctx, ntprinter->info_2->portname);
4027         W_ERROR_HAVE_NO_MEMORY(r->portname);
4028 
4029         r->attributes   = ntprinter->info_2->attributes;
4030 
4031         /* these two are not used by NT+ according to MSDN */
4032 
4033         r->device_not_selected_timeout          = 0x0;  /* have seen 0x3a98 */
4034         r->transmission_retry_timeout           = 0x0;  /* have seen 0xafc8 */
4035 
4036         return WERR_OK;
4037 }
4038 
4039 /********************************************************************
4040  * construct_printer_info_6
4041  * fill a spoolss_PrinterInfo6 struct
4042  ********************************************************************/
4043 
4044 static WERROR construct_printer_info6(TALLOC_CTX *mem_ctx,
     /* [<][>][^][v][top][bottom][index][help] */
4045                                       const NT_PRINTER_INFO_LEVEL *ntprinter,
4046                                       struct spoolss_PrinterInfo6 *r,
4047                                       int snum)
4048 {
4049         int count;
4050         print_status_struct status;
4051 
4052         count = print_queue_length(snum, &status);
4053 
4054         r->status = nt_printq_status(status.status);
4055 
4056         return WERR_OK;
4057 }
4058 
4059 /********************************************************************
4060  * construct_printer_info7
4061  * fill a spoolss_PrinterInfo7 struct
4062  ********************************************************************/
4063 
4064 static WERROR construct_printer_info7(TALLOC_CTX *mem_ctx,
     /* [<][>][^][v][top][bottom][index][help] */
4065                                       Printer_entry *print_hnd,
4066                                       struct spoolss_PrinterInfo7 *r,
4067                                       int snum)
4068 {
4069         struct GUID guid;
4070 
4071         if (is_printer_published(print_hnd, snum, &guid)) {
4072                 r->guid = talloc_strdup_upper(mem_ctx, GUID_string2(mem_ctx, &guid));
4073                 r->action = DSPRINT_PUBLISH;
4074         } else {
4075                 r->guid = talloc_strdup(mem_ctx, "");
4076                 r->action = DSPRINT_UNPUBLISH;
4077         }
4078         W_ERROR_HAVE_NO_MEMORY(r->guid);
4079 
4080         return WERR_OK;
4081 }
4082 
4083 /********************************************************************
4084  * construct_printer_info8
4085  * fill a spoolss_PrinterInfo8 struct
4086  ********************************************************************/
4087 
4088 static WERROR construct_printer_info8(TALLOC_CTX *mem_ctx,
     /* [<][>][^][v][top][bottom][index][help] */
4089                                       const NT_PRINTER_INFO_LEVEL *ntprinter,
4090                                       struct spoolss_DeviceModeInfo *r,
4091                                       int snum)
4092 {
4093         struct spoolss_DeviceMode *devmode;
4094         WERROR result;
4095 
4096         if (!ntprinter->info_2->devmode) {
4097                 r->devmode = NULL;
4098                 return WERR_OK;
4099         }
4100 
4101         devmode = TALLOC_ZERO_P(mem_ctx, struct spoolss_DeviceMode);
4102         W_ERROR_HAVE_NO_MEMORY(devmode);
4103 
4104         result = convert_nt_devicemode(mem_ctx, devmode, ntprinter->info_2->devmode);
4105         if (!W_ERROR_IS_OK(result)) {
4106                 TALLOC_FREE(devmode);
4107                 return result;
4108         }
4109 
4110         r->devmode      = devmode;
4111 
4112         return WERR_OK;
4113 }
4114 
4115 
4116 /********************************************************************
4117  * construct_printer_info1
4118  * fill a spoolss_PrinterInfo1 struct
4119 ********************************************************************/
4120 
4121 static WERROR construct_printer_info1(TALLOC_CTX *mem_ctx,
     /* [<][>][^][v][top][bottom][index][help] */
4122                                       const NT_PRINTER_INFO_LEVEL *ntprinter,
4123                                       uint32_t flags,
4124                                       struct spoolss_PrinterInfo1 *r,
4125                                       int snum)
4126 {
4127         r->flags                = flags;
4128 
4129         r->description          = talloc_asprintf(mem_ctx, "%s,%s,%s",
4130                                                   ntprinter->info_2->printername,
4131                                                   ntprinter->info_2->drivername,
4132                                                   ntprinter->info_2->location);
4133         W_ERROR_HAVE_NO_MEMORY(r->description);
4134 
4135         if (*ntprinter->info_2->comment == '\0') {
4136                 r->comment      = talloc_strdup(mem_ctx, lp_comment(snum));
4137         } else {
4138                 r->comment      = talloc_strdup(mem_ctx, ntprinter->info_2->comment); /* saved comment */
4139         }
4140         W_ERROR_HAVE_NO_MEMORY(r->comment);
4141 
4142         r->name                 = talloc_strdup(mem_ctx, ntprinter->info_2->printername);
4143         W_ERROR_HAVE_NO_MEMORY(r->name);
4144 
4145         return WERR_OK;
4146 }
4147 
4148 /********************************************************************
4149  * construct_printer_info2
4150  * fill a spoolss_PrinterInfo2 struct
4151 ********************************************************************/
4152 
4153 static WERROR construct_printer_info2(TALLOC_CTX *mem_ctx,
     /* [<][>][^][v][top][bottom][index][help] */
4154                                       const NT_PRINTER_INFO_LEVEL *ntprinter,
4155                                       struct spoolss_PrinterInfo2 *r,
4156                                       int snum)
4157 {
4158         int count;
4159 
4160         print_status_struct status;
4161 
4162         count = print_queue_length(snum, &status);
4163 
4164         r->servername           = talloc_strdup(mem_ctx, ntprinter->info_2->servername);
4165         W_ERROR_HAVE_NO_MEMORY(r->servername);
4166         r->printername          = talloc_strdup(mem_ctx, ntprinter->info_2->printername);
4167         W_ERROR_HAVE_NO_MEMORY(r->printername);
4168         r->sharename            = talloc_strdup(mem_ctx, lp_servicename(snum));
4169         W_ERROR_HAVE_NO_MEMORY(r->sharename);
4170         r->portname             = talloc_strdup(mem_ctx, ntprinter->info_2->portname);
4171         W_ERROR_HAVE_NO_MEMORY(r->portname);
4172         r->drivername           = talloc_strdup(mem_ctx, ntprinter->info_2->drivername);
4173         W_ERROR_HAVE_NO_MEMORY(r->drivername);
4174 
4175         if (*ntprinter->info_2->comment == '\0') {
4176                 r->comment      = talloc_strdup(mem_ctx, lp_comment(snum));
4177         } else {
4178                 r->comment      = talloc_strdup(mem_ctx, ntprinter->info_2->comment);
4179         }
4180         W_ERROR_HAVE_NO_MEMORY(r->comment);
4181 
4182         r->location             = talloc_strdup(mem_ctx, ntprinter->info_2->location);
4183         W_ERROR_HAVE_NO_MEMORY(r->location);
4184         r->sepfile              = talloc_strdup(mem_ctx, ntprinter->info_2->sepfile);
4185         W_ERROR_HAVE_NO_MEMORY(r->sepfile);
4186         r->printprocessor       = talloc_strdup(mem_ctx, ntprinter->info_2->printprocessor);
4187         W_ERROR_HAVE_NO_MEMORY(r->printprocessor);
4188         r->datatype             = talloc_strdup(mem_ctx, ntprinter->info_2->datatype);
4189         W_ERROR_HAVE_NO_MEMORY(r->datatype);
4190         r->parameters           = talloc_strdup(mem_ctx, ntprinter->info_2->parameters);
4191         W_ERROR_HAVE_NO_MEMORY(r->parameters);
4192 
4193         r->attributes           = ntprinter->info_2->attributes;
4194 
4195         r->priority             = ntprinter->info_2->priority;
4196         r->defaultpriority      = ntprinter->info_2->default_priority;
4197         r->starttime            = ntprinter->info_2->starttime;
4198         r->untiltime            = ntprinter->info_2->untiltime;
4199         r->status               = nt_printq_status(status.status);
4200         r->cjobs                = count;
4201         r->averageppm           = ntprinter->info_2->averageppm;
4202 
4203         r->devmode = construct_dev_mode(mem_ctx, lp_const_servicename(snum));
4204         if (!r->devmode) {
4205                 DEBUG(8,("Returning NULL Devicemode!\n"));
4206         }
4207 
4208         r->secdesc              = NULL;
4209 
4210         if (ntprinter->info_2->secdesc_buf && ntprinter->info_2->secdesc_buf->sd_size != 0) {
4211                 /* don't use talloc_steal() here unless you do a deep steal of all
4212                    the SEC_DESC members */
4213 
4214                 r->secdesc      = dup_sec_desc(mem_ctx, ntprinter->info_2->secdesc_buf->sd);
4215         }
4216 
4217         return WERR_OK;
4218 }
4219 
4220 /********************************************************************
4221 ********************************************************************/
4222 
4223 static bool snum_is_shared_printer(int snum)
     /* [<][>][^][v][top][bottom][index][help] */
4224 {
4225         return (lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum));
4226 }
4227 
4228 /********************************************************************
4229  Spoolss_enumprinters.
4230 ********************************************************************/
4231 
4232 static WERROR enum_all_printers_info_level(TALLOC_CTX *mem_ctx,
     /* [<][>][^][v][top][bottom][index][help] */
4233                                            uint32_t level,
4234                                            uint32_t flags,
4235                                            union spoolss_PrinterInfo **info_p,
4236                                            uint32_t *count_p)
4237 {
4238         int snum;
4239         int n_services = lp_numservices();
4240         union spoolss_PrinterInfo *info = NULL;
4241         uint32_t count = 0;
4242         WERROR result = WERR_OK;
4243 
4244         *count_p = 0;
4245         *info_p = NULL;
4246 
4247         for (snum = 0; snum < n_services; snum++) {
4248 
4249                 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4250 
4251                 if (!snum_is_shared_printer(snum)) {
4252                         continue;
4253                 }
4254 
4255                 DEBUG(4,("Found a printer in smb.conf: %s[%x]\n",
4256                         lp_servicename(snum), snum));
4257 
4258                 info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
4259                                             union spoolss_PrinterInfo,
4260                                             count + 1);
4261                 if (!info) {
4262                         result = WERR_NOMEM;
4263                         goto out;
4264                 }
4265 
4266                 result = get_a_printer(NULL, &ntprinter, 2,
4267                                        lp_const_servicename(snum));
4268                 if (!W_ERROR_IS_OK(result)) {
4269                         goto out;
4270                 }
4271 
4272                 switch (level) {
4273                 case 0:
4274                         result = construct_printer_info0(info, ntprinter,
4275                                                          &info[count].info0, snum);
4276                         break;
4277                 case 1:
4278                         result = construct_printer_info1(info, ntprinter, flags,
4279                                                          &info[count].info1, snum);
4280                         break;
4281                 case 2:
4282                         result = construct_printer_info2(info, ntprinter,
4283                                                          &info[count].info2, snum);
4284                         break;
4285                 case 4:
4286                         result = construct_printer_info4(info, ntprinter,
4287                                                          &info[count].info4, snum);
4288                         break;
4289                 case 5:
4290                         result = construct_printer_info5(info, ntprinter,
4291                                                          &info[count].info5, snum);
4292                         break;
4293 
4294                 default:
4295                         result = WERR_UNKNOWN_LEVEL;
4296                         free_a_printer(&ntprinter, 2);
4297                         goto out;
4298                 }
4299 
4300                 free_a_printer(&ntprinter, 2);
4301                 if (!W_ERROR_IS_OK(result)) {
4302                         goto out;
4303                 }
4304 
4305                 count++;
4306         }
4307 
4308         *count_p = count;
4309         *info_p = info;
4310 
4311  out:
4312         if (!W_ERROR_IS_OK(result)) {
4313                 TALLOC_FREE(info);
4314                 return result;
4315         }
4316 
4317         *info_p = info;
4318 
4319         return WERR_OK;
4320 }
4321 
4322 /********************************************************************
4323  * handle enumeration of printers at level 0
4324  ********************************************************************/
4325 
4326 static WERROR enumprinters_level0(TALLOC_CTX *mem_ctx,
     /* [<][>][^][v][top][bottom][index][help] */
4327                                   uint32_t flags,
4328                                   const char *servername,
4329                                   union spoolss_PrinterInfo **info,
4330                                   uint32_t *count)
4331 {
4332         DEBUG(4,("enum_all_printers_info_0\n"));
4333 
4334         return enum_all_printers_info_level(mem_ctx, 0, flags, info, count);
4335 }
4336 
4337 
4338 /********************************************************************
4339 ********************************************************************/
4340 
4341 static WERROR enum_all_printers_info_1(TALLOC_CTX *mem_ctx,
     /* [<][>][^][v][top][bottom][index][help] */
4342                                        uint32_t flags,
4343                                        union spoolss_PrinterInfo **info,
4344                                        uint32_t *count)
4345 {
4346         DEBUG(4,("enum_all_printers_info_1\n"));
4347 
4348         return enum_all_printers_info_level(mem_ctx, 1, flags, info, count);
4349 }
4350 
4351 /********************************************************************
4352  enum_all_printers_info_1_local.
4353 *********************************************************************/
4354 
4355 static WERROR enum_all_printers_info_1_local(TALLOC_CTX *mem_ctx,
     /* [<][>][^][v][top][bottom][index][help] */
4356                                              union spoolss_PrinterInfo **info,
4357                                              uint32_t *count)
4358 {
4359         DEBUG(4,("enum_all_printers_info_1_local\n"));
4360 
4361         return enum_all_printers_info_1(mem_ctx, PRINTER_ENUM_ICON8, info, count);
4362 }
4363 
4364 /********************************************************************
4365  enum_all_printers_info_1_name.
4366 *********************************************************************/
4367 
4368 static WERROR enum_all_printers_info_1_name(TALLOC_CTX *mem_ctx,
     /* [<][>][^][v][top][bottom][index][help] */
4369                                             const char *name,
4370                                             union spoolss_PrinterInfo **info,
4371                                             uint32_t *count)
4372 {
4373         const char *s = name;
4374 
4375         DEBUG(4,("enum_all_printers_info_1_name\n"));
4376 
4377         if ((name[0] == '\\') && (name[1] == '\\')) {
4378                 s = name + 2;
4379         }
4380 
4381         if (!is_myname_or_ipaddr(s)) {
4382                 return WERR_INVALID_NAME;
4383         }
4384 
4385         return enum_all_printers_info_1(mem_ctx, PRINTER_ENUM_ICON8, info, count);
4386 }
4387 
4388 /********************************************************************
4389  enum_all_printers_info_1_network.
4390 *********************************************************************/
4391 
4392 static WERROR enum_all_printers_info_1_network(TALLOC_CTX *mem_ctx,
     /* [<][>][^][v][top][bottom][index][help] */
4393                                                const char *name,
4394                                                union spoolss_PrinterInfo **info,
4395                                                uint32_t *count)
4396 {
4397         const char *s = name;
4398 
4399         DEBUG(4,("enum_all_printers_info_1_network\n"));
4400 
4401         /* If we respond to a enum_printers level 1 on our name with flags
4402            set to PRINTER_ENUM_REMOTE with a list of printers then these
4403            printers incorrectly appear in the APW browse list.
4404            Specifically the printers for the server appear at the workgroup
4405            level where all the other servers in the domain are
4406            listed. Windows responds to this call with a
4407            WERR_CAN_NOT_COMPLETE so we should do the same. */
4408 
4409         if (name[0] == '\\' && name[1] == '\\') {
4410                  s = name + 2;
4411         }
4412 
4413         if (is_myname_or_ipaddr(s)) {
4414                  return WERR_CAN_NOT_COMPLETE;
4415         }
4416 
4417         return enum_all_printers_info_1(mem_ctx, PRINTER_ENUM_NAME, info, count);
4418 }
4419 
4420 /********************************************************************
4421  * api_spoolss_enumprinters
4422  *
4423  * called from api_spoolss_enumprinters (see this to understand)
4424  ********************************************************************/
4425 
4426 static WERROR enum_all_printers_info_2(TALLOC_CTX *mem_ctx,
     /* [<][>][^][v][top][bottom][index][help] */
4427                                        union spoolss_PrinterInfo **info,
4428                                        uint32_t *count)
4429 {
4430         DEBUG(4,("enum_all_printers_info_2\n"));
4431 
4432         return enum_all_printers_info_level(mem_ctx, 2, 0, info, count);
4433 }
4434 
4435 /********************************************************************
4436  * handle enumeration of printers at level 1
4437  ********************************************************************/
4438 
4439 static WERROR enumprinters_level1(TALLOC_CTX *mem_ctx,
     /* [<][>][^][v][top][bottom][index][help] */
4440                                   uint32_t flags,
4441                                   const char *name,
4442                                   union spoolss_PrinterInfo **info,
4443                                   uint32_t *count)
4444 {
4445         /* Not all the flags are equals */
4446 
4447         if (flags & PRINTER_ENUM_LOCAL) {
4448                 return enum_all_printers_info_1_local(mem_ctx, info, count);
4449         }
4450 
4451         if (flags & PRINTER_ENUM_NAME) {
4452                 return enum_all_printers_info_1_name(mem_ctx, name, info, count);
4453         }
4454 
4455         if (flags & PRINTER_ENUM_NETWORK) {
4456                 return enum_all_printers_info_1_network(mem_ctx, name, info, count);
4457         }
4458 
4459         return WERR_OK; /* NT4sp5 does that */
4460 }
4461 
4462 /********************************************************************
4463  * handle enumeration of printers at level 2
4464  ********************************************************************/
4465 
4466 static WERROR enumprinters_level2(TALLOC_CTX *mem_ctx,
     /* [<][>][^][v][top][bottom][index][help] */
4467                                   uint32_t flags,
4468                                   const char *servername,
4469                                   union spoolss_PrinterInfo **info,
4470                                   uint32_t *count)
4471 {
4472         if (flags & PRINTER_ENUM_LOCAL) {
4473                 return enum_all_printers_info_2(mem_ctx, info, count);
4474         }
4475 
4476         if (flags & PRINTER_ENUM_NAME) {
4477                 if (!is_myname_or_ipaddr(canon_servername(servername))) {
4478                         return WERR_INVALID_NAME;
4479                 }
4480 
4481                 return enum_all_printers_info_2(mem_ctx, info, count);
4482         }
4483 
4484         if (flags & PRINTER_ENUM_REMOTE) {
4485                 return WERR_UNKNOWN_LEVEL;
4486         }
4487 
4488         return WERR_OK;
4489 }
4490 
4491 /********************************************************************
4492  * handle enumeration of printers at level 4
4493  ********************************************************************/
4494 
4495 static WERROR enumprinters_level4(TALLOC_CTX *mem_ctx,
     /* [<][>][^][v][top][bottom][index][help] */
4496                                   uint32_t flags,
4497                                   const char *servername,
4498                                   union spoolss_PrinterInfo **info,
4499                                   uint32_t *count)
4500 {
4501         DEBUG(4,("enum_all_printers_info_4\n"));
4502 
4503         return enum_all_printers_info_level(mem_ctx, 4, flags, info, count);
4504 }
4505 
4506 
4507 /********************************************************************
4508  * handle enumeration of printers at level 5
4509  ********************************************************************/
4510 
4511 static WERROR enumprinters_level5(TALLOC_CTX *mem_ctx,
     /* [<][>][^][v][top][bottom][index][help] */
4512                                   uint32_t flags,
4513                                   const char *servername,
4514                                   union spoolss_PrinterInfo **info,
4515                                   uint32_t *count)
4516 {
4517         DEBUG(4,("enum_all_printers_info_5\n"));
4518 
4519         return enum_all_printers_info_level(mem_ctx, 5, flags, info, count);
4520 }
4521 
4522 /****************************************************************
4523  _spoolss_EnumPrinters
4524 ****************************************************************/
4525 
4526 WERROR _spoolss_EnumPrinters(pipes_struct *p,
     /* [<][>][^][v][top][bottom][index][help] */
4527                              struct spoolss_EnumPrinters *r)
4528 {
4529         const char *name;
4530         WERROR result;
4531 
4532         /* that's an [in out] buffer */
4533 
4534         if (!r->in.buffer && (r->in.offered != 0)) {
4535                 return WERR_INVALID_PARAM;
4536         }
4537 
4538         DEBUG(4,("_spoolss_EnumPrinters\n"));
4539 
4540         *r->out.needed = 0;
4541         *r->out.count = 0;
4542         *r->out.info = NULL;
4543 
4544         /*
4545          * Level 1:
4546          *          flags==PRINTER_ENUM_NAME
4547          *           if name=="" then enumerates all printers
4548          *           if name!="" then enumerate the printer
4549          *          flags==PRINTER_ENUM_REMOTE
4550          *          name is NULL, enumerate printers
4551          * Level 2: name!="" enumerates printers, name can't be NULL
4552          * Level 3: doesn't exist
4553          * Level 4: does a local registry lookup
4554          * Level 5: same as Level 2
4555          */
4556 
4557         name = talloc_strdup_upper(p->mem_ctx, r->in.server);
4558         W_ERROR_HAVE_NO_MEMORY(name);
4559 
4560         switch (r->in.level) {
4561         case 0:
4562                 result = enumprinters_level0(p->mem_ctx, r->in.flags, name,
4563                                              r->out.info, r->out.count);
4564                 break;
4565         case 1:
4566                 result = enumprinters_level1(p->mem_ctx, r->in.flags, name,
4567                                              r->out.info, r->out.count);
4568                 break;
4569         case 2:
4570                 result = enumprinters_level2(p->mem_ctx, r->in.flags, name,
4571                                              r->out.info, r->out.count);
4572                 break;
4573         case 4:
4574                 result = enumprinters_level4(p->mem_ctx, r->in.flags, name,
4575                                              r->out.info, r->out.count);
4576                 break;
4577         case 5:
4578                 result = enumprinters_level5(p->mem_ctx, r->in.flags, name,
4579                                              r->out.info, r->out.count);
4580                 break;
4581         default:
4582                 return WERR_UNKNOWN_LEVEL;
4583         }
4584 
4585         if (!W_ERROR_IS_OK(result)) {
4586                 return result;
4587         }
4588 
4589         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
4590                                                      spoolss_EnumPrinters, NULL,
4591                                                      *r->out.info, r->in.level,
4592                                                      *r->out.count);
4593         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
4594         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
4595 
4596         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
4597 }
4598 
4599 /****************************************************************
4600  _spoolss_GetPrinter
4601 ****************************************************************/
4602 
4603 WERROR _spoolss_GetPrinter(pipes_struct *p,
     /* [<][>][^][v][top][bottom][index][help] */
4604                            struct spoolss_GetPrinter *r)
4605 {
4606         Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
4607         NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4608         WERROR result = WERR_OK;
4609 
4610         int snum;
4611 
4612         /* that's an [in out] buffer */
4613 
4614         if (!r->in.buffer && (r->in.offered != 0)) {
4615                 return WERR_INVALID_PARAM;
4616         }
4617 
4618         *r->out.needed = 0;
4619 
4620         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
4621                 return WERR_BADFID;
4622         }
4623 
4624         result = get_a_printer(Printer, &ntprinter, 2,
4625                                lp_const_servicename(snum));
4626         if (!W_ERROR_IS_OK(result)) {
4627                 return result;
4628         }
4629 
4630         switch (r->in.level) {
4631         case 0:
4632                 result = construct_printer_info0(p->mem_ctx, ntprinter,
4633                                                  &r->out.info->info0, snum);
4634                 break;
4635         case 1:
4636                 result = construct_printer_info1(p->mem_ctx, ntprinter,
4637                                                  PRINTER_ENUM_ICON8,
4638                                                  &r->out.info->info1, snum);
4639                 break;
4640         case 2:
4641                 result = construct_printer_info2(p->mem_ctx, ntprinter,
4642                                                  &r->out.info->info2, snum);
4643                 break;
4644         case 3:
4645                 result = construct_printer_info3(p->mem_ctx, ntprinter,
4646                                                  &r->out.info->info3, snum);
4647                 break;
4648         case 4:
4649                 result = construct_printer_info4(p->mem_ctx, ntprinter,
4650                                                  &r->out.info->info4, snum);
4651                 break;
4652         case 5:
4653                 result = construct_printer_info5(p->mem_ctx, ntprinter,
4654                                                  &r->out.info->info5, snum);
4655                 break;
4656         case 6:
4657                 result = construct_printer_info6(p->mem_ctx, ntprinter,
4658                                                  &r->out.info->info6, snum);
4659                 break;
4660         case 7:
4661                 result = construct_printer_info7(p->mem_ctx, Printer,
4662                                                  &r->out.info->info7, snum);
4663                 break;
4664         case 8:
4665                 result = construct_printer_info8(p->mem_ctx, ntprinter,
4666                                                  &r->out.info->info8, snum);
4667                 break;
4668         default:
4669                 result = WERR_UNKNOWN_LEVEL;
4670                 break;
4671         }
4672 
4673         free_a_printer(&ntprinter, 2);
4674 
4675         if (!W_ERROR_IS_OK(result)) {
4676                 TALLOC_FREE(r->out.info);
4677                 return result;
4678         }
4679 
4680         *r->out.needed  = SPOOLSS_BUFFER_UNION(spoolss_PrinterInfo, NULL,
4681                                                r->out.info, r->in.level);
4682         r->out.info     = SPOOLSS_BUFFER_OK(r->out.info, NULL);
4683 
4684         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
4685 }
4686 
4687 /********************************************************************
4688  ********************************************************************/
4689 
4690 static const char **string_array_from_driver_info(TALLOC_CTX *mem_ctx,
     /* [<][>][^][v][top][bottom][index][help] */
4691                                                   fstring *fstring_array,
4692                                                   const char *cservername)
4693 {
4694         int i, num_strings = 0;
4695         const char **array = NULL;
4696 
4697         for (i=0; fstring_array && fstring_array[i][0] != '\0'; i++) {
4698 
4699                 const char *str = talloc_asprintf(mem_ctx, "\\\\%s%s",
4700                                                   cservername, fstring_array[i]);
4701                 if (!str) {
4702                         TALLOC_FREE(array);
4703                         return NULL;
4704                 }
4705 
4706 
4707                 if (!add_string_to_array(mem_ctx, str, &array, &num_strings)) {
4708                         TALLOC_FREE(array);
4709                         return NULL;
4710                 }
4711         }
4712 
4713         if (i > 0) {
4714                 ADD_TO_ARRAY(mem_ctx, const char *, NULL,
4715                              &array, &num_strings);
4716         }
4717 
4718         return array;
4719 }
4720 
4721 /********************************************************************
4722  * fill a spoolss_DriverInfo1 struct
4723  ********************************************************************/
4724 
4725 static WERROR fill_printer_driver_info1(TALLOC_CTX *mem_ctx,
     /* [<][>][^][v][top][bottom][index][help] */
4726                                         struct spoolss_DriverInfo1 *r,
4727                                         const NT_PRINTER_DRIVER_INFO_LEVEL *driver,
4728                                         const char *servername,
4729                                         const char *architecture)
4730 {
4731         r->driver_name          = talloc_strdup(mem_ctx, driver->info_3->name);
4732         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4733 
4734         return WERR_OK;
4735 }
4736 
4737 /********************************************************************
4738  * fill a spoolss_DriverInfo2 struct
4739  ********************************************************************/
4740 
4741 static WERROR fill_printer_driver_info2(TALLOC_CTX *mem_ctx,
     /* [<][>][^][v][top][bottom][index][help] */
4742                                         struct spoolss_DriverInfo2 *r,
4743                                         const NT_PRINTER_DRIVER_INFO_LEVEL *driver,
4744                                         const char *servername)
4745 
4746 {
4747         const char *cservername = canon_servername(servername);
4748 
4749         r->version              = driver->info_3->cversion;
4750 
4751         r->driver_name          = talloc_strdup(mem_ctx, driver->info_3->name);
4752         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4753         r->architecture         = talloc_strdup(mem_ctx, driver->info_3->environment);
4754         W_ERROR_HAVE_NO_MEMORY(r->architecture);
4755 
4756         if (strlen(driver->info_3->driverpath)) {
4757                 r->driver_path  = talloc_asprintf(mem_ctx, "\\\\%s%s",
4758                                 cservername, driver->info_3->driverpath);
4759         } else {
4760                 r->driver_path  = talloc_strdup(mem_ctx, "");
4761         }
4762         W_ERROR_HAVE_NO_MEMORY(r->driver_path);
4763 
4764         if (strlen(driver->info_3->datafile)) {
4765                 r->data_file    = talloc_asprintf(mem_ctx, "\\\\%s%s",
4766                                 cservername, driver->info_3->datafile);
4767         } else {
4768                 r->data_file    = talloc_strdup(mem_ctx, "");
4769         }
4770         W_ERROR_HAVE_NO_MEMORY(r->data_file);
4771 
4772         if (strlen(driver->info_3->configfile)) {
4773                 r->config_file  = talloc_asprintf(mem_ctx, "\\\\%s%s",
4774                                 cservername, driver->info_3->configfile);
4775         } else {
4776                 r->config_file  = talloc_strdup(mem_ctx, "");
4777         }
4778         W_ERROR_HAVE_NO_MEMORY(r->config_file);
4779 
4780         return WERR_OK;
4781 }
4782 
4783 /********************************************************************
4784  * fill a spoolss_DriverInfo3 struct
4785  ********************************************************************/
4786 
4787 static WERROR fill_printer_driver_info3(TALLOC_CTX *mem_ctx,
     /* [<][>][^][v][top][bottom][index][help] */
4788                                         struct spoolss_DriverInfo3 *r,
4789                                         const NT_PRINTER_DRIVER_INFO_LEVEL *driver,
4790                                         const char *servername)
4791 {
4792         const char *cservername = canon_servername(servername);
4793 
4794         r->version              = driver->info_3->cversion;
4795 
4796         r->driver_name          = talloc_strdup(mem_ctx, driver->info_3->name);
4797         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4798         r->architecture         = talloc_strdup(mem_ctx, driver->info_3->environment);
4799         W_ERROR_HAVE_NO_MEMORY(r->architecture);
4800 
4801         if (strlen(driver->info_3->driverpath)) {
4802                 r->driver_path  = talloc_asprintf(mem_ctx, "\\\\%s%s",
4803                                 cservername, driver->info_3->driverpath);
4804         } else {
4805                 r->driver_path  = talloc_strdup(mem_ctx, "");
4806         }
4807         W_ERROR_HAVE_NO_MEMORY(r->driver_path);
4808 
4809         if (strlen(driver->info_3->datafile)) {
4810                 r->data_file    = talloc_asprintf(mem_ctx, "\\\\%s%s",
4811                                 cservername, driver->info_3->datafile);
4812         } else {
4813                 r->data_file    = talloc_strdup(mem_ctx, "");
4814         }
4815         W_ERROR_HAVE_NO_MEMORY(r->data_file);
4816 
4817         if (strlen(driver->info_3->configfile)) {
4818                 r->config_file  = talloc_asprintf(mem_ctx, "\\\\%s%s",
4819                                 cservername, driver->info_3->configfile);
4820         } else {
4821                 r->config_file  = talloc_strdup(mem_ctx, "");
4822         }
4823         W_ERROR_HAVE_NO_MEMORY(r->config_file);
4824 
4825         if (strlen(driver->info_3->helpfile)) {
4826                 r->help_file    = talloc_asprintf(mem_ctx, "\\\\%s%s",
4827                                 cservername, driver->info_3->helpfile);
4828         } else {
4829                 r->help_file    = talloc_strdup(mem_ctx, "");
4830         }
4831         W_ERROR_HAVE_NO_MEMORY(r->help_file);
4832 
4833         r->monitor_name         = talloc_strdup(mem_ctx, driver->info_3->monitorname);
4834         W_ERROR_HAVE_NO_MEMORY(r->monitor_name);
4835         r->default_datatype     = talloc_strdup(mem_ctx, driver->info_3->defaultdatatype);
4836         W_ERROR_HAVE_NO_MEMORY(r->default_datatype);
4837 
4838         r->dependent_files = string_array_from_driver_info(mem_ctx,
4839                                                            driver->info_3->dependentfiles,
4840                                                            cservername);
4841         return WERR_OK;
4842 }
4843 
4844 /********************************************************************
4845  * fill a spoolss_DriverInfo4 struct
4846  ********************************************************************/
4847 
4848 static WERROR fill_printer_driver_info4(TALLOC_CTX *mem_ctx,
     /* [<][>][^][v][top][bottom][index][help] */
4849                                         struct spoolss_DriverInfo4 *r,
4850                                         const NT_PRINTER_DRIVER_INFO_LEVEL *driver,
4851                                         const char *servername)
4852 {
4853         const char *cservername = canon_servername(servername);
4854 
4855         r->version              = driver->info_3->cversion;
4856 
4857         r->driver_name          = talloc_strdup(mem_ctx, driver->info_3->name);
4858         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4859         r->architecture         = talloc_strdup(mem_ctx, driver->info_3->environment);
4860         W_ERROR_HAVE_NO_MEMORY(r->architecture);
4861 
4862         if (strlen(driver->info_3->driverpath)) {
4863                 r->driver_path  = talloc_asprintf(mem_ctx, "\\\\%s%s",
4864                                 cservername, driver->info_3->driverpath);
4865         } else {
4866                 r->driver_path  = talloc_strdup(mem_ctx, "");
4867         }
4868         W_ERROR_HAVE_NO_MEMORY(r->driver_path);
4869 
4870         if (strlen(driver->info_3->datafile)) {
4871                 r->data_file    = talloc_asprintf(mem_ctx, "\\\\%s%s",
4872                                 cservername, driver->info_3->datafile);
4873         } else {
4874                 r->data_file    = talloc_strdup(mem_ctx, "");
4875         }
4876         W_ERROR_HAVE_NO_MEMORY(r->data_file);
4877 
4878         if (strlen(driver->info_3->configfile)) {
4879                 r->config_file  = talloc_asprintf(mem_ctx, "\\\\%s%s",
4880                                 cservername, driver->info_3->configfile);
4881         } else {
4882                 r->config_file  = talloc_strdup(mem_ctx, "");
4883         }
4884         W_ERROR_HAVE_NO_MEMORY(r->config_file);
4885 
4886         if (strlen(driver->info_3->helpfile)) {
4887                 r->help_file    = talloc_asprintf(mem_ctx, "\\\\%s%s",
4888                                 cservername, driver->info_3->helpfile);
4889         } else {
4890                 r->help_file    = talloc_strdup(mem_ctx, "");
4891         }
4892         W_ERROR_HAVE_NO_MEMORY(r->help_file);
4893 
4894         r->dependent_files = string_array_from_driver_info(mem_ctx,
4895                                                            driver->info_3->dependentfiles,
4896                                                            cservername);
4897 
4898 
4899         r->monitor_name         = talloc_strdup(mem_ctx, driver->info_3->monitorname);
4900         W_ERROR_HAVE_NO_MEMORY(r->monitor_name);
4901         r->default_datatype     = talloc_strdup(mem_ctx, driver->info_3->defaultdatatype);
4902         W_ERROR_HAVE_NO_MEMORY(r->default_datatype);
4903 
4904         r->previous_names = string_array_from_driver_info(mem_ctx,
4905                                                           NULL,
4906                                                           cservername);
4907 
4908         return WERR_OK;
4909 }
4910 
4911 /********************************************************************
4912  * fill a spoolss_DriverInfo5 struct
4913  ********************************************************************/
4914 
4915 static WERROR fill_printer_driver_info5(TALLOC_CTX *mem_ctx,
     /* [<][>][^][v][top][bottom][index][help] */
4916                                         struct spoolss_DriverInfo5 *r,
4917                                         const NT_PRINTER_DRIVER_INFO_LEVEL *driver,
4918                                         const char *servername)
4919 {
4920         const char *cservername = canon_servername(servername);
4921 
4922         r->version              = driver->info_3->cversion;
4923 
4924         r->driver_name          = talloc_strdup(mem_ctx, driver->info_3->name);
4925         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4926         r->architecture         = talloc_strdup(mem_ctx, driver->info_3->environment);
4927         W_ERROR_HAVE_NO_MEMORY(r->architecture);
4928 
4929         if (strlen(driver->info_3->driverpath)) {
4930                 r->driver_path  = talloc_asprintf(mem_ctx, "\\\\%s%s",
4931                                 cservername, driver->info_3->driverpath);
4932         } else {
4933                 r->driver_path  = talloc_strdup(mem_ctx, "");
4934         }
4935         W_ERROR_HAVE_NO_MEMORY(r->driver_path);
4936 
4937         if (strlen(driver->info_3->datafile)) {
4938                 r->data_file    = talloc_asprintf(mem_ctx, "\\\\%s%s",
4939                                 cservername, driver->info_3->datafile);
4940         } else {
4941                 r->data_file    = talloc_strdup(mem_ctx, "");
4942         }
4943         W_ERROR_HAVE_NO_MEMORY(r->data_file);
4944 
4945         if (strlen(driver->info_3->configfile)) {
4946                 r->config_file  = talloc_asprintf(mem_ctx, "\\\\%s%s",
4947                                 cservername, driver->info_3->configfile);
4948         } else {
4949                 r->config_file  = talloc_strdup(mem_ctx, "");
4950         }
4951         W_ERROR_HAVE_NO_MEMORY(r->config_file);
4952 
4953         r->driver_attributes    = 0;
4954         r->config_version       = 0;
4955         r->driver_version       = 0;
4956 
4957         return WERR_OK;
4958 }
4959 /********************************************************************
4960  * fill a spoolss_DriverInfo6 struct
4961  ********************************************************************/
4962 
4963 static WERROR fill_printer_driver_info6(TALLOC_CTX *mem_ctx,
     /* [<][>][^][v][top][bottom][index][help] */
4964                                         struct spoolss_DriverInfo6 *r,
4965                                         const NT_PRINTER_DRIVER_INFO_LEVEL *driver,
4966                                         const char *servername)
4967 {
4968         const char *cservername = canon_servername(servername);
4969 
4970         r->version              = driver->info_3->cversion;
4971 
4972         r->driver_name          = talloc_strdup(mem_ctx, driver->info_3->name);
4973         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4974         r->architecture         = talloc_strdup(mem_ctx, driver->info_3->environment);
4975         W_ERROR_HAVE_NO_MEMORY(r->architecture);
4976 
4977         if (strlen(driver->info_3->driverpath)) {
4978                 r->driver_path  = talloc_asprintf(mem_ctx, "\\\\%s%s",
4979                                 cservername, driver->info_3->driverpath);
4980         } else {
4981                 r->driver_path  = talloc_strdup(mem_ctx, "");
4982         }
4983         W_ERROR_HAVE_NO_MEMORY(r->driver_path);
4984 
4985         if (strlen(driver->info_3->datafile)) {
4986                 r->data_file    = talloc_asprintf(mem_ctx, "\\\\%s%s",
4987                                 cservername, driver->info_3->datafile);
4988         } else {
4989                 r->data_file    = talloc_strdup(mem_ctx, "");
4990         }
4991         W_ERROR_HAVE_NO_MEMORY(r->data_file);
4992 
4993         if (strlen(driver->info_3->configfile)) {
4994                 r->config_file  = talloc_asprintf(mem_ctx, "\\\\%s%s",
4995                                 cservername, driver->info_3->configfile);
4996         } else {
4997                 r->config_file  = talloc_strdup(mem_ctx, "");
4998         }
4999         W_ERROR_HAVE_NO_MEMORY(r->config_file);
5000 
5001         if (strlen(driver->info_3->helpfile)) {
5002                 r->help_file    = talloc_asprintf(mem_ctx, "\\\\%s%s",
5003                                 cservername, driver->info_3->helpfile);
5004         } else {
5005                 r->help_file    = talloc_strdup(mem_ctx, "");
5006         }
5007         W_ERROR_HAVE_NO_MEMORY(r->help_file);
5008 
5009         r->monitor_name         = talloc_strdup(mem_ctx, driver->info_3->monitorname);
5010         W_ERROR_HAVE_NO_MEMORY(r->monitor_name);
5011         r->default_datatype     = talloc_strdup(mem_ctx, driver->info_3->defaultdatatype);
5012         W_ERROR_HAVE_NO_MEMORY(r->default_datatype);
5013 
5014         r->dependent_files = string_array_from_driver_info(mem_ctx,
5015                                                            driver->info_3->dependentfiles,
5016                                                            cservername);
5017         r->previous_names = string_array_from_driver_info(mem_ctx,
5018                                                           NULL,
5019                                                           cservername);
5020 
5021         r->driver_date          = 0;
5022         r->driver_version       = 0;
5023 
5024         r->manufacturer_name    = talloc_strdup(mem_ctx, "");
5025         W_ERROR_HAVE_NO_MEMORY(r->manufacturer_name);
5026         r->manufacturer_url     = talloc_strdup(mem_ctx, "");
5027         W_ERROR_HAVE_NO_MEMORY(r->manufacturer_url);
5028         r->hardware_id          = talloc_strdup(mem_ctx, "");
5029         W_ERROR_HAVE_NO_MEMORY(r->hardware_id);
5030         r->provider             = talloc_strdup(mem_ctx, "");
5031         W_ERROR_HAVE_NO_MEMORY(r->provider);
5032 
5033         return WERR_OK;
5034 }
5035 
5036 /********************************************************************
5037  ********************************************************************/
5038 
5039 static WERROR fill_spoolss_DriverFileInfo(TALLOC_CTX *mem_ctx,
     /* [<][>][^][v][top][bottom][index][help] */
5040                                           struct spoolss_DriverFileInfo *r,
5041                                           const char *cservername,
5042                                           const char *file_name,
5043                                           enum spoolss_DriverFileType file_type,
5044                                           uint32_t file_version)
5045 {
5046         r->file_name    = talloc_asprintf(mem_ctx, "\\\\%s%s",
5047                                           cservername, file_name);
5048         W_ERROR_HAVE_NO_MEMORY(r->file_name);
5049         r->file_type    = file_type;
5050         r->file_version = file_version;
5051 
5052         return WERR_OK;
5053 }
5054 
5055 /********************************************************************
5056  ********************************************************************/
5057 
5058 static WERROR spoolss_DriverFileInfo_from_driver(TALLOC_CTX *mem_ctx,
     /* [<][>][^][v][top][bottom][index][help] */
5059                                                  const NT_PRINTER_DRIVER_INFO_LEVEL *driver,
5060                                                  const char *cservername,
5061                                                  struct spoolss_DriverFileInfo **info_p,
5062                                                  uint32_t *count_p)
5063 {
5064         struct spoolss_DriverFileInfo *info = NULL;
5065         uint32_t count = 0;
5066         WERROR result;
5067         uint32_t i;
5068 
5069         *info_p = NULL;
5070         *count_p = 0;
5071 
5072         if (strlen(driver->info_3->driverpath)) {
5073                 info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
5074                                             struct spoolss_DriverFileInfo,
5075                                             count + 1);
5076                 W_ERROR_HAVE_NO_MEMORY(info);
5077                 result = fill_spoolss_DriverFileInfo(info,
5078                                                      &info[count],
5079                                                      cservername,
5080                                                      driver->info_3->driverpath,
5081                                                      SPOOLSS_DRIVER_FILE_TYPE_RENDERING,
5082                                                      0);
5083                 W_ERROR_NOT_OK_RETURN(result);
5084                 count++;
5085         }
5086 
5087         if (strlen(driver->info_3->configfile)) {
5088                 info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
5089                                             struct spoolss_DriverFileInfo,
5090                                             count + 1);
5091                 W_ERROR_HAVE_NO_MEMORY(info);
5092                 result = fill_spoolss_DriverFileInfo(info,
5093                                                      &info[count],
5094                                                      cservername,
5095                                                      driver->info_3->configfile,
5096                                                      SPOOLSS_DRIVER_FILE_TYPE_CONFIGURATION,
5097                                                      0);
5098                 W_ERROR_NOT_OK_RETURN(result);
5099                 count++;
5100         }
5101 
5102         if (strlen(driver->info_3->datafile)) {
5103                 info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
5104                                             struct spoolss_DriverFileInfo,
5105                                             count + 1);
5106                 W_ERROR_HAVE_NO_MEMORY(info);
5107                 result = fill_spoolss_DriverFileInfo(info,
5108                                                      &info[count],
5109                                                      cservername,
5110                                                      driver->info_3->datafile,
5111                                                      SPOOLSS_DRIVER_FILE_TYPE_DATA,
5112                                                      0);
5113                 W_ERROR_NOT_OK_RETURN(result);
5114                 count++;
5115         }
5116 
5117         if (strlen(driver->info_3->helpfile)) {
5118                 info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
5119                                             struct spoolss_DriverFileInfo,
5120                                             count + 1);
5121                 W_ERROR_HAVE_NO_MEMORY(info);
5122                 result = fill_spoolss_DriverFileInfo(info,
5123                                                      &info[count],
5124                                                      cservername,
5125                                                      driver->info_3->helpfile,
5126                                                      SPOOLSS_DRIVER_FILE_TYPE_HELP,
5127                                                      0);
5128                 W_ERROR_NOT_OK_RETURN(result);
5129                 count++;
5130         }
5131 
5132         for (i=0; driver->info_3->dependentfiles[i][0] != '\0'; i++) {
5133                 info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
5134                                             struct spoolss_DriverFileInfo,
5135                                             count + 1);
5136                 W_ERROR_HAVE_NO_MEMORY(info);
5137                 result = fill_spoolss_DriverFileInfo(info,
5138                                                      &info[count],
5139                                                      cservername,
5140                                                      driver->info_3->dependentfiles[i],
5141                                                      SPOOLSS_DRIVER_FILE_TYPE_OTHER,
5142                                                      0);
5143                 W_ERROR_NOT_OK_RETURN(result);
5144                 count++;
5145         }
5146 
5147         *info_p = info;
5148         *count_p = count;
5149 
5150         return WERR_OK;
5151 }
5152 
5153 /********************************************************************
5154  * fill a spoolss_DriverInfo101 sttruct
5155  ********************************************************************/
5156 
5157 static WERROR fill_printer_driver_info101(TALLOC_CTX *mem_ctx,
     /* [<][>][^][v][top][bottom][index][help] */
5158                                           struct spoolss_DriverInfo101 *r,
5159                                           const NT_PRINTER_DRIVER_INFO_LEVEL *driver,
5160                                           const char *servername)
5161 {
5162         const char *cservername = canon_servername(servername);
5163         WERROR result;
5164 
5165         r->version              = driver->info_3->cversion;
5166 
5167         r->driver_name          = talloc_strdup(mem_ctx, driver->info_3->name);
5168         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
5169         r->architecture         = talloc_strdup(mem_ctx, driver->info_3->environment);
5170         W_ERROR_HAVE_NO_MEMORY(r->architecture);
5171 
5172         result = spoolss_DriverFileInfo_from_driver(mem_ctx, driver,
5173                                                     cservername,
5174                                                     &r->file_info,
5175                                                     &r->file_count);
5176         if (!W_ERROR_IS_OK(result)) {
5177                 return result;
5178         }
5179 
5180         r->monitor_name         = talloc_strdup(mem_ctx, driver->info_3->monitorname);
5181         W_ERROR_HAVE_NO_MEMORY(r->monitor_name);
5182 
5183         r->default_datatype     = talloc_strdup(mem_ctx, driver->info_3->defaultdatatype);
5184         W_ERROR_HAVE_NO_MEMORY(r->default_datatype);
5185 
5186         r->previous_names = string_array_from_driver_info(mem_ctx,
5187                                                           NULL,
5188                                                           cservername);
5189         r->driver_date          = 0;
5190         r->driver_version       = 0;
5191 
5192         r->manufacturer_name    = talloc_strdup(mem_ctx, "");
5193         W_ERROR_HAVE_NO_MEMORY(r->manufacturer_name);
5194         r->manufacturer_url     = talloc_strdup(mem_ctx, "");
5195         W_ERROR_HAVE_NO_MEMORY(r->manufacturer_url);
5196         r->hardware_id          = talloc_strdup(mem_ctx, "");
5197         W_ERROR_HAVE_NO_MEMORY(r->hardware_id);
5198         r->provider             = talloc_strdup(mem_ctx, "");
5199         W_ERROR_HAVE_NO_MEMORY(r->provider);
5200 
5201         return WERR_OK;
5202 }
5203 
5204 /********************************************************************
5205  * construct_printer_driver_info_1
5206  ********************************************************************/
5207 
5208 static WERROR construct_printer_driver_info_1(TALLOC_CTX *mem_ctx,
     /* [<][>][^][v][top][bottom][index][help] */
5209                                               struct spoolss_DriverInfo1 *r,
5210                                               int snum,
5211                                               const char *servername,
5212                                               const char *architecture,
5213                                               uint32_t version)
5214 {
5215         NT_PRINTER_INFO_LEVEL *printer = NULL;
5216         NT_PRINTER_DRIVER_INFO_LEVEL driver;
5217         WERROR result;
5218 
5219         ZERO_STRUCT(driver);
5220 
5221         if (!W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, lp_const_servicename(snum))))
5222                 return WERR_INVALID_PRINTER_NAME;
5223 
5224         if (!W_ERROR_IS_OK(get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version))) {
5225                 free_a_printer(&printer, 2);
5226                 return WERR_UNKNOWN_PRINTER_DRIVER;
5227         }
5228 
5229         result = fill_printer_driver_info1(mem_ctx, r, &driver, servername, architecture);
5230 
5231         free_a_printer(&printer,2);
5232 
5233         return result;
5234 }
5235 
5236 /********************************************************************
5237  * construct_printer_driver_info_2
5238  * fill a printer_info_2 struct
5239  ********************************************************************/
5240 
5241 static WERROR construct_printer_driver_info_2(TALLOC_CTX *mem_ctx,
     /* [<][>][^][v][top][bottom][index][help] */
5242                                               struct spoolss_DriverInfo2 *r,
5243                                               int snum,
5244                                               const char *servername,
5245                                               const char *architecture,
5246                                               uint32_t version)
5247 {
5248         NT_PRINTER_INFO_LEVEL *printer = NULL;
5249         NT_PRINTER_DRIVER_INFO_LEVEL driver;
5250         WERROR result;
5251 
5252         ZERO_STRUCT(printer);
5253         ZERO_STRUCT(driver);
5254 
5255         if (!W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, lp_const_servicename(snum))))
5256                 return WERR_INVALID_PRINTER_NAME;
5257 
5258         if (!W_ERROR_IS_OK(get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version))) {
5259                 free_a_printer(&printer, 2);
5260                 return WERR_UNKNOWN_PRINTER_DRIVER;
5261         }
5262 
5263         result = fill_printer_driver_info2(mem_ctx, r, &driver, servername);
5264 
5265         free_a_printer(&printer,2);
5266 
5267         return result;
5268 }
5269 
5270 /********************************************************************
5271  * construct_printer_info_3
5272  * fill a printer_info_3 struct
5273  ********************************************************************/
5274 
5275 static WERROR construct_printer_driver_info_3(TALLOC_CTX *mem_ctx,
     /* [<][>][^][v][top][bottom][index][help] */
5276                                               struct spoolss_DriverInfo3 *r,
5277                                               int snum,
5278                                               const char *servername,
5279                                               const char *architecture,
5280                                               uint32_t version)
5281 {
5282         NT_PRINTER_INFO_LEVEL *printer = NULL;
5283         NT_PRINTER_DRIVER_INFO_LEVEL driver;
5284         WERROR status;
5285         ZERO_STRUCT(driver);
5286 
5287         status=get_a_printer(NULL, &printer, 2, lp_const_servicename(snum) );
5288         DEBUG(8,("construct_printer_driver_info_3: status: %s\n", win_errstr(status)));
5289         if (!W_ERROR_IS_OK(status))
5290                 return WERR_INVALID_PRINTER_NAME;
5291 
5292         status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
5293         DEBUG(8,("construct_printer_driver_info_3: status: %s\n", win_errstr(status)));
5294 
5295 #if 0   /* JERRY */
5296 
5297         /*
5298          * I put this code in during testing.  Helpful when commenting out the
5299          * support for DRIVER_INFO_6 in regards to win2k.  Not needed in general
5300          * as win2k always queries the driver using an infor level of 6.
5301          * I've left it in (but ifdef'd out) because I'll probably
5302          * use it in experimentation again in the future.   --jerry 22/01/2002
5303          */
5304 
5305         if (!W_ERROR_IS_OK(status)) {
5306                 /*
5307                  * Is this a W2k client ?
5308                  */
5309                 if (version == 3) {
5310                         /* Yes - try again with a WinNT driver. */
5311                         version = 2;
5312                         status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
5313                         DEBUG(8,("construct_printer_driver_info_3: status: %s\n", win_errstr(status)));
5314                 }
5315 #endif
5316 
5317                 if (!W_ERROR_IS_OK(status)) {
5318                         free_a_printer(&printer,2);
5319                         return WERR_UNKNOWN_PRINTER_DRIVER;
5320                 }
5321 
5322 #if 0   /* JERRY */
5323         }
5324 #endif
5325 
5326 
5327         status = fill_printer_driver_info3(mem_ctx, r, &driver, servername);
5328 
5329         free_a_printer(&printer,2);
5330 
5331         return status;
5332 }
5333 
5334 /********************************************************************
5335  * construct_printer_info_6
5336  * fill a printer_info_6 struct
5337  ********************************************************************/
5338 
5339 static WERROR construct_printer_driver_info_6(TALLOC_CTX *mem_ctx,
     /* [<][>][^][v][top][bottom][index][help] */
5340                                               struct spoolss_DriverInfo6 *r,
5341                                               int snum,
5342                                               const char *servername,
5343                                               const char *architecture,
5344                                               uint32_t version)
5345 {
5346         NT_PRINTER_INFO_LEVEL           *printer = NULL;
5347         NT_PRINTER_DRIVER_INFO_LEVEL    driver;
5348         WERROR                          status;
5349 
5350         ZERO_STRUCT(driver);
5351 
5352         status=get_a_printer(NULL, &printer, 2, lp_const_servicename(snum) );
5353 
5354         DEBUG(8,("construct_printer_driver_info_6: status: %s\n", win_errstr(status)));
5355 
5356         if (!W_ERROR_IS_OK(status))
5357                 return WERR_INVALID_PRINTER_NAME;
5358 
5359         status = get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
5360 
5361         DEBUG(8,("construct_printer_driver_info_6: status: %s\n", win_errstr(status)));
5362 
5363         if (!W_ERROR_IS_OK(status))
5364         {
5365                 /*
5366                  * Is this a W2k client ?
5367                  */
5368 
5369                 if (version < 3) {
5370                         free_a_printer(&printer,2);
5371                         return WERR_UNKNOWN_PRINTER_DRIVER;
5372                 }
5373 
5374                 /* Yes - try again with a WinNT driver. */
5375                 version = 2;
5376                 status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
5377                 DEBUG(8,("construct_printer_driver_info_6: status: %s\n", win_errstr(status)));
5378                 if (!W_ERROR_IS_OK(status)) {
5379                         free_a_printer(&printer,2);
5380                         return WERR_UNKNOWN_PRINTER_DRIVER;
5381                 }
5382         }
5383 
5384         status = fill_printer_driver_info6(mem_ctx, r, &driver, servername);
5385 
5386         free_a_printer(&printer,2);
5387         free_a_printer_driver(driver, 3);
5388 
5389         return status;
5390 }
5391 
5392 /********************************************************************
5393  * construct_printer_info_101
5394  * fill a printer_info_101 struct
5395  ********************************************************************/
5396 
5397 static WERROR construct_printer_driver_info_101(TALLOC_CTX *mem_ctx,
     /* [<][>][^][v][top][bottom][index][help] */
5398                                                 struct spoolss_DriverInfo101 *r,
5399                                                 int snum,
5400                                                 const char *servername,
5401                                                 const char *architecture,
5402                                                 uint32_t version)
5403 {
5404         NT_PRINTER_INFO_LEVEL           *printer = NULL;
5405         NT_PRINTER_DRIVER_INFO_LEVEL    driver;
5406         WERROR                          result;
5407 
5408         ZERO_STRUCT(driver);
5409 
5410         result = get_a_printer(NULL, &printer, 2, lp_const_servicename(snum));
5411 
5412         DEBUG(8,("construct_printer_driver_info_101: status: %s\n",
5413                 win_errstr(result)));
5414 
5415         if (!W_ERROR_IS_OK(result)) {
5416                 return WERR_INVALID_PRINTER_NAME;
5417         }
5418 
5419         result = get_a_printer_driver(&driver, 3, printer->info_2->drivername,
5420                                       architecture, version);
5421 
5422         DEBUG(8,("construct_printer_driver_info_101: status: %s\n",
5423                 win_errstr(result)));
5424 
5425         if (!W_ERROR_IS_OK(result)) {
5426                 /*
5427                  * Is this a W2k client ?
5428                  */
5429 
5430                 if (version < 3) {
5431                         free_a_printer(&printer, 2);
5432                         return WERR_UNKNOWN_PRINTER_DRIVER;
5433                 }
5434 
5435                 /* Yes - try again with a WinNT driver. */
5436                 version = 2;
5437                 result = get_a_printer_driver(&driver, 3, printer->info_2->drivername,
5438                                               architecture, version);
5439                 DEBUG(8,("construct_printer_driver_info_6: status: %s\n",
5440                         win_errstr(result)));
5441                 if (!W_ERROR_IS_OK(result)) {
5442                         free_a_printer(&printer, 2);
5443                         return WERR_UNKNOWN_PRINTER_DRIVER;
5444                 }
5445         }
5446 
5447         result = fill_printer_driver_info101(mem_ctx, r, &driver, servername);
5448 
5449         free_a_printer(&printer, 2);
5450         free_a_printer_driver(driver, 3);
5451 
5452         return result;
5453 }
5454 
5455 /****************************************************************
5456  _spoolss_GetPrinterDriver2
5457 ****************************************************************/
5458 
5459 WERROR _spoolss_GetPrinterDriver2(pipes_struct *p,
     /* [<][>][^][v][top][bottom][index][help] */
5460                                   struct spoolss_GetPrinterDriver2 *r)
5461 {
5462         Printer_entry *printer;
5463         WERROR result;
5464 
5465         const char *servername;
5466         int snum;
5467 
5468         /* that's an [in out] buffer */
5469 
5470         if (!r->in.buffer && (r->in.offered != 0)) {
5471                 return WERR_INVALID_PARAM;
5472         }
5473 
5474         DEBUG(4,("_spoolss_GetPrinterDriver2\n"));
5475 
5476         if (!(printer = find_printer_index_by_hnd(p, r->in.handle))) {
5477                 DEBUG(0,("_spoolss_GetPrinterDriver2: invalid printer handle!\n"));
5478                 return WERR_INVALID_PRINTER_NAME;
5479         }
5480 
5481         *r->out.needed = 0;
5482         *r->out.server_major_version = 0;
5483         *r->out.server_minor_version = 0;
5484 
5485         servername = get_server_name(printer);
5486 
5487         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
5488                 return WERR_BADFID;
5489         }
5490 
5491         switch (r->in.level) {
5492         case 1:
5493                 result = construct_printer_driver_info_1(p->mem_ctx,
5494                                                          &r->out.info->info1,
5495                                                          snum,
5496                                                          servername,
5497                                                          r->in.architecture,
5498                                                          r->in.client_major_version);
5499                 break;
5500         case 2:
5501                 result = construct_printer_driver_info_2(p->mem_ctx,
5502                                                          &r->out.info->info2,
5503                                                          snum,
5504                                                          servername,
5505                                                          r->in.architecture,
5506                                                          r->in.client_major_version);
5507                 break;
5508         case 3:
5509                 result = construct_printer_driver_info_3(p->mem_ctx,
5510                                                          &r->out.info->info3,
5511                                                          snum,
5512                                                          servername,
5513                                                          r->in.architecture,
5514                                                          r->in.client_major_version);
5515                 break;
5516         case 6:
5517                 result = construct_printer_driver_info_6(p->mem_ctx,
5518                                                          &r->out.info->info6,
5519                                                          snum,
5520                                                          servername,
5521                                                          r->in.architecture,
5522                                                          r->in.client_major_version);
5523                 break;
5524         case 101:
5525                 result = construct_printer_driver_info_101(p->mem_ctx,
5526                                                            &r->out.info->info101,
5527                                                            snum,
5528                                                            servername,
5529                                                            r->in.architecture,
5530                                                            r->in.client_major_version);
5531                 break;
5532         default:
5533                 result = WERR_UNKNOWN_LEVEL;
5534                 break;
5535         }
5536 
5537         if (!W_ERROR_IS_OK(result)) {
5538                 TALLOC_FREE(r->out.info);
5539                 return result;
5540         }
5541 
5542         *r->out.needed  = SPOOLSS_BUFFER_UNION(spoolss_DriverInfo, NULL,
5543                                                r->out.info, r->in.level);
5544         r->out.info     = SPOOLSS_BUFFER_OK(r->out.info, NULL);
5545 
5546         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
5547 }
5548 
5549 
5550 /****************************************************************
5551  _spoolss_StartPagePrinter
5552 ****************************************************************/
5553 
5554 WERROR _spoolss_StartPagePrinter(pipes_struct *p,
     /* [<][>][^][v][top][bottom][index][help] */
5555                                  struct spoolss_StartPagePrinter *r)
5556 {
5557         Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
5558 
5559         if (!Printer) {
5560                 DEBUG(3,("_spoolss_StartPagePrinter: "
5561                         "Error in startpageprinter printer handle\n"));
5562                 return WERR_BADFID;
5563         }
5564 
5565         Printer->page_started = true;
5566         return WERR_OK;
5567 }
5568 
5569 /****************************************************************
5570  _spoolss_EndPagePrinter
5571 ****************************************************************/
5572 
5573 WERROR _spoolss_EndPagePrinter(pipes_struct *p,
     /* [<][>][^][v][top][bottom][index][help] */
5574                                struct spoolss_EndPagePrinter *r)
5575 {
5576         int snum;
5577 
5578         Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
5579 
5580         if (!Printer) {
5581                 DEBUG(2,("_spoolss_EndPagePrinter: Invalid handle (%s:%u:%u).\n",
5582                         OUR_HANDLE(r->in.handle)));
5583                 return WERR_BADFID;
5584         }
5585 
5586         if (!get_printer_snum(p, r->in.handle, &snum, NULL))
5587                 return WERR_BADFID;
5588 
5589         Printer->page_started = false;
5590         print_job_endpage(snum, Printer->jobid);
5591 
5592         return WERR_OK;
5593 }
5594 
5595 /****************************************************************
5596  _spoolss_StartDocPrinter
5597 ****************************************************************/
5598 
5599 WERROR _spoolss_StartDocPrinter(pipes_struct *p,
     /* [<][>][^][v][top][bottom][index][help] */
5600                                 struct spoolss_StartDocPrinter *r)
5601 {
5602         struct spoolss_DocumentInfo1 *info_1;
5603         int snum;
5604         Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
5605 
5606         if (!Printer) {
5607                 DEBUG(2,("_spoolss_StartDocPrinter: "
5608                         "Invalid handle (%s:%u:%u)\n",
5609                         OUR_HANDLE(r->in.handle)));
5610                 return WERR_BADFID;
5611         }
5612 
5613         if (r->in.level != 1) {
5614                 return WERR_UNKNOWN_LEVEL;
5615         }
5616 
5617         info_1 = r->in.info.info1;
5618 
5619         /*
5620          * a nice thing with NT is it doesn't listen to what you tell it.
5621          * when asked to send _only_ RAW datas, it tries to send datas
5622          * in EMF format.
5623          *
5624          * So I add checks like in NT Server ...
5625          */
5626 
5627         if (info_1->datatype) {
5628                 if (strcmp(info_1->datatype, "RAW") != 0) {
5629                         *r->out.job_id = 0;
5630                         return WERR_INVALID_DATATYPE;
5631                 }
5632         }
5633 
5634         /* get the share number of the printer */
5635         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
5636                 return WERR_BADFID;
5637         }
5638 
5639         Printer->jobid = print_job_start(p->server_info, snum,
5640                                          info_1->document_name,
5641                                          Printer->nt_devmode);
5642 
5643         /* An error occured in print_job_start() so return an appropriate
5644            NT error code. */
5645 
5646         if (Printer->jobid == -1) {
5647                 return map_werror_from_unix(errno);
5648         }
5649 
5650         Printer->document_started = true;
5651         *r->out.job_id = Printer->jobid;
5652 
5653         return WERR_OK;
5654 }
5655 
5656 /****************************************************************
5657  _spoolss_EndDocPrinter
5658 ****************************************************************/
5659 
5660 WERROR _spoolss_EndDocPrinter(pipes_struct *p,
     /* [<][>][^][v][top][bottom][index][help] */
5661                               struct spoolss_EndDocPrinter *r)
5662 {
5663         return _spoolss_enddocprinter_internal(p, r->in.handle);
5664 }
5665 
5666 /****************************************************************
5667  _spoolss_WritePrinter
5668 ****************************************************************/
5669 
5670 WERROR _spoolss_WritePrinter(pipes_struct *p,
     /* [<][>][^][v][top][bottom][index][help] */
5671                              struct spoolss_WritePrinter *r)
5672 {
5673         uint32_t buffer_written;
5674         int snum;
5675         Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
5676 
5677         if (!Printer) {
5678                 DEBUG(2,("_spoolss_WritePrinter: Invalid handle (%s:%u:%u)\n",
5679                         OUR_HANDLE(r->in.handle)));
5680                 *r->out.num_written = r->in._data_size;
5681                 return WERR_BADFID;
5682         }
5683 
5684         if (!get_printer_snum(p, r->in.handle, &snum, NULL))
5685                 return WERR_BADFID;
5686 
5687         buffer_written = (uint32_t)print_job_write(snum, Printer->jobid,
5688                                                    (const char *)r->in.data.data,
5689                                                    (SMB_OFF_T)-1,
5690                                                    (size_t)r->in._data_size);
5691         if (buffer_written == (uint32_t)-1) {
5692                 *r->out.num_written = 0;
5693                 if (errno == ENOSPC)
5694                         return WERR_NO_SPOOL_SPACE;
5695                 else
5696                         return WERR_ACCESS_DENIED;
5697         }
5698 
5699         *r->out.num_written = r->in._data_size;
5700 
5701         return WERR_OK;
5702 }
5703 
5704 /********************************************************************
5705  * api_spoolss_getprinter
5706  * called from the spoolss dispatcher
5707  *
5708  ********************************************************************/
5709 
5710 static WERROR control_printer(struct policy_handle *handle, uint32_t command,
     /* [<][>][^][v][top][bottom][index][help] */
5711                               pipes_struct *p)
5712 {
5713         int snum;
5714         WERROR errcode = WERR_BADFUNC;
5715         Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5716 
5717         if (!Printer) {
5718                 DEBUG(2,("control_printer: Invalid handle (%s:%u:%u)\n",
5719                         OUR_HANDLE(handle)));
5720                 return WERR_BADFID;
5721         }
5722 
5723         if (!get_printer_snum(p, handle, &snum, NULL))
5724                 return WERR_BADFID;
5725 
5726         switch (command) {
5727         case SPOOLSS_PRINTER_CONTROL_PAUSE:
5728                 errcode = print_queue_pause(p->server_info, snum);
5729                 break;
5730         case SPOOLSS_PRINTER_CONTROL_RESUME:
5731         case SPOOLSS_PRINTER_CONTROL_UNPAUSE:
5732                 errcode = print_queue_resume(p->server_info, snum);
5733                 break;
5734         case SPOOLSS_PRINTER_CONTROL_PURGE:
5735                 errcode = print_queue_purge(p->server_info, snum);
5736                 break;
5737         default:
5738                 return WERR_UNKNOWN_LEVEL;
5739         }
5740 
5741         return errcode;
5742 }
5743 
5744 
5745 /****************************************************************
5746  _spoolss_AbortPrinter
5747  * From MSDN: "Deletes printer's spool file if printer is configured
5748  * for spooling"
5749 ****************************************************************/
5750 
5751 WERROR _spoolss_AbortPrinter(pipes_struct *p,
     /* [<][>][^][v][top][bottom][index][help] */
5752                              struct spoolss_AbortPrinter *r)
5753 {
5754         Printer_entry   *Printer = find_printer_index_by_hnd(p, r->in.handle);
5755         int             snum;
5756         WERROR          errcode = WERR_OK;
5757 
5758         if (!Printer) {
5759                 DEBUG(2,("_spoolss_AbortPrinter: Invalid handle (%s:%u:%u)\n",
5760                         OUR_HANDLE(r->in.handle)));
5761                 return WERR_BADFID;
5762         }
5763 
5764         if (!get_printer_snum(p, r->in.handle, &snum, NULL))
5765                 return WERR_BADFID;
5766 
5767         print_job_delete(p->server_info, snum, Printer->jobid, &errcode );
5768 
5769         return errcode;
5770 }
5771 
5772 /********************************************************************
5773  * called by spoolss_api_setprinter
5774  * when updating a printer description
5775  ********************************************************************/
5776 
5777 static WERROR update_printer_sec(struct policy_handle *handle,
     /* [<][>][^][v][top][bottom][index][help] */
5778                                  pipes_struct *p, SEC_DESC_BUF *secdesc_ctr)
5779 {
5780         SEC_DESC_BUF *new_secdesc_ctr = NULL, *old_secdesc_ctr = NULL;
5781         WERROR result;
5782         int snum;
5783 
5784         Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5785 
5786         if (!Printer || !get_printer_snum(p, handle, &snum, NULL)) {
5787                 DEBUG(2,("update_printer_sec: Invalid handle (%s:%u:%u)\n",
5788                          OUR_HANDLE(handle)));
5789 
5790                 result = WERR_BADFID;
5791                 goto done;
5792         }
5793 
5794         if (!secdesc_ctr) {
5795                 DEBUG(10,("update_printer_sec: secdesc_ctr is NULL !\n"));
5796                 result = WERR_INVALID_PARAM;
5797                 goto done;
5798         }
5799 
5800         /* Check the user has permissions to change the security
5801            descriptor.  By experimentation with two NT machines, the user
5802            requires Full Access to the printer to change security
5803            information. */
5804 
5805         if ( Printer->access_granted != PRINTER_ACCESS_ADMINISTER ) {
5806                 DEBUG(4,("update_printer_sec: updated denied by printer permissions\n"));
5807                 result = WERR_ACCESS_DENIED;
5808                 goto done;
5809         }
5810 
5811         /* NT seems to like setting the security descriptor even though
5812            nothing may have actually changed. */
5813 
5814         if ( !nt_printing_getsec(p->mem_ctx, Printer->sharename, &old_secdesc_ctr)) {
5815                 DEBUG(2,("update_printer_sec: nt_printing_getsec() failed\n"));
5816                 result = WERR_BADFID;
5817                 goto done;
5818         }
5819 
5820         if (DEBUGLEVEL >= 10) {
5821                 SEC_ACL *the_acl;
5822                 int i;
5823 
5824                 the_acl = old_secdesc_ctr->sd->dacl;
5825                 DEBUG(10, ("old_secdesc_ctr for %s has %d aces:\n",
5826                            PRINTERNAME(snum), the_acl->num_aces));
5827 
5828                 for (i = 0; i < the_acl->num_aces; i++) {
5829                         DEBUG(10, ("%s 0x%08x\n", sid_string_dbg(
5830                                            &the_acl->aces[i].trustee),
5831                                   the_acl->aces[i].access_mask));
5832                 }
5833 
5834                 the_acl = secdesc_ctr->sd->dacl;
5835 
5836                 if (the_acl) {
5837                         DEBUG(10, ("secdesc_ctr for %s has %d aces:\n",
5838                                    PRINTERNAME(snum), the_acl->num_aces));
5839 
5840                         for (i = 0; i < the_acl->num_aces; i++) {
5841                                 DEBUG(10, ("%s 0x%08x\n", sid_string_dbg(
5842                                                    &the_acl->aces[i].trustee),
5843                                            the_acl->aces[i].access_mask));
5844                         }
5845                 } else {
5846                         DEBUG(10, ("dacl for secdesc_ctr is NULL\n"));
5847                 }
5848         }
5849 
5850         new_secdesc_ctr = sec_desc_merge(p->mem_ctx, secdesc_ctr, old_secdesc_ctr);
5851         if (!new_secdesc_ctr) {
5852                 result = WERR_NOMEM;
5853                 goto done;
5854         }
5855 
5856         if (sec_desc_equal(new_secdesc_ctr->sd, old_secdesc_ctr->sd)) {
5857                 result = WERR_OK;
5858                 goto done;
5859         }
5860 
5861         result = nt_printing_setsec(Printer->sharename, new_secdesc_ctr);
5862 
5863  done:
5864 
5865         return result;
5866 }
5867 
5868 /********************************************************************
5869  Canonicalize printer info from a client
5870 
5871  ATTN: It does not matter what we set the servername to hear
5872  since we do the necessary work in get_a_printer() to set it to
5873  the correct value based on what the client sent in the
5874  _spoolss_open_printer_ex().
5875  ********************************************************************/
5876 
5877 static bool check_printer_ok(NT_PRINTER_INFO_LEVEL_2 *info, int snum)
     /* [<][>][^][v][top][bottom][index][help] */
5878 {
5879         fstring printername;
5880         const char *p;
5881 
5882         DEBUG(5,("check_printer_ok: servername=%s printername=%s sharename=%s "
5883                 "portname=%s drivername=%s comment=%s location=%s\n",
5884                 info->servername, info->printername, info->sharename,
5885                 info->portname, info->drivername, info->comment, info->location));
5886 
5887         /* we force some elements to "correct" values */
5888         slprintf(info->servername, sizeof(info->servername)-1, "\\\\%s", global_myname());
5889         fstrcpy(info->sharename, lp_servicename(snum));
5890 
5891         /* check to see if we allow printername != sharename */
5892 
5893         if ( lp_force_printername(snum) ) {
5894                 slprintf(info->printername, sizeof(info->printername)-1, "\\\\%s\\%s",
5895                         global_myname(), info->sharename );
5896         } else {
5897 
5898                 /* make sure printername is in \\server\printername format */
5899 
5900                 fstrcpy( printername, info->printername );
5901                 p = printername;
5902                 if ( printername[0] == '\\' && printername[1] == '\\' ) {
5903                         if ( (p = strchr_m( &printername[2], '\\' )) != NULL )
5904                                 p++;
5905                 }
5906 
5907                 slprintf(info->printername, sizeof(info->printername)-1, "\\\\%s\\%s",
5908                          global_myname(), p );
5909         }
5910 
5911         info->attributes |= PRINTER_ATTRIBUTE_SAMBA;
5912         info->attributes &= ~PRINTER_ATTRIBUTE_NOT_SAMBA;
5913 
5914 
5915 
5916         return true;
5917 }
5918 
5919 /****************************************************************************
5920 ****************************************************************************/
5921 
5922 WERROR add_port_hook(TALLOC_CTX *ctx, NT_USER_TOKEN *token, const char *portname, const char *uri )
     /* [<][>][^][v][top][bottom][index][help] */
5923 {
5924         char *cmd = lp_addport_cmd();
5925         char *command = NULL;
5926         int ret;
5927         SE_PRIV se_printop = SE_PRINT_OPERATOR;
5928         bool is_print_op = false;
5929 
5930         if ( !*cmd ) {
5931                 return WERR_ACCESS_DENIED;
5932         }
5933 
5934         command = talloc_asprintf(ctx,
5935                         "%s \"%s\" \"%s\"", cmd, portname, uri );
5936         if (!command) {
5937                 return WERR_NOMEM;
5938         }
5939 
5940         if ( token )
5941                 is_print_op = user_has_privileges( token, &se_printop );
5942 
5943         DEBUG(10,("Running [%s]\n", command));
5944 
5945         /********* BEGIN SePrintOperatorPrivilege **********/
5946 
5947         if ( is_print_op )
5948                 become_root();
5949 
5950         ret = smbrun(command, NULL);
5951 
5952         if ( is_print_op )
5953                 unbecome_root();
5954 
5955         /********* END SePrintOperatorPrivilege **********/
5956 
5957         DEBUGADD(10,("returned [%d]\n", ret));
5958 
5959         TALLOC_FREE(command);
5960 
5961         if ( ret != 0 ) {
5962                 return WERR_ACCESS_DENIED;
5963         }
5964 
5965         return WERR_OK;
5966 }
5967 
5968 /****************************************************************************
5969 ****************************************************************************/
5970 
5971 bool add_printer_hook(TALLOC_CTX *ctx, NT_USER_TOKEN *token, NT_PRINTER_INFO_LEVEL *printer)
     /* [<][>][^][v][top][bottom][index][help] */
5972 {
5973         char *cmd = lp_addprinter_cmd();
5974         char **qlines;
5975         char *command = NULL;
5976         int numlines;
5977         int ret;
5978         int fd;
5979         SE_PRIV se_printop = SE_PRINT_OPERATOR;
5980         bool is_print_op = false;
5981         char *remote_machine = talloc_strdup(ctx, "%m");
5982 
5983         if (!remote_machine) {
5984                 return false;
5985         }
5986         remote_machine = talloc_sub_basic(ctx,
5987                                 current_user_info.smb_name,
5988                                 current_user_info.domain,
5989                                 remote_machine);
5990         if (!remote_machine) {
5991                 return false;
5992         }
5993 
5994         command = talloc_asprintf(ctx,
5995                         "%s \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\"",
5996                         cmd, printer->info_2->printername, printer->info_2->sharename,
5997                         printer->info_2->portname, printer->info_2->drivername,
5998                         printer->info_2->location, printer->info_2->comment, remote_machine);
5999         if (!command) {
6000                 return false;
6001         }
6002 
6003         if ( token )
6004                 is_print_op = user_has_privileges( token, &se_printop );
6005 
6006         DEBUG(10,("Running [%s]\n", command));
6007 
6008         /********* BEGIN SePrintOperatorPrivilege **********/
6009 
6010         if ( is_print_op )
6011                 become_root();
6012 
6013         if ( (ret = smbrun(command, &fd)) == 0 ) {
6014                 /* Tell everyone we updated smb.conf. */
6015                 message_send_all(smbd_messaging_context(),
6016                                  MSG_SMB_CONF_UPDATED, NULL, 0, NULL);
6017         }
6018 
6019         if ( is_print_op )
6020                 unbecome_root();
6021 
6022         /********* END SePrintOperatorPrivilege **********/
6023 
6024         DEBUGADD(10,("returned [%d]\n", ret));
6025 
6026         TALLOC_FREE(command);
6027         TALLOC_FREE(remote_machine);
6028 
6029         if ( ret != 0 ) {
6030                 if (fd != -1)
6031                         close(fd);
6032                 return false;
6033         }
6034 
6035         /* reload our services immediately */
6036         become_root();
6037         reload_services(false);
6038         unbecome_root();
6039 
6040         numlines = 0;
6041         /* Get lines and convert them back to dos-codepage */
6042         qlines = fd_lines_load(fd, &numlines, 0, NULL);
6043         DEBUGADD(10,("Lines returned = [%d]\n", numlines));
6044         close(fd);
6045 
6046         /* Set the portname to what the script says the portname should be. */
6047         /* but don't require anything to be return from the script exit a good error code */
6048 
6049         if (numlines) {
6050                 /* Set the portname to what the script says the portname should be. */
6051                 strncpy(printer->info_2->portname, qlines[0], sizeof(printer->info_2->portname));
6052                 DEBUGADD(6,("Line[0] = [%s]\n", qlines[0]));
6053         }
6054 
6055         TALLOC_FREE(qlines);
6056         return true;
6057 }
6058 
6059 
6060 /********************************************************************
6061  * Called by spoolss_api_setprinter
6062  * when updating a printer description.
6063  ********************************************************************/
6064 
6065 static WERROR update_printer(pipes_struct *p, struct policy_handle *handle,
     /* [<][>][^][v][top][bottom][index][help] */
6066                              struct spoolss_SetPrinterInfoCtr *info_ctr,
6067                              struct spoolss_DeviceMode *devmode)
6068 {
6069         int snum;
6070         NT_PRINTER_INFO_LEVEL *printer = NULL, *old_printer = NULL;
6071         Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
6072         WERROR result;
6073         UNISTR2 buffer;
6074         fstring asc_buffer;
6075 
6076         DEBUG(8,("update_printer\n"));
6077 
6078         result = WERR_OK;
6079 
6080         if (!Printer) {
6081                 result = WERR_BADFID;
6082                 goto done;
6083         }
6084 
6085         if (!get_printer_snum(p, handle, &snum, NULL)) {
6086                 result = WERR_BADFID;
6087                 goto done;
6088         }
6089 
6090         if (!W_ERROR_IS_OK(get_a_printer(Printer, &printer, 2, lp_const_servicename(snum))) ||
6091             (!W_ERROR_IS_OK(get_a_printer(Printer, &old_printer, 2, lp_const_servicename(snum))))) {
6092                 result = WERR_BADFID;
6093                 goto done;
6094         }
6095 
6096         DEBUGADD(8,("Converting info_2 struct\n"));
6097 
6098         /*
6099          * convert_printer_info converts the incoming
6100          * info from the client and overwrites the info
6101          * just read from the tdb in the pointer 'printer'.
6102          */
6103 
6104         if (!convert_printer_info(info_ctr, printer)) {
6105                 result =  WERR_NOMEM;
6106                 goto done;
6107         }
6108 
6109         if (devmode) {
6110                 /* we have a valid devmode
6111                    convert it and link it*/
6112 
6113                 DEBUGADD(8,("update_printer: Converting the devicemode struct\n"));
6114                 if (!convert_devicemode(printer->info_2->printername, devmode,
6115                                         &printer->info_2->devmode)) {
6116                         result =  WERR_NOMEM;
6117                         goto done;
6118                 }
6119         }
6120 
6121         /* Do sanity check on the requested changes for Samba */
6122 
6123         if (!check_printer_ok(printer->info_2, snum)) {
6124                 result = WERR_INVALID_PARAM;
6125                 goto done;
6126         }
6127 
6128         /* FIXME!!! If the driver has changed we really should verify that
6129            it is installed before doing much else   --jerry */
6130 
6131         /* Check calling user has permission to update printer description */
6132 
6133         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
6134                 DEBUG(3, ("update_printer: printer property change denied by handle\n"));
6135                 result = WERR_ACCESS_DENIED;
6136                 goto done;
6137         }
6138 
6139         /* Call addprinter hook */
6140         /* Check changes to see if this is really needed */
6141 
6142         if ( *lp_addprinter_cmd()
6143                 && (!strequal(printer->info_2->drivername, old_printer->info_2->drivername)
6144                         || !strequal(printer->info_2->comment, old_printer->info_2->comment)
6145                         || !strequal(printer->info_2->portname, old_printer->info_2->portname)
6146                         || !strequal(printer->info_2->location, old_printer->info_2->location)) )
6147         {
6148                 /* add_printer_hook() will call reload_services() */
6149 
6150                 if ( !add_printer_hook(p->mem_ctx, p->server_info->ptok,
6151                                        printer) ) {
6152                         result = WERR_ACCESS_DENIED;
6153                         goto done;
6154                 }
6155         }
6156 
6157         /*
6158          * When a *new* driver is bound to a printer, the drivername is used to
6159          * lookup previously saved driver initialization info, which is then
6160          * bound to the printer, simulating what happens in the Windows arch.
6161          */
6162         if (!strequal(printer->info_2->drivername, old_printer->info_2->drivername))
6163         {
6164                 if (!set_driver_init(printer, 2))
6165                 {
6166                         DEBUG(5,("update_printer: Error restoring driver initialization data for driver [%s]!\n",
6167                                 printer->info_2->drivername));
6168                 }
6169 
6170                 DEBUG(10,("update_printer: changing driver [%s]!  Sending event!\n",
6171                         printer->info_2->drivername));
6172 
6173                 notify_printer_driver(snum, printer->info_2->drivername);
6174         }
6175 
6176         /*
6177          * flag which changes actually occured.  This is a small subset of
6178          * all the possible changes.  We also have to update things in the
6179          * DsSpooler key.
6180          */
6181 
6182         if (!strequal(printer->info_2->comment, old_printer->info_2->comment)) {
6183                 init_unistr2( &buffer, printer->info_2->comment, UNI_STR_TERMINATE);
6184                 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "description",
6185                         REG_SZ, (uint8_t *)buffer.buffer, buffer.uni_str_len*2 );
6186 
6187                 notify_printer_comment(snum, printer->info_2->comment);
6188         }
6189 
6190         if (!strequal(printer->info_2->sharename, old_printer->info_2->sharename)) {
6191                 init_unistr2( &buffer, printer->info_2->sharename, UNI_STR_TERMINATE);
6192                 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "shareName",
6193                         REG_SZ, (uint8_t *)buffer.buffer, buffer.uni_str_len*2 );
6194 
6195                 notify_printer_sharename(snum, printer->info_2->sharename);
6196         }
6197 
6198         if (!strequal(printer->info_2->printername, old_printer->info_2->printername)) {
6199                 char *pname;
6200 
6201                 if ( (pname = strchr_m( printer->info_2->printername+2, '\\' )) != NULL )
6202                         pname++;
6203                 else
6204                         pname = printer->info_2->printername;
6205 
6206 
6207                 init_unistr2( &buffer, pname, UNI_STR_TERMINATE);
6208                 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "printerName",
6209                         REG_SZ, (uint8_t *)buffer.buffer, buffer.uni_str_len*2 );
6210 
6211                 notify_printer_printername( snum, pname );
6212         }
6213 
6214         if (!strequal(printer->info_2->portname, old_printer->info_2->portname)) {
6215                 init_unistr2( &buffer, printer->info_2->portname, UNI_STR_TERMINATE);
6216                 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "portName",
6217                         REG_SZ, (uint8_t *)buffer.buffer, buffer.uni_str_len*2 );
6218 
6219                 notify_printer_port(snum, printer->info_2->portname);
6220         }
6221 
6222         if (!strequal(printer->info_2->location, old_printer->info_2->location)) {
6223                 init_unistr2( &buffer, printer->info_2->location, UNI_STR_TERMINATE);
6224                 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "location",
6225                         REG_SZ, (uint8_t *)buffer.buffer, buffer.uni_str_len*2 );
6226 
6227                 notify_printer_location(snum, printer->info_2->location);
6228         }
6229 
6230         /* here we need to update some more DsSpooler keys */
6231         /* uNCName, serverName, shortServerName */
6232 
6233         init_unistr2( &buffer, global_myname(), UNI_STR_TERMINATE);
6234         set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "serverName",
6235                 REG_SZ, (uint8_t *)buffer.buffer, buffer.uni_str_len*2 );
6236         set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "shortServerName",
6237                 REG_SZ, (uint8_t *)buffer.buffer, buffer.uni_str_len*2 );
6238 
6239         slprintf( asc_buffer, sizeof(asc_buffer)-1, "\\\\%s\\%s",
6240                  global_myname(), printer->info_2->sharename );
6241         init_unistr2( &buffer, asc_buffer, UNI_STR_TERMINATE);
6242         set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "uNCName",
6243                 REG_SZ, (uint8_t *)buffer.buffer, buffer.uni_str_len*2 );
6244 
6245         /* Update printer info */
6246         result = mod_a_printer(printer, 2);
6247 
6248 done:
6249         free_a_printer(&printer, 2);
6250         free_a_printer(&old_printer, 2);
6251 
6252 
6253         return result;
6254 }
6255 
6256 /****************************************************************************
6257 ****************************************************************************/
6258 static WERROR publish_or_unpublish_printer(pipes_struct *p,
     /* [<][>][^][v][top][bottom][index][help] */
6259                                            struct policy_handle *handle,
6260                                            struct spoolss_SetPrinterInfo7 *info7)
6261 {
6262 #ifdef HAVE_ADS
6263         int snum;
6264         Printer_entry *Printer;
6265 
6266         if ( lp_security() != SEC_ADS ) {
6267                 return WERR_UNKNOWN_LEVEL;
6268         }
6269 
6270         Printer = find_printer_index_by_hnd(p, handle);
6271 
6272         DEBUG(5,("publish_or_unpublish_printer, action = %d\n",info7->action));
6273 
6274         if (!Printer)
6275                 return WERR_BADFID;
6276 
6277         if (!get_printer_snum(p, handle, &snum, NULL))
6278                 return WERR_BADFID;
6279 
6280         nt_printer_publish(Printer, snum, info7->action);
6281 
6282         return WERR_OK;
6283 #else
6284         return WERR_UNKNOWN_LEVEL;
6285 #endif
6286 }
6287 
6288 /****************************************************************
6289  _spoolss_SetPrinter
6290 ****************************************************************/
6291 
6292 WERROR _spoolss_SetPrinter(pipes_struct *p,
     /* [<][>][^][v][top][bottom][index][help] */
6293                            struct spoolss_SetPrinter *r)
6294 {
6295         WERROR result;
6296 
6297         Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
6298 
6299         if (!Printer) {
6300                 DEBUG(2,("_spoolss_SetPrinter: Invalid handle (%s:%u:%u)\n",
6301                         OUR_HANDLE(r->in.handle)));
6302                 return WERR_BADFID;
6303         }
6304 
6305         /* check the level */
6306         switch (r->in.info_ctr->level) {
6307                 case 0:
6308                         return control_printer(r->in.handle, r->in.command, p);
6309                 case 2:
6310                         result = update_printer(p, r->in.handle,
6311                                                 r->in.info_ctr,
6312                                                 r->in.devmode_ctr->devmode);
6313                         if (!W_ERROR_IS_OK(result))
6314                                 return result;
6315                         if (r->in.secdesc_ctr->sd)
6316                                 result = update_printer_sec(r->in.handle, p,
6317                                                             r->in.secdesc_ctr);
6318                         return result;
6319                 case 3:
6320                         return update_printer_sec(r->in.handle, p,
6321                                                   r->in.secdesc_ctr);
6322                 case 7:
6323                         return publish_or_unpublish_printer(p, r->in.handle,
6324                                                             r->in.info_ctr->info.info7);
6325                 default:
6326                         return WERR_UNKNOWN_LEVEL;
6327         }
6328 }
6329 
6330 /****************************************************************
6331  _spoolss_FindClosePrinterNotify
6332 ****************************************************************/
6333 
6334 WERROR _spoolss_FindClosePrinterNotify(pipes_struct *p,
     /* [<][>][^][v][top][bottom][index][help] */
6335                                        struct spoolss_FindClosePrinterNotify *r)
6336 {
6337         Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
6338 
6339         if (!Printer) {
6340                 DEBUG(2,("_spoolss_FindClosePrinterNotify: "
6341                         "Invalid handle (%s:%u:%u)\n", OUR_HANDLE(r->in.handle)));
6342                 return WERR_BADFID;
6343         }
6344 
6345         if (Printer->notify.client_connected == true) {
6346                 int snum = -1;
6347 
6348                 if ( Printer->printer_type == SPLHND_SERVER)
6349                         snum = -1;
6350                 else if ( (Printer->printer_type == SPLHND_PRINTER) &&
6351                                 !get_printer_snum(p, r->in.handle, &snum, NULL) )
6352                         return WERR_BADFID;
6353 
6354                 srv_spoolss_replycloseprinter(snum, &Printer->notify.client_hnd);
6355         }
6356 
6357         Printer->notify.flags=0;
6358         Printer->notify.options=0;
6359         Printer->notify.localmachine[0]='\0';
6360         Printer->notify.printerlocal=0;
6361         TALLOC_FREE(Printer->notify.option);
6362         Printer->notify.client_connected = false;
6363 
6364         return WERR_OK;
6365 }
6366 
6367 /****************************************************************
6368  _spoolss_AddJob
6369 ****************************************************************/
6370 
6371 WERROR _spoolss_AddJob(pipes_struct *p,
     /* [<][>][^][v][top][bottom][index][help] */
6372                        struct spoolss_AddJob *r)
6373 {
6374         if (!r->in.buffer && (r->in.offered != 0)) {
6375                 return WERR_INVALID_PARAM;
6376         }
6377 
6378         /* this is what a NT server returns for AddJob. AddJob must fail on
6379          * non-local printers */
6380 
6381         if (r->in.level != 1) {
6382                 return WERR_UNKNOWN_LEVEL;
6383         }
6384 
6385         return WERR_INVALID_PARAM;
6386 }
6387 
6388 /****************************************************************************
6389 fill_job_info1
6390 ****************************************************************************/
6391 
6392 static WERROR fill_job_info1(TALLOC_CTX *mem_ctx,
     /* [<][>][^][v][top][bottom][index][help] */
6393                              struct spoolss_JobInfo1 *r,
6394                              const print_queue_struct *queue,
6395                              int position, int snum,
6396                              const NT_PRINTER_INFO_LEVEL *ntprinter)
6397 {
6398         struct tm *t;
6399 
6400         t = gmtime(&queue->time);
6401 
6402         r->job_id               = queue->job;
6403 
6404         r->printer_name         = talloc_strdup(mem_ctx, lp_servicename(snum));
6405         W_ERROR_HAVE_NO_MEMORY(r->printer_name);
6406         r->server_name          = talloc_strdup(mem_ctx, ntprinter->info_2->servername);
6407         W_ERROR_HAVE_NO_MEMORY(r->server_name);
6408         r->user_name            = talloc_strdup(mem_ctx, queue->fs_user);
6409         W_ERROR_HAVE_NO_MEMORY(r->user_name);
6410         r->document_name        = talloc_strdup(mem_ctx, queue->fs_file);
6411         W_ERROR_HAVE_NO_MEMORY(r->document_name);
6412         r->data_type            = talloc_strdup(mem_ctx, "RAW");
6413         W_ERROR_HAVE_NO_MEMORY(r->data_type);
6414         r->text_status          = talloc_strdup(mem_ctx, "");
6415         W_ERROR_HAVE_NO_MEMORY(r->text_status);
6416 
6417         r->status               = nt_printj_status(queue->status);
6418         r->priority             = queue->priority;
6419         r->position             = position;
6420         r->total_pages          = queue->page_count;
6421         r->pages_printed        = 0; /* ??? */
6422 
6423         init_systemtime(&r->submitted, t);
6424 
6425         return WERR_OK;
6426 }
6427 
6428 /****************************************************************************
6429 fill_job_info2
6430 ****************************************************************************/
6431 
6432 static WERROR fill_job_info2(TALLOC_CTX *mem_ctx,
     /* [<][>][^][v][top][bottom][index][help] */
6433                              struct spoolss_JobInfo2 *r,
6434                              const print_queue_struct *queue,
6435                              int position, int snum,
6436                              const NT_PRINTER_INFO_LEVEL *ntprinter,
6437                              struct spoolss_DeviceMode *devmode)
6438 {
6439         struct tm *t;
6440 
6441         t = gmtime(&queue->time);
6442 
6443         r->job_id               = queue->job;
6444 
6445         r->printer_name         = talloc_strdup(mem_ctx, lp_servicename(snum));
6446         W_ERROR_HAVE_NO_MEMORY(r->printer_name);
6447         r->server_name          = talloc_strdup(mem_ctx, ntprinter->info_2->servername);
6448         W_ERROR_HAVE_NO_MEMORY(r->server_name);
6449         r->user_name            = talloc_strdup(mem_ctx, queue->fs_user);
6450         W_ERROR_HAVE_NO_MEMORY(r->user_name);
6451         r->document_name        = talloc_strdup(mem_ctx, queue->fs_file);
6452         W_ERROR_HAVE_NO_MEMORY(r->document_name);
6453         r->notify_name          = talloc_strdup(mem_ctx, queue->fs_user);
6454         W_ERROR_HAVE_NO_MEMORY(r->notify_name);
6455         r->data_type            = talloc_strdup(mem_ctx, "RAW");
6456         W_ERROR_HAVE_NO_MEMORY(r->data_type);
6457         r->print_processor      = talloc_strdup(mem_ctx, "winprint");
6458         W_ERROR_HAVE_NO_MEMORY(r->print_processor);
6459         r->parameters           = talloc_strdup(mem_ctx, "");
6460         W_ERROR_HAVE_NO_MEMORY(r->parameters);
6461         r->driver_name          = talloc_strdup(mem_ctx, ntprinter->info_2->drivername);
6462         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
6463 
6464         r->devmode              = devmode;
6465 
6466         r->text_status          = talloc_strdup(mem_ctx, "");
6467         W_ERROR_HAVE_NO_MEMORY(r->text_status);
6468 
6469         r->secdesc              = NULL;
6470 
6471         r->status               = nt_printj_status(queue->status);
6472         r->priority             = queue->priority;
6473         r->position             = position;
6474         r->start_time           = 0;
6475         r->until_time           = 0;
6476         r->total_pages          = queue->page_count;
6477         r->size                 = queue->size;
6478         init_systemtime(&r->submitted, t);
6479         r->time                 = 0;
6480         r->pages_printed        = 0; /* ??? */
6481 
6482         return WERR_OK;
6483 }
6484 
6485 /****************************************************************************
6486  Enumjobs at level 1.
6487 ****************************************************************************/
6488 
6489 static WERROR enumjobs_level1(TALLOC_CTX *mem_ctx,
     /* [<][>][^][v][top][bottom][index][help] */
6490                               const print_queue_struct *queue,
6491                               uint32_t num_queues, int snum,
6492                               const NT_PRINTER_INFO_LEVEL *ntprinter,
6493                               union spoolss_JobInfo **info_p,
6494                               uint32_t *count)
6495 {
6496         union spoolss_JobInfo *info;
6497         int i;
6498         WERROR result = WERR_OK;
6499 
6500         info = TALLOC_ARRAY(mem_ctx, union spoolss_JobInfo, num_queues);
6501         W_ERROR_HAVE_NO_MEMORY(info);
6502 
6503         *count = num_queues;
6504 
6505         for (i=0; i<*count; i++) {
6506                 result = fill_job_info1(info,
6507                                         &info[i].info1,
6508                                         &queue[i],
6509                                         i,
6510                                         snum,
6511                                         ntprinter);
6512                 if (!W_ERROR_IS_OK(result)) {
6513                         goto out;
6514                 }
6515         }
6516 
6517  out:
6518         if (!W_ERROR_IS_OK(result)) {
6519                 TALLOC_FREE(info);
6520                 *count = 0;
6521                 return result;
6522         }
6523 
6524         *info_p = info;
6525 
6526         return WERR_OK;
6527 }
6528 
6529 /****************************************************************************
6530  Enumjobs at level 2.
6531 ****************************************************************************/
6532 
6533 static WERROR enumjobs_level2(TALLOC_CTX *mem_ctx,
     /* [<][>][^][v][top][bottom][index][help] */
6534                               const print_queue_struct *queue,
6535                               uint32_t num_queues, int snum,
6536                               const NT_PRINTER_INFO_LEVEL *ntprinter,
6537                               union spoolss_JobInfo **info_p,
6538                               uint32_t *count)
6539 {
6540         union spoolss_JobInfo *info;
6541         int i;
6542         WERROR result = WERR_OK;
6543 
6544         info = TALLOC_ARRAY(mem_ctx, union spoolss_JobInfo, num_queues);
6545         W_ERROR_HAVE_NO_MEMORY(info);
6546 
6547         *count = num_queues;
6548 
6549         for (i=0; i<*count; i++) {
6550 
6551                 struct spoolss_DeviceMode *devmode;
6552 
6553                 devmode = construct_dev_mode(info, lp_const_servicename(snum));
6554                 if (!devmode) {
6555                         result = WERR_NOMEM;
6556                         goto out;
6557                 }
6558 
6559                 result = fill_job_info2(info,
6560                                         &info[i].info2,
6561                                         &queue[i],
6562                                         i,
6563                                         snum,
6564                                         ntprinter,
6565                                         devmode);
6566                 if (!W_ERROR_IS_OK(result)) {
6567                         goto out;
6568                 }
6569         }
6570 
6571  out:
6572         if (!W_ERROR_IS_OK(result)) {
6573                 TALLOC_FREE(info);
6574                 *count = 0;
6575                 return result;
6576         }
6577 
6578         *info_p = info;
6579 
6580         return WERR_OK;
6581 }
6582 
6583 /****************************************************************
6584  _spoolss_EnumJobs
6585 ****************************************************************/
6586 
6587 WERROR _spoolss_EnumJobs(pipes_struct *p,
     /* [<][>][^][v][top][bottom][index][help] */
6588                          struct spoolss_EnumJobs *r)
6589 {
6590         WERROR result;
6591         NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
6592         int snum;
6593         print_status_struct prt_status;
6594         print_queue_struct *queue = NULL;
6595         uint32_t count;
6596 
6597         /* that's an [in out] buffer */
6598 
6599         if (!r->in.buffer && (r->in.offered != 0)) {
6600                 return WERR_INVALID_PARAM;
6601         }
6602 
6603         DEBUG(4,("_spoolss_EnumJobs\n"));
6604 
6605         *r->out.needed = 0;
6606         *r->out.count = 0;
6607         *r->out.info = NULL;
6608 
6609         /* lookup the printer snum and tdb entry */
6610 
6611         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
6612                 return WERR_BADFID;
6613         }
6614 
6615         result = get_a_printer(NULL, &ntprinter, 2, lp_servicename(snum));
6616         if (!W_ERROR_IS_OK(result)) {
6617                 return result;
6618         }
6619 
6620         count = print_queue_status(snum, &queue, &prt_status);
6621         DEBUGADD(4,("count:[%d], status:[%d], [%s]\n",
6622                 count, prt_status.status, prt_status.message));
6623 
6624         if (count == 0) {
6625                 SAFE_FREE(queue);
6626                 free_a_printer(&ntprinter, 2);
6627                 return WERR_OK;
6628         }
6629 
6630         switch (r->in.level) {
6631         case 1:
6632                 result = enumjobs_level1(p->mem_ctx, queue, count, snum,
6633                                          ntprinter, r->out.info, r->out.count);
6634                 break;
6635         case 2:
6636                 result = enumjobs_level2(p->mem_ctx, queue, count, snum,
6637                                          ntprinter, r->out.info, r->out.count);
6638                 break;
6639         default:
6640                 result = WERR_UNKNOWN_LEVEL;
6641                 break;
6642         }
6643 
6644         SAFE_FREE(queue);
6645         free_a_printer(&ntprinter, 2);
6646 
6647         if (!W_ERROR_IS_OK(result)) {
6648                 return result;
6649         }
6650 
6651         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
6652                                                      spoolss_EnumJobs, NULL,
6653                                                      *r->out.info, r->in.level,
6654                                                      *r->out.count);
6655         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
6656         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
6657 
6658         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
6659 }
6660 
6661 /****************************************************************
6662  _spoolss_ScheduleJob
6663 ****************************************************************/
6664 
6665 WERROR _spoolss_ScheduleJob(pipes_struct *p,
     /* [<][>][^][v][top][bottom][index][help] */
6666                             struct spoolss_ScheduleJob *r)
6667 {
6668         return WERR_OK;
6669 }
6670 
6671 /****************************************************************
6672  _spoolss_SetJob
6673 ****************************************************************/
6674 
6675 WERROR _spoolss_SetJob(pipes_struct *p,
     /* [<][>][^][v][top][bottom][index][help] */
6676                        struct spoolss_SetJob *r)
6677 {
6678         int snum;
6679         WERROR errcode = WERR_BADFUNC;
6680 
6681         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
6682                 return WERR_BADFID;
6683         }
6684 
6685         if (!print_job_exists(lp_const_servicename(snum), r->in.job_id)) {
6686                 return WERR_INVALID_PRINTER_NAME;
6687         }
6688 
6689         switch (r->in.command) {
6690         case SPOOLSS_JOB_CONTROL_CANCEL:
6691         case SPOOLSS_JOB_CONTROL_DELETE:
6692                 if (print_job_delete(p->server_info, snum, r->in.job_id, &errcode)) {
6693                         errcode = WERR_OK;
6694                 }
6695                 break;
6696         case SPOOLSS_JOB_CONTROL_PAUSE:
6697                 if (print_job_pause(p->server_info, snum, r->in.job_id, &errcode)) {
6698                         errcode = WERR_OK;
6699                 }
6700                 break;
6701         case SPOOLSS_JOB_CONTROL_RESTART:
6702         case SPOOLSS_JOB_CONTROL_RESUME:
6703                 if (print_job_resume(p->server_info, snum, r->in.job_id, &errcode)) {
6704                         errcode = WERR_OK;
6705                 }
6706                 break;
6707         default:
6708                 return WERR_UNKNOWN_LEVEL;
6709         }
6710 
6711         return errcode;
6712 }
6713 
6714 /****************************************************************************
6715  Enumerates all printer drivers by level.
6716 ****************************************************************************/
6717 
6718 static WERROR enumprinterdrivers_level(TALLOC_CTX *mem_ctx,
     /* [<][>][^][v][top][bottom][index][help] */
6719                                        const char *servername,
6720                                        const char *architecture,
6721                                        uint32_t level,
6722                                        union spoolss_DriverInfo **info_p,
6723                                        uint32_t *count_p)
6724 {
6725         int i;
6726         int ndrivers;
6727         uint32_t version;
6728         fstring *list = NULL;
6729         NT_PRINTER_DRIVER_INFO_LEVEL driver;
6730         union spoolss_DriverInfo *info = NULL;
6731         uint32_t count = 0;
6732         WERROR result = WERR_OK;
6733 
6734         *count_p = 0;
6735         *info_p = NULL;
6736 
6737         for (version=0; version<DRIVER_MAX_VERSION; version++) {
6738                 list = NULL;
6739                 ndrivers = get_ntdrivers(&list, architecture, version);
6740                 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n",
6741                         ndrivers, architecture, version));
6742 
6743                 if (ndrivers == -1) {
6744                         result = WERR_NOMEM;
6745                         goto out;
6746                 }
6747 
6748                 if (ndrivers != 0) {
6749                         info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
6750                                                     union spoolss_DriverInfo,
6751                                                     count + ndrivers);
6752                         if (!info) {
6753                                 DEBUG(0,("enumprinterdrivers_level1: "
6754                                         "failed to enlarge driver info buffer!\n"));
6755                                 result = WERR_NOMEM;
6756                                 goto out;
6757                         }
6758                 }
6759 
6760                 for (i=0; i<ndrivers; i++) {
6761                         DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
6762                         ZERO_STRUCT(driver);
6763                         result = get_a_printer_driver(&driver, 3, list[i],
6764                                                       architecture, version);
6765                         if (!W_ERROR_IS_OK(result)) {
6766                                 goto out;
6767                         }
6768 
6769                         switch (level) {
6770                         case 1:
6771                                 result = fill_printer_driver_info1(info, &info[count+i].info1,
6772                                                                    &driver, servername,
6773                                                                    architecture);
6774                                 break;
6775                         case 2:
6776                                 result = fill_printer_driver_info2(info, &info[count+i].info2,
6777                                                                    &driver, servername);
6778                                 break;
6779                         case 3:
6780                                 result = fill_printer_driver_info3(info, &info[count+i].info3,
6781                                                                    &driver, servername);
6782                                 break;
6783                         case 4:
6784                                 result = fill_printer_driver_info4(info, &info[count+i].info4,
6785                                                                    &driver, servername);
6786                                 break;
6787                         case 5:
6788                                 result = fill_printer_driver_info5(info, &info[count+i].info5,
6789                                                                    &driver, servername);
6790                                 break;
6791                         case 6:
6792                                 result = fill_printer_driver_info6(info, &info[count+i].info6,
6793                                                                    &driver, servername);
6794                                 break;
6795                         default:
6796                                 result = WERR_UNKNOWN_LEVEL;
6797                                 break;
6798                         }
6799 
6800                         if (!W_ERROR_IS_OK(result)) {
6801                                 free_a_printer_driver(driver, 3);
6802                                 goto out;
6803                         }
6804                         free_a_printer_driver(driver, 3);
6805                 }
6806 
6807                 count += ndrivers;
6808                 SAFE_FREE(list);
6809         }
6810 
6811  out:
6812         SAFE_FREE(list);
6813 
6814         if (!W_ERROR_IS_OK(result)) {
6815                 TALLOC_FREE(info);
6816                 return result;
6817         }
6818 
6819         *info_p = info;
6820         *count_p = count;
6821 
6822         return WERR_OK;
6823 }
6824 
6825 /****************************************************************************
6826  Enumerates all printer drivers at level 1.
6827 ****************************************************************************/
6828 
6829 static WERROR enumprinterdrivers_level1(TALLOC_CTX *mem_ctx,
     /* [<][>][^][v][top][bottom][index][help] */
6830                                         const char *servername,
6831                                         const char *architecture,
6832                                         union spoolss_DriverInfo **info_p,
6833                                         uint32_t *count)
6834 {
6835         return enumprinterdrivers_level(mem_ctx, servername, architecture, 1,
6836                                         info_p, count);
6837 }
6838 
6839 /****************************************************************************
6840  Enumerates all printer drivers at level 2.
6841 ****************************************************************************/
6842 
6843 static WERROR enumprinterdrivers_level2(TALLOC_CTX *mem_ctx,
     /* [<][>][^][v][top][bottom][index][help] */
6844                                         const char *servername,
6845                                         const char *architecture,
6846                                         union spoolss_DriverInfo **info_p,
6847                                         uint32_t *count)
6848 {
6849         return enumprinterdrivers_level(mem_ctx, servername, architecture, 2,
6850                                         info_p, count);
6851 }
6852 
6853 /****************************************************************************
6854  Enumerates all printer drivers at level 3.
6855 ****************************************************************************/
6856 
6857 static WERROR enumprinterdrivers_level3(TALLOC_CTX *mem_ctx,
     /* [<][>][^][v][top][bottom][index][help] */
6858                                         const char *servername,
6859                                         const char *architecture,
6860                                         union spoolss_DriverInfo **info_p,
6861                                         uint32_t *count)
6862 {
6863         return enumprinterdrivers_level(mem_ctx, servername, architecture, 3,
6864                                         info_p, count);
6865 }
6866 
6867 /****************************************************************************
6868  Enumerates all printer drivers at level 4.
6869 ****************************************************************************/
6870 
6871 static WERROR enumprinterdrivers_level4(TALLOC_CTX *mem_ctx,
     /* [<][>][^][v][top][bottom][index][help] */
6872                                         const char *servername,
6873                                         const char *architecture,
6874                                         union spoolss_DriverInfo **info_p,
6875                                         uint32_t *count)
6876 {
6877         return enumprinterdrivers_level(mem_ctx, servername, architecture, 4,
6878                                         info_p, count);
6879 }
6880 
6881 /****************************************************************************
6882  Enumerates all printer drivers at level 5.
6883 ****************************************************************************/
6884 
6885 static WERROR enumprinterdrivers_level5(TALLOC_CTX *mem_ctx,
     /* [<][>][^][v][top][bottom][index][help] */
6886                                         const char *servername,
6887                                         const char *architecture,
6888                                         union spoolss_DriverInfo **info_p,
6889                                         uint32_t *count)
6890 {
6891         return enumprinterdrivers_level(mem_ctx, servername, architecture, 5,
6892                                         info_p, count);
6893 }
6894 
6895 /****************************************************************************
6896  Enumerates all printer drivers at level 6.
6897 ****************************************************************************/
6898 
6899 static WERROR enumprinterdrivers_level6(TALLOC_CTX *mem_ctx,
     /* [<][>][^][v][top][bottom][index][help] */
6900                                         const char *servername,
6901                                         const char *architecture,
6902                                         union spoolss_DriverInfo **info_p,
6903                                         uint32_t *count)
6904 {
6905         return enumprinterdrivers_level(mem_ctx, servername, architecture, 6,
6906                                         info_p, count);
6907 }
6908 
6909 
6910 /****************************************************************
6911  _spoolss_EnumPrinterDrivers
6912 ****************************************************************/
6913 
6914 WERROR _spoolss_EnumPrinterDrivers(pipes_struct *p,
     /* [<][>][^][v][top][bottom][index][help] */
6915                                    struct spoolss_EnumPrinterDrivers *r)
6916 {
6917         const char *cservername;
6918         WERROR result;
6919 
6920         /* that's an [in out] buffer */
6921 
6922         if (!r->in.buffer && (r->in.offered != 0)) {
6923                 return WERR_INVALID_PARAM;
6924         }
6925 
6926         DEBUG(4,("_spoolss_EnumPrinterDrivers\n"));
6927 
6928         *r->out.needed = 0;
6929         *r->out.count = 0;
6930         *r->out.info = NULL;
6931 
6932         cservername = canon_servername(r->in.server);
6933 
6934         if (!is_myname_or_ipaddr(cservername)) {
6935                 return WERR_UNKNOWN_PRINTER_DRIVER;
6936         }
6937 
6938         switch (r->in.level) {
6939         case 1:
6940                 result = enumprinterdrivers_level1(p->mem_ctx, cservername,
6941                                                    r->in.environment,
6942                                                    r->out.info, r->out.count);
6943                 break;
6944         case 2:
6945                 result = enumprinterdrivers_level2(p->mem_ctx, cservername,
6946                                                    r->in.environment,
6947                                                    r->out.info, r->out.count);
6948                 break;
6949         case 3:
6950                 result = enumprinterdrivers_level3(p->mem_ctx, cservername,
6951                                                    r->in.environment,
6952                                                    r->out.info, r->out.count);
6953                 break;
6954         case 4:
6955                 result = enumprinterdrivers_level4(p->mem_ctx, cservername,
6956                                                    r->in.environment,
6957                                                    r->out.info, r->out.count);
6958                 break;
6959         case 5:
6960                 result = enumprinterdrivers_level5(p->mem_ctx, cservername,
6961                                                    r->in.environment,
6962                                                    r->out.info, r->out.count);
6963                 break;
6964         case 6:
6965                 result = enumprinterdrivers_level6(p->mem_ctx, cservername,
6966                                                    r->in.environment,
6967                                                    r->out.info, r->out.count);
6968                 break;
6969         default:
6970                 return WERR_UNKNOWN_LEVEL;
6971         }
6972 
6973         if (!W_ERROR_IS_OK(result)) {
6974                 return result;
6975         }
6976 
6977         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
6978                                                      spoolss_EnumPrinterDrivers, NULL,
6979                                                      *r->out.info, r->in.level,
6980                                                      *r->out.count);
6981         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
6982         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
6983 
6984         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
6985 }
6986 
6987 /****************************************************************************
6988 ****************************************************************************/
6989 
6990 static WERROR fill_form_info_1(TALLOC_CTX *mem_ctx,
     /* [<][>][^][v][top][bottom][index][help] */
6991                                struct spoolss_FormInfo1 *r,
6992                                const nt_forms_struct *form)
6993 {
6994         r->form_name    = talloc_strdup(mem_ctx, form->name);
6995         W_ERROR_HAVE_NO_MEMORY(r->form_name);
6996 
6997         r->flags        = form->flag;
6998         r->size.width   = form->width;
6999         r->size.height  = form->length;
7000         r->area.left    = form->left;
7001         r->area.top     = form->top;
7002         r->area.right   = form->right;
7003         r->area.bottom  = form->bottom;
7004 
7005         return WERR_OK;
7006 }
7007 
7008 /****************************************************************
7009  spoolss_enumforms_level1
7010 ****************************************************************/
7011 
7012 static WERROR spoolss_enumforms_level1(TALLOC_CTX *mem_ctx,
     /* [<][>][^][v][top][bottom][index][help] */
7013                                        const nt_forms_struct *builtin_forms,
7014                                        uint32_t num_builtin_forms,
7015                                        const nt_forms_struct *user_forms,
7016                                        uint32_t num_user_forms,
7017                                        union spoolss_FormInfo **info_p,
7018                                        uint32_t *count)
7019 {
7020         union spoolss_FormInfo *info;
7021         WERROR result = WERR_OK;
7022         int i;
7023 
7024         *count = num_builtin_forms + num_user_forms;
7025 
7026         info = TALLOC_ARRAY(mem_ctx, union spoolss_FormInfo, *count);
7027         W_ERROR_HAVE_NO_MEMORY(info);
7028 
7029         /* construct the list of form structures */
7030         for (i=0; i<num_builtin_forms; i++) {
7031                 DEBUGADD(6,("Filling builtin form number [%d]\n",i));
7032                 result = fill_form_info_1(info, &info[i].info1,
7033                                           &builtin_forms[i]);
7034                 if (!W_ERROR_IS_OK(result)) {
7035                         goto out;
7036                 }
7037         }
7038 
7039         for (i=0; i<num_user_forms; i++) {
7040                 DEBUGADD(6,("Filling user form number [%d]\n",i));
7041                 result = fill_form_info_1(info, &info[i+num_builtin_forms].info1,
7042                                           &user_forms[i]);
7043                 if (!W_ERROR_IS_OK(result)) {
7044                         goto out;
7045                 }
7046         }
7047 
7048  out:
7049         if (!W_ERROR_IS_OK(result)) {
7050                 TALLOC_FREE(info);
7051                 *count = 0;
7052                 return result;
7053         }
7054 
7055         *info_p = info;
7056 
7057         return WERR_OK;
7058 }
7059 
7060 /****************************************************************
7061  _spoolss_EnumForms
7062 ****************************************************************/
7063 
7064 WERROR _spoolss_EnumForms(pipes_struct *p,
     /* [<][>][^][v][top][bottom][index][help] */
7065                           struct spoolss_EnumForms *r)
7066 {
7067         WERROR result;
7068         nt_forms_struct *user_forms = NULL;
7069         nt_forms_struct *builtin_forms = NULL;
7070         uint32_t num_user_forms;
7071         uint32_t num_builtin_forms;
7072 
7073         *r->out.count = 0;
7074         *r->out.needed = 0;
7075         *r->out.info = NULL;
7076 
7077         /* that's an [in out] buffer */
7078 
7079         if (!r->in.buffer && (r->in.offered != 0) ) {
7080                 return WERR_INVALID_PARAM;
7081         }
7082 
7083         DEBUG(4,("_spoolss_EnumForms\n"));
7084         DEBUGADD(5,("Offered buffer size [%d]\n", r->in.offered));
7085         DEBUGADD(5,("Info level [%d]\n",          r->in.level));
7086 
7087         num_builtin_forms = get_builtin_ntforms(&builtin_forms);
7088         DEBUGADD(5,("Number of builtin forms [%d]\n", num_builtin_forms));
7089         num_user_forms = get_ntforms(&user_forms);
7090         DEBUGADD(5,("Number of user forms [%d]\n", num_user_forms));
7091 
7092         if (num_user_forms + num_builtin_forms == 0) {
7093                 SAFE_FREE(builtin_forms);
7094                 SAFE_FREE(user_forms);
7095                 return WERR_NO_MORE_ITEMS;
7096         }
7097 
7098         switch (r->in.level) {
7099         case 1:
7100                 result = spoolss_enumforms_level1(p->mem_ctx,
7101                                                   builtin_forms,
7102                                                   num_builtin_forms,
7103                                                   user_forms,
7104                                                   num_user_forms,
7105                                                   r->out.info,
7106                                                   r->out.count);
7107                 break;
7108         default:
7109                 result = WERR_UNKNOWN_LEVEL;
7110                 break;
7111         }
7112 
7113         SAFE_FREE(user_forms);
7114         SAFE_FREE(builtin_forms);
7115 
7116         if (!W_ERROR_IS_OK(result)) {
7117                 return result;
7118         }
7119 
7120         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
7121                                                      spoolss_EnumForms, NULL,
7122                                                      *r->out.info, r->in.level,
7123                                                      *r->out.count);
7124         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
7125         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
7126 
7127         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
7128 }
7129 
7130 /****************************************************************
7131 ****************************************************************/
7132 
7133 static WERROR find_form_byname(const char *name,
     /* [<][>][^][v][top][bottom][index][help] */
7134                                nt_forms_struct *form)
7135 {
7136         nt_forms_struct *list = NULL;
7137         int num_forms = 0, i = 0;
7138 
7139         if (get_a_builtin_ntform_by_string(name, form)) {
7140                 return WERR_OK;
7141         }
7142 
7143         num_forms = get_ntforms(&list);
7144         DEBUGADD(5,("Number of forms [%d]\n", num_forms));
7145 
7146         if (num_forms == 0) {
7147                 return WERR_BADFID;
7148         }
7149 
7150         /* Check if the requested name is in the list of form structures */
7151         for (i = 0; i < num_forms; i++) {
7152 
7153                 DEBUG(4,("checking form %s (want %s)\n", list[i].name, name));
7154 
7155                 if (strequal(name, list[i].name)) {
7156                         DEBUGADD(6,("Found form %s number [%d]\n", name, i));
7157                         *form = list[i];
7158                         SAFE_FREE(list);
7159                         return WERR_OK;
7160                 }
7161         }
7162 
7163         SAFE_FREE(list);
7164 
7165         return WERR_BADFID;
7166 }
7167 
7168 /****************************************************************
7169  _spoolss_GetForm
7170 ****************************************************************/
7171 
7172 WERROR _spoolss_GetForm(pipes_struct *p,
     /* [<][>][^][v][top][bottom][index][help] */
7173                         struct spoolss_GetForm *r)
7174 {
7175         WERROR result;
7176         nt_forms_struct form;
7177 
7178         /* that's an [in out] buffer */
7179 
7180         if (!r->in.buffer && (r->in.offered != 0)) {
7181                 return WERR_INVALID_PARAM;
7182         }
7183 
7184         DEBUG(4,("_spoolss_GetForm\n"));
7185         DEBUGADD(5,("Offered buffer size [%d]\n", r->in.offered));
7186         DEBUGADD(5,("Info level [%d]\n",          r->in.level));
7187 
7188         result = find_form_byname(r->in.form_name, &form);
7189         if (!W_ERROR_IS_OK(result)) {
7190                 TALLOC_FREE(r->out.info);
7191                 return result;
7192         }
7193 
7194         switch (r->in.level) {
7195         case 1:
7196                 result = fill_form_info_1(p->mem_ctx,
7197                                           &r->out.info->info1,
7198                                           &form);
7199                 break;
7200 
7201         default:
7202                 result = WERR_UNKNOWN_LEVEL;
7203                 break;
7204         }
7205 
7206         if (!W_ERROR_IS_OK(result)) {
7207                 TALLOC_FREE(r->out.info);
7208                 return result;
7209         }
7210 
7211         *r->out.needed  = SPOOLSS_BUFFER_UNION(spoolss_FormInfo, NULL,
7212                                                r->out.info, r->in.level);
7213         r->out.info     = SPOOLSS_BUFFER_OK(r->out.info, NULL);
7214 
7215         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
7216 }
7217 
7218 /****************************************************************************
7219 ****************************************************************************/
7220 
7221 static WERROR fill_port_1(TALLOC_CTX *mem_ctx,
     /* [<][>][^][v][top][bottom][index][help] */
7222                           struct spoolss_PortInfo1 *r,
7223                           const char *name)
7224 {
7225         r->port_name = talloc_strdup(mem_ctx, name);
7226         W_ERROR_HAVE_NO_MEMORY(r->port_name);
7227 
7228         return WERR_OK;
7229 }
7230 
7231 /****************************************************************************
7232  TODO: This probably needs distinguish between TCP/IP and Local ports
7233  somehow.
7234 ****************************************************************************/
7235 
7236 static WERROR fill_port_2(TALLOC_CTX *mem_ctx,
     /* [<][>][^][v][top][bottom][index][help] */
7237                           struct spoolss_PortInfo2 *r,
7238                           const char *name)
7239 {
7240         r->port_name = talloc_strdup(mem_ctx, name);
7241         W_ERROR_HAVE_NO_MEMORY(r->port_name);
7242 
7243         r->monitor_name = talloc_strdup(mem_ctx, "Local Monitor");
7244         W_ERROR_HAVE_NO_MEMORY(r->monitor_name);
7245 
7246         r->description = talloc_strdup(mem_ctx, SPL_LOCAL_PORT);
7247         W_ERROR_HAVE_NO_MEMORY(r->description);
7248 
7249         r->port_type = SPOOLSS_PORT_TYPE_WRITE;
7250         r->reserved = 0;
7251 
7252         return WERR_OK;
7253 }
7254 
7255 
7256 /****************************************************************************
7257  wrapper around the enumer ports command
7258 ****************************************************************************/
7259 
7260 WERROR enumports_hook(TALLOC_CTX *ctx, int *count, char ***lines )
     /* [<][>][^][v][top][bottom][index][help] */
7261 {
7262         char *cmd = lp_enumports_cmd();
7263         char **qlines = NULL;
7264         char *command = NULL;
7265         int numlines;
7266         int ret;
7267         int fd;
7268 
7269         *count = 0;
7270         *lines = NULL;
7271 
7272         /* if no hook then just fill in the default port */
7273 
7274         if ( !*cmd ) {
7275                 if (!(qlines = TALLOC_ARRAY( NULL, char*, 2 ))) {
7276                         return WERR_NOMEM;
7277                 }
7278                 if (!(qlines[0] = talloc_strdup(qlines, SAMBA_PRINTER_PORT_NAME ))) {
7279                         TALLOC_FREE(qlines);
7280                         return WERR_NOMEM;
7281                 }
7282                 qlines[1] = NULL;
7283                 numlines = 1;
7284         }
7285         else {
7286                 /* we have a valid enumport command */
7287 
7288                 command = talloc_asprintf(ctx, "%s \"%d\"", cmd, 1);
7289                 if (!command) {
7290                         return WERR_NOMEM;
7291                 }
7292 
7293                 DEBUG(10,("Running [%s]\n", command));
7294                 ret = smbrun(command, &fd);
7295                 DEBUG(10,("Returned [%d]\n", ret));
7296                 TALLOC_FREE(command);
7297                 if (ret != 0) {
7298                         if (fd != -1) {
7299                                 close(fd);
7300                         }
7301                         return WERR_ACCESS_DENIED;
7302                 }
7303 
7304                 numlines = 0;
7305                 qlines = fd_lines_load(fd, &numlines, 0, NULL);
7306                 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
7307                 close(fd);
7308         }
7309 
7310         *count = numlines;
7311         *lines = qlines;
7312 
7313         return WERR_OK;
7314 }
7315 
7316 /****************************************************************************
7317  enumports level 1.
7318 ****************************************************************************/
7319 
7320 static WERROR enumports_level_1(TALLOC_CTX *mem_ctx,
     /* [<][>][^][v][top][bottom][index][help] */
7321                                 union spoolss_PortInfo **info_p,
7322                                 uint32_t *count)
7323 {
7324         union spoolss_PortInfo *info = NULL;
7325         int i=0;
7326         WERROR result = WERR_OK;
7327         char **qlines = NULL;
7328         int numlines = 0;
7329 
7330         result = enumports_hook(talloc_tos(), &numlines, &qlines );
7331         if (!W_ERROR_IS_OK(result)) {
7332                 goto out;
7333         }
7334 
7335         if (numlines) {
7336                 info = TALLOC_ARRAY(mem_ctx, union spoolss_PortInfo, numlines);
7337                 if (!info) {
7338                         DEBUG(10,("Returning WERR_NOMEM\n"));
7339                         result = WERR_NOMEM;
7340                         goto out;
7341                 }
7342 
7343                 for (i=0; i<numlines; i++) {
7344                         DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
7345                         result = fill_port_1(info, &info[i].info1, qlines[i]);
7346                         if (!W_ERROR_IS_OK(result)) {
7347                                 goto out;
7348                         }
7349                 }
7350         }
7351         TALLOC_FREE(qlines);
7352 
7353 out:
7354         if (!W_ERROR_IS_OK(result)) {
7355                 TALLOC_FREE(info);
7356                 TALLOC_FREE(qlines);
7357                 *count = 0;
7358                 *info_p = NULL;
7359                 return result;
7360         }
7361 
7362         *info_p = info;
7363         *count = numlines;
7364 
7365         return WERR_OK;
7366 }
7367 
7368 /****************************************************************************
7369  enumports level 2.
7370 ****************************************************************************/
7371 
7372 static WERROR enumports_level_2(TALLOC_CTX *mem_ctx,
     /* [<][>][^][v][top][bottom][index][help] */
7373                                 union spoolss_PortInfo **info_p,
7374                                 uint32_t *count)
7375 {
7376         union spoolss_PortInfo *info = NULL;
7377         int i=0;
7378         WERROR result = WERR_OK;
7379         char **qlines = NULL;
7380         int numlines = 0;
7381 
7382         result = enumports_hook(talloc_tos(), &numlines, &qlines );
7383         if (!W_ERROR_IS_OK(result)) {
7384                 goto out;
7385         }
7386 
7387         if (numlines) {
7388                 info = TALLOC_ARRAY(mem_ctx, union spoolss_PortInfo, numlines);
7389                 if (!info) {
7390                         DEBUG(10,("Returning WERR_NOMEM\n"));
7391                         result = WERR_NOMEM;
7392                         goto out;
7393                 }
7394 
7395                 for (i=0; i<numlines; i++) {
7396                         DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
7397                         result = fill_port_2(info, &info[i].info2, qlines[i]);
7398                         if (!W_ERROR_IS_OK(result)) {
7399                                 goto out;
7400                         }
7401                 }
7402         }
7403         TALLOC_FREE(qlines);
7404 
7405 out:
7406         if (!W_ERROR_IS_OK(result)) {
7407                 TALLOC_FREE(info);
7408                 TALLOC_FREE(qlines);
7409                 *count = 0;
7410                 *info_p = NULL;
7411                 return result;
7412         }
7413 
7414         *info_p = info;
7415         *count = numlines;
7416 
7417         return WERR_OK;
7418 }
7419 
7420 /****************************************************************
7421  _spoolss_EnumPorts
7422 ****************************************************************/
7423 
7424 WERROR _spoolss_EnumPorts(pipes_struct *p,
     /* [<][>][^][v][top][bottom][index][help] */
7425                           struct spoolss_EnumPorts *r)
7426 {
7427         WERROR result;
7428 
7429         /* that's an [in out] buffer */
7430 
7431         if (!r->in.buffer && (r->in.offered != 0)) {
7432                 return WERR_INVALID_PARAM;
7433         }
7434 
7435         DEBUG(4,("_spoolss_EnumPorts\n"));
7436 
7437         *r->out.count = 0;
7438         *r->out.needed = 0;
7439         *r->out.info = NULL;
7440 
7441         switch (r->in.level) {
7442         case 1:
7443                 result = enumports_level_1(p->mem_ctx, r->out.info,
7444                                            r->out.count);
7445                 break;
7446         case 2:
7447                 result = enumports_level_2(p->mem_ctx, r->out.info,
7448                                            r->out.count);
7449                 break;
7450         default:
7451                 return WERR_UNKNOWN_LEVEL;
7452         }
7453 
7454         if (!W_ERROR_IS_OK(result)) {
7455                 return result;
7456         }
7457 
7458         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
7459                                                      spoolss_EnumPorts, NULL,
7460                                                      *r->out.info, r->in.level,
7461                                                      *r->out.count);
7462         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
7463         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
7464 
7465         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
7466 }
7467 
7468 /****************************************************************************
7469 ****************************************************************************/
7470 
7471 static WERROR spoolss_addprinterex_level_2(pipes_struct *p,
     /* [<][>][^][v][top][bottom][index][help] */
7472                                            const char *server,
7473                                            struct spoolss_SetPrinterInfoCtr *info_ctr,
7474                                            struct spoolss_DeviceMode *devmode,
7475                                            struct security_descriptor *sec_desc,
7476                                            struct spoolss_UserLevelCtr *user_ctr,
7477                                            struct policy_handle *handle)
7478 {
7479         NT_PRINTER_INFO_LEVEL *printer = NULL;
7480         fstring name;
7481         int     snum;
7482         WERROR err = WERR_OK;
7483 
7484         if ( !(printer = TALLOC_ZERO_P(NULL, NT_PRINTER_INFO_LEVEL)) ) {
7485                 DEBUG(0,("spoolss_addprinterex_level_2: malloc fail.\n"));
7486                 return WERR_NOMEM;
7487         }
7488 
7489         /* convert from UNICODE to ASCII - this allocates the info_2 struct inside *printer.*/
7490         if (!convert_printer_info(info_ctr, printer)) {
7491                 free_a_printer(&printer, 2);
7492                 return WERR_NOMEM;
7493         }
7494 
7495         /* check to see if the printer already exists */
7496 
7497         if ((snum = print_queue_snum(printer->info_2->sharename)) != -1) {
7498                 DEBUG(5, ("spoolss_addprinterex_level_2: Attempted to add a printer named [%s] when one already existed!\n",
7499                         printer->info_2->sharename));
7500                 free_a_printer(&printer, 2);
7501                 return WERR_PRINTER_ALREADY_EXISTS;
7502         }
7503 
7504         /* FIXME!!!  smbd should check to see if the driver is installed before
7505            trying to add a printer like this  --jerry */
7506 
7507         if (*lp_addprinter_cmd() ) {
7508                 if ( !add_printer_hook(p->mem_ctx, p->server_info->ptok,
7509                                        printer) ) {
7510                         free_a_printer(&printer,2);
7511                         return WERR_ACCESS_DENIED;
7512                 }
7513         } else {
7514                 DEBUG(0,("spoolss_addprinterex_level_2: add printer for printer %s called and no"
7515                         "smb.conf parameter \"addprinter command\" is defined. This"
7516                         "parameter must exist for this call to succeed\n",
7517                         printer->info_2->sharename ));
7518         }
7519 
7520         /* use our primary netbios name since get_a_printer() will convert
7521            it to what the client expects on a case by case basis */
7522 
7523         slprintf(name, sizeof(name)-1, "\\\\%s\\%s", global_myname(),
7524              printer->info_2->sharename);
7525 
7526 
7527         if ((snum = print_queue_snum(printer->info_2->sharename)) == -1) {
7528                 free_a_printer(&printer,2);
7529                 return WERR_ACCESS_DENIED;
7530         }
7531 
7532         /* you must be a printer admin to add a new printer */
7533         if (!print_access_check(p->server_info, snum, PRINTER_ACCESS_ADMINISTER)) {
7534                 free_a_printer(&printer,2);
7535                 return WERR_ACCESS_DENIED;
7536         }
7537 
7538         /*
7539          * Do sanity check on the requested changes for Samba.
7540          */
7541 
7542         if (!check_printer_ok(printer->info_2, snum)) {
7543                 free_a_printer(&printer,2);
7544                 return WERR_INVALID_PARAM;
7545         }
7546 
7547         /*
7548          * When a printer is created, the drivername bound to the printer is used
7549          * to lookup previously saved driver initialization info, which is then
7550          * bound to the new printer, simulating what happens in the Windows arch.
7551          */
7552 
7553         if (!devmode)
7554         {
7555                 set_driver_init(printer, 2);
7556         }
7557         else
7558         {
7559                 /* A valid devmode was included, convert and link it
7560                 */
7561                 DEBUGADD(10, ("spoolss_addprinterex_level_2: devmode included, converting\n"));
7562 
7563                 if (!convert_devicemode(printer->info_2->printername, devmode,
7564                                         &printer->info_2->devmode)) {
7565                         return  WERR_NOMEM;
7566                 }
7567         }
7568 
7569         /* write the ASCII on disk */
7570         err = mod_a_printer(printer, 2);
7571         if (!W_ERROR_IS_OK(err)) {
7572                 free_a_printer(&printer,2);
7573                 return err;
7574         }
7575 
7576         if (!open_printer_hnd(p, handle, name, PRINTER_ACCESS_ADMINISTER)) {
7577                 /* Handle open failed - remove addition. */
7578                 del_a_printer(printer->info_2->sharename);
7579                 free_a_printer(&printer,2);
7580                 ZERO_STRUCTP(handle);
7581                 return WERR_ACCESS_DENIED;
7582         }
7583 
7584         update_c_setprinter(false);
7585         free_a_printer(&printer,2);
7586 
7587         return WERR_OK;
7588 }
7589 
7590 /****************************************************************
7591  _spoolss_AddPrinterEx
7592 ****************************************************************/
7593 
7594 WERROR _spoolss_AddPrinterEx(pipes_struct *p,
     /* [<][>][^][v][top][bottom][index][help] */
7595                              struct spoolss_AddPrinterEx *r)
7596 {
7597         switch (r->in.info_ctr->level) {
7598         case 1:
7599                 /* we don't handle yet */
7600                 /* but I know what to do ... */
7601                 return WERR_UNKNOWN_LEVEL;
7602         case 2:
7603                 return spoolss_addprinterex_level_2(p, r->in.server,
7604                                                     r->in.info_ctr,
7605                                                     r->in.devmode_ctr->devmode,
7606                                                     r->in.secdesc_ctr->sd,
7607                                                     r->in.userlevel_ctr,
7608                                                     r->out.handle);
7609         default:
7610                 return WERR_UNKNOWN_LEVEL;
7611         }
7612 }
7613 
7614 /****************************************************************
7615  _spoolss_AddPrinterDriver
7616 ****************************************************************/
7617 
7618 WERROR _spoolss_AddPrinterDriver(pipes_struct *p,
     /* [<][>][^][v][top][bottom][index][help] */
7619                                  struct spoolss_AddPrinterDriver *r)
7620 {
7621         uint32_t level = r->in.info_ctr->level;
7622         struct spoolss_AddDriverInfoCtr *info = r->in.info_ctr;
7623         WERROR err = WERR_OK;
7624         NT_PRINTER_DRIVER_INFO_LEVEL driver;
7625         const char *driver_name = NULL;
7626         uint32_t version;
7627         const char *fn;
7628 
7629         switch (p->hdr_req.opnum) {
7630                 case NDR_SPOOLSS_ADDPRINTERDRIVER:
7631                         fn = "_spoolss_AddPrinterDriver";
7632                         break;
7633                 case NDR_SPOOLSS_ADDPRINTERDRIVEREX:
7634                         fn = "_spoolss_AddPrinterDriverEx";
7635                         break;
7636                 default:
7637                         return WERR_INVALID_PARAM;
7638         }
7639 
7640 
7641         /* FIXME */
7642         if (level != 3 && level != 6) {
7643                 /* Clever hack from Martin Zielinski <mz@seh.de>
7644                  * to allow downgrade from level 8 (Vista).
7645                  */
7646                 DEBUG(0,("%s: level %d not yet implemented\n", fn, level));
7647                 return WERR_UNKNOWN_LEVEL;
7648         }
7649 
7650         ZERO_STRUCT(driver);
7651 
7652         if (!convert_printer_driver_info(info, &driver, level)) {
7653                 err = WERR_NOMEM;
7654                 goto done;
7655         }
7656 
7657         DEBUG(5,("Cleaning driver's information\n"));
7658         err = clean_up_driver_struct(p, driver, level);
7659         if (!W_ERROR_IS_OK(err))
7660                 goto done;
7661 
7662         DEBUG(5,("Moving driver to final destination\n"));
7663         if( !W_ERROR_IS_OK(err = move_driver_to_download_area(p, driver, level,
7664                                                               &err)) ) {
7665                 goto done;
7666         }
7667 
7668         if (add_a_printer_driver(driver, level)!=0) {
7669                 err = WERR_ACCESS_DENIED;
7670                 goto done;
7671         }
7672 
7673         switch(level) {
7674         case 3:
7675                 driver_name = driver.info_3->name ? driver.info_3->name : "";
7676                 break;
7677         case 6:
7678                 driver_name = driver.info_6->name ? driver.info_6->name : "";
7679                 break;
7680         }
7681 
7682         /*
7683          * I think this is where he DrvUpgradePrinter() hook would be
7684          * be called in a driver's interface DLL on a Windows NT 4.0/2k
7685          * server.  Right now, we just need to send ourselves a message
7686          * to update each printer bound to this driver.   --jerry
7687          */
7688 
7689         if (!srv_spoolss_drv_upgrade_printer(driver_name)) {
7690                 DEBUG(0,("%s: Failed to send message about upgrading driver [%s]!\n",
7691                         fn, driver_name));
7692         }
7693 
7694         /*
7695          * Based on the version (e.g. driver destination dir: 0=9x,2=Nt/2k,3=2k/Xp),
7696          * decide if the driver init data should be deleted. The rules are:
7697          *  1) never delete init data if it is a 9x driver, they don't use it anyway
7698          *  2) delete init data only if there is no 2k/Xp driver
7699          *  3) always delete init data
7700          * The generalized rule is always use init data from the highest order driver.
7701          * It is necessary to follow the driver install by an initialization step to
7702          * finish off this process.
7703         */
7704         if (level == 3)
7705                 version = driver.info_3->cversion;
7706         else if (level == 6)
7707                 version = driver.info_6->version;
7708         else
7709                 version = -1;
7710         switch (version) {
7711                 /*
7712                  * 9x printer driver - never delete init data
7713                 */
7714                 case 0:
7715                         DEBUG(10,("%s: init data not deleted for 9x driver [%s]\n",
7716                                 fn, driver_name));
7717                         break;
7718 
7719                 /*
7720                  * Nt or 2k (compatiblity mode) printer driver - only delete init data if
7721                  * there is no 2k/Xp driver init data for this driver name.
7722                 */
7723                 case 2:
7724                 {
7725                         NT_PRINTER_DRIVER_INFO_LEVEL driver1;
7726 
7727                         if (!W_ERROR_IS_OK(get_a_printer_driver(&driver1, 3, driver_name, "Windows NT x86", 3))) {
7728                                 /*
7729                                  * No 2k/Xp driver found, delete init data (if any) for the new Nt driver.
7730                                 */
7731                                 if (!del_driver_init(driver_name))
7732                                         DEBUG(6,("%s: del_driver_init(%s) Nt failed!\n",
7733                                                 fn, driver_name));
7734                         } else {
7735                                 /*
7736                                  * a 2k/Xp driver was found, don't delete init data because Nt driver will use it.
7737                                 */
7738                                 free_a_printer_driver(driver1,3);
7739                                 DEBUG(10,("%s: init data not deleted for Nt driver [%s]\n",
7740                                         fn, driver_name));
7741                         }
7742                 }
7743                 break;
7744 
7745                 /*
7746                  * 2k or Xp printer driver - always delete init data
7747                 */
7748                 case 3:
7749                         if (!del_driver_init(driver_name))
7750                                 DEBUG(6,("%s: del_driver_init(%s) 2k/Xp failed!\n",
7751                                         fn, driver_name));
7752                         break;
7753 
7754                 default:
7755                         DEBUG(0,("%s: invalid level=%d\n", fn, level));
7756                         break;
7757         }
7758 
7759 
7760 done:
7761         free_a_printer_driver(driver, level);
7762         return err;
7763 }
7764 
7765 /****************************************************************
7766  _spoolss_AddPrinterDriverEx
7767 ****************************************************************/
7768 
7769 WERROR _spoolss_AddPrinterDriverEx(pipes_struct *p,
     /* [<][>][^][v][top][bottom][index][help] */
7770                                    struct spoolss_AddPrinterDriverEx *r)
7771 {
7772         struct spoolss_AddPrinterDriver a;
7773 
7774         /*
7775          * we only support the semantics of AddPrinterDriver()
7776          * i.e. only copy files that are newer than existing ones
7777          */
7778 
7779         if (r->in.flags != APD_COPY_NEW_FILES) {
7780                 return WERR_ACCESS_DENIED;
7781         }
7782 
7783         a.in.servername         = r->in.servername;
7784         a.in.info_ctr           = r->in.info_ctr;
7785 
7786         return _spoolss_AddPrinterDriver(p, &a);
7787 }
7788 
7789 /****************************************************************************
7790 ****************************************************************************/
7791 
7792 struct _spoolss_paths {
7793         int type;
7794         const char *share;
7795         const char *dir;
7796 };
7797 
7798 enum { SPOOLSS_DRIVER_PATH, SPOOLSS_PRTPROCS_PATH };
7799 
7800 static const struct _spoolss_paths spoolss_paths[]= {
7801         { SPOOLSS_DRIVER_PATH,          "print$",       "DRIVERS" },
7802         { SPOOLSS_PRTPROCS_PATH,        "prnproc$",     "PRTPROCS" }
7803 };
7804 
7805 static WERROR compose_spoolss_server_path(TALLOC_CTX *mem_ctx,
     /* [<][>][^][v][top][bottom][index][help] */
7806                                           const char *servername,
7807                                           const char *environment,
7808                                           int component,
7809                                           char **path)
7810 {
7811         const char *pservername = NULL;
7812         const char *long_archi = SPOOLSS_ARCHITECTURE_NT_X86;
7813         const char *short_archi;
7814 
7815         *path = NULL;
7816 
7817         /* environment may be empty */
7818         if (environment && strlen(environment)) {
7819                 long_archi = environment;
7820         }
7821 
7822         /* servername may be empty */
7823         if (servername && strlen(servername)) {
7824                 pservername = canon_servername(servername);
7825 
7826                 if (!is_myname_or_ipaddr(pservername)) {
7827                         return WERR_INVALID_PARAM;
7828                 }
7829         }
7830 
7831         if (!(short_archi = get_short_archi(long_archi))) {
7832                 return WERR_INVALID_ENVIRONMENT;
7833         }
7834 
7835         switch (component) {
7836         case SPOOLSS_PRTPROCS_PATH:
7837         case SPOOLSS_DRIVER_PATH:
7838                 if (pservername) {
7839                         *path = talloc_asprintf(mem_ctx,
7840                                         "\\\\%s\\%s\\%s",
7841                                         pservername,
7842                                         spoolss_paths[component].share,
7843                                         short_archi);
7844                 } else {
7845                         *path = talloc_asprintf(mem_ctx, "%s\\%s\\%s",
7846                                         SPOOLSS_DEFAULT_SERVER_PATH,
7847                                         spoolss_paths[component].dir,
7848                                         short_archi);
7849                 }
7850                 break;
7851         default:
7852                 return WERR_INVALID_PARAM;
7853         }
7854 
7855         if (!*path) {
7856                 return WERR_NOMEM;
7857         }
7858 
7859         return WERR_OK;
7860 }
7861 
7862 /****************************************************************************
7863 ****************************************************************************/
7864 
7865 static WERROR getprinterdriverdir_level_1(TALLOC_CTX *mem_ctx,
     /* [<][>][^][v][top][bottom][index][help] */
7866                                           const char *servername,
7867                                           const char *environment,
7868                                           struct spoolss_DriverDirectoryInfo1 *r)
7869 {
7870         WERROR werr;
7871         char *path = NULL;
7872 
7873         werr = compose_spoolss_server_path(mem_ctx,
7874                                            servername,
7875                                            environment,
7876                                            SPOOLSS_DRIVER_PATH,
7877                                            &path);
7878         if (!W_ERROR_IS_OK(werr)) {
7879                 return werr;
7880         }
7881 
7882         DEBUG(4,("printer driver directory: [%s]\n", path));
7883 
7884         r->directory_name = path;
7885 
7886         return WERR_OK;
7887 }
7888 
7889 /****************************************************************
7890  _spoolss_GetPrinterDriverDirectory
7891 ****************************************************************/
7892 
7893 WERROR _spoolss_GetPrinterDriverDirectory(pipes_struct *p,
     /* [<][>][^][v][top][bottom][index][help] */
7894                                           struct spoolss_GetPrinterDriverDirectory *r)
7895 {
7896         WERROR werror;
7897 
7898         /* that's an [in out] buffer */
7899 
7900         if (!r->in.buffer && (r->in.offered != 0)) {
7901                 return WERR_INVALID_PARAM;
7902         }
7903 
7904         DEBUG(5,("_spoolss_GetPrinterDriverDirectory: level %d\n",
7905                 r->in.level));
7906 
7907         *r->out.needed = 0;
7908 
7909         /* r->in.level is ignored */
7910 
7911         werror = getprinterdriverdir_level_1(p->mem_ctx,
7912                                              r->in.server,
7913                                              r->in.environment,
7914                                              &r->out.info->info1);
7915         if (!W_ERROR_IS_OK(werror)) {
7916                 TALLOC_FREE(r->out.info);
7917                 return werror;
7918         }
7919 
7920         *r->out.needed  = SPOOLSS_BUFFER_UNION(spoolss_DriverDirectoryInfo, NULL,
7921                                                r->out.info, r->in.level);
7922         r->out.info     = SPOOLSS_BUFFER_OK(r->out.info, NULL);
7923 
7924         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
7925 }
7926 
7927 /****************************************************************
7928  _spoolss_EnumPrinterData
7929 ****************************************************************/
7930 
7931 WERROR _spoolss_EnumPrinterData(pipes_struct *p,
     /* [<][>][^][v][top][bottom][index][help] */
7932                                 struct spoolss_EnumPrinterData *r)
7933 {
7934         NT_PRINTER_INFO_LEVEL *printer = NULL;
7935         Printer_entry   *Printer = find_printer_index_by_hnd(p, r->in.handle);
7936         int             snum;
7937         WERROR          result;
7938         REGISTRY_VALUE  *val = NULL;
7939         NT_PRINTER_DATA *p_data;
7940         int             i, key_index, num_values;
7941         int             name_length;
7942 
7943         *r->out.value_needed    = 0;
7944         *r->out.type            = REG_NONE;
7945         *r->out.data_needed     = 0;
7946 
7947         DEBUG(5,("_spoolss_EnumPrinterData\n"));
7948 
7949         if (!Printer) {
7950                 DEBUG(2,("_spoolss_EnumPrinterData: Invalid handle (%s:%u:%u).\n",
7951                         OUR_HANDLE(r->in.handle)));
7952                 return WERR_BADFID;
7953         }
7954 
7955         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
7956                 return WERR_BADFID;
7957         }
7958 
7959         result = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
7960         if (!W_ERROR_IS_OK(result)) {
7961                 return result;
7962         }
7963 
7964         p_data = printer->info_2->data;
7965         key_index = lookup_printerkey( p_data, SPOOL_PRINTERDATA_KEY );
7966 
7967         result = WERR_OK;
7968 
7969         /*
7970          * The NT machine wants to know the biggest size of value and data
7971          *
7972          * cf: MSDN EnumPrinterData remark section
7973          */
7974 
7975         if (!r->in.value_offered && !r->in.data_offered && (key_index != -1)) {
7976 
7977                 uint32_t biggest_valuesize = 0;
7978                 uint32_t biggest_datasize = 0;
7979 
7980                 DEBUGADD(6,("Activating NT mega-hack to find sizes\n"));
7981 
7982                 num_values = regval_ctr_numvals( p_data->keys[key_index].values );
7983 
7984                 for ( i=0; i<num_values; i++ )
7985                 {
7986                         val = regval_ctr_specific_value( p_data->keys[key_index].values, i );
7987 
7988                         name_length = strlen(val->valuename);
7989                         if ( strlen(val->valuename) > biggest_valuesize )
7990                                 biggest_valuesize = name_length;
7991 
7992                         if ( val->size > biggest_datasize )
7993                                 biggest_datasize = val->size;
7994 
7995                         DEBUG(6,("current values: [%d], [%d]\n", biggest_valuesize,
7996                                 biggest_datasize));
7997                 }
7998 
7999                 /* the value is an UNICODE string but real_value_size is the length
8000                    in bytes including the trailing 0 */
8001 
8002                 *r->out.value_needed = 2 * (1 + biggest_valuesize);
8003                 *r->out.data_needed  = biggest_datasize;
8004 
8005                 DEBUG(6,("final values: [%d], [%d]\n",
8006                         *r->out.value_needed, *r->out.data_needed));
8007 
8008                 goto done;
8009         }
8010 
8011         /*
8012          * the value len is wrong in NT sp3
8013          * that's the number of bytes not the number of unicode chars
8014          */
8015 
8016         if (key_index != -1) {
8017                 val = regval_ctr_specific_value(p_data->keys[key_index].values,
8018                                                 r->in.enum_index);
8019         }
8020 
8021         if (!val) {
8022 
8023                 /* out_value should default to "" or else NT4 has
8024                    problems unmarshalling the response */
8025 
8026                 if (r->in.value_offered) {
8027                         *r->out.value_needed = 1;
8028                         r->out.value_name = talloc_strdup(r, "");
8029                         if (!r->out.value_name) {
8030                                 result = WERR_NOMEM;
8031                                 goto done;
8032                         }
8033                 } else {
8034                         r->out.value_name = NULL;
8035                         *r->out.value_needed = 0;
8036                 }
8037 
8038                 /* the data is counted in bytes */
8039 
8040                 *r->out.data_needed = r->in.data_offered;
8041 
8042                 result = WERR_NO_MORE_ITEMS;
8043         } else {
8044                 /*
8045                  * the value is:
8046                  * - counted in bytes in the request
8047                  * - counted in UNICODE chars in the max reply
8048                  * - counted in bytes in the real size
8049                  *
8050                  * take a pause *before* coding not *during* coding
8051                  */
8052 
8053                 /* name */
8054                 if (r->in.value_offered) {
8055                         r->out.value_name = talloc_strdup(r, regval_name(val));
8056                         if (!r->out.value_name) {
8057                                 result = WERR_NOMEM;
8058                                 goto done;
8059                         }
8060                         *r->out.value_needed = strlen_m(regval_name(val));
8061                 } else {
8062                         r->out.value_name = NULL;
8063                         *r->out.value_needed = 0;
8064                 }
8065 
8066                 /* type */
8067 
8068                 *r->out.type = regval_type(val);
8069 
8070                 /* data - counted in bytes */
8071 
8072                 if (r->out.data && regval_size(val)) {
8073                         memcpy(r->out.data, regval_data_p(val), regval_size(val));
8074                 }
8075 
8076                 *r->out.data_needed = regval_size(val);
8077         }
8078 
8079 done:
8080         free_a_printer(&printer, 2);
8081         return result;
8082 }
8083 
8084 /****************************************************************
8085  _spoolss_SetPrinterData
8086 ****************************************************************/
8087 
8088 WERROR _spoolss_SetPrinterData(pipes_struct *p,
     /* [<][>][^][v][top][bottom][index][help] */
8089                                struct spoolss_SetPrinterData *r)
8090 {
8091         NT_PRINTER_INFO_LEVEL *printer = NULL;
8092         int snum=0;
8093         WERROR result = WERR_OK;
8094         Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
8095         DATA_BLOB blob;
8096 
8097         DEBUG(5,("_spoolss_SetPrinterData\n"));
8098 
8099         if (!Printer) {
8100                 DEBUG(2,("_spoolss_SetPrinterData: Invalid handle (%s:%u:%u).\n",
8101                         OUR_HANDLE(r->in.handle)));
8102                 return WERR_BADFID;
8103         }
8104 
8105         if (Printer->printer_type == SPLHND_SERVER) {
8106                 DEBUG(10,("_spoolss_SetPrinterData: "
8107                         "Not implemented for server handles yet\n"));
8108                 return WERR_INVALID_PARAM;
8109         }
8110 
8111         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
8112                 return WERR_BADFID;
8113         }
8114 
8115         /*
8116          * Access check : NT returns "access denied" if you make a
8117          * SetPrinterData call without the necessary privildge.
8118          * we were originally returning OK if nothing changed
8119          * which made Win2k issue **a lot** of SetPrinterData
8120          * when connecting to a printer  --jerry
8121          */
8122 
8123         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
8124                 DEBUG(3,("_spoolss_SetPrinterData: "
8125                         "change denied by handle access permissions\n"));
8126                 result = WERR_ACCESS_DENIED;
8127                 goto done;
8128         }
8129 
8130         result = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8131         if (!W_ERROR_IS_OK(result)) {
8132                 return result;
8133         }
8134 
8135         result = push_spoolss_PrinterData(p->mem_ctx, &blob,
8136                                           r->in.type, &r->in.data);
8137         if (!W_ERROR_IS_OK(result)) {
8138                 goto done;
8139         }
8140 
8141         /*
8142          * When client side code sets a magic printer data key, detect it and save
8143          * the current printer data and the magic key's data (its the DEVMODE) for
8144          * future printer/driver initializations.
8145          */
8146         if ((r->in.type == REG_BINARY) && strequal(r->in.value_name, PHANTOM_DEVMODE_KEY)) {
8147                 /* Set devmode and printer initialization info */
8148                 result = save_driver_init(printer, 2, blob.data, blob.length);
8149 
8150                 srv_spoolss_reset_printerdata(printer->info_2->drivername);
8151 
8152                 goto done;
8153         }
8154 
8155         result = set_printer_dataex(printer, SPOOL_PRINTERDATA_KEY,
8156                                     r->in.value_name, r->in.type,
8157                                     blob.data, blob.length);
8158         if (W_ERROR_IS_OK(result)) {
8159                 result = mod_a_printer(printer, 2);
8160         }
8161 
8162 done:
8163         free_a_printer(&printer, 2);
8164 
8165         return result;
8166 }
8167 
8168 /****************************************************************
8169  _spoolss_ResetPrinter
8170 ****************************************************************/
8171 
8172 WERROR _spoolss_ResetPrinter(pipes_struct *p,
     /* [<][>][^][v][top][bottom][index][help] */
8173                              struct spoolss_ResetPrinter *r)
8174 {
8175         Printer_entry   *Printer = find_printer_index_by_hnd(p, r->in.handle);
8176         int             snum;
8177 
8178         DEBUG(5,("_spoolss_ResetPrinter\n"));
8179 
8180         /*
8181          * All we do is to check to see if the handle and queue is valid.
8182          * This call really doesn't mean anything to us because we only
8183          * support RAW printing.   --jerry
8184          */
8185 
8186         if (!Printer) {
8187                 DEBUG(2,("_spoolss_ResetPrinter: Invalid handle (%s:%u:%u).\n",
8188                         OUR_HANDLE(r->in.handle)));
8189                 return WERR_BADFID;
8190         }
8191 
8192         if (!get_printer_snum(p, r->in.handle, &snum, NULL))
8193                 return WERR_BADFID;
8194 
8195 
8196         /* blindly return success */
8197         return WERR_OK;
8198 }
8199 
8200 /****************************************************************
8201  _spoolss_DeletePrinterData
8202 ****************************************************************/
8203 
8204 WERROR _spoolss_DeletePrinterData(pipes_struct *p,
     /* [<][>][^][v][top][bottom][index][help] */
8205                                   struct spoolss_DeletePrinterData *r)
8206 {
8207         NT_PRINTER_INFO_LEVEL   *printer = NULL;
8208         int             snum=0;
8209         WERROR          status = WERR_OK;
8210         Printer_entry   *Printer = find_printer_index_by_hnd(p, r->in.handle);
8211 
8212         DEBUG(5,("_spoolss_DeletePrinterData\n"));
8213 
8214         if (!Printer) {
8215                 DEBUG(2,("_spoolss_DeletePrinterData: Invalid handle (%s:%u:%u).\n",
8216                         OUR_HANDLE(r->in.handle)));
8217                 return WERR_BADFID;
8218         }
8219 
8220         if (!get_printer_snum(p, r->in.handle, &snum, NULL))
8221                 return WERR_BADFID;
8222 
8223         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
8224                 DEBUG(3, ("_spoolss_DeletePrinterData: "
8225                         "printer properties change denied by handle\n"));
8226                 return WERR_ACCESS_DENIED;
8227         }
8228 
8229         status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8230         if (!W_ERROR_IS_OK(status))
8231                 return status;
8232 
8233         if (!r->in.value_name) {
8234                 free_a_printer(&printer, 2);
8235                 return WERR_NOMEM;
8236         }
8237 
8238         status = delete_printer_dataex( printer, SPOOL_PRINTERDATA_KEY,
8239                                         r->in.value_name );
8240 
8241         if ( W_ERROR_IS_OK(status) )
8242                 mod_a_printer( printer, 2 );
8243 
8244         free_a_printer(&printer, 2);
8245 
8246         return status;
8247 }
8248 
8249 /****************************************************************
8250  _spoolss_AddForm
8251 ****************************************************************/
8252 
8253 WERROR _spoolss_AddForm(pipes_struct *p,
     /* [<][>][^][v][top][bottom][index][help] */
8254                         struct spoolss_AddForm *r)
8255 {
8256         struct spoolss_AddFormInfo1 *form = r->in.info.info1;
8257         nt_forms_struct tmpForm;
8258         int snum = -1;
8259         WERROR status = WERR_OK;
8260         NT_PRINTER_INFO_LEVEL *printer = NULL;
8261         SE_PRIV se_printop = SE_PRINT_OPERATOR;
8262 
8263         int count=0;
8264         nt_forms_struct *list=NULL;
8265         Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
8266 
8267         DEBUG(5,("_spoolss_AddForm\n"));
8268 
8269         if (!Printer) {
8270                 DEBUG(2,("_spoolss_AddForm: Invalid handle (%s:%u:%u).\n",
8271                         OUR_HANDLE(r->in.handle)));
8272                 return WERR_BADFID;
8273         }
8274 
8275 
8276         /* forms can be added on printer of on the print server handle */
8277 
8278         if ( Printer->printer_type == SPLHND_PRINTER )
8279         {
8280                 if (!get_printer_snum(p, r->in.handle, &snum, NULL))
8281                         return WERR_BADFID;
8282 
8283                 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8284                 if (!W_ERROR_IS_OK(status))
8285                         goto done;
8286         }
8287 
8288         /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
8289            and not a printer admin, then fail */
8290 
8291         if ((p->server_info->utok.uid != sec_initial_uid()) &&
8292              !user_has_privileges(p->server_info->ptok, &se_printop) &&
8293              !token_contains_name_in_list(uidtoname(p->server_info->utok.uid),
8294                                           NULL, NULL,
8295                                           p->server_info->ptok,
8296                                           lp_printer_admin(snum))) {
8297                 DEBUG(2,("_spoolss_Addform: denied by insufficient permissions.\n"));
8298                 return WERR_ACCESS_DENIED;
8299         }
8300 
8301         /* can't add if builtin */
8302 
8303         if (get_a_builtin_ntform_by_string(form->form_name, &tmpForm)) {
8304                 status = WERR_FILE_EXISTS;
8305                 goto done;
8306         }
8307 
8308         count = get_ntforms(&list);
8309 
8310         if(!add_a_form(&list, form, &count)) {
8311                 status =  WERR_NOMEM;
8312                 goto done;
8313         }
8314 
8315         become_root();
8316         write_ntforms(&list, count);
8317         unbecome_root();
8318 
8319         /*
8320          * ChangeID must always be set if this is a printer
8321          */
8322 
8323         if ( Printer->printer_type == SPLHND_PRINTER )
8324                 status = mod_a_printer(printer, 2);
8325 
8326 done:
8327         if ( printer )
8328                 free_a_printer(&printer, 2);
8329         SAFE_FREE(list);
8330 
8331         return status;
8332 }
8333 
8334 /****************************************************************
8335  _spoolss_DeleteForm
8336 ****************************************************************/
8337 
8338 WERROR _spoolss_DeleteForm(pipes_struct *p,
     /* [<][>][^][v][top][bottom][index][help] */
8339                            struct spoolss_DeleteForm *r)
8340 {
8341         const char *form_name = r->in.form_name;
8342         nt_forms_struct tmpForm;
8343         int count=0;
8344         nt_forms_struct *list=NULL;
8345         Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
8346         int snum = -1;
8347         WERROR status = WERR_OK;
8348         NT_PRINTER_INFO_LEVEL *printer = NULL;
8349         SE_PRIV se_printop = SE_PRINT_OPERATOR;
8350         bool ret = false;
8351 
8352         DEBUG(5,("_spoolss_DeleteForm\n"));
8353 
8354         if (!Printer) {
8355                 DEBUG(2,("_spoolss_DeleteForm: Invalid handle (%s:%u:%u).\n",
8356                         OUR_HANDLE(r->in.handle)));
8357                 return WERR_BADFID;
8358         }
8359 
8360         /* forms can be deleted on printer of on the print server handle */
8361 
8362         if ( Printer->printer_type == SPLHND_PRINTER )
8363         {
8364                 if (!get_printer_snum(p, r->in.handle, &snum, NULL))
8365                         return WERR_BADFID;
8366 
8367                 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8368                 if (!W_ERROR_IS_OK(status))
8369                         goto done;
8370         }
8371 
8372         if ((p->server_info->utok.uid != sec_initial_uid()) &&
8373              !user_has_privileges(p->server_info->ptok, &se_printop) &&
8374              !token_contains_name_in_list(uidtoname(p->server_info->utok.uid),
8375                                           NULL, NULL,
8376                                           p->server_info->ptok,
8377                                           lp_printer_admin(snum))) {
8378                 DEBUG(2,("_spoolss_DeleteForm: denied by insufficient permissions.\n"));
8379                 return WERR_ACCESS_DENIED;
8380         }
8381 
8382 
8383         /* can't delete if builtin */
8384 
8385         if (get_a_builtin_ntform_by_string(form_name,&tmpForm)) {
8386                 status = WERR_INVALID_PARAM;
8387                 goto done;
8388         }
8389 
8390         count = get_ntforms(&list);
8391 
8392         become_root();
8393         ret = delete_a_form(&list, form_name, &count, &status);
8394         unbecome_root();
8395         if (ret == false) {
8396                 goto done;
8397         }
8398 
8399         /*
8400          * ChangeID must always be set if this is a printer
8401          */
8402 
8403         if ( Printer->printer_type == SPLHND_PRINTER )
8404                 status = mod_a_printer(printer, 2);
8405 
8406 done:
8407         if ( printer )
8408                 free_a_printer(&printer, 2);
8409         SAFE_FREE(list);
8410 
8411         return status;
8412 }
8413 
8414 /****************************************************************
8415  _spoolss_SetForm
8416 ****************************************************************/
8417 
8418 WERROR _spoolss_SetForm(pipes_struct *p,
     /* [<][>][^][v][top][bottom][index][help] */
8419                         struct spoolss_SetForm *r)
8420 {
8421         struct spoolss_AddFormInfo1 *form = r->in.info.info1;
8422         nt_forms_struct tmpForm;
8423         int snum = -1;
8424         WERROR status = WERR_OK;
8425         NT_PRINTER_INFO_LEVEL *printer = NULL;
8426         SE_PRIV se_printop = SE_PRINT_OPERATOR;
8427 
8428         int count=0;
8429         nt_forms_struct *list=NULL;
8430         Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
8431 
8432         DEBUG(5,("_spoolss_SetForm\n"));
8433 
8434         if (!Printer) {
8435                 DEBUG(2,("_spoolss_SetForm: Invalid handle (%s:%u:%u).\n",
8436                         OUR_HANDLE(r->in.handle)));
8437                 return WERR_BADFID;
8438         }
8439 
8440         /* forms can be modified on printer of on the print server handle */
8441 
8442         if ( Printer->printer_type == SPLHND_PRINTER )
8443         {
8444                 if (!get_printer_snum(p, r->in.handle, &snum, NULL))
8445                         return WERR_BADFID;
8446 
8447                 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8448                 if (!W_ERROR_IS_OK(status))
8449                         goto done;
8450         }
8451 
8452         /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
8453            and not a printer admin, then fail */
8454 
8455         if ((p->server_info->utok.uid != sec_initial_uid()) &&
8456              !user_has_privileges(p->server_info->ptok, &se_printop) &&
8457              !token_contains_name_in_list(uidtoname(p->server_info->utok.uid),
8458                                           NULL, NULL,
8459                                           p->server_info->ptok,
8460                                           lp_printer_admin(snum))) {
8461                 DEBUG(2,("_spoolss_Setform: denied by insufficient permissions.\n"));
8462                 return WERR_ACCESS_DENIED;
8463         }
8464 
8465         /* can't set if builtin */
8466         if (get_a_builtin_ntform_by_string(form->form_name, &tmpForm)) {
8467                 status = WERR_INVALID_PARAM;
8468                 goto done;
8469         }
8470 
8471         count = get_ntforms(&list);
8472         update_a_form(&list, form, count);
8473         become_root();
8474         write_ntforms(&list, count);
8475         unbecome_root();
8476 
8477         /*
8478          * ChangeID must always be set if this is a printer
8479          */
8480 
8481         if ( Printer->printer_type == SPLHND_PRINTER )
8482                 status = mod_a_printer(printer, 2);
8483 
8484 
8485 done:
8486         if ( printer )
8487                 free_a_printer(&printer, 2);
8488         SAFE_FREE(list);
8489 
8490         return status;
8491 }
8492 
8493 /****************************************************************************
8494  fill_print_processor1
8495 ****************************************************************************/
8496 
8497 static WERROR fill_print_processor1(TALLOC_CTX *mem_ctx,
     /* [<][>][^][v][top][bottom][index][help] */
8498                                     struct spoolss_PrintProcessorInfo1 *r,
8499                                     const char *print_processor_name)
8500 {
8501         r->print_processor_name = talloc_strdup(mem_ctx, print_processor_name);
8502         W_ERROR_HAVE_NO_MEMORY(r->print_processor_name);
8503 
8504         return WERR_OK;
8505 }
8506 
8507 /****************************************************************************
8508  enumprintprocessors level 1.
8509 ****************************************************************************/
8510 
8511 static WERROR enumprintprocessors_level_1(TALLOC_CTX *mem_ctx,
     /* [<][>][^][v][top][bottom][index][help] */
8512                                           union spoolss_PrintProcessorInfo **info_p,
8513                                           uint32_t *count)
8514 {
8515         union spoolss_PrintProcessorInfo *info;
8516         WERROR result;
8517 
8518         info = TALLOC_ARRAY(mem_ctx, union spoolss_PrintProcessorInfo, 1);
8519         W_ERROR_HAVE_NO_MEMORY(info);
8520 
8521         *count = 1;
8522 
8523         result = fill_print_processor1(info, &info[0].info1, "winprint");
8524         if (!W_ERROR_IS_OK(result)) {
8525                 goto out;
8526         }
8527 
8528  out:
8529         if (!W_ERROR_IS_OK(result)) {
8530                 TALLOC_FREE(info);
8531                 *count = 0;
8532                 return result;
8533         }
8534 
8535         *info_p = info;
8536 
8537         return WERR_OK;
8538 }
8539 
8540 /****************************************************************
8541  _spoolss_EnumPrintProcessors
8542 ****************************************************************/
8543 
8544 WERROR _spoolss_EnumPrintProcessors(pipes_struct *p,
     /* [<][>][^][v][top][bottom][index][help] */
8545                                     struct spoolss_EnumPrintProcessors *r)
8546 {
8547         WERROR result;
8548 
8549         /* that's an [in out] buffer */
8550 
8551         if (!r->in.buffer && (r->in.offered != 0)) {
8552                 return WERR_INVALID_PARAM;
8553         }
8554 
8555         DEBUG(5,("_spoolss_EnumPrintProcessors\n"));
8556 
8557         /*
8558          * Enumerate the print processors ...
8559          *
8560          * Just reply with "winprint", to keep NT happy
8561          * and I can use my nice printer checker.
8562          */
8563 
8564         *r->out.count = 0;
8565         *r->out.needed = 0;
8566         *r->out.info = NULL;
8567 
8568         switch (r->in.level) {
8569         case 1:
8570                 result = enumprintprocessors_level_1(p->mem_ctx, r->out.info,
8571                                                      r->out.count);
8572                 break;
8573         default:
8574                 return WERR_UNKNOWN_LEVEL;
8575         }
8576 
8577         if (!W_ERROR_IS_OK(result)) {
8578                 return result;
8579         }
8580 
8581         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
8582                                                      spoolss_EnumPrintProcessors, NULL,
8583                                                      *r->out.info, r->in.level,
8584                                                      *r->out.count);
8585         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
8586         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
8587 
8588         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
8589 }
8590 
8591 /****************************************************************************
8592  fill_printprocdatatype1
8593 ****************************************************************************/
8594 
8595 static WERROR fill_printprocdatatype1(TALLOC_CTX *mem_ctx,
     /* [<][>][^][v][top][bottom][index][help] */
8596                                       struct spoolss_PrintProcDataTypesInfo1 *r,
8597                                       const char *name_array)
8598 {
8599         r->name_array = talloc_strdup(mem_ctx, name_array);
8600         W_ERROR_HAVE_NO_MEMORY(r->name_array);
8601 
8602         return WERR_OK;
8603 }
8604 
8605 /****************************************************************************
8606  enumprintprocdatatypes level 1.
8607 ****************************************************************************/
8608 
8609 static WERROR enumprintprocdatatypes_level_1(TALLOC_CTX *mem_ctx,
     /* [<][>][^][v][top][bottom][index][help] */
8610                                              union spoolss_PrintProcDataTypesInfo **info_p,
8611                                              uint32_t *count)
8612 {
8613         WERROR result;
8614         union spoolss_PrintProcDataTypesInfo *info;
8615 
8616         info = TALLOC_ARRAY(mem_ctx, union spoolss_PrintProcDataTypesInfo, 1);
8617         W_ERROR_HAVE_NO_MEMORY(info);
8618 
8619         *count = 1;
8620 
8621         result = fill_printprocdatatype1(info, &info[0].info1, "RAW");
8622         if (!W_ERROR_IS_OK(result)) {
8623                 goto out;
8624         }
8625 
8626  out:
8627         if (!W_ERROR_IS_OK(result)) {
8628                 TALLOC_FREE(info);
8629                 *count = 0;
8630                 return result;
8631         }
8632 
8633         *info_p = info;
8634 
8635         return WERR_OK;
8636 }
8637 
8638 /****************************************************************
8639  _spoolss_EnumPrintProcDataTypes
8640 ****************************************************************/
8641 
8642 WERROR _spoolss_EnumPrintProcDataTypes(pipes_struct *p,
     /* [<][>][^][v][top][bottom][index][help] */
8643                                        struct spoolss_EnumPrintProcDataTypes *r)
8644 {
8645         WERROR result;
8646 
8647         /* that's an [in out] buffer */
8648 
8649         if (!r->in.buffer && (r->in.offered != 0)) {
8650                 return WERR_INVALID_PARAM;
8651         }
8652 
8653         DEBUG(5,("_spoolss_EnumPrintProcDataTypes\n"));
8654 
8655         *r->out.count = 0;
8656         *r->out.needed = 0;
8657         *r->out.info = NULL;
8658 
8659         switch (r->in.level) {
8660         case 1:
8661                 result = enumprintprocdatatypes_level_1(p->mem_ctx, r->out.info,
8662                                                         r->out.count);
8663                 break;
8664         default:
8665                 return WERR_UNKNOWN_LEVEL;
8666         }
8667 
8668         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
8669                                                      spoolss_EnumPrintProcDataTypes, NULL,
8670                                                      *r->out.info, r->in.level,
8671                                                      *r->out.count);
8672         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
8673         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
8674 
8675         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
8676 }
8677 
8678 /****************************************************************************
8679  fill_monitor_1
8680 ****************************************************************************/
8681 
8682 static WERROR fill_monitor_1(TALLOC_CTX *mem_ctx,
     /* [<][>][^][v][top][bottom][index][help] */
8683                              struct spoolss_MonitorInfo1 *r,
8684                              const char *monitor_name)
8685 {
8686         r->monitor_name                 = talloc_strdup(mem_ctx, monitor_name);
8687         W_ERROR_HAVE_NO_MEMORY(r->monitor_name);
8688 
8689         return WERR_OK;
8690 }
8691 
8692 /****************************************************************************
8693  fill_monitor_2
8694 ****************************************************************************/
8695 
8696 static WERROR fill_monitor_2(TALLOC_CTX *mem_ctx,
     /* [<][>][^][v][top][bottom][index][help] */
8697                              struct spoolss_MonitorInfo2 *r,
8698                              const char *monitor_name,
8699                              const char *environment,
8700                              const char *dll_name)
8701 {
8702         r->monitor_name                 = talloc_strdup(mem_ctx, monitor_name);
8703         W_ERROR_HAVE_NO_MEMORY(r->monitor_name);
8704         r->environment                  = talloc_strdup(mem_ctx, environment);
8705         W_ERROR_HAVE_NO_MEMORY(r->environment);
8706         r->dll_name                     = talloc_strdup(mem_ctx, dll_name);
8707         W_ERROR_HAVE_NO_MEMORY(r->dll_name);
8708 
8709         return WERR_OK;
8710 }
8711 
8712 /****************************************************************************
8713  enumprintmonitors level 1.
8714 ****************************************************************************/
8715 
8716 static WERROR enumprintmonitors_level_1(TALLOC_CTX *mem_ctx,
     /* [<][>][^][v][top][bottom][index][help] */
8717                                         union spoolss_MonitorInfo **info_p,
8718                                         uint32_t *count)
8719 {
8720         union spoolss_MonitorInfo *info;
8721         WERROR result = WERR_OK;
8722 
8723         info = TALLOC_ARRAY(mem_ctx, union spoolss_MonitorInfo, 2);
8724         W_ERROR_HAVE_NO_MEMORY(info);
8725 
8726         *count = 2;
8727 
8728         result = fill_monitor_1(info, &info[0].info1,
8729                                 SPL_LOCAL_PORT);
8730         if (!W_ERROR_IS_OK(result)) {
8731                 goto out;
8732         }
8733 
8734         result = fill_monitor_1(info, &info[1].info1,
8735                                 SPL_TCPIP_PORT);
8736         if (!W_ERROR_IS_OK(result)) {
8737                 goto out;
8738         }
8739 
8740 out:
8741         if (!W_ERROR_IS_OK(result)) {
8742                 TALLOC_FREE(info);
8743                 *count = 0;
8744                 return result;
8745         }
8746 
8747         *info_p = info;
8748 
8749         return WERR_OK;
8750 }
8751 
8752 /****************************************************************************
8753  enumprintmonitors level 2.
8754 ****************************************************************************/
8755 
8756 static WERROR enumprintmonitors_level_2(TALLOC_CTX *mem_ctx,
     /* [<][>][^][v][top][bottom][index][help] */
8757                                         union spoolss_MonitorInfo **info_p,
8758                                         uint32_t *count)
8759 {
8760         union spoolss_MonitorInfo *info;
8761         WERROR result = WERR_OK;
8762 
8763         info = TALLOC_ARRAY(mem_ctx, union spoolss_MonitorInfo, 2);
8764         W_ERROR_HAVE_NO_MEMORY(info);
8765 
8766         *count = 2;
8767 
8768         result = fill_monitor_2(info, &info[0].info2,
8769                                 SPL_LOCAL_PORT,
8770                                 "Windows NT X86", /* FIXME */
8771                                 "localmon.dll");
8772         if (!W_ERROR_IS_OK(result)) {
8773                 goto out;
8774         }
8775 
8776         result = fill_monitor_2(info, &info[1].info2,
8777                                 SPL_TCPIP_PORT,
8778                                 "Windows NT X86", /* FIXME */
8779                                 "tcpmon.dll");
8780         if (!W_ERROR_IS_OK(result)) {
8781                 goto out;
8782         }
8783 
8784 out:
8785         if (!W_ERROR_IS_OK(result)) {
8786                 TALLOC_FREE(info);
8787                 *count = 0;
8788                 return result;
8789         }
8790 
8791         *info_p = info;
8792 
8793         return WERR_OK;
8794 }
8795 
8796 /****************************************************************
8797  _spoolss_EnumMonitors
8798 ****************************************************************/
8799 
8800 WERROR _spoolss_EnumMonitors(pipes_struct *p,
     /* [<][>][^][v][top][bottom][index][help] */
8801                              struct spoolss_EnumMonitors *r)
8802 {
8803         WERROR result;
8804 
8805         /* that's an [in out] buffer */
8806 
8807         if (!r->in.buffer && (r->in.offered != 0)) {
8808                 return WERR_INVALID_PARAM;
8809         }
8810 
8811         DEBUG(5,("_spoolss_EnumMonitors\n"));
8812 
8813         /*
8814          * Enumerate the print monitors ...
8815          *
8816          * Just reply with "Local Port", to keep NT happy
8817          * and I can use my nice printer checker.
8818          */
8819 
8820         *r->out.count = 0;
8821         *r->out.needed = 0;
8822         *r->out.info = NULL;
8823 
8824         switch (r->in.level) {
8825         case 1:
8826                 result = enumprintmonitors_level_1(p->mem_ctx, r->out.info,
8827                                                    r->out.count);
8828                 break;
8829         case 2:
8830                 result = enumprintmonitors_level_2(p->mem_ctx, r->out.info,
8831                                                    r->out.count);
8832                 break;
8833         default:
8834                 return WERR_UNKNOWN_LEVEL;
8835         }
8836 
8837         if (!W_ERROR_IS_OK(result)) {
8838                 return result;
8839         }
8840 
8841         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
8842                                                      spoolss_EnumMonitors, NULL,
8843                                                      *r->out.info, r->in.level,
8844                                                      *r->out.count);
8845         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
8846         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
8847 
8848         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
8849 }
8850 
8851 /****************************************************************************
8852 ****************************************************************************/
8853 
8854 static WERROR getjob_level_1(TALLOC_CTX *mem_ctx,
     /* [<][>][^][v][top][bottom][index][help] */
8855                              const print_queue_struct *queue,
8856                              int count, int snum,
8857                              const NT_PRINTER_INFO_LEVEL *ntprinter,
8858                              uint32_t jobid,
8859                              struct spoolss_JobInfo1 *r)
8860 {
8861         int i = 0;
8862         bool found = false;
8863 
8864         for (i=0; i<count && found == false; i++) {
8865                 if (queue[i].job == (int)jobid) {
8866                         found = true;
8867                 }
8868         }
8869 
8870         if (found == false) {
8871                 /* NT treats not found as bad param... yet another bad choice */
8872                 return WERR_INVALID_PARAM;
8873         }
8874 
8875         return fill_job_info1(mem_ctx,
8876                               r,
8877                               &queue[i-1],
8878                               i,
8879                               snum,
8880                               ntprinter);
8881 }
8882 
8883 /****************************************************************************
8884 ****************************************************************************/
8885 
8886 static WERROR getjob_level_2(TALLOC_CTX *mem_ctx,
     /* [<][>][^][v][top][bottom][index][help] */
8887                              const print_queue_struct *queue,
8888                              int count, int snum,
8889                              const NT_PRINTER_INFO_LEVEL *ntprinter,
8890                              uint32_t jobid,
8891                              struct spoolss_JobInfo2 *r)
8892 {
8893         int i = 0;
8894         bool found = false;
8895         struct spoolss_DeviceMode *devmode;
8896         NT_DEVICEMODE *nt_devmode;
8897         WERROR result;
8898 
8899         for (i=0; i<count && found == false; i++) {
8900                 if (queue[i].job == (int)jobid) {
8901                         found = true;
8902                 }
8903         }
8904 
8905         if (found == false) {
8906                 /* NT treats not found as bad param... yet another bad
8907                    choice */
8908                 return WERR_INVALID_PARAM;
8909         }
8910 
8911         /*
8912          * if the print job does not have a DEVMODE associated with it,
8913          * just use the one for the printer. A NULL devicemode is not
8914          *  a failure condition
8915          */
8916 
8917         nt_devmode = print_job_devmode(lp_const_servicename(snum), jobid);
8918         if (nt_devmode) {
8919                 devmode = TALLOC_ZERO_P(mem_ctx, struct spoolss_DeviceMode);
8920                 W_ERROR_HAVE_NO_MEMORY(devmode);
8921                 result = convert_nt_devicemode(devmode, devmode, nt_devmode);
8922                 if (!W_ERROR_IS_OK(result)) {
8923                         return result;
8924                 }
8925         } else {
8926                 devmode = construct_dev_mode(mem_ctx, lp_const_servicename(snum));
8927                 W_ERROR_HAVE_NO_MEMORY(devmode);
8928         }
8929 
8930         return fill_job_info2(mem_ctx,
8931                               r,
8932                               &queue[i-1],
8933                               i,
8934                               snum,
8935                               ntprinter,
8936                               devmode);
8937 }
8938 
8939 /****************************************************************
8940  _spoolss_GetJob
8941 ****************************************************************/
8942 
8943 WERROR _spoolss_GetJob(pipes_struct *p,
     /* [<][>][^][v][top][bottom][index][help] */
8944                        struct spoolss_GetJob *r)
8945 {
8946         WERROR result = WERR_OK;
8947         NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
8948         int snum;
8949         int count;
8950         print_queue_struct      *queue = NULL;
8951         print_status_struct prt_status;
8952 
8953         /* that's an [in out] buffer */
8954 
8955         if (!r->in.buffer && (r->in.offered != 0)) {
8956                 return WERR_INVALID_PARAM;
8957         }
8958 
8959         DEBUG(5,("_spoolss_GetJob\n"));
8960 
8961         *r->out.needed = 0;
8962 
8963         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
8964                 return WERR_BADFID;
8965         }
8966 
8967         result = get_a_printer(NULL, &ntprinter, 2, lp_servicename(snum));
8968         if (!W_ERROR_IS_OK(result)) {
8969                 return result;
8970         }
8971 
8972         count = print_queue_status(snum, &queue, &prt_status);
8973 
8974         DEBUGADD(4,("count:[%d], prt_status:[%d], [%s]\n",
8975                      count, prt_status.status, prt_status.message));
8976 
8977         switch (r->in.level) {
8978         case 1:
8979                 result = getjob_level_1(p->mem_ctx,
8980                                         queue, count, snum, ntprinter,
8981                                         r->in.job_id, &r->out.info->info1);
8982                 break;
8983         case 2:
8984                 result = getjob_level_2(p->mem_ctx,
8985                                         queue, count, snum, ntprinter,
8986                                         r->in.job_id, &r->out.info->info2);
8987                 break;
8988         default:
8989                 result = WERR_UNKNOWN_LEVEL;
8990                 break;
8991         }
8992 
8993         SAFE_FREE(queue);
8994         free_a_printer(&ntprinter, 2);
8995 
8996         if (!W_ERROR_IS_OK(result)) {
8997                 TALLOC_FREE(r->out.info);
8998                 return result;
8999         }
9000 
9001         *r->out.needed  = SPOOLSS_BUFFER_UNION(spoolss_JobInfo, NULL,
9002                                                r->out.info, r->in.level);
9003         r->out.info     = SPOOLSS_BUFFER_OK(r->out.info, NULL);
9004 
9005         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
9006 }
9007 
9008 /****************************************************************
9009  _spoolss_GetPrinterDataEx
9010 
9011  From MSDN documentation of GetPrinterDataEx: pass request
9012  to GetPrinterData if key is "PrinterDriverData".
9013 ****************************************************************/
9014 
9015 WERROR _spoolss_GetPrinterDataEx(pipes_struct *p,
     /* [<][>][^][v][top][bottom][index][help] */
9016                                  struct spoolss_GetPrinterDataEx *r)
9017 {
9018 
9019         Printer_entry   *Printer = find_printer_index_by_hnd(p, r->in.handle);
9020         REGISTRY_VALUE          *val = NULL;
9021         NT_PRINTER_INFO_LEVEL   *printer = NULL;
9022         int                     snum = 0;
9023         WERROR result = WERR_OK;
9024 
9025         DEBUG(4,("_spoolss_GetPrinterDataEx\n"));
9026 
9027         DEBUG(10, ("_spoolss_GetPrinterDataEx: key => [%s], value => [%s]\n",
9028                 r->in.key_name, r->in.value_name));
9029 
9030         /* in case of problem, return some default values */
9031 
9032         *r->out.needed  = 0;
9033         *r->out.type    = REG_NONE;
9034 
9035         if (!Printer) {
9036                 DEBUG(2,("_spoolss_GetPrinterDataEx: Invalid handle (%s:%u:%u).\n",
9037                         OUR_HANDLE(r->in.handle)));
9038                 result = WERR_BADFID;
9039                 goto done;
9040         }
9041 
9042         /* Is the handle to a printer or to the server? */
9043 
9044         if (Printer->printer_type == SPLHND_SERVER) {
9045                 DEBUG(10,("_spoolss_GetPrinterDataEx: "
9046                         "Not implemented for server handles yet\n"));
9047                 result = WERR_INVALID_PARAM;
9048                 goto done;
9049         }
9050 
9051         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9052                 return WERR_BADFID;
9053         }
9054 
9055         result = get_a_printer(Printer, &printer, 2, lp_servicename(snum));
9056         if (!W_ERROR_IS_OK(result)) {
9057                 goto done;
9058         }
9059 
9060         /* check to see if the keyname is valid */
9061         if (!strlen(r->in.key_name)) {
9062                 result = WERR_INVALID_PARAM;
9063                 goto done;
9064         }
9065 
9066         if (lookup_printerkey(printer->info_2->data, r->in.key_name) == -1) {
9067                 DEBUG(4,("_spoolss_GetPrinterDataEx: "
9068                         "Invalid keyname [%s]\n", r->in.key_name ));
9069                 result = WERR_BADFILE;
9070                 goto done;
9071         }
9072 
9073         /* When given a new keyname, we should just create it */
9074 
9075         val = get_printer_data(printer->info_2,
9076                                r->in.key_name, r->in.value_name);
9077         if (!val) {
9078                 result = WERR_BADFILE;
9079                 goto done;
9080         }
9081 
9082         *r->out.needed = regval_size(val);
9083 
9084         if (*r->out.needed > r->in.offered) {
9085                 result = WERR_MORE_DATA;
9086                 goto done;
9087         }
9088 
9089         *r->out.type = regval_type(val);
9090 
9091         memcpy(r->out.buffer, regval_data_p(val), regval_size(val));
9092 
9093  done:
9094         if (printer) {
9095                 free_a_printer(&printer, 2);
9096         }
9097 
9098         return result;
9099 }
9100 
9101 /****************************************************************
9102  _spoolss_SetPrinterDataEx
9103 ****************************************************************/
9104 
9105 WERROR _spoolss_SetPrinterDataEx(pipes_struct *p,
     /* [<][>][^][v][top][bottom][index][help] */
9106                                  struct spoolss_SetPrinterDataEx *r)
9107 {
9108         NT_PRINTER_INFO_LEVEL   *printer = NULL;
9109         int                     snum = 0;
9110         WERROR                  result = WERR_OK;
9111         Printer_entry           *Printer = find_printer_index_by_hnd(p, r->in.handle);
9112         char                    *oid_string;
9113 
9114         DEBUG(4,("_spoolss_SetPrinterDataEx\n"));
9115 
9116         /* From MSDN documentation of SetPrinterDataEx: pass request to
9117            SetPrinterData if key is "PrinterDriverData" */
9118 
9119         if (!Printer) {
9120                 DEBUG(2,("_spoolss_SetPrinterDataEx: Invalid handle (%s:%u:%u).\n",
9121                         OUR_HANDLE(r->in.handle)));
9122                 return WERR_BADFID;
9123         }
9124 
9125         if (Printer->printer_type == SPLHND_SERVER) {
9126                 DEBUG(10,("_spoolss_SetPrinterDataEx: "
9127                         "Not implemented for server handles yet\n"));
9128                 return WERR_INVALID_PARAM;
9129         }
9130 
9131         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9132                 return WERR_BADFID;
9133         }
9134 
9135         /*
9136          * Access check : NT returns "access denied" if you make a
9137          * SetPrinterData call without the necessary privildge.
9138          * we were originally returning OK if nothing changed
9139          * which made Win2k issue **a lot** of SetPrinterData
9140          * when connecting to a printer  --jerry
9141          */
9142 
9143         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
9144                 DEBUG(3, ("_spoolss_SetPrinterDataEx: "
9145                         "change denied by handle access permissions\n"));
9146                 return WERR_ACCESS_DENIED;
9147         }
9148 
9149         result = get_a_printer(Printer, &printer, 2, lp_servicename(snum));
9150         if (!W_ERROR_IS_OK(result)) {
9151                 return result;
9152         }
9153 
9154         /* check for OID in valuename */
9155 
9156         oid_string = strchr(r->in.value_name, ',');
9157         if (oid_string) {
9158                 *oid_string = '\0';
9159                 oid_string++;
9160         }
9161 
9162         /* save the registry data */
9163 
9164         result = set_printer_dataex(printer, r->in.key_name, r->in.value_name,
9165                                     r->in.type, r->in.buffer, r->in.offered);
9166 
9167         if (W_ERROR_IS_OK(result)) {
9168                 /* save the OID if one was specified */
9169                 if (oid_string) {
9170                         char *str = talloc_asprintf(p->mem_ctx, "%s\\%s",
9171                                 r->in.key_name, SPOOL_OID_KEY);
9172                         if (!str) {
9173                                 result = WERR_NOMEM;
9174                                 goto done;
9175                         }
9176 
9177                         /*
9178                          * I'm not checking the status here on purpose.  Don't know
9179                          * if this is right, but I'm returning the status from the
9180                          * previous set_printer_dataex() call.  I have no idea if
9181                          * this is right.    --jerry
9182                          */
9183 
9184                         set_printer_dataex(printer, str, r->in.value_name,
9185                                            REG_SZ, (uint8_t *)oid_string,
9186                                            strlen(oid_string)+1);
9187                 }
9188 
9189                 result = mod_a_printer(printer, 2);
9190         }
9191 
9192  done:
9193         free_a_printer(&printer, 2);
9194 
9195         return result;
9196 }
9197 
9198 /****************************************************************
9199  _spoolss_DeletePrinterDataEx
9200 ****************************************************************/
9201 
9202 WERROR _spoolss_DeletePrinterDataEx(pipes_struct *p,
     /* [<][>][^][v][top][bottom][index][help] */
9203                                     struct spoolss_DeletePrinterDataEx *r)
9204 {
9205         NT_PRINTER_INFO_LEVEL   *printer = NULL;
9206         int             snum=0;
9207         WERROR          status = WERR_OK;
9208         Printer_entry   *Printer = find_printer_index_by_hnd(p, r->in.handle);
9209 
9210         DEBUG(5,("_spoolss_DeletePrinterDataEx\n"));
9211 
9212         if (!Printer) {
9213                 DEBUG(2,("_spoolss_DeletePrinterDataEx: "
9214                         "Invalid handle (%s:%u:%u).\n",
9215                         OUR_HANDLE(r->in.handle)));
9216                 return WERR_BADFID;
9217         }
9218 
9219         if (!get_printer_snum(p, r->in.handle, &snum, NULL))
9220                 return WERR_BADFID;
9221 
9222         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
9223                 DEBUG(3, ("_spoolss_DeletePrinterDataEx: "
9224                         "printer properties change denied by handle\n"));
9225                 return WERR_ACCESS_DENIED;
9226         }
9227 
9228         if (!r->in.value_name || !r->in.key_name) {
9229                 return WERR_NOMEM;
9230         }
9231 
9232         status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
9233         if (!W_ERROR_IS_OK(status))
9234                 return status;
9235 
9236         status = delete_printer_dataex( printer, r->in.key_name, r->in.value_name );
9237 
9238         if ( W_ERROR_IS_OK(status) )
9239                 mod_a_printer( printer, 2 );
9240 
9241         free_a_printer(&printer, 2);
9242 
9243         return status;
9244 }
9245 
9246 /****************************************************************
9247  _spoolss_EnumPrinterKey
9248 ****************************************************************/
9249 
9250 WERROR _spoolss_EnumPrinterKey(pipes_struct *p,
     /* [<][>][^][v][top][bottom][index][help] */
9251                                struct spoolss_EnumPrinterKey *r)
9252 {
9253         fstring         *keynames = NULL;
9254         int             num_keys;
9255         Printer_entry   *Printer = find_printer_index_by_hnd(p, r->in.handle);
9256         NT_PRINTER_DATA *data;
9257         NT_PRINTER_INFO_LEVEL   *printer = NULL;
9258         int             snum = 0;
9259         WERROR          result = WERR_BADFILE;
9260         int i;
9261         const char **array = NULL;
9262 
9263 
9264         DEBUG(4,("_spoolss_EnumPrinterKey\n"));
9265 
9266         if (!Printer) {
9267                 DEBUG(2,("_spoolss_EnumPrinterKey: Invalid handle (%s:%u:%u).\n",
9268                         OUR_HANDLE(r->in.handle)));
9269                 return WERR_BADFID;
9270         }
9271 
9272         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9273                 return WERR_BADFID;
9274         }
9275 
9276         result = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
9277         if (!W_ERROR_IS_OK(result)) {
9278                 return result;
9279         }
9280 
9281         /* get the list of subkey names */
9282 
9283         data = printer->info_2->data;
9284 
9285         num_keys = get_printer_subkeys(data, r->in.key_name, &keynames);
9286         if (num_keys == -1) {
9287                 result = WERR_BADFILE;
9288                 goto done;
9289         }
9290 
9291         *r->out.needed = 4;
9292 
9293         array = talloc_zero_array(r->out.key_buffer, const char *, num_keys + 1);
9294         if (!array) {
9295                 result = WERR_NOMEM;
9296                 goto done;
9297         }
9298 
9299         for (i=0; i < num_keys; i++) {
9300                 array[i] = talloc_strdup(array, keynames[i]);
9301                 if (!array[i]) {
9302                         result = WERR_NOMEM;
9303                         goto done;
9304                 }
9305 
9306                 *r->out.needed += strlen_m_term(keynames[i]) * 2;
9307         }
9308 
9309         if (r->in.offered < *r->out.needed) {
9310                 result = WERR_MORE_DATA;
9311                 goto done;
9312         }
9313 
9314         result = WERR_OK;
9315 
9316         *r->out.key_buffer = array;
9317 
9318  done:
9319         if (!W_ERROR_IS_OK(result)) {
9320                 TALLOC_FREE(array);
9321                 ZERO_STRUCTP(r->out.key_buffer);
9322         }
9323 
9324         free_a_printer(&printer, 2);
9325         SAFE_FREE(keynames);
9326 
9327         return result;
9328 }
9329 
9330 /****************************************************************
9331  _spoolss_DeletePrinterKey
9332 ****************************************************************/
9333 
9334 WERROR _spoolss_DeletePrinterKey(pipes_struct *p,
     /* [<][>][^][v][top][bottom][index][help] */
9335                                  struct spoolss_DeletePrinterKey *r)
9336 {
9337         Printer_entry           *Printer = find_printer_index_by_hnd(p, r->in.handle);
9338         NT_PRINTER_INFO_LEVEL   *printer = NULL;
9339         int                     snum=0;
9340         WERROR                  status;
9341 
9342         DEBUG(5,("_spoolss_DeletePrinterKey\n"));
9343 
9344         if (!Printer) {
9345                 DEBUG(2,("_spoolss_DeletePrinterKey: Invalid handle (%s:%u:%u).\n",
9346                         OUR_HANDLE(r->in.handle)));
9347                 return WERR_BADFID;
9348         }
9349 
9350         /* if keyname == NULL, return error */
9351 
9352         if ( !r->in.key_name )
9353                 return WERR_INVALID_PARAM;
9354 
9355         if (!get_printer_snum(p, r->in.handle, &snum, NULL))
9356                 return WERR_BADFID;
9357 
9358         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
9359                 DEBUG(3, ("_spoolss_DeletePrinterKey: "
9360                         "printer properties change denied by handle\n"));
9361                 return WERR_ACCESS_DENIED;
9362         }
9363 
9364         status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
9365         if (!W_ERROR_IS_OK(status))
9366                 return status;
9367 
9368         /* delete the key and all subneys */
9369 
9370         status = delete_all_printer_data( printer->info_2, r->in.key_name );
9371 
9372         if ( W_ERROR_IS_OK(status) )
9373                 status = mod_a_printer(printer, 2);
9374 
9375         free_a_printer( &printer, 2 );
9376 
9377         return status;
9378 }
9379 
9380 /****************************************************************
9381 ****************************************************************/
9382 
9383 static WERROR registry_value_to_printer_enum_value(TALLOC_CTX *mem_ctx,
     /* [<][>][^][v][top][bottom][index][help] */
9384                                                    REGISTRY_VALUE *v,
9385                                                    struct spoolss_PrinterEnumValues *r)
9386 {
9387         WERROR result;
9388 
9389         r->data = TALLOC_ZERO_P(mem_ctx, union spoolss_PrinterData);
9390         W_ERROR_HAVE_NO_MEMORY(r->data);
9391 
9392         r->value_name   = talloc_strdup(mem_ctx, regval_name(v));
9393         W_ERROR_HAVE_NO_MEMORY(r->value_name);
9394 
9395         r->type         = regval_type(v);
9396         r->data_length  = regval_size(v);
9397 
9398         if (r->data_length) {
9399                 DATA_BLOB blob = data_blob_const(regval_data_p(v),
9400                                                  regval_size(v));
9401                 result = pull_spoolss_PrinterData(mem_ctx, &blob,
9402                                                   r->data,
9403                                                   r->type);
9404                 if (!W_ERROR_IS_OK(result)) {
9405                         return result;
9406                 }
9407         }
9408 
9409         return WERR_OK;
9410 }
9411 
9412 /****************************************************************
9413  _spoolss_EnumPrinterDataEx
9414 ****************************************************************/
9415 
9416 WERROR _spoolss_EnumPrinterDataEx(pipes_struct *p,
     /* [<][>][^][v][top][bottom][index][help] */
9417                                   struct spoolss_EnumPrinterDataEx *r)
9418 {
9419         uint32_t        count = 0;
9420         NT_PRINTER_INFO_LEVEL   *printer = NULL;
9421         struct spoolss_PrinterEnumValues *info = NULL;
9422         NT_PRINTER_DATA         *p_data;
9423         Printer_entry   *Printer = find_printer_index_by_hnd(p, r->in.handle);
9424         int             snum;
9425         WERROR          result;
9426         int             key_index;
9427         int             i;
9428 
9429         DEBUG(4,("_spoolss_EnumPrinterDataEx\n"));
9430 
9431         *r->out.count = 0;
9432         *r->out.needed = 0;
9433         *r->out.info = NULL;
9434 
9435         if (!Printer) {
9436                 DEBUG(2,("_spoolss_EnumPrinterDataEx: Invalid handle (%s:%u:%u1<).\n",
9437                         OUR_HANDLE(r->in.handle)));
9438                 return WERR_BADFID;
9439         }
9440 
9441         /*
9442          * first check for a keyname of NULL or "".  Win2k seems to send
9443          * this a lot and we should send back WERR_INVALID_PARAM
9444          * no need to spend time looking up the printer in this case.
9445          * --jerry
9446          */
9447 
9448         if (!strlen(r->in.key_name)) {
9449                 result = WERR_INVALID_PARAM;
9450                 goto done;
9451         }
9452 
9453         /* get the printer off of disk */
9454 
9455         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9456                 return WERR_BADFID;
9457         }
9458 
9459         ZERO_STRUCT(printer);
9460         result = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
9461         if (!W_ERROR_IS_OK(result)) {
9462                 return result;
9463         }
9464 
9465         /* now look for a match on the key name */
9466 
9467         p_data = printer->info_2->data;
9468 
9469         key_index = lookup_printerkey(p_data, r->in.key_name);
9470         if (key_index == -1) {
9471                 DEBUG(10,("_spoolss_EnumPrinterDataEx: Unknown keyname [%s]\n",
9472                         r->in.key_name));
9473                 result = WERR_INVALID_PARAM;
9474                 goto done;
9475         }
9476 
9477         /* allocate the memory for the array of pointers -- if necessary */
9478 
9479         count = regval_ctr_numvals(p_data->keys[key_index].values);
9480         if (!count) {
9481                 result = WERR_OK; /* ??? */
9482                 goto done;
9483         }
9484 
9485         info = TALLOC_ZERO_ARRAY(p->mem_ctx,
9486                                  struct spoolss_PrinterEnumValues,
9487                                  count);
9488         if (!info) {
9489                 DEBUG(0,("_spoolss_EnumPrinterDataEx: talloc() failed\n"));
9490                 result = WERR_NOMEM;
9491                 goto done;
9492         }
9493 
9494         /*
9495          * loop through all params and build the array to pass
9496          * back to the  client
9497          */
9498 
9499         for (i=0; i < count; i++) {
9500 
9501                 REGISTRY_VALUE  *val;
9502 
9503                 /* lookup the registry value */
9504 
9505                 val = regval_ctr_specific_value(p_data->keys[key_index].values, i);
9506 
9507                 DEBUG(10,("retrieved value number [%d] [%s]\n", i, regval_name(val)));
9508 
9509                 /* copy the data */
9510 
9511                 result = registry_value_to_printer_enum_value(info, val, &info[i]);
9512                 if (!W_ERROR_IS_OK(result)) {
9513                         goto done;
9514                 }
9515         }
9516 
9517 #if 0 /* FIXME - gd */
9518         /* housekeeping information in the reply */
9519 
9520         /* Fix from Martin Zielinski <mz@seh.de> - ensure
9521          * the hand marshalled container size is a multiple
9522          * of 4 bytes for RPC alignment.
9523          */
9524 
9525         if (needed % 4) {
9526                 needed += 4-(needed % 4);
9527         }
9528 #endif
9529         *r->out.count   = count;
9530         *r->out.info    = info;
9531 
9532  done:
9533 
9534         if (printer) {
9535                 free_a_printer(&printer, 2);
9536         }
9537 
9538         if (!W_ERROR_IS_OK(result)) {
9539                 return result;
9540         }
9541 
9542         *r->out.needed  = SPOOLSS_BUFFER_ARRAY(p->mem_ctx,
9543                                                spoolss_EnumPrinterDataEx, NULL,
9544                                                *r->out.info,
9545                                                *r->out.count);
9546         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
9547         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, *r->out.count);
9548 
9549         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_MORE_DATA);
9550 }
9551 
9552 /****************************************************************************
9553 ****************************************************************************/
9554 
9555 static WERROR getprintprocessordirectory_level_1(TALLOC_CTX *mem_ctx,
     /* [<][>][^][v][top][bottom][index][help] */
9556                                                  const char *servername,
9557                                                  const char *environment,
9558                                                  struct spoolss_PrintProcessorDirectoryInfo1 *r)
9559 {
9560         WERROR werr;
9561         char *path = NULL;
9562 
9563         werr = compose_spoolss_server_path(mem_ctx,
9564                                            servername,
9565                                            environment,
9566                                            SPOOLSS_PRTPROCS_PATH,
9567                                            &path);
9568         if (!W_ERROR_IS_OK(werr)) {
9569                 return werr;
9570         }
9571 
9572         DEBUG(4,("print processor directory: [%s]\n", path));
9573 
9574         r->directory_name = path;
9575 
9576         return WERR_OK;
9577 }
9578 
9579 /****************************************************************
9580  _spoolss_GetPrintProcessorDirectory
9581 ****************************************************************/
9582 
9583 WERROR _spoolss_GetPrintProcessorDirectory(pipes_struct *p,
     /* [<][>][^][v][top][bottom][index][help] */
9584                                            struct spoolss_GetPrintProcessorDirectory *r)
9585 {
9586         WERROR result;
9587 
9588         /* that's an [in out] buffer */
9589 
9590         if (!r->in.buffer && (r->in.offered != 0)) {
9591                 return WERR_INVALID_PARAM;
9592         }
9593 
9594         DEBUG(5,("_spoolss_GetPrintProcessorDirectory: level %d\n",
9595                 r->in.level));
9596 
9597         *r->out.needed = 0;
9598 
9599         /* r->in.level is ignored */
9600 
9601         /* We always should reply with a local print processor directory so that
9602          * users are not forced to have a [prnproc$] share on the Samba spoolss
9603          * server - Guenther */
9604 
9605         result = getprintprocessordirectory_level_1(p->mem_ctx,
9606                                                     NULL, /* r->in.server */
9607                                                     r->in.environment,
9608                                                     &r->out.info->info1);
9609         if (!W_ERROR_IS_OK(result)) {
9610                 TALLOC_FREE(r->out.info);
9611                 return result;
9612         }
9613 
9614         *r->out.needed  = SPOOLSS_BUFFER_UNION(spoolss_PrintProcessorDirectoryInfo, NULL,
9615                                                r->out.info, r->in.level);
9616         r->out.info     = SPOOLSS_BUFFER_OK(r->out.info, NULL);
9617 
9618         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
9619 }
9620 
9621 /*******************************************************************
9622  ********************************************************************/
9623 
9624 static bool push_monitorui_buf(TALLOC_CTX *mem_ctx, DATA_BLOB *buf,
     /* [<][>][^][v][top][bottom][index][help] */
9625                                const char *dllname)
9626 {
9627         enum ndr_err_code ndr_err;
9628         struct spoolss_MonitorUi ui;
9629 
9630         ui.dll_name = dllname;
9631 
9632         ndr_err = ndr_push_struct_blob(buf, mem_ctx, NULL, &ui,
9633                        (ndr_push_flags_fn_t)ndr_push_spoolss_MonitorUi);
9634         if (NDR_ERR_CODE_IS_SUCCESS(ndr_err) && (DEBUGLEVEL >= 10)) {
9635                 NDR_PRINT_DEBUG(spoolss_MonitorUi, &ui);
9636         }
9637         return NDR_ERR_CODE_IS_SUCCESS(ndr_err);
9638 }
9639 
9640 /*******************************************************************
9641  Streams the monitor UI DLL name in UNICODE
9642 *******************************************************************/
9643 
9644 static WERROR xcvtcp_monitorui(TALLOC_CTX *mem_ctx,
     /* [<][>][^][v][top][bottom][index][help] */
9645                                NT_USER_TOKEN *token, DATA_BLOB *in,
9646                                DATA_BLOB *out, uint32_t *needed)
9647 {
9648         const char *dllname = "tcpmonui.dll";
9649 
9650         *needed = (strlen(dllname)+1) * 2;
9651 
9652         if (out->length < *needed) {
9653                 return WERR_INSUFFICIENT_BUFFER;
9654         }
9655 
9656         if (!push_monitorui_buf(mem_ctx, out, dllname)) {
9657                 return WERR_NOMEM;
9658         }
9659 
9660         return WERR_OK;
9661 }
9662 
9663 /*******************************************************************
9664  ********************************************************************/
9665 
9666 static bool pull_port_data_1(TALLOC_CTX *mem_ctx,
     /* [<][>][^][v][top][bottom][index][help] */
9667                              struct spoolss_PortData1 *port1,
9668                              const DATA_BLOB *buf)
9669 {
9670         enum ndr_err_code ndr_err;
9671         ndr_err = ndr_pull_struct_blob(buf, mem_ctx, NULL, port1,
9672                        (ndr_pull_flags_fn_t)ndr_pull_spoolss_PortData1);
9673         if (NDR_ERR_CODE_IS_SUCCESS(ndr_err) && (DEBUGLEVEL >= 10)) {
9674                 NDR_PRINT_DEBUG(spoolss_PortData1, port1);
9675         }
9676         return NDR_ERR_CODE_IS_SUCCESS(ndr_err);
9677 }
9678 
9679 /*******************************************************************
9680  ********************************************************************/
9681 
9682 static bool pull_port_data_2(TALLOC_CTX *mem_ctx,
     /* [<][>][^][v][top][bottom][index][help] */
9683                              struct spoolss_PortData2 *port2,
9684                              const DATA_BLOB *buf)
9685 {
9686         enum ndr_err_code ndr_err;
9687         ndr_err = ndr_pull_struct_blob(buf, mem_ctx, NULL, port2,
9688                        (ndr_pull_flags_fn_t)ndr_pull_spoolss_PortData2);
9689         if (NDR_ERR_CODE_IS_SUCCESS(ndr_err) && (DEBUGLEVEL >= 10)) {
9690                 NDR_PRINT_DEBUG(spoolss_PortData2, port2);
9691         }
9692         return NDR_ERR_CODE_IS_SUCCESS(ndr_err);
9693 }
9694 
9695 /*******************************************************************
9696  Create a new TCP/IP port
9697 *******************************************************************/
9698 
9699 static WERROR xcvtcp_addport(TALLOC_CTX *mem_ctx,
     /* [<][>][^][v][top][bottom][index][help] */
9700                              NT_USER_TOKEN *token, DATA_BLOB *in,
9701                              DATA_BLOB *out, uint32_t *needed)
9702 {
9703         struct spoolss_PortData1 port1;
9704         struct spoolss_PortData2 port2;
9705         char *device_uri = NULL;
9706         uint32_t version;
9707 
9708         const char *portname;
9709         const char *hostaddress;
9710         const char *queue;
9711         uint32_t port_number;
9712         uint32_t protocol;
9713 
9714         /* peek for spoolss_PortData version */
9715 
9716         if (!in || (in->length < (128 + 4))) {
9717                 return WERR_GENERAL_FAILURE;
9718         }
9719 
9720         version = IVAL(in->data, 128);
9721 
9722         switch (version) {
9723                 case 1:
9724                         ZERO_STRUCT(port1);
9725 
9726                         if (!pull_port_data_1(mem_ctx, &port1, in)) {
9727                                 return WERR_NOMEM;
9728                         }
9729 
9730                         portname        = port1.portname;
9731                         hostaddress     = port1.hostaddress;
9732                         queue           = port1.queue;
9733                         protocol        = port1.protocol;
9734                         port_number     = port1.port_number;
9735 
9736                         break;
9737                 case 2:
9738                         ZERO_STRUCT(port2);
9739 
9740                         if (!pull_port_data_2(mem_ctx, &port2, in)) {
9741                                 return WERR_NOMEM;
9742                         }
9743 
9744                         portname        = port2.portname;
9745                         hostaddress     = port2.hostaddress;
9746                         queue           = port2.queue;
9747                         protocol        = port2.protocol;
9748                         port_number     = port2.port_number;
9749 
9750                         break;
9751                 default:
9752                         DEBUG(1,("xcvtcp_addport: "
9753                                 "unknown version of port_data: %d\n", version));
9754                         return WERR_UNKNOWN_PORT;
9755         }
9756 
9757         /* create the device URI and call the add_port_hook() */
9758 
9759         switch (protocol) {
9760         case PROTOCOL_RAWTCP_TYPE:
9761                 device_uri = talloc_asprintf(mem_ctx,
9762                                 "socket://%s:%d/", hostaddress,
9763                                 port_number);
9764                 break;
9765 
9766         case PROTOCOL_LPR_TYPE:
9767                 device_uri = talloc_asprintf(mem_ctx,
9768                         "lpr://%s/%s", hostaddress, queue );
9769                 break;
9770 
9771         default:
9772                 return WERR_UNKNOWN_PORT;
9773         }
9774 
9775         if (!device_uri) {
9776                 return WERR_NOMEM;
9777         }
9778 
9779         return add_port_hook(mem_ctx, token, portname, device_uri);
9780 }
9781 
9782 /*******************************************************************
9783 *******************************************************************/
9784 
9785 struct xcv_api_table xcvtcp_cmds[] = {
9786         { "MonitorUI",  xcvtcp_monitorui },
9787         { "AddPort",    xcvtcp_addport},
9788         { NULL,         NULL }
9789 };
9790 
9791 static WERROR process_xcvtcp_command(TALLOC_CTX *mem_ctx,
     /* [<][>][^][v][top][bottom][index][help] */
9792                                      NT_USER_TOKEN *token, const char *command,
9793                                      DATA_BLOB *inbuf,
9794                                      DATA_BLOB *outbuf,
9795                                      uint32_t *needed )
9796 {
9797         int i;
9798 
9799         DEBUG(10,("process_xcvtcp_command: Received command \"%s\"\n", command));
9800 
9801         for ( i=0; xcvtcp_cmds[i].name; i++ ) {
9802                 if ( strcmp( command, xcvtcp_cmds[i].name ) == 0 )
9803                         return xcvtcp_cmds[i].fn(mem_ctx, token, inbuf, outbuf, needed);
9804         }
9805 
9806         return WERR_BADFUNC;
9807 }
9808 
9809 /*******************************************************************
9810 *******************************************************************/
9811 #if 0   /* don't support management using the "Local Port" monitor */
9812 
9813 static WERROR xcvlocal_monitorui(TALLOC_CTX *mem_ctx,
     /* [<][>][^][v][top][bottom][index][help] */
9814                                  NT_USER_TOKEN *token, DATA_BLOB *in,
9815                                  DATA_BLOB *out, uint32_t *needed)
9816 {
9817         const char *dllname = "localui.dll";
9818 
9819         *needed = (strlen(dllname)+1) * 2;
9820 
9821         if (out->length < *needed) {
9822                 return WERR_INSUFFICIENT_BUFFER;
9823         }
9824 
9825         if (!push_monitorui_buf(mem_ctx, out, dllname)) {
9826                 return WERR_NOMEM;
9827         }
9828 
9829         return WERR_OK;
9830 }
9831 
9832 /*******************************************************************
9833 *******************************************************************/
9834 
9835 struct xcv_api_table xcvlocal_cmds[] = {
9836         { "MonitorUI",  xcvlocal_monitorui },
9837         { NULL,         NULL }
9838 };
9839 #else
9840 struct xcv_api_table xcvlocal_cmds[] = {
9841         { NULL,         NULL }
9842 };
9843 #endif
9844 
9845 
9846 
9847 /*******************************************************************
9848 *******************************************************************/
9849 
9850 static WERROR process_xcvlocal_command(TALLOC_CTX *mem_ctx,
     /* [<][>][^][v][top][bottom][index][help] */
9851                                        NT_USER_TOKEN *token, const char *command,
9852                                        DATA_BLOB *inbuf, DATA_BLOB *outbuf,
9853                                        uint32_t *needed)
9854 {
9855         int i;
9856 
9857         DEBUG(10,("process_xcvlocal_command: Received command \"%s\"\n", command));
9858 
9859         for ( i=0; xcvlocal_cmds[i].name; i++ ) {
9860                 if ( strcmp( command, xcvlocal_cmds[i].name ) == 0 )
9861                         return xcvlocal_cmds[i].fn(mem_ctx, token, inbuf, outbuf, needed);
9862         }
9863         return WERR_BADFUNC;
9864 }
9865 
9866 /****************************************************************
9867  _spoolss_XcvData
9868 ****************************************************************/
9869 
9870 WERROR _spoolss_XcvData(pipes_struct *p,
     /* [<][>][^][v][top][bottom][index][help] */
9871                         struct spoolss_XcvData *r)
9872 {
9873         Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
9874         DATA_BLOB out_data = data_blob_null;
9875         WERROR werror;
9876 
9877         if (!Printer) {
9878                 DEBUG(2,("_spoolss_XcvData: Invalid handle (%s:%u:%u).\n",
9879                         OUR_HANDLE(r->in.handle)));
9880                 return WERR_BADFID;
9881         }
9882 
9883         /* Has to be a handle to the TCP/IP port monitor */
9884 
9885         if ( !(Printer->printer_type & (SPLHND_PORTMON_LOCAL|SPLHND_PORTMON_TCP)) ) {
9886                 DEBUG(2,("_spoolss_XcvData: Call only valid for Port Monitors\n"));
9887                 return WERR_BADFID;
9888         }
9889 
9890         /* requires administrative access to the server */
9891 
9892         if ( !(Printer->access_granted & SERVER_ACCESS_ADMINISTER) ) {
9893                 DEBUG(2,("_spoolss_XcvData: denied by handle permissions.\n"));
9894                 return WERR_ACCESS_DENIED;
9895         }
9896 
9897         /* Allocate the outgoing buffer */
9898 
9899         if (r->in.out_data_size) {
9900                 out_data = data_blob_talloc_zero(p->mem_ctx, r->in.out_data_size);
9901                 if (out_data.data == NULL) {
9902                         return WERR_NOMEM;
9903                 }
9904         }
9905 
9906         switch ( Printer->printer_type ) {
9907         case SPLHND_PORTMON_TCP:
9908                 werror = process_xcvtcp_command(p->mem_ctx,
9909                                                 p->server_info->ptok,
9910                                                 r->in.function_name,
9911                                                 &r->in.in_data, &out_data,
9912                                                 r->out.needed);
9913                 break;
9914         case SPLHND_PORTMON_LOCAL:
9915                 werror = process_xcvlocal_command(p->mem_ctx,
9916                                                   p->server_info->ptok,
9917                                                   r->in.function_name,
9918                                                   &r->in.in_data, &out_data,
9919                                                   r->out.needed);
9920                 break;
9921         default:
9922                 werror = WERR_INVALID_PRINT_MONITOR;
9923         }
9924 
9925         if (!W_ERROR_IS_OK(werror)) {
9926                 return werror;
9927         }
9928 
9929         *r->out.status_code = 0;
9930 
9931         memcpy(r->out.out_data, out_data.data, out_data.length);
9932 
9933         return WERR_OK;
9934 }
9935 
9936 /****************************************************************
9937  _spoolss_AddPrintProcessor
9938 ****************************************************************/
9939 
9940 WERROR _spoolss_AddPrintProcessor(pipes_struct *p,
     /* [<][>][^][v][top][bottom][index][help] */
9941                                   struct spoolss_AddPrintProcessor *r)
9942 {
9943         /* for now, just indicate success and ignore the add.  We'll
9944            automatically set the winprint processor for printer
9945            entries later.  Used to debug the LexMark Optra S 1855 PCL
9946            driver --jerry */
9947 
9948         return WERR_OK;
9949 }
9950 
9951 /****************************************************************
9952  _spoolss_AddPort
9953 ****************************************************************/
9954 
9955 WERROR _spoolss_AddPort(pipes_struct *p,
     /* [<][>][^][v][top][bottom][index][help] */
9956                         struct spoolss_AddPort *r)
9957 {
9958         /* do what w2k3 does */
9959 
9960         return WERR_NOT_SUPPORTED;
9961 }
9962 
9963 /****************************************************************
9964  _spoolss_AddPrinter
9965 ****************************************************************/
9966 
9967 WERROR _spoolss_AddPrinter(pipes_struct *p,
     /* [<][>][^][v][top][bottom][index][help] */
9968                            struct spoolss_AddPrinter *r)
9969 {
9970         p->rng_fault_state = true;
9971         return WERR_NOT_SUPPORTED;
9972 }
9973 
9974 /****************************************************************
9975  _spoolss_GetPrinterDriver
9976 ****************************************************************/
9977 
9978 WERROR _spoolss_GetPrinterDriver(pipes_struct *p,
     /* [<][>][^][v][top][bottom][index][help] */
9979                                  struct spoolss_GetPrinterDriver *r)
9980 {
9981         p->rng_fault_state = true;
9982         return WERR_NOT_SUPPORTED;
9983 }
9984 
9985 /****************************************************************
9986  _spoolss_ReadPrinter
9987 ****************************************************************/
9988 
9989 WERROR _spoolss_ReadPrinter(pipes_struct *p,
     /* [<][>][^][v][top][bottom][index][help] */
9990                             struct spoolss_ReadPrinter *r)
9991 {
9992         p->rng_fault_state = true;
9993         return WERR_NOT_SUPPORTED;
9994 }
9995 
9996 /****************************************************************
9997  _spoolss_WaitForPrinterChange
9998 ****************************************************************/
9999 
10000 WERROR _spoolss_WaitForPrinterChange(pipes_struct *p,
     /* [<][>][^][v][top][bottom][index][help] */
10001                                      struct spoolss_WaitForPrinterChange *r)
10002 {
10003         p->rng_fault_state = true;
10004         return WERR_NOT_SUPPORTED;
10005 }
10006 
10007 /****************************************************************
10008  _spoolss_ConfigurePort
10009 ****************************************************************/
10010 
10011 WERROR _spoolss_ConfigurePort(pipes_struct *p,
     /* [<][>][^][v][top][bottom][index][help] */
10012                               struct spoolss_ConfigurePort *r)
10013 {
10014         p->rng_fault_state = true;
10015         return WERR_NOT_SUPPORTED;
10016 }
10017 
10018 /****************************************************************
10019  _spoolss_DeletePort
10020 ****************************************************************/
10021 
10022 WERROR _spoolss_DeletePort(pipes_struct *p,
     /* [<][>][^][v][top][bottom][index][help] */
10023                            struct spoolss_DeletePort *r)
10024 {
10025         p->rng_fault_state = true;
10026         return WERR_NOT_SUPPORTED;
10027 }
10028 
10029 /****************************************************************
10030  _spoolss_CreatePrinterIC
10031 ****************************************************************/
10032 
10033 WERROR _spoolss_CreatePrinterIC(pipes_struct *p,
     /* [<][>][^][v][top][bottom][index][help] */
10034                                 struct spoolss_CreatePrinterIC *r)
10035 {
10036         p->rng_fault_state = true;
10037         return WERR_NOT_SUPPORTED;
10038 }
10039 
10040 /****************************************************************
10041  _spoolss_PlayGDIScriptOnPrinterIC
10042 ****************************************************************/
10043 
10044 WERROR _spoolss_PlayGDIScriptOnPrinterIC(pipes_struct *p,
     /* [<][>][^][v][top][bottom][index][help] */
10045                                          struct spoolss_PlayGDIScriptOnPrinterIC *r)
10046 {
10047         p->rng_fault_state = true;
10048         return WERR_NOT_SUPPORTED;
10049 }
10050 
10051 /****************************************************************
10052  _spoolss_DeletePrinterIC
10053 ****************************************************************/
10054 
10055 WERROR _spoolss_DeletePrinterIC(pipes_struct *p,
     /* [<][>][^][v][top][bottom][index][help] */
10056                                 struct spoolss_DeletePrinterIC *r)
10057 {
10058         p->rng_fault_state = true;
10059         return WERR_NOT_SUPPORTED;
10060 }
10061 
10062 /****************************************************************
10063  _spoolss_AddPrinterConnection
10064 ****************************************************************/
10065 
10066 WERROR _spoolss_AddPrinterConnection(pipes_struct *p,
     /* [<][>][^][v][top][bottom][index][help] */
10067                                      struct spoolss_AddPrinterConnection *r)
10068 {
10069         p->rng_fault_state = true;
10070         return WERR_NOT_SUPPORTED;
10071 }
10072 
10073 /****************************************************************
10074  _spoolss_DeletePrinterConnection
10075 ****************************************************************/
10076 
10077 WERROR _spoolss_DeletePrinterConnection(pipes_struct *p,
     /* [<][>][^][v][top][bottom][index][help] */
10078                                         struct spoolss_DeletePrinterConnection *r)
10079 {
10080         p->rng_fault_state = true;
10081         return WERR_NOT_SUPPORTED;
10082 }
10083 
10084 /****************************************************************
10085  _spoolss_PrinterMessageBox
10086 ****************************************************************/
10087 
10088 WERROR _spoolss_PrinterMessageBox(pipes_struct *p,
     /* [<][>][^][v][top][bottom][index][help] */
10089                                   struct spoolss_PrinterMessageBox *r)
10090 {
10091         p->rng_fault_state = true;
10092         return WERR_NOT_SUPPORTED;
10093 }
10094 
10095 /****************************************************************
10096  _spoolss_AddMonitor
10097 ****************************************************************/
10098 
10099 WERROR _spoolss_AddMonitor(pipes_struct *p,
     /* [<][>][^][v][top][bottom][index][help] */
10100                            struct spoolss_AddMonitor *r)
10101 {
10102         p->rng_fault_state = true;
10103         return WERR_NOT_SUPPORTED;
10104 }
10105 
10106 /****************************************************************
10107  _spoolss_DeleteMonitor
10108 ****************************************************************/
10109 
10110 WERROR _spoolss_DeleteMonitor(pipes_struct *p,
     /* [<][>][^][v][top][bottom][index][help] */
10111                               struct spoolss_DeleteMonitor *r)
10112 {
10113         p->rng_fault_state = true;
10114         return WERR_NOT_SUPPORTED;
10115 }
10116 
10117 /****************************************************************
10118  _spoolss_DeletePrintProcessor
10119 ****************************************************************/
10120 
10121 WERROR _spoolss_DeletePrintProcessor(pipes_struct *p,
     /* [<][>][^][v][top][bottom][index][help] */
10122                                      struct spoolss_DeletePrintProcessor *r)
10123 {
10124         p->rng_fault_state = true;
10125         return WERR_NOT_SUPPORTED;
10126 }
10127 
10128 /****************************************************************
10129  _spoolss_AddPrintProvidor
10130 ****************************************************************/
10131 
10132 WERROR _spoolss_AddPrintProvidor(pipes_struct *p,
     /* [<][>][^][v][top][bottom][index][help] */
10133                                  struct spoolss_AddPrintProvidor *r)
10134 {
10135         p->rng_fault_state = true;
10136         return WERR_NOT_SUPPORTED;
10137 }
10138 
10139 /****************************************************************
10140  _spoolss_DeletePrintProvidor
10141 ****************************************************************/
10142 
10143 WERROR _spoolss_DeletePrintProvidor(pipes_struct *p,
     /* [<][>][^][v][top][bottom][index][help] */
10144                                     struct spoolss_DeletePrintProvidor *r)
10145 {
10146         p->rng_fault_state = true;
10147         return WERR_NOT_SUPPORTED;
10148 }
10149 
10150 /****************************************************************
10151  _spoolss_FindFirstPrinterChangeNotification
10152 ****************************************************************/
10153 
10154 WERROR _spoolss_FindFirstPrinterChangeNotification(pipes_struct *p,
     /* [<][>][^][v][top][bottom][index][help] */
10155                                                    struct spoolss_FindFirstPrinterChangeNotification *r)
10156 {
10157         p->rng_fault_state = true;
10158         return WERR_NOT_SUPPORTED;
10159 }
10160 
10161 /****************************************************************
10162  _spoolss_FindNextPrinterChangeNotification
10163 ****************************************************************/
10164 
10165 WERROR _spoolss_FindNextPrinterChangeNotification(pipes_struct *p,
     /* [<][>][^][v][top][bottom][index][help] */
10166                                                   struct spoolss_FindNextPrinterChangeNotification *r)
10167 {
10168         p->rng_fault_state = true;
10169         return WERR_NOT_SUPPORTED;
10170 }
10171 
10172 /****************************************************************
10173  _spoolss_RouterFindFirstPrinterChangeNotificationOld
10174 ****************************************************************/
10175 
10176 WERROR _spoolss_RouterFindFirstPrinterChangeNotificationOld(pipes_struct *p,
     /* [<][>][^][v][top][bottom][index][help] */
10177                                                             struct spoolss_RouterFindFirstPrinterChangeNotificationOld *r)
10178 {
10179         p->rng_fault_state = true;
10180         return WERR_NOT_SUPPORTED;
10181 }
10182 
10183 /****************************************************************
10184  _spoolss_ReplyOpenPrinter
10185 ****************************************************************/
10186 
10187 WERROR _spoolss_ReplyOpenPrinter(pipes_struct *p,
     /* [<][>][^][v][top][bottom][index][help] */
10188                                  struct spoolss_ReplyOpenPrinter *r)
10189 {
10190         p->rng_fault_state = true;
10191         return WERR_NOT_SUPPORTED;
10192 }
10193 
10194 /****************************************************************
10195  _spoolss_RouterReplyPrinter
10196 ****************************************************************/
10197 
10198 WERROR _spoolss_RouterReplyPrinter(pipes_struct *p,
     /* [<][>][^][v][top][bottom][index][help] */
10199                                    struct spoolss_RouterReplyPrinter *r)
10200 {
10201         p->rng_fault_state = true;
10202         return WERR_NOT_SUPPORTED;
10203 }
10204 
10205 /****************************************************************
10206  _spoolss_ReplyClosePrinter
10207 ****************************************************************/
10208 
10209 WERROR _spoolss_ReplyClosePrinter(pipes_struct *p,
     /* [<][>][^][v][top][bottom][index][help] */
10210                                   struct spoolss_ReplyClosePrinter *r)
10211 {
10212         p->rng_fault_state = true;
10213         return WERR_NOT_SUPPORTED;
10214 }
10215 
10216 /****************************************************************
10217  _spoolss_AddPortEx
10218 ****************************************************************/
10219 
10220 WERROR _spoolss_AddPortEx(pipes_struct *p,
     /* [<][>][^][v][top][bottom][index][help] */
10221                           struct spoolss_AddPortEx *r)
10222 {
10223         p->rng_fault_state = true;
10224         return WERR_NOT_SUPPORTED;
10225 }
10226 
10227 /****************************************************************
10228  _spoolss_RouterFindFirstPrinterChangeNotification
10229 ****************************************************************/
10230 
10231 WERROR _spoolss_RouterFindFirstPrinterChangeNotification(pipes_struct *p,
     /* [<][>][^][v][top][bottom][index][help] */
10232                                                          struct spoolss_RouterFindFirstPrinterChangeNotification *r)
10233 {
10234         p->rng_fault_state = true;
10235         return WERR_NOT_SUPPORTED;
10236 }
10237 
10238 /****************************************************************
10239  _spoolss_SpoolerInit
10240 ****************************************************************/
10241 
10242 WERROR _spoolss_SpoolerInit(pipes_struct *p,
     /* [<][>][^][v][top][bottom][index][help] */
10243                             struct spoolss_SpoolerInit *r)
10244 {
10245         p->rng_fault_state = true;
10246         return WERR_NOT_SUPPORTED;
10247 }
10248 
10249 /****************************************************************
10250  _spoolss_ResetPrinterEx
10251 ****************************************************************/
10252 
10253 WERROR _spoolss_ResetPrinterEx(pipes_struct *p,
     /* [<][>][^][v][top][bottom][index][help] */
10254                                struct spoolss_ResetPrinterEx *r)
10255 {
10256         p->rng_fault_state = true;
10257         return WERR_NOT_SUPPORTED;
10258 }
10259 
10260 /****************************************************************
10261  _spoolss_RouterReplyPrinterEx
10262 ****************************************************************/
10263 
10264 WERROR _spoolss_RouterReplyPrinterEx(pipes_struct *p,
     /* [<][>][^][v][top][bottom][index][help] */
10265                                      struct spoolss_RouterReplyPrinterEx *r)
10266 {
10267         p->rng_fault_state = true;
10268         return WERR_NOT_SUPPORTED;
10269 }
10270 
10271 /****************************************************************
10272  _spoolss_44
10273 ****************************************************************/
10274 
10275 WERROR _spoolss_44(pipes_struct *p,
     /* [<][>][^][v][top][bottom][index][help] */
10276                    struct spoolss_44 *r)
10277 {
10278         p->rng_fault_state = true;
10279         return WERR_NOT_SUPPORTED;
10280 }
10281 
10282 /****************************************************************
10283  _spoolss_47
10284 ****************************************************************/
10285 
10286 WERROR _spoolss_47(pipes_struct *p,
     /* [<][>][^][v][top][bottom][index][help] */
10287                    struct spoolss_47 *r)
10288 {
10289         p->rng_fault_state = true;
10290         return WERR_NOT_SUPPORTED;
10291 }
10292 
10293 /****************************************************************
10294  _spoolss_4a
10295 ****************************************************************/
10296 
10297 WERROR _spoolss_4a(pipes_struct *p,
     /* [<][>][^][v][top][bottom][index][help] */
10298                    struct spoolss_4a *r)
10299 {
10300         p->rng_fault_state = true;
10301         return WERR_NOT_SUPPORTED;
10302 }
10303 
10304 /****************************************************************
10305  _spoolss_4b
10306 ****************************************************************/
10307 
10308 WERROR _spoolss_4b(pipes_struct *p,
     /* [<][>][^][v][top][bottom][index][help] */
10309                    struct spoolss_4b *r)
10310 {
10311         p->rng_fault_state = true;
10312         return WERR_NOT_SUPPORTED;
10313 }
10314 
10315 /****************************************************************
10316  _spoolss_4c
10317 ****************************************************************/
10318 
10319 WERROR _spoolss_4c(pipes_struct *p,
     /* [<][>][^][v][top][bottom][index][help] */
10320                    struct spoolss_4c *r)
10321 {
10322         p->rng_fault_state = true;
10323         return WERR_NOT_SUPPORTED;
10324 }
10325 
10326 /****************************************************************
10327  _spoolss_53
10328 ****************************************************************/
10329 
10330 WERROR _spoolss_53(pipes_struct *p,
     /* [<][>][^][v][top][bottom][index][help] */
10331                    struct spoolss_53 *r)
10332 {
10333         p->rng_fault_state = true;
10334         return WERR_NOT_SUPPORTED;
10335 }
10336 
10337 /****************************************************************
10338  _spoolss_55
10339 ****************************************************************/
10340 
10341 WERROR _spoolss_55(pipes_struct *p,
     /* [<][>][^][v][top][bottom][index][help] */
10342                    struct spoolss_55 *r)
10343 {
10344         p->rng_fault_state = true;
10345         return WERR_NOT_SUPPORTED;
10346 }
10347 
10348 /****************************************************************
10349  _spoolss_56
10350 ****************************************************************/
10351 
10352 WERROR _spoolss_56(pipes_struct *p,
     /* [<][>][^][v][top][bottom][index][help] */
10353                    struct spoolss_56 *r)
10354 {
10355         p->rng_fault_state = true;
10356         return WERR_NOT_SUPPORTED;
10357 }
10358 
10359 /****************************************************************
10360  _spoolss_57
10361 ****************************************************************/
10362 
10363 WERROR _spoolss_57(pipes_struct *p,
     /* [<][>][^][v][top][bottom][index][help] */
10364                    struct spoolss_57 *r)
10365 {
10366         p->rng_fault_state = true;
10367         return WERR_NOT_SUPPORTED;
10368 }
10369 
10370 /****************************************************************
10371  _spoolss_5a
10372 ****************************************************************/
10373 
10374 WERROR _spoolss_5a(pipes_struct *p,
     /* [<][>][^][v][top][bottom][index][help] */
10375                    struct spoolss_5a *r)
10376 {
10377         p->rng_fault_state = true;
10378         return WERR_NOT_SUPPORTED;
10379 }
10380 
10381 /****************************************************************
10382  _spoolss_5b
10383 ****************************************************************/
10384 
10385 WERROR _spoolss_5b(pipes_struct *p,
     /* [<][>][^][v][top][bottom][index][help] */
10386                    struct spoolss_5b *r)
10387 {
10388         p->rng_fault_state = true;
10389         return WERR_NOT_SUPPORTED;
10390 }
10391 
10392 /****************************************************************
10393  _spoolss_5c
10394 ****************************************************************/
10395 
10396 WERROR _spoolss_5c(pipes_struct *p,
     /* [<][>][^][v][top][bottom][index][help] */
10397                    struct spoolss_5c *r)
10398 {
10399         p->rng_fault_state = true;
10400         return WERR_NOT_SUPPORTED;
10401 }
10402 
10403 /****************************************************************
10404  _spoolss_5d
10405 ****************************************************************/
10406 
10407 WERROR _spoolss_5d(pipes_struct *p,
     /* [<][>][^][v][top][bottom][index][help] */
10408                    struct spoolss_5d *r)
10409 {
10410         p->rng_fault_state = true;
10411         return WERR_NOT_SUPPORTED;
10412 }
10413 
10414 /****************************************************************
10415  _spoolss_5e
10416 ****************************************************************/
10417 
10418 WERROR _spoolss_5e(pipes_struct *p,
     /* [<][>][^][v][top][bottom][index][help] */
10419                    struct spoolss_5e *r)
10420 {
10421         p->rng_fault_state = true;
10422         return WERR_NOT_SUPPORTED;
10423 }
10424 
10425 /****************************************************************
10426  _spoolss_5f
10427 ****************************************************************/
10428 
10429 WERROR _spoolss_5f(pipes_struct *p,
     /* [<][>][^][v][top][bottom][index][help] */
10430                    struct spoolss_5f *r)
10431 {
10432         p->rng_fault_state = true;
10433         return WERR_NOT_SUPPORTED;
10434 }
10435 

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