1 /*
   2  * CDDL HEADER START
   3  *
   4  * The contents of this file are subject to the terms of the
   5  * Common Development and Distribution License (the "License").
   6  * You may not use this file except in compliance with the License.
   7  *
   8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
   9  * or http://www.opensolaris.org/os/licensing.
  10  * See the License for the specific language governing permissions
  11  * and limitations under the License.
  12  *
  13  * When distributing Covered Code, include this CDDL HEADER in each
  14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
  15  * If applicable, add the following below this CDDL HEADER, with the
  16  * fields enclosed by brackets "[]" replaced with your own identifying
  17  * information: Portions Copyright [yyyy] [name of copyright owner]
  18  *
  19  * CDDL HEADER END
  20  */
  21 /*
  22  * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
  23  * Copyright 2013 Nexenta Systems, Inc.  All rights reserved.
  24  */
  25 
  26 /*
  27  * Printing and Spooling RPC service.
  28  */
  29 #include <sys/types.h>
  30 #include <sys/stat.h>
  31 #include <sys/utsname.h>
  32 #include <sys/atomic.h>
  33 #include <unistd.h>
  34 #include <stdlib.h>
  35 #include <strings.h>
  36 #include <fcntl.h>
  37 #include <errno.h>
  38 #include <libmlrpc/libmlrpc.h>
  39 #include <smbsrv/libsmb.h>
  40 #include <smbsrv/libmlsvc.h>
  41 #include <smbsrv/smb.h>
  42 #include <smbsrv/ndl/spoolss.ndl>
  43 #include <smbsrv/ndl/winreg.ndl>
  44 #include <smb/nterror.h>
  45 #include <smbsrv/smbinfo.h>
  46 #include <smbsrv/nmpipes.h>
  47 #include <mlsvc.h>
  48 
  49 #ifdef  HAVE_CUPS
  50 
  51 #define SPOOLSS_PRINTER         "Postscript"
  52 
  53 typedef struct smb_spool {
  54         list_t          sp_list;
  55         int             sp_cnt;
  56         rwlock_t        sp_rwl;
  57         int             sp_initialized;
  58 } smb_spool_t;
  59 
  60 typedef struct smb_spooldoc {
  61         uint32_t        sd_magic;
  62         list_node_t     sd_lnd;
  63         smb_inaddr_t    sd_ipaddr;
  64         int             sd_spool_num;
  65         char            sd_username[MAXNAMELEN];
  66         char            sd_path[MAXPATHLEN];
  67         char            sd_doc_name[MAXNAMELEN];
  68         char            sd_printer_name[MAXPATHLEN];
  69         int32_t         sd_fd;
  70         ndr_hdid_t      sd_handle;
  71 } smb_spooldoc_t;
  72 
  73 typedef struct {
  74         char            *name;
  75         uint32_t        value;
  76 } spoolss_winreg_t;
  77 
  78 typedef struct {
  79         uint8_t         *sd_buf;
  80         uint32_t        sd_size;
  81 } spoolss_sd_t;
  82 
  83 static uint32_t spoolss_cnt;
  84 static smb_spool_t spoolss_splist;
  85 
  86 void (*spoolss_copyfile_callback)(smb_inaddr_t *, char *, char *, char *);
  87 
  88 DECL_FIXUP_STRUCT(spoolss_GetPrinter_result_u);
  89 DECL_FIXUP_STRUCT(spoolss_GetPrinter_result);
  90 DECL_FIXUP_STRUCT(spoolss_GetPrinter);
  91 
  92 DECL_FIXUP_STRUCT(spoolss_RPC_V2_NOTIFY_INFO_DATA_DATA);
  93 DECL_FIXUP_STRUCT(spoolss_RPC_V2_NOTIFY_INFO_DATA);
  94 DECL_FIXUP_STRUCT(spoolss_RPC_V2_NOTIFY_INFO);
  95 DECL_FIXUP_STRUCT(spoolss_RFNPCNEX);
  96 
  97 uint32_t srvsvc_sd_set_relative(smb_sd_t *, uint8_t *);
  98 static int spoolss_getservername(char *, size_t);
  99 static uint32_t spoolss_make_sd(ndr_xa_t *, spoolss_sd_t *);
 100 static uint32_t spoolss_format_sd(smb_sd_t *);
 101 static int spoolss_find_document(ndr_hdid_t *);
 102 
 103 static int spoolss_s_OpenPrinter(void *, ndr_xa_t *);
 104 static int spoolss_s_ClosePrinter(void *, ndr_xa_t *);
 105 static int spoolss_s_AbortPrinter(void *, ndr_xa_t *);
 106 static int spoolss_s_ResetPrinter(void *, ndr_xa_t *);
 107 static int spoolss_s_GetPrinter(void *, ndr_xa_t *);
 108 static int spoolss_s_GetPrinterData(void *, ndr_xa_t *);
 109 static int spoolss_s_AddJob(void *, ndr_xa_t *);
 110 static int spoolss_s_GetJob(void *, ndr_xa_t *);
 111 static int spoolss_s_EnumJobs(void *, ndr_xa_t *);
 112 static int spoolss_s_ScheduleJob(void *, ndr_xa_t *);
 113 static int spoolss_s_StartDocPrinter(void *, ndr_xa_t *);
 114 static int spoolss_s_EndDocPrinter(void *, ndr_xa_t *);
 115 static int spoolss_s_StartPagePrinter(void *, ndr_xa_t *);
 116 static int spoolss_s_EndPagePrinter(void *, ndr_xa_t *);
 117 static int spoolss_s_rfnpcnex(void *, ndr_xa_t *);
 118 static int spoolss_s_WritePrinter(void *, ndr_xa_t *);
 119 static int spoolss_s_AddForm(void *, ndr_xa_t *);
 120 static int spoolss_s_DeleteForm(void *, ndr_xa_t *);
 121 static int spoolss_s_EnumForms(void *, ndr_xa_t *);
 122 static int spoolss_s_AddMonitor(void *, ndr_xa_t *);
 123 static int spoolss_s_DeleteMonitor(void *, ndr_xa_t *);
 124 static int spoolss_s_DeletePort(void *, ndr_xa_t *);
 125 static int spoolss_s_AddPortEx(void *, ndr_xa_t *);
 126 static int spoolss_s_SetPort(void *, ndr_xa_t *);
 127 static int spoolss_s_stub(void *, ndr_xa_t *);
 128 
 129 static ndr_stub_table_t spoolss_stub_table[] = {
 130         { spoolss_s_GetJob,             SPOOLSS_OPNUM_GetJob },
 131         { spoolss_s_EnumJobs,           SPOOLSS_OPNUM_EnumJobs },
 132         { spoolss_s_stub, SPOOLSS_OPNUM_DeletePrinter },
 133         { spoolss_s_GetPrinter,         SPOOLSS_OPNUM_GetPrinter },
 134         { spoolss_s_stub,               SPOOLSS_OPNUM_GetPrinterDriver },
 135         { spoolss_s_stub,               SPOOLSS_OPNUM_DeletePrinterDriver },
 136         { spoolss_s_OpenPrinter,        SPOOLSS_OPNUM_OpenPrinter },
 137         { spoolss_s_StartDocPrinter,    SPOOLSS_OPNUM_StartDocPrinter },
 138         { spoolss_s_WritePrinter,       SPOOLSS_OPNUM_WritePrinter },
 139         { spoolss_s_EndDocPrinter,      SPOOLSS_OPNUM_EndDocPrinter },
 140         { spoolss_s_StartPagePrinter,   SPOOLSS_OPNUM_StartPagePrinter },
 141         { spoolss_s_EndPagePrinter,     SPOOLSS_OPNUM_EndPagePrinter },
 142         { spoolss_s_AbortPrinter,       SPOOLSS_OPNUM_AbortPrinter },
 143         { spoolss_s_ResetPrinter,       SPOOLSS_OPNUM_ResetPrinter },
 144         { spoolss_s_AddJob,             SPOOLSS_OPNUM_AddJob },
 145         { spoolss_s_ScheduleJob,        SPOOLSS_OPNUM_ScheduleJob },
 146         { spoolss_s_GetPrinterData,     SPOOLSS_OPNUM_GetPrinterData },
 147         { spoolss_s_ClosePrinter,       SPOOLSS_OPNUM_ClosePrinter },
 148         { spoolss_s_AddForm,            SPOOLSS_OPNUM_AddForm },
 149         { spoolss_s_DeleteForm,         SPOOLSS_OPNUM_DeleteForm },
 150         { spoolss_s_EnumForms,          SPOOLSS_OPNUM_EnumForms },
 151         { spoolss_s_AddMonitor,         SPOOLSS_OPNUM_AddMonitor },
 152         { spoolss_s_DeleteMonitor,      SPOOLSS_OPNUM_DeleteMonitor },
 153         { spoolss_s_DeletePort,         SPOOLSS_OPNUM_DeletePort },
 154         { spoolss_s_AddPortEx,          SPOOLSS_OPNUM_AddPortEx },
 155         { spoolss_s_SetPort,            SPOOLSS_OPNUM_SetPort },
 156         { spoolss_s_stub,               SPOOLSS_OPNUM_GetPrinterDriver2 },
 157         { spoolss_s_stub,               SPOOLSS_OPNUM_FCPN },
 158         { spoolss_s_stub,               SPOOLSS_OPNUM_ReplyOpenPrinter },
 159         { spoolss_s_stub,               SPOOLSS_OPNUM_ReplyClosePrinter },
 160         { spoolss_s_stub,               SPOOLSS_OPNUM_RFFPCNEX },
 161         { spoolss_s_rfnpcnex,           SPOOLSS_OPNUM_RFNPCNEX },
 162         { spoolss_s_stub,               SPOOLSS_OPNUM_RRPCN },
 163         { spoolss_s_OpenPrinter,        SPOOLSS_OPNUM_OpenPrinterEx },
 164         { spoolss_s_stub,               SPOOLSS_OPNUM_EnumPrinterData },
 165         { spoolss_s_stub,               SPOOLSS_OPNUM_EnumPrinterDataEx },
 166         { spoolss_s_stub,               SPOOLSS_OPNUM_EnumPrinterKey },
 167         {0}
 168 };
 169 
 170 static ndr_service_t spoolss_service = {
 171         "SPOOLSS",                      /* name */
 172         "Print Spool Service",          /* desc */
 173         "\\spoolss",                    /* endpoint */
 174         PIPE_SPOOLSS,                   /* sec_addr_port */
 175         "12345678-1234-abcd-ef00-0123456789ab", 1,      /* abstract */
 176         NDR_TRANSFER_SYNTAX_UUID,               2,      /* transfer */
 177         0,                              /* no bind_instance_size */
 178         0,                              /* no bind_req() */
 179         0,                              /* no unbind_and_close() */
 180         0,                              /* use generic_call_stub() */
 181         &TYPEINFO(spoolss_interface),       /* interface ti */
 182         spoolss_stub_table              /* stub_table */
 183 };
 184 
 185 void
 186 spoolss_initialize(void)
 187 {
 188         if (!spoolss_splist.sp_initialized) {
 189                 list_create(&spoolss_splist.sp_list,
 190                     sizeof (smb_spooldoc_t),
 191                     offsetof(smb_spooldoc_t, sd_lnd));
 192                 spoolss_splist.sp_initialized = 1;
 193         }
 194 
 195         spoolss_copyfile_callback = NULL;
 196 
 197         (void) ndr_svc_register(&spoolss_service);
 198 }
 199 
 200 void
 201 spoolss_finalize(void)
 202 {
 203         spoolss_copyfile_callback = NULL;
 204 }
 205 
 206 /*
 207  * Register a copyfile callback that the spoolss service can use to
 208  * copy files to the spool directory.
 209  *
 210  * Set a null pointer to disable the copying of files to the spool
 211  * directory.
 212  */
 213 void
 214 spoolss_register_copyfile(spoolss_copyfile_t copyfile)
 215 {
 216         spoolss_copyfile_callback = copyfile;
 217 }
 218 
 219 static void
 220 spoolss_copyfile(smb_inaddr_t *ipaddr, char *username, char *path,
 221     char *docname)
 222 {
 223         if (spoolss_copyfile_callback != NULL)
 224                 (*spoolss_copyfile_callback)(ipaddr, username, path, docname);
 225 }
 226 
 227 static int
 228 spoolss_s_OpenPrinter(void *arg, ndr_xa_t *mxa)
 229 {
 230         struct spoolss_OpenPrinter *param = arg;
 231         char            *name = (char *)param->printer_name;
 232         ndr_hdid_t      *id;
 233 
 234         if (name != NULL && *name != '\0') {
 235                 if (strspn(name, "\\") > 2) {
 236                         bzero(&param->handle, sizeof (spoolss_handle_t));
 237                         param->status = ERROR_INVALID_PRINTER_NAME;
 238                         return (NDR_DRC_OK);
 239                 }
 240 
 241                 smb_tracef("spoolss_s_OpenPrinter: %s", name);
 242         }
 243 
 244         if ((id = ndr_hdalloc(mxa, NULL)) == NULL) {
 245                 bzero(&param->handle, sizeof (spoolss_handle_t));
 246                 param->status = ERROR_NOT_ENOUGH_MEMORY;
 247                 return (NDR_DRC_OK);
 248         }
 249 
 250         bcopy(id, &param->handle, sizeof (spoolss_handle_t));
 251         param->status = 0;
 252         return (NDR_DRC_OK);
 253 }
 254 
 255 /*ARGSUSED*/
 256 static int
 257 spoolss_s_StartPagePrinter(void *arg, ndr_xa_t *mxa)
 258 {
 259         struct spoolss_StartPagePrinter *param = arg;
 260 
 261         param->status = ERROR_SUCCESS;
 262 
 263         return (NDR_DRC_OK);
 264 }
 265 
 266 /*ARGSUSED*/
 267 static int
 268 spoolss_s_EndPagePrinter(void *arg, ndr_xa_t *mxa)
 269 {
 270         struct spoolss_EndPagePrinter *param = arg;
 271 
 272         param->status = ERROR_SUCCESS;
 273 
 274         return (NDR_DRC_OK);
 275 }
 276 
 277 /*
 278  * Windows XP and 2000 use this mechanism to write spool files.
 279  * Create a spool file fd to be used by spoolss_s_WritePrinter
 280  * and add it to the tail of the spool list.
 281  */
 282 static int
 283 spoolss_s_StartDocPrinter(void *arg, ndr_xa_t *mxa)
 284 {
 285         struct spoolss_StartDocPrinter *param = arg;
 286         ndr_hdid_t *id = (ndr_hdid_t *)&param->handle;
 287         smb_spooldoc_t *spfile;
 288         spoolss_DocInfo_t *docinfo;
 289         char g_path[MAXPATHLEN];
 290         smb_share_t si;
 291         int rc;
 292         int fd;
 293 
 294         if (ndr_hdlookup(mxa, id) == NULL) {
 295                 smb_tracef("spoolss_s_StartDocPrinter: invalid handle");
 296                 param->status = ERROR_INVALID_HANDLE;
 297                 return (NDR_DRC_OK);
 298         }
 299 
 300         if ((docinfo = param->dinfo.DocInfoContainer) == NULL) {
 301                 param->status = ERROR_INVALID_PARAMETER;
 302                 return (NDR_DRC_OK);
 303         }
 304 
 305         if ((rc = smb_shr_get(SMB_SHARE_PRINT, &si)) != NERR_Success) {
 306                 smb_tracef("spoolss_s_StartDocPrinter: %s error=%d",
 307                     SMB_SHARE_PRINT, rc);
 308                 param->status = rc;
 309                 return (NDR_DRC_OK);
 310         }
 311 
 312         if ((spfile = calloc(1, sizeof (smb_spooldoc_t))) == NULL) {
 313                 param->status = ERROR_NOT_ENOUGH_MEMORY;
 314                 return (NDR_DRC_OK);
 315         }
 316 
 317         if (docinfo->doc_name != NULL)
 318                 (void) strlcpy(spfile->sd_doc_name,
 319                     (char *)docinfo->doc_name, MAXNAMELEN);
 320         else
 321                 (void) strlcpy(spfile->sd_doc_name, "document", MAXNAMELEN);
 322 
 323         if (docinfo->printer_name != NULL)
 324                 (void) strlcpy(spfile->sd_printer_name,
 325                     (char *)docinfo->printer_name, MAXPATHLEN);
 326         else
 327                 (void) strlcpy(spfile->sd_printer_name, "printer", MAXPATHLEN);
 328 
 329         spfile->sd_ipaddr = mxa->pipe->np_user->ui_ipaddr;
 330         (void) strlcpy((char *)spfile->sd_username,
 331             mxa->pipe->np_user->ui_account, MAXNAMELEN);
 332         (void) memcpy(&spfile->sd_handle, &param->handle, sizeof (ndr_hdid_t));
 333 
 334         /*
 335          *      write temporary spool file to print$
 336          */
 337         (void) snprintf(g_path, MAXPATHLEN, "%s/%s%d", si.shr_path,
 338             spfile->sd_username, spoolss_cnt);
 339         atomic_inc_32(&spoolss_cnt);
 340 
 341         fd = open(g_path, O_CREAT | O_RDWR, 0600);
 342         if (fd == -1) {
 343                 smb_tracef("spoolss_s_StartDocPrinter: %s: %s",
 344                     g_path, strerror(errno));
 345                 param->status = ERROR_OPEN_FAILED;
 346                 free(spfile);
 347         } else {
 348                 (void) strlcpy((char *)spfile->sd_path, g_path, MAXPATHLEN);
 349                 spfile->sd_fd = (uint16_t)fd;
 350 
 351                 /*
 352                  * Add the document to the spool list.
 353                  */
 354                 (void) rw_wrlock(&spoolss_splist.sp_rwl);
 355                 list_insert_tail(&spoolss_splist.sp_list, spfile);
 356                 spoolss_splist.sp_cnt++;
 357                 (void) rw_unlock(&spoolss_splist.sp_rwl);
 358 
 359                 /*
 360                  * JobId isn't used now, but if printQ management is added
 361                  * this will have to be incremented per job submitted.
 362                  */
 363                 param->JobId = 46;
 364                 param->status = ERROR_SUCCESS;
 365         }
 366         return (NDR_DRC_OK);
 367 }
 368 
 369 /*
 370  * Windows XP and 2000 use this mechanism to write spool files
 371  * Search the spooldoc list for a matching RPC handle and pass
 372  * the spool the file for printing.
 373  */
 374 static int
 375 spoolss_s_EndDocPrinter(void *arg, ndr_xa_t *mxa)
 376 {
 377         struct spoolss_EndDocPrinter *param = arg;
 378         ndr_hdid_t      *id = (ndr_hdid_t *)&param->handle;
 379         smb_spooldoc_t  *sp;
 380 
 381         if (ndr_hdlookup(mxa, id) == NULL) {
 382                 smb_tracef("spoolss_s_EndDocPrinter: invalid handle");
 383                 param->status = ERROR_INVALID_HANDLE;
 384                 return (NDR_DRC_OK);
 385         }
 386 
 387         param->status = ERROR_INVALID_HANDLE;
 388         (void) rw_wrlock(&spoolss_splist.sp_rwl);
 389 
 390         sp = list_head(&spoolss_splist.sp_list);
 391         while (sp != NULL) {
 392                 if (!memcmp(id, &(sp->sd_handle), sizeof (ndr_hdid_t))) {
 393                         spoolss_copyfile(&sp->sd_ipaddr,
 394                             sp->sd_username, sp->sd_path, sp->sd_doc_name);
 395                         (void) close(sp->sd_fd);
 396                         list_remove(&spoolss_splist.sp_list, sp);
 397                         free(sp);
 398                         param->status = ERROR_SUCCESS;
 399                         break;
 400                 }
 401 
 402                 sp = list_next(&spoolss_splist.sp_list, sp);
 403         }
 404 
 405         (void) rw_unlock(&spoolss_splist.sp_rwl);
 406 
 407         if (param->status != ERROR_SUCCESS)
 408                 smb_tracef("spoolss_s_EndDocPrinter: document not found");
 409         return (NDR_DRC_OK);
 410 }
 411 
 412 /*ARGSUSED*/
 413 static int
 414 spoolss_s_AbortPrinter(void *arg, ndr_xa_t *mxa)
 415 {
 416         struct spoolss_AbortPrinter *param = arg;
 417 
 418         param->status = ERROR_SUCCESS;
 419         return (NDR_DRC_OK);
 420 }
 421 
 422 /*ARGSUSED*/
 423 static int
 424 spoolss_s_ResetPrinter(void *arg, ndr_xa_t *mxa)
 425 {
 426         struct spoolss_AbortPrinter *param = arg;
 427 
 428         param->status = ERROR_SUCCESS;
 429         return (NDR_DRC_OK);
 430 }
 431 
 432 static int
 433 spoolss_s_ClosePrinter(void *arg, ndr_xa_t *mxa)
 434 {
 435         struct spoolss_ClosePrinter *param = arg;
 436         ndr_hdid_t      *id = (ndr_hdid_t *)&param->handle;
 437         ndr_handle_t    *hd;
 438 
 439         if ((hd = ndr_hdlookup(mxa, id)) != NULL) {
 440                 free(hd->nh_data);
 441                 hd->nh_data = NULL;
 442         }
 443 
 444         ndr_hdfree(mxa, id);
 445         bzero(&param->result_handle, sizeof (spoolss_handle_t));
 446         param->status = ERROR_SUCCESS;
 447         return (NDR_DRC_OK);
 448 }
 449 
 450 static int
 451 spoolss_s_AddForm(void *arg, ndr_xa_t *mxa)
 452 {
 453         struct spoolss_AddForm *param = arg;
 454         ndr_hdid_t *id = (ndr_hdid_t *)&param->handle;
 455 
 456         if (ndr_hdlookup(mxa, id) == NULL) {
 457                 bzero(param, sizeof (struct spoolss_AddForm));
 458                 param->status = ERROR_INVALID_HANDLE;
 459                 return (NDR_DRC_OK);
 460         }
 461 
 462         bzero(param, sizeof (struct spoolss_AddForm));
 463         param->status = ERROR_SUCCESS;
 464         return (NDR_DRC_OK);
 465 }
 466 
 467 static int
 468 spoolss_s_DeleteForm(void *arg, ndr_xa_t *mxa)
 469 {
 470         struct spoolss_DeleteForm *param = arg;
 471         ndr_hdid_t *id = (ndr_hdid_t *)&param->handle;
 472 
 473         if (ndr_hdlookup(mxa, id) == NULL) {
 474                 bzero(param, sizeof (struct spoolss_DeleteForm));
 475                 param->status = ERROR_INVALID_HANDLE;
 476                 return (NDR_DRC_OK);
 477         }
 478 
 479         bzero(param, sizeof (struct spoolss_DeleteForm));
 480         param->status = ERROR_SUCCESS;
 481         return (NDR_DRC_OK);
 482 }
 483 
 484 static int
 485 spoolss_s_EnumForms(void *arg, ndr_xa_t *mxa)
 486 {
 487         struct spoolss_EnumForms *param = arg;
 488         ndr_hdid_t *id = (ndr_hdid_t *)&param->handle;
 489 
 490         if (ndr_hdlookup(mxa, id) == NULL) {
 491                 bzero(param, sizeof (struct spoolss_EnumForms));
 492                 param->status = ERROR_INVALID_HANDLE;
 493                 return (NDR_DRC_OK);
 494         }
 495 
 496         bzero(param, sizeof (struct spoolss_EnumForms));
 497         param->status = ERROR_SUCCESS;
 498         param->needed = 0;
 499         return (NDR_DRC_OK);
 500 }
 501 
 502 /*ARGSUSED*/
 503 static int
 504 spoolss_s_AddMonitor(void *arg, ndr_xa_t *mxa)
 505 {
 506         struct spoolss_AddMonitor *param = arg;
 507 
 508         param->status = ERROR_SUCCESS;
 509         return (NDR_DRC_OK);
 510 }
 511 
 512 /*ARGSUSED*/
 513 static int
 514 spoolss_s_DeleteMonitor(void *arg, ndr_xa_t *mxa)
 515 {
 516         struct spoolss_DeleteMonitor *param = arg;
 517 
 518         param->status = ERROR_SUCCESS;
 519         return (NDR_DRC_OK);
 520 }
 521 
 522 /*ARGSUSED*/
 523 static int
 524 spoolss_s_DeletePort(void *arg, ndr_xa_t *mxa)
 525 {
 526         struct spoolss_DeletePort *param = arg;
 527 
 528         param->status = ERROR_SUCCESS;
 529         return (NDR_DRC_OK);
 530 }
 531 
 532 /*ARGSUSED*/
 533 static int
 534 spoolss_s_AddPortEx(void *arg, ndr_xa_t *mxa)
 535 {
 536         struct spoolss_AddPortEx *param = arg;
 537 
 538         param->status = ERROR_SUCCESS;
 539         return (NDR_DRC_OK);
 540 }
 541 
 542 /*ARGSUSED*/
 543 static int
 544 spoolss_s_SetPort(void *arg, ndr_xa_t *mxa)
 545 {
 546         struct spoolss_SetPort *param = arg;
 547 
 548         param->status = ERROR_SUCCESS;
 549         return (NDR_DRC_OK);
 550 }
 551 
 552 /*ARGSUSED*/
 553 static int
 554 spoolss_s_EnumJobs(void *arg, ndr_xa_t *mxa)
 555 {
 556         struct spoolss_EnumJobs *param = arg;
 557         DWORD status = ERROR_SUCCESS;
 558 
 559         switch (param->level) {
 560         case 1:
 561         case 2:
 562         case 3:
 563         case 4:
 564         default:
 565                 break;
 566         }
 567 
 568         param->status = status;
 569         param->needed = 0;
 570         param->needed2 = 0;
 571         return (NDR_DRC_OK);
 572 }
 573 
 574 
 575 /*ARGSUSED*/
 576 static int
 577 spoolss_s_GetJob(void *arg, ndr_xa_t *mxa)
 578 {
 579         struct spoolss_GetJob *param = arg;
 580         DWORD status = ERROR_SUCCESS;
 581 
 582         if (param->BufCount == 0)
 583                 param->status = ERROR_INSUFFICIENT_BUFFER;
 584         else
 585                 param->status = status;
 586         param->needed = 0;
 587         return (NDR_DRC_OK);
 588 }
 589 
 590 
 591 /*ARGSUSED*/
 592 static int
 593 spoolss_s_ScheduleJob(void *arg, ndr_xa_t *mxa)
 594 {
 595         struct spoolss_ScheduleJob *param = arg;
 596         DWORD status = ERROR_SPL_NO_ADDJOB;
 597 
 598         param->status = status;
 599         return (NDR_DRC_OK);
 600 }
 601 
 602 /*ARGSUSED*/
 603 static int
 604 spoolss_s_AddJob(void *arg, ndr_xa_t *mxa)
 605 {
 606         struct spoolss_AddJob *param = arg;
 607 
 608         param->status = ERROR_SUCCESS;
 609         param->needed = 0;
 610         return (NDR_DRC_OK);
 611 }
 612 
 613 /*ARGSUSED*/
 614 static int
 615 spoolss_s_rfnpcnex(void *arg, ndr_xa_t *mxa)
 616 {
 617         struct spoolss_RFNPCNEX *param = arg;
 618 
 619         param->ppinfo = 0;
 620         param->status = ERROR_SUCCESS;
 621         return (NDR_DRC_OK);
 622 }
 623 
 624 /*
 625  * Use the RPC context handle to find the fd and write the document content.
 626  */
 627 static int
 628 spoolss_s_WritePrinter(void *arg, ndr_xa_t *mxa)
 629 {
 630         struct spoolss_WritePrinter *param = arg;
 631         int written = 0;
 632         ndr_hdid_t *id = (ndr_hdid_t *)&param->handle;
 633         int spfd;
 634 
 635         if (ndr_hdlookup(mxa, id) == NULL) {
 636                 param->written = 0;
 637                 param->status = ERROR_INVALID_HANDLE;
 638                 smb_tracef("spoolss_s_WritePrinter: invalid handle");
 639                 return (NDR_DRC_OK);
 640         }
 641 
 642         if ((spfd = spoolss_find_document(id)) < 0) {
 643                 param->written = 0;
 644                 param->status = ERROR_INVALID_HANDLE;
 645                 smb_tracef("spoolss_s_WritePrinter: document not found");
 646                 return (NDR_DRC_OK);
 647         }
 648 
 649         written = write(spfd, param->pBuf, param->BufCount);
 650         if (written < param->BufCount) {
 651                 smb_tracef("spoolss_s_WritePrinter: write failed");
 652                 param->written = 0;
 653                 param->status = ERROR_CANTWRITE;
 654                 return (NDR_DRC_OK);
 655         }
 656 
 657         param->written = written;
 658         param->status = ERROR_SUCCESS;
 659         return (NDR_DRC_OK);
 660 }
 661 
 662 /*
 663  * Find a document by RPC handle in the spool list and return the fd.
 664  */
 665 static int
 666 spoolss_find_document(ndr_hdid_t *handle)
 667 {
 668         smb_spooldoc_t *sp;
 669 
 670         (void) rw_rdlock(&spoolss_splist.sp_rwl);
 671 
 672         sp = list_head(&spoolss_splist.sp_list);
 673         while (sp != NULL) {
 674                 if (!memcmp(handle, &(sp->sd_handle), sizeof (ndr_hdid_t))) {
 675                         (void) rw_unlock(&spoolss_splist.sp_rwl);
 676                         return (sp->sd_fd);
 677                 }
 678                 sp = list_next(&spoolss_splist.sp_list, sp);
 679         }
 680 
 681         (void) rw_unlock(&spoolss_splist.sp_rwl);
 682         return (-1);
 683 }
 684 
 685 /*
 686  * GetPrinterData is used t obtain values from the registry for a
 687  * printer or a print server.  See [MS-RPRN] for value descriptions.
 688  * The registry returns ERROR_FILE_NOT_FOUND for unknown keys.
 689  */
 690 static int
 691 spoolss_s_GetPrinterData(void *arg, ndr_xa_t *mxa)
 692 {
 693         static spoolss_winreg_t reg[] = {
 694                 { "ChangeId",                   0x0050acf2 },
 695                 { "W3SvcInstalled",             0x00000000 },
 696                 { "BeepEnabled",                0x00000000 },
 697                 { "EventLog",                   0x0000001f },
 698                 { "NetPopup",                   0x00000000 },
 699                 { "NetPopupToComputer",         0x00000000 },
 700                 { "MajorVersion",               0x00000003 },
 701                 { "MinorVersion",               0x00000000 },
 702                 { "DsPresent",                  0x00000000 }
 703         };
 704 
 705         struct spoolss_GetPrinterData *param = arg;
 706         char                    *name = (char *)param->pValueName;
 707         char                    buf[MAXPATHLEN];
 708         static uint8_t          reserved_buf[4];
 709         spoolss_winreg_t        *rp;
 710         smb_share_t             si;
 711         smb_version_t           *osversion;
 712         struct utsname          sysname;
 713         smb_wchar_t             *wcs;
 714         uint32_t                value;
 715         uint32_t                status;
 716         int                     wcslen;
 717         int                     i;
 718 
 719         if (name == NULL || *name == '\0') {
 720                 status = ERROR_FILE_NOT_FOUND;
 721                 goto report_error;
 722         }
 723 
 724         for (i = 0; i < sizeof (reg) / sizeof (reg[0]); ++i) {
 725                 param->pType = WINREG_DWORD;
 726                 param->Needed = sizeof (uint32_t);
 727                 rp = &reg[i];
 728 
 729                 if (strcasecmp(name, rp->name) != 0)
 730                         continue;
 731 
 732                 if (param->Size < sizeof (uint32_t)) {
 733                         param->Size = 0;
 734                         goto need_more_data;
 735                 }
 736 
 737                 if ((param->Buf = NDR_NEW(mxa, uint32_t)) == NULL) {
 738                         status = ERROR_NOT_ENOUGH_MEMORY;
 739                         goto report_error;
 740                 }
 741 
 742                 value = rp->value;
 743 
 744                 if ((strcasecmp(name, "DsPresent") == 0) &&
 745                     (smb_config_get_secmode() == SMB_SECMODE_DOMAIN))
 746                         value = 0x00000001;
 747 
 748                 bcopy(&value, param->Buf, sizeof (uint32_t));
 749                 param->Size = sizeof (uint32_t);
 750                 param->status = ERROR_SUCCESS;
 751                 return (NDR_DRC_OK);
 752         }
 753 
 754         if (strcasecmp(name, "OSVersion") == 0) {
 755                 param->pType = WINREG_BINARY;
 756                 param->Needed = sizeof (smb_version_t);
 757 
 758                 if (param->Size < sizeof (smb_version_t)) {
 759                         param->Size = sizeof (smb_version_t);
 760                         goto need_more_data;
 761                 }
 762 
 763                 if ((osversion = NDR_NEW(mxa, smb_version_t)) == NULL) {
 764                         status = ERROR_NOT_ENOUGH_MEMORY;
 765                         goto report_error;
 766                 }
 767 
 768                 smb_config_get_version(osversion);
 769                 param->Buf = (uint8_t *)osversion;
 770                 param->status = ERROR_SUCCESS;
 771                 return (NDR_DRC_OK);
 772         }
 773 
 774         if (strcasecmp(name, "DNSMachineName") == 0) {
 775                 param->pType = WINREG_SZ;
 776                 buf[0] = '\0';
 777                 (void) smb_getfqhostname(buf, MAXHOSTNAMELEN);
 778                 goto encode_string;
 779         }
 780 
 781         if (strcasecmp(name, "DefaultSpoolDirectory") == 0) {
 782                 param->pType = WINREG_SZ;
 783                 buf[0] = '\0';
 784 
 785                 if (smb_shr_get(SMB_SHARE_PRINT, &si) != NERR_Success) {
 786                         status = ERROR_FILE_NOT_FOUND;
 787                         goto report_error;
 788                 }
 789 
 790                 (void) snprintf(buf, MAXPATHLEN, "C:/%s", si.shr_path);
 791                 (void) strcanon(buf, "/\\");
 792                 (void) strsubst(buf, '/', '\\');
 793                 goto encode_string;
 794         }
 795 
 796         if (strcasecmp(name, "Architecture") == 0) {
 797                 param->pType = WINREG_SZ;
 798 
 799                 if (uname(&sysname) < 0)
 800                         (void) strlcpy(buf, "Solaris", MAXPATHLEN);
 801                 else
 802                         (void) snprintf(buf, MAXPATHLEN, "%s %s",
 803                             sysname.sysname, sysname.machine);
 804 
 805                 goto encode_string;
 806         }
 807 
 808         status = ERROR_FILE_NOT_FOUND;
 809 
 810 report_error:
 811         bzero(param, sizeof (struct spoolss_GetPrinterData));
 812         param->Buf = reserved_buf;
 813         param->status = status;
 814         return (NDR_DRC_OK);
 815 
 816 encode_string:
 817         wcslen = smb_wcequiv_strlen(buf) + sizeof (smb_wchar_t);
 818         if (param->Size < wcslen) {
 819                 param->Needed = wcslen;
 820                 goto need_more_data;
 821         }
 822 
 823         if ((wcs = NDR_MALLOC(mxa, wcslen)) == NULL) {
 824                 status = ERROR_NOT_ENOUGH_MEMORY;
 825                 goto report_error;
 826         }
 827 
 828         (void) ndr_mbstowcs(NULL, wcs, buf, wcslen);
 829         param->Buf = (uint8_t *)wcs;
 830         param->Needed = wcslen;
 831         param->status = ERROR_SUCCESS;
 832         return (NDR_DRC_OK);
 833 
 834 need_more_data:
 835         param->Size = 0;
 836         param->Buf = reserved_buf;
 837         param->status = ERROR_MORE_DATA;
 838         return (NDR_DRC_OK);
 839 }
 840 
 841 void
 842 smb_rpc_off(char *dst, char *src, uint32_t *offset, uint32_t *outoffset)
 843 {
 844         int nwchars;
 845         int bytes;
 846 
 847         bytes = smb_wcequiv_strlen(src) + 2;
 848         nwchars = strlen(src) + 1;
 849         *offset -= bytes;
 850         *outoffset = *offset;
 851         /*LINTED E_BAD_PTR_CAST_ALIGN*/
 852         (void) smb_mbstowcs(((smb_wchar_t *)(dst + *offset)), src, nwchars);
 853 }
 854 
 855 int
 856 spoolss_s_GetPrinter(void *arg, ndr_xa_t *mxa)
 857 {
 858         struct spoolss_GetPrinter       *param = arg;
 859         struct spoolss_GetPrinter0      *pinfo0;
 860         struct spoolss_GetPrinter1      *pinfo1;
 861         struct spoolss_GetPrinter2      *pinfo2;
 862         struct spoolss_DeviceMode       *devmode2;
 863         ndr_hdid_t      *id = (ndr_hdid_t *)&param->handle;
 864         spoolss_sd_t    secdesc;
 865         char            server[MAXNAMELEN];
 866         char            printer[MAXNAMELEN];
 867         DWORD           status = ERROR_SUCCESS;
 868         char            *wname;
 869         uint32_t        offset;
 870         uint8_t         *tmpbuf;
 871 
 872         if (ndr_hdlookup(mxa, id) == NULL) {
 873                 status = ERROR_INVALID_HANDLE;
 874                 goto error_out;
 875         }
 876 
 877         if (spoolss_getservername(server, MAXNAMELEN) != 0) {
 878                 status = ERROR_INTERNAL_ERROR;
 879                 goto error_out;
 880         }
 881 
 882         (void) snprintf(printer, MAXNAMELEN, "%s\\%s", server, SPOOLSS_PRINTER);
 883 
 884         switch (param->switch_value) {
 885         case 0:
 886         case 1:
 887                 param->needed = 460;
 888                 break;
 889         case 2:
 890                 param->needed = 712;
 891                 break;
 892         default:
 893                 status = ERROR_INVALID_LEVEL;
 894                 goto error_out;
 895         }
 896 
 897         if (param->BufCount < param->needed) {
 898                 param->BufCount = 0;
 899                 param->Buf = NULL;
 900                 param->status = ERROR_INSUFFICIENT_BUFFER;
 901                 return (NDR_DRC_OK);
 902         }
 903 
 904         if ((param->Buf = NDR_MALLOC(mxa, param->BufCount)) == NULL) {
 905                 status = ERROR_NOT_ENOUGH_MEMORY;
 906                 goto error_out;
 907         }
 908 
 909         bzero(param->Buf, param->BufCount);
 910         wname = (char *)param->Buf;
 911         offset = param->needed;
 912 
 913         switch (param->switch_value) {
 914         case 0:
 915                 /*LINTED E_BAD_PTR_CAST_ALIGN*/
 916                 pinfo0 = (struct spoolss_GetPrinter0 *)param->Buf;
 917 
 918                 smb_rpc_off(wname, server, &offset, &pinfo0->servername);
 919                 smb_rpc_off(wname, printer, &offset, &pinfo0->printername);
 920                 pinfo0->cjobs = 0;
 921                 pinfo0->total_jobs = 6;
 922                 pinfo0->total_bytes = 1040771;
 923                 pinfo0->time0 = 0;
 924                 pinfo0->time1 = 0;
 925                 pinfo0->time2 = 3;
 926                 pinfo0->time3 = 0;
 927                 pinfo0->global_counter = 2162710;
 928                 pinfo0->total_pages = 21495865;
 929                 pinfo0->version = 10;
 930                 pinfo0->session_counter = 1;
 931                 pinfo0->job_error = 0x6;
 932                 pinfo0->change_id  = 0x1;
 933                 pinfo0->status = 0;
 934                 pinfo0->c_setprinter = 0;
 935                 break;
 936         case 1:
 937                 /*LINTED E_BAD_PTR_CAST_ALIGN*/
 938                 pinfo1 = (struct spoolss_GetPrinter1 *)param->Buf;
 939 
 940                 pinfo1->flags = PRINTER_ENUM_ICON8;
 941                 smb_rpc_off(wname, printer, &offset, &pinfo1->flags);
 942                 smb_rpc_off(wname, printer, &offset, &pinfo1->description);
 943                 smb_rpc_off(wname, printer, &offset, &pinfo1->comment);
 944                 break;
 945         case 2:
 946                 /*LINTED E_BAD_PTR_CAST_ALIGN*/
 947                 pinfo2 = (struct spoolss_GetPrinter2 *)param->Buf;
 948 
 949                 smb_rpc_off(wname, server, &offset, &pinfo2->servername);
 950                 smb_rpc_off(wname, printer, &offset, &pinfo2->printername);
 951                 smb_rpc_off(wname, SPOOLSS_PRINTER, &offset,
 952                     &pinfo2->sharename);
 953                 smb_rpc_off(wname, "CIFS Printer Port", &offset,
 954                     &pinfo2->portname);
 955                 smb_rpc_off(wname, "", &offset, &pinfo2->drivername);
 956                 smb_rpc_off(wname, SPOOLSS_PRINTER, &offset,
 957                     &pinfo2->comment);
 958                 smb_rpc_off(wname, "farside", &offset, &pinfo2->location);
 959 
 960                 offset -= sizeof (struct spoolss_DeviceMode);
 961                 pinfo2->devmode = offset;
 962                 /*LINTED E_BAD_PTR_CAST_ALIGN*/
 963                 devmode2 = (struct spoolss_DeviceMode *)(param->Buf + offset);
 964 
 965                 smb_rpc_off(wname, "farside", &offset, &pinfo2->sepfile);
 966                 smb_rpc_off(wname, "winprint", &offset,
 967                     &pinfo2->printprocessor);
 968                 smb_rpc_off(wname, "RAW", &offset, &pinfo2->datatype);
 969                 smb_rpc_off(wname, "", &offset, &pinfo2->parameters);
 970 
 971                 status = spoolss_make_sd(mxa, &secdesc);
 972                 if (status == ERROR_SUCCESS) {
 973                         offset -= secdesc.sd_size;
 974                         pinfo2->secdesc = offset;
 975                         tmpbuf = (uint8_t *)(param->Buf + offset);
 976                         bcopy(secdesc.sd_buf, tmpbuf, secdesc.sd_size);
 977                 }
 978 
 979                 pinfo2->attributes = 0x00001048;
 980                 pinfo2->status = 0x00000000;
 981                 pinfo2->starttime = 0;
 982                 pinfo2->untiltime = 0;
 983                 pinfo2->cjobs = 0;
 984                 pinfo2->averageppm = 0;
 985                 pinfo2->defaultpriority = 0;
 986 
 987                 /*LINTED E_BAD_PTR_CAST_ALIGN*/
 988                 (void) smb_mbstowcs((smb_wchar_t *)devmode2->devicename,
 989                     printer, 32);
 990                 devmode2->specversion = 0x0401;
 991                 devmode2->driverversion = 1024;
 992                 devmode2->size = 220;
 993                 devmode2->driverextra_length = 0;
 994                 devmode2->fields = 0x00014713;
 995                 devmode2->orientation = 1;
 996                 devmode2->papersize = 1;
 997                 devmode2->paperlength = 0;
 998                 devmode2->paperwidth = 0;
 999                 devmode2->scale = 100;
1000                 devmode2->copies = 1;
1001                 devmode2->defaultsource = 15;
1002                 devmode2->printquality = 65532;
1003                 devmode2->color = 1;
1004                 devmode2->duplex = 1;
1005                 devmode2->yresolution = 1;
1006                 devmode2->ttoption = 1;
1007                 devmode2->collate = 0;
1008                 /*LINTED E_BAD_PTR_CAST_ALIGN*/
1009                 (void) smb_mbstowcs((smb_wchar_t *)devmode2->formname,
1010                     "Letter", 32);
1011                 devmode2->logpixels = 0;
1012                 devmode2->bitsperpel = 0;
1013                 devmode2->pelswidth = 0;
1014                 devmode2->pelsheight = 0;
1015                 devmode2->displayflags = 0;
1016                 devmode2->displayfrequency = 0;
1017                 devmode2->icmmethod = 0;
1018                 devmode2->icmintent = 0;
1019                 devmode2->mediatype = 0;
1020                 devmode2->dithertype = 0;
1021                 devmode2->reserved1 = 0;
1022                 devmode2->reserved2 = 0;
1023                 devmode2->panningwidth = 0;
1024                 devmode2->panningheight = 0;
1025                 break;
1026 
1027         default:
1028                 break;
1029         }
1030 
1031         param->status = status;
1032         return (NDR_DRC_OK);
1033 
1034 error_out:
1035         smb_tracef("spoolss_s_GetPrinter: error %u", status);
1036         bzero(param, sizeof (struct spoolss_GetPrinter));
1037         param->status = status;
1038         return (NDR_DRC_OK);
1039 }
1040 
1041 static int
1042 spoolss_getservername(char *name, size_t namelen)
1043 {
1044         char            hostname[MAXHOSTNAMELEN];
1045         char            ipstr[INET6_ADDRSTRLEN];
1046         smb_inaddr_t    ipaddr;
1047         struct hostent  *h;
1048         const char      *p;
1049         int             error;
1050 
1051         if (smb_gethostname(hostname, MAXHOSTNAMELEN, 0) != 0) {
1052                 smb_tracef("spoolss_s_GetPrinter: gethostname failed");
1053                 return (-1);
1054         }
1055 
1056         if ((h = smb_gethostbyname(hostname, &error)) == NULL) {
1057                 smb_tracef("spoolss_s_GetPrinter: gethostbyname failed: %d",
1058                     error);
1059                 return (-1);
1060         }
1061 
1062         bcopy(h->h_addr, &ipaddr, h->h_length);
1063         ipaddr.a_family = h->h_addrtype;
1064         freehostent(h);
1065 
1066         p = smb_inet_ntop(&ipaddr, ipstr, SMB_IPSTRLEN(ipaddr.a_family));
1067         if (p == NULL) {
1068                 smb_tracef("spoolss_s_GetPrinter: inet_ntop failed");
1069                 return (-1);
1070         }
1071 
1072         (void) snprintf(name, namelen, "\\\\%s", ipstr);
1073         return (0);
1074 }
1075 
1076 static uint32_t
1077 spoolss_make_sd(ndr_xa_t *mxa, spoolss_sd_t *secdesc)
1078 {
1079         smb_sd_t        sd;
1080         uint8_t         *sd_buf;
1081         uint32_t        sd_len;
1082         uint32_t        status;
1083 
1084         bzero(&sd, sizeof (smb_sd_t));
1085 
1086         if ((status = spoolss_format_sd(&sd)) != ERROR_SUCCESS)
1087                 return (status);
1088 
1089         sd_len = smb_sd_len(&sd, SMB_ALL_SECINFO);
1090 
1091         if ((sd_buf = NDR_MALLOC(mxa, sd_len)) == NULL)
1092                 return (ERROR_NOT_ENOUGH_MEMORY);
1093 
1094         secdesc->sd_buf = sd_buf;
1095         secdesc->sd_size = sd_len;
1096 
1097         status = srvsvc_sd_set_relative(&sd, sd_buf);
1098         smb_sd_term(&sd);
1099         return (status);
1100 }
1101 
1102 static uint32_t
1103 spoolss_format_sd(smb_sd_t *sd)
1104 {
1105         smb_fssd_t      fs_sd;
1106         acl_t           *acl;
1107         uint32_t        status = ERROR_SUCCESS;
1108 
1109         if (acl_fromtext("everyone@:full_set::allow", &acl) != 0) {
1110                 smb_tracef("spoolss_format_sd: NOT_ENOUGH_MEMORY");
1111                 return (ERROR_NOT_ENOUGH_MEMORY);
1112         }
1113         smb_fssd_init(&fs_sd, SMB_ALL_SECINFO, SMB_FSSD_FLAGS_DIR);
1114         fs_sd.sd_uid = 0;
1115         fs_sd.sd_gid = 0;
1116         fs_sd.sd_zdacl = acl;
1117         fs_sd.sd_zsacl = NULL;
1118 
1119         status = smb_sd_fromfs(&fs_sd, sd);
1120         if (status != NT_STATUS_SUCCESS) {
1121                 smb_tracef("spoolss_format_sd: %u", status);
1122                 status = ERROR_ACCESS_DENIED;
1123         }
1124         smb_fssd_term(&fs_sd);
1125         return (status);
1126 }
1127 
1128 /*ARGSUSED*/
1129 static int
1130 spoolss_s_stub(void *arg, ndr_xa_t *mxa)
1131 {
1132         return (NDR_DRC_FAULT_PARAM_0_UNIMPLEMENTED);
1133 }
1134 
1135 void
1136 fixup_spoolss_RFNPCNEX(struct spoolss_RFNPCNEX *val)
1137 {
1138         unsigned short size1 = 0;
1139         unsigned short size2 = 0;
1140         unsigned short size3 = 0;
1141         struct spoolss_RPC_V2_NOTIFY_INFO *pinfo;
1142 
1143         pinfo = val->ppinfo->pinfo;
1144         switch (pinfo->aData->Reserved) {
1145         case TABLE_STRING:
1146                 size1 = sizeof (struct STRING_CONTAINER);
1147                 break;
1148         case TABLE_DWORD:
1149                 size1 = sizeof (DWORD) * 2;
1150                 break;
1151         case TABLE_TIME:
1152                 size1 = sizeof (struct SYSTEMTIME_CONTAINER);
1153                 break;
1154         case TABLE_DEVMODE:
1155                 size1 = sizeof (struct spoolssDevmodeContainer);
1156                 break;
1157         case TABLE_SECURITY_DESCRIPTOR:
1158                 size1 = sizeof (struct SECURITY_CONTAINER);
1159                 break;
1160         default:
1161                 return;
1162         }
1163         size2 = size1 + (2 * sizeof (DWORD));
1164         size3 = size2 + sizeof (ndr_request_hdr_t) + sizeof (DWORD);
1165 
1166         FIXUP_PDU_SIZE(spoolss_RPC_V2_NOTIFY_INFO_DATA_DATA, size1);
1167         FIXUP_PDU_SIZE(spoolss_RPC_V2_NOTIFY_INFO_DATA, size2);
1168         FIXUP_PDU_SIZE(spoolss_RPC_V2_NOTIFY_INFO, size3);
1169         FIXUP_PDU_SIZE(spoolss_RFNPCNEX, size3);
1170 }
1171 
1172 void
1173 fixup_spoolss_GetPrinter(struct spoolss_GetPrinter *val)
1174 {
1175         unsigned short size1 = 0;
1176         unsigned short size2 = 0;
1177         unsigned short size3 = 0;
1178 
1179         switch (val->switch_value) {
1180         CASE_INFO_ENT(spoolss_GetPrinter, 0);
1181         CASE_INFO_ENT(spoolss_GetPrinter, 1);
1182         CASE_INFO_ENT(spoolss_GetPrinter, 2);
1183         CASE_INFO_ENT(spoolss_GetPrinter, 3);
1184         CASE_INFO_ENT(spoolss_GetPrinter, 4);
1185         CASE_INFO_ENT(spoolss_GetPrinter, 5);
1186         CASE_INFO_ENT(spoolss_GetPrinter, 6);
1187         CASE_INFO_ENT(spoolss_GetPrinter, 7);
1188         CASE_INFO_ENT(spoolss_GetPrinter, 8);
1189 
1190         default:
1191                 return;
1192         };
1193 
1194         size2 = size1 + (2 * sizeof (DWORD));
1195         size3 = size2 + sizeof (ndr_request_hdr_t) + sizeof (DWORD);
1196 
1197         FIXUP_PDU_SIZE(spoolss_GetPrinter_result_u, size1);
1198         FIXUP_PDU_SIZE(spoolss_GetPrinter_result, size2);
1199         FIXUP_PDU_SIZE(spoolss_GetPrinter, size3);
1200 }
1201 
1202 #else   /* HAVE_CUPS */
1203 
1204 /*
1205  * If not HAVE_CUPS, just provide a few "stubs".
1206  */
1207 
1208 void
1209 spoolss_initialize(void)
1210 {
1211 }
1212 
1213 void
1214 spoolss_finalize(void)
1215 {
1216 }
1217 
1218 /*ARGSUSED*/
1219 void
1220 spoolss_register_copyfile(spoolss_copyfile_t copyfile)
1221 {
1222 }
1223 
1224 #endif  /* HAVE_CUPS */