diff options
-rw-r--r-- | source3/include/doserr.h | 5 | ||||
-rw-r--r-- | source3/printing/nt_printing.c | 354 | ||||
-rw-r--r-- | source3/rpc_server/srv_spoolss_nt.c | 491 |
3 files changed, 553 insertions, 297 deletions
diff --git a/source3/include/doserr.h b/source3/include/doserr.h index c1431117f0..a2c53791cc 100644 --- a/source3/include/doserr.h +++ b/source3/include/doserr.h @@ -1,5 +1,6 @@ /* - Unix SMB/CIFS implementation. + Unix SMB/Netbios implementation. + Version 1.9. DOS error code constants Copyright (C) Andrew Tridgell 1992-2000 Copyright (C) John H Terpstra 1996-2000 @@ -154,10 +155,10 @@ #define WERR_BADFUNC W_ERROR(1) #define WERR_INSUFFICIENT_BUFFER W_ERROR(122) #define WERR_NO_SUCH_SHARE W_ERROR(67) +#define WERR_ALREADY_EXISTS W_ERROR(80) #define WERR_INVALID_PARAM W_ERROR(87) #define WERR_NOT_SUPPORTED W_ERROR(50) #define WERR_BAD_PASSWORD W_ERROR(86) -#define WERR_FILE_EXISTS W_ERROR(80) #define WERR_NOMEM W_ERROR(8) #define WERR_INVALID_NAME W_ERROR(123) #define WERR_UNKNOWN_LEVEL W_ERROR(124) diff --git a/source3/printing/nt_printing.c b/source3/printing/nt_printing.c index 14d746a50d..de12e63847 100644 --- a/source3/printing/nt_printing.c +++ b/source3/printing/nt_printing.c @@ -1,5 +1,5 @@ /* - * Unix SMB/CIFS implementation. + * Unix SMB/Netbios implementation. * RPC Pipe client / server routines * Copyright (C) Andrew Tridgell 1992-2000, * Copyright (C) Jean François Micouleau 1998-2000. @@ -32,6 +32,7 @@ static TDB_CONTEXT *tdb_printers; /* used for printers files */ #define DRIVER_INIT_PREFIX "DRIVER_INIT/" #define PRINTERS_PREFIX "PRINTERS/" #define SECDESC_PREFIX "SECDESC/" +#define GLOBAL_C_SETPRINTER "GLOBALS/c_setprinter" #define NTDRIVERS_DATABASE_VERSION_1 1 #define NTDRIVERS_DATABASE_VERSION_2 2 @@ -276,24 +277,93 @@ BOOL nt_printing_init(void) } if (vers_id != NTDRIVERS_DATABASE_VERSION) { - - if ((vers_id == NTDRIVERS_DATABASE_VERSION_1) || (IREV(vers_id) == NTDRIVERS_DATABASE_VERSION_1)) { + + if ((vers_id == NTDRIVERS_DATABASE_VERSION_1) || (IREV(vers_id) == NTDRIVERS_DATABASE_VERSION_1)) { if (!upgrade_to_version_3()) return False; } else tdb_traverse(tdb_drivers, tdb_traverse_delete_fn, NULL); - + tdb_store_int32(tdb_drivers, vstring, NTDRIVERS_DATABASE_VERSION); } } tdb_unlock_bystring(tdb_drivers, vstring); + update_c_setprinter(True); + return True; } +/******************************************************************* + tdb traversal function for counting printers. +********************************************************************/ + +static int traverse_counting_printers(TDB_CONTEXT *t, TDB_DATA key, + TDB_DATA data, void *context) +{ + int *printer_count = (int*)context; + + if (memcmp(PRINTERS_PREFIX, key.dptr, sizeof(PRINTERS_PREFIX)-1) == 0) { + (*printer_count)++; + DEBUG(10,("traverse_counting_printers: printer = [%s] printer_count = %d\n", key.dptr, *printer_count)); + } + + return 0; +} + +/******************************************************************* + Update the spooler global c_setprinter. This variable is initialized + when the parent smbd starts with the number of existing printers. It + is monotonically increased by the current number of printers *after* + each add or delete printer RPC. Only Microsoft knows why... JRR020119 +********************************************************************/ + +uint32 update_c_setprinter(BOOL initialize) +{ + int32 c_setprinter; + int32 printer_count = 0; + + tdb_lock_bystring(tdb_printers, GLOBAL_C_SETPRINTER); + + /* Traverse the tdb, counting the printers */ + tdb_traverse(tdb_printers, traverse_counting_printers, (void *)&printer_count); + + /* If initializing, set c_setprinter to current printers count + * otherwise, bump it by the current printer count + */ + if (!initialize) + c_setprinter = tdb_fetch_int32(tdb_printers, GLOBAL_C_SETPRINTER) + printer_count; + else + c_setprinter = printer_count; + + DEBUG(10,("update_c_setprinter: c_setprinter = %u\n", (unsigned int)c_setprinter)); + tdb_store_int32(tdb_printers, GLOBAL_C_SETPRINTER, c_setprinter); + + tdb_unlock_bystring(tdb_printers, GLOBAL_C_SETPRINTER); + + return (uint32)c_setprinter; +} + +/******************************************************************* + Get the spooler global c_setprinter, accounting for initialization. +********************************************************************/ + +uint32 get_c_setprinter(void) +{ + int32 c_setprinter = tdb_fetch_int32(tdb_printers, GLOBAL_C_SETPRINTER); + + if (c_setprinter == (int32)-1) + c_setprinter = update_c_setprinter(True); + + DEBUG(10,("get_c_setprinter: c_setprinter = %d\n", c_setprinter)); + + return (uint32)c_setprinter; +} + /**************************************************************************** - get builtin form struct list + Get builtin form struct list. ****************************************************************************/ + int get_builtin_ntforms(nt_forms_struct **list) { *list = (nt_forms_struct *)memdup(&default_forms[0], sizeof(default_forms)); @@ -354,7 +424,7 @@ int get_ntforms(nt_forms_struct **list) DEBUG(0,("get_ntforms: Realloc fail.\n")); return 0; } - *list = tl; + *list = tl; (*list)[n] = form; n++; } @@ -940,7 +1010,7 @@ static uint32 get_correct_cversion(fstring architecture, fstring driverpath_in, int access_mode; int action; NTSTATUS nt_status; - pstring driverpath; + pstring driverpath; DATA_BLOB null_pw; files_struct *fsp = NULL; BOOL bad_path; @@ -958,11 +1028,14 @@ static uint32 get_correct_cversion(fstring architecture, fstring driverpath_in, return 0; } - /* connect to the print$ share under the same account as the user connected to the rpc pipe */ + /* + * Connect to the print$ share under the same account as the user connected + * to the rpc pipe. Note we must still be root to do this. + */ + /* Null password is ok - we are already an authenticated user... */ null_pw = data_blob(NULL, 0); - - become_root(); + become_root(); conn = make_connection("print$", null_pw, "A:", user->vuid, &nt_status); unbecome_root(); @@ -1029,8 +1102,8 @@ static uint32 get_correct_cversion(fstring architecture, fstring driverpath_in, driverpath, major, minor)); } - DEBUG(10,("get_correct_cversion: Driver file [%s] cversion = %d\n", - driverpath, cversion)); + DEBUG(10,("get_correct_cversion: Driver file [%s] cversion = %d\n", + driverpath, cversion)); close_file(fsp, True); close_cnum(conn, user->vuid); @@ -1038,11 +1111,12 @@ static uint32 get_correct_cversion(fstring architecture, fstring driverpath_in, *perr = WERR_OK; return cversion; + error_exit: if(fsp) close_file(fsp, True); - + close_cnum(conn, user->vuid); unbecome_user(); return -1; @@ -1051,7 +1125,7 @@ static uint32 get_correct_cversion(fstring architecture, fstring driverpath_in, /**************************************************************************** ****************************************************************************/ static WERROR clean_up_driver_struct_level_3(NT_PRINTER_DRIVER_INFO_LEVEL_3 *driver, - struct current_user *user) + struct current_user *user) { fstring architecture; fstring new_name; @@ -1107,7 +1181,7 @@ static WERROR clean_up_driver_struct_level_3(NT_PRINTER_DRIVER_INFO_LEVEL_3 *dri * NT2K: cversion=3 */ if ((driver->cversion = get_correct_cversion( architecture, - driver->driverpath, user, &err)) == -1) + driver->driverpath, user, &err)) == -1) return err; return WERR_OK; @@ -1116,7 +1190,7 @@ static WERROR clean_up_driver_struct_level_3(NT_PRINTER_DRIVER_INFO_LEVEL_3 *dri /**************************************************************************** ****************************************************************************/ static WERROR clean_up_driver_struct_level_6(NT_PRINTER_DRIVER_INFO_LEVEL_6 *driver, - struct current_user *user) + struct current_user *user) { fstring architecture; fstring new_name; @@ -1172,7 +1246,7 @@ static WERROR clean_up_driver_struct_level_6(NT_PRINTER_DRIVER_INFO_LEVEL_6 *dri * NT2K: cversion=3 */ if ((driver->version = get_correct_cversion(architecture, - driver->driverpath, user, &err)) == -1) + driver->driverpath, user, &err)) == -1) return err; return WERR_OK; @@ -1252,9 +1326,13 @@ BOOL move_driver_to_download_area(NT_PRINTER_DRIVER_INFO_LEVEL driver_abstract, DATA_BLOB null_pw; connection_struct *conn; NTSTATUS nt_status; + pstring inbuf; + pstring outbuf; int ver = 0; int i; + memset(inbuf, '\0', sizeof(inbuf)); + memset(outbuf, '\0', sizeof(outbuf)); *perr = WERR_OK; if (level==3) @@ -1269,10 +1347,15 @@ BOOL move_driver_to_download_area(NT_PRINTER_DRIVER_INFO_LEVEL driver_abstract, get_short_archi(architecture, driver->environment); - /* connect to the print$ share under the same account as the user connected to the rpc pipe */ - /* Null password is ok - we are already an authenticated user... */ + /* + * Connect to the print$ share under the same account as the user connected to the rpc pipe. + * Note we must be root to do this. + */ + + become_root(); null_pw = data_blob(NULL, 0); conn = make_connection("print$", null_pw, "A:", user->vuid, &nt_status); + unbecome_root(); if (conn == NULL) { DEBUG(0,("move_driver_to_download_area: Unable to connect\n")); @@ -1284,11 +1367,8 @@ BOOL move_driver_to_download_area(NT_PRINTER_DRIVER_INFO_LEVEL driver_abstract, * Save who we are - we are temporarily becoming the connection user. */ - push_sec_ctx(); - if (!become_user(conn, conn->vuid)) { DEBUG(0,("move_driver_to_download_area: Can't become user!\n")); - pop_sec_ctx(); return False; } @@ -1434,7 +1514,7 @@ BOOL move_driver_to_download_area(NT_PRINTER_DRIVER_INFO_LEVEL driver_abstract, } close_cnum(conn, user->vuid); - pop_sec_ctx(); + unbecome_user(); return ver == -1 ? False : True; } @@ -1461,36 +1541,36 @@ static uint32 add_a_printer_driver_3(NT_PRINTER_DRIVER_INFO_LEVEL_3 *driver) slprintf(directory, sizeof(directory)-1, "\\print$\\%s\\%d\\", architecture, driver->cversion); - /* .inf files do not always list a file for each of the four standard files. - * Don't prepend a path to a null filename, or client claims: - * "The server on which the printer resides does not have a suitable - * <printer driver name> printer driver installed. Click OK if you - * wish to install the driver on your local machine." - */ + /* .inf files do not always list a file for each of the four standard files. + * Don't prepend a path to a null filename, or client claims: + * "The server on which the printer resides does not have a suitable + * <printer driver name> printer driver installed. Click OK if you + * wish to install the driver on your local machine." + */ if (strlen(driver->driverpath)) { - fstrcpy(temp_name, driver->driverpath); - slprintf(driver->driverpath, sizeof(driver->driverpath)-1, "%s%s", directory, temp_name); - } + fstrcpy(temp_name, driver->driverpath); + slprintf(driver->driverpath, sizeof(driver->driverpath)-1, "%s%s", directory, temp_name); + } if (strlen(driver->datafile)) { - fstrcpy(temp_name, driver->datafile); - slprintf(driver->datafile, sizeof(driver->datafile)-1, "%s%s", directory, temp_name); - } + fstrcpy(temp_name, driver->datafile); + slprintf(driver->datafile, sizeof(driver->datafile)-1, "%s%s", directory, temp_name); + } if (strlen(driver->configfile)) { - fstrcpy(temp_name, driver->configfile); - slprintf(driver->configfile, sizeof(driver->configfile)-1, "%s%s", directory, temp_name); - } + fstrcpy(temp_name, driver->configfile); + slprintf(driver->configfile, sizeof(driver->configfile)-1, "%s%s", directory, temp_name); + } if (strlen(driver->helpfile)) { - fstrcpy(temp_name, driver->helpfile); - slprintf(driver->helpfile, sizeof(driver->helpfile)-1, "%s%s", directory, temp_name); - } + fstrcpy(temp_name, driver->helpfile); + slprintf(driver->helpfile, sizeof(driver->helpfile)-1, "%s%s", directory, temp_name); + } if (driver->dependentfiles) { for (i=0; *driver->dependentfiles[i]; i++) { - fstrcpy(temp_name, driver->dependentfiles[i]); - slprintf(driver->dependentfiles[i], sizeof(driver->dependentfiles[i])-1, "%s%s", directory, temp_name); + fstrcpy(temp_name, driver->dependentfiles[i]); + slprintf(driver->dependentfiles[i], sizeof(driver->dependentfiles[i])-1, "%s%s", directory, temp_name); } } @@ -1523,7 +1603,7 @@ static uint32 add_a_printer_driver_3(NT_PRINTER_DRIVER_INFO_LEVEL_3 *driver) if (len != buflen) { char *tb; - + tb = (char *)Realloc(buf, len); if (!tb) { DEBUG(0,("add_a_printer_driver_3: failed to enlarge buffer\n!")); @@ -1642,7 +1722,7 @@ static WERROR get_a_printer_driver_3(NT_PRINTER_DRIVER_INFO_LEVEL_3 **info_ptr, i=0; while (len < dbuf.dsize) { fstring *tddfs; - + tddfs = (fstring *)Realloc(driver.dependentfiles, sizeof(fstring)*(i+2)); if (tddfs == NULL) { @@ -1661,7 +1741,7 @@ static WERROR get_a_printer_driver_3(NT_PRINTER_DRIVER_INFO_LEVEL_3 **info_ptr, SAFE_FREE(dbuf.dptr); if (len != dbuf.dsize) { - SAFE_FREE(driver.dependentfiles); + SAFE_FREE(driver.dependentfiles); return get_a_printer_driver_3_default(info_ptr, in_prt, in_arch); } @@ -1686,42 +1766,43 @@ uint32 get_a_printer_driver_9x_compatible(pstring line, fstring model) kbuf.dptr = key; kbuf.dsize = strlen(key)+1; - if (!tdb_exists(tdb_drivers, kbuf)) return False; + if (!tdb_exists(tdb_drivers, kbuf)) + return False; ZERO_STRUCT(info3); get_a_printer_driver_3(&info3, model, "Windows 4.0", 0); - DEBUGADD(10,("info3->name [%s]\n", info3->name)); - DEBUGADD(10,("info3->datafile [%s]\n", info3->datafile)); - DEBUGADD(10,("info3->helpfile [%s]\n", info3->helpfile)); - DEBUGADD(10,("info3->monitorname [%s]\n", info3->monitorname)); - DEBUGADD(10,("info3->defaultdatatype [%s]\n", info3->defaultdatatype)); + DEBUGADD(10,("info3->name [%s]\n", info3->name)); + DEBUGADD(10,("info3->datafile [%s]\n", info3->datafile)); + DEBUGADD(10,("info3->helpfile [%s]\n", info3->helpfile)); + DEBUGADD(10,("info3->monitorname [%s]\n", info3->monitorname)); + DEBUGADD(10,("info3->defaultdatatype [%s]\n", info3->defaultdatatype)); for (i=0; info3->dependentfiles && *info3->dependentfiles[i]; i++) { - DEBUGADD(10,("info3->dependentfiles [%s]\n", info3->dependentfiles[i])); - } - DEBUGADD(10,("info3->environment [%s]\n", info3->environment)); - DEBUGADD(10,("info3->driverpath [%s]\n", info3->driverpath)); - DEBUGADD(10,("info3->configfile [%s]\n", info3->configfile)); + DEBUGADD(10,("info3->dependentfiles [%s]\n", info3->dependentfiles[i])); + } + DEBUGADD(10,("info3->environment [%s]\n", info3->environment)); + DEBUGADD(10,("info3->driverpath [%s]\n", info3->driverpath)); + DEBUGADD(10,("info3->configfile [%s]\n", info3->configfile)); /*pstrcat(line, info3->name); pstrcat(line, ":");*/ trim_string(info3->configfile, "\\print$\\WIN40\\0\\", 0); pstrcat(line, info3->configfile); - pstrcat(line, ":"); + pstrcat(line, ":"); trim_string(info3->datafile, "\\print$\\WIN40\\0\\", 0); pstrcat(line, info3->datafile); - pstrcat(line, ":"); + pstrcat(line, ":"); trim_string(info3->helpfile, "\\print$\\WIN40\\0\\", 0); pstrcat(line, info3->helpfile); - pstrcat(line, ":"); + pstrcat(line, ":"); trim_string(info3->monitorname, "\\print$\\WIN40\\0\\", 0); pstrcat(line, info3->monitorname); - pstrcat(line, ":"); + pstrcat(line, ":"); pstrcat(line, "RAW"); /*info3->defaultdatatype);*/ - pstrcat(line, ":"); + pstrcat(line, ":"); - for (i=0; info3->dependentfiles && - *info3->dependentfiles[i]; i++) { - if (i) pstrcat(line, ","); /* don't end in a "," */ + for (i=0; info3->dependentfiles && *info3->dependentfiles[i]; i++) { + if (i) + pstrcat(line, ","); /* don't end in a "," */ trim_string(info3->dependentfiles[i], "\\print$\\WIN40\\0\\", 0); pstrcat(line, info3->dependentfiles[i]); } @@ -1732,8 +1813,9 @@ uint32 get_a_printer_driver_9x_compatible(pstring line, fstring model) } /**************************************************************************** -debugging function, dump at level 6 the struct in the logs + Debugging function, dump at level 6 the struct in the logs. ****************************************************************************/ + static uint32 dump_a_printer_driver(NT_PRINTER_DRIVER_INFO_LEVEL driver, uint32 level) { uint32 result; @@ -1771,7 +1853,7 @@ static uint32 dump_a_printer_driver(NT_PRINTER_DRIVER_INFO_LEVEL driver, uint32 break; } default: - DEBUGADD(1,("Level not implemented\n")); + DEBUGADD(106,("dump_a_printer_driver: Level %u not implemented\n", (unsigned int)level)); result=1; break; } @@ -1863,9 +1945,10 @@ static int pack_specifics(NT_PRINTER_PARAM *param, char *buf, int buflen) /**************************************************************************** -delete a printer - this just deletes the printer info file, any open -handles are not affected + Delete a printer - this just deletes the printer info file, any open + handles are not affected. ****************************************************************************/ + uint32 del_a_printer(char *sharename) { pstring key; @@ -1953,7 +2036,7 @@ static WERROR update_a_printer_2(NT_PRINTER_INFO_LEVEL_2 *info) if (buflen != len) { char *tb; - + tb = (char *)Realloc(buf, len); if (!tb) { DEBUG(0,("update_a_printer_2: failed to enlarge buffer!\n")); @@ -2067,7 +2150,7 @@ void free_nt_printer_param(NT_PRINTER_PARAM **param_ptr) DEBUG(106,("free_nt_printer_param: deleting param [%s]\n", param->value)); - SAFE_FREE(param->data); + SAFE_FREE(param->data); SAFE_FREE(*param_ptr); } @@ -2176,7 +2259,7 @@ void free_nt_devicemode(NT_DEVICEMODE **devmode_ptr) DEBUG(106,("free_nt_devicemode: deleting DEVMODE\n")); - SAFE_FREE(nt_devmode->private); + SAFE_FREE(nt_devmode->private); SAFE_FREE(*devmode_ptr); } @@ -2424,13 +2507,13 @@ static WERROR get_a_printer_2_default(NT_PRINTER_INFO_LEVEL_2 **info_ptr, fstrin fstrcpy(info.printprocessor, "winprint"); fstrcpy(info.datatype, "RAW"); - info.attributes = (PRINTER_ATTRIBUTE_SHARED | PRINTER_ATTRIBUTE_NETWORK); + info.attributes = PRINTER_ATTRIBUTE_SHARED | PRINTER_ATTRIBUTE_NETWORK; /* attributes */ info.starttime = 0; /* Minutes since 12:00am GMT */ info.untiltime = 0; /* Minutes since 12:00am GMT */ info.priority = 1; info.default_priority = 1; - info.setuptime = (uint32)time(NULL) - 86400; /* minus 1 day */ + info.setuptime = (uint32)time(NULL); /* * I changed this as I think it is better to have a generic @@ -2465,7 +2548,6 @@ static WERROR get_a_printer_2_default(NT_PRINTER_INFO_LEVEL_2 **info_ptr, fstrin return WERR_OK; fail: - if (info.devmode) free_nt_devicemode(&info.devmode); return WERR_ACCESS_DENIED; @@ -2611,7 +2693,7 @@ static uint32 dump_a_printer(NT_PRINTER_INFO_LEVEL printer, uint32 level) break; } default: - DEBUGADD(1,("Level not implemented\n")); + DEBUGADD(106,("dump_a_printer: Level %u not implemented\n", (unsigned int)level )); result=1; break; } @@ -2626,7 +2708,7 @@ static uint32 dump_a_printer(NT_PRINTER_INFO_LEVEL printer, uint32 level) void get_printer_subst_params(int snum, fstring *printername, fstring *sharename, fstring *portname) { NT_PRINTER_INFO_LEVEL *printer = NULL; - + **printername = **sharename = **portname = '\0'; if (!W_ERROR_IS_OK(get_a_printer(&printer, 2, lp_servicename(snum)))) @@ -2652,8 +2734,9 @@ static uint32 rev_changeid(void) struct timeval tv; get_process_uptime(&tv); - /* This value is in ms * 100 */ - return (((tv.tv_sec * 1000000) + tv.tv_usec)/100); + + /* Return changeid as msec since spooler restart */ + return tv.tv_sec * 1000 + tv.tv_usec / 1000; } /* @@ -2678,8 +2761,8 @@ WERROR mod_a_printer(NT_PRINTER_INFO_LEVEL printer, uint32 level) { /* * Update the changestamp. Emperical tests show that the - * ChangeID is always updated,but c_setprinter is only - * incremented on a SetPrinter() call. + * ChangeID is always updated,but c_setprinter is + * global spooler variable (not per printer). */ /* ChangeID **must** be increasing over the lifetime @@ -2721,6 +2804,7 @@ WERROR mod_a_printer(NT_PRINTER_INFO_LEVEL printer, uint32 level) /**************************************************************************** Initialize printer devmode & data with previously saved driver init values. ****************************************************************************/ + static uint32 set_driver_init_2(NT_PRINTER_INFO_LEVEL_2 *info_ptr) { int len = 0; @@ -2729,6 +2813,17 @@ static uint32 set_driver_init_2(NT_PRINTER_INFO_LEVEL_2 *info_ptr) NT_PRINTER_PARAM *current; NT_PRINTER_INFO_LEVEL_2 info; + /* + * Delete any printer data 'specifics' already set. When called for driver + * replace, there will generally be some, but during an add printer, there + * should not be any (if there are delete them). + */ + while ( (current=info_ptr->specific) != NULL ) { + info_ptr->specific=current->next; + SAFE_FREE(current->data); + SAFE_FREE(current); + } + ZERO_STRUCT(info); slprintf(key, sizeof(key)-1, "%s%s", DRIVER_INIT_PREFIX, info_ptr->drivername); @@ -2737,8 +2832,14 @@ static uint32 set_driver_init_2(NT_PRINTER_INFO_LEVEL_2 *info_ptr) kbuf.dsize = strlen(key)+1; dbuf = tdb_fetch(tdb_drivers, kbuf); - if (!dbuf.dptr) + if (!dbuf.dptr) { + /* + * When changing to a driver that has no init info in the tdb, remove + * the previous drivers init info and leave the new on blank. + */ + free_nt_devicemode(&info_ptr->devmode); return False; + } /* * Get the saved DEVMODE.. @@ -2762,16 +2863,6 @@ static uint32 set_driver_init_2(NT_PRINTER_INFO_LEVEL_2 *info_ptr) info_ptr->printername, info_ptr->drivername)); /* - * There should not be any printer data 'specifics' already set during the - * add printer operation, if there are delete them. - */ - while ( (current=info_ptr->specific) != NULL ) { - info_ptr->specific=current->next; - SAFE_FREE(current->data); - SAFE_FREE(current); - } - - /* * Add the printer data 'specifics' to the new printer */ len += unpack_specifics(&info_ptr->specific,dbuf.dptr+len, dbuf.dsize-len); @@ -2814,6 +2905,7 @@ uint32 set_driver_init(NT_PRINTER_INFO_LEVEL *printer, uint32 level) of whether it was installed from NT or 2K. Technically, they should be different, but they work out to the same struct. ****************************************************************************/ + static uint32 update_driver_init_2(NT_PRINTER_INFO_LEVEL_2 *info) { pstring key; @@ -2832,7 +2924,7 @@ static uint32 update_driver_init_2(NT_PRINTER_INFO_LEVEL_2 *info) if (buflen != len) { char *tb; - + tb = (char *)Realloc(buf, len); if (!tb) { DEBUG(0, ("update_driver_init_2: failed to enlarge buffer!\n")); @@ -2869,7 +2961,7 @@ done: Update (i.e. save) the driver init info (DEVMODE and specifics) for a printer ****************************************************************************/ -static uint32 update_driver_init(NT_PRINTER_INFO_LEVEL printer, uint32 level) +uint32 update_driver_init(NT_PRINTER_INFO_LEVEL printer, uint32 level) { uint32 result; @@ -2946,27 +3038,36 @@ static WERROR save_driver_init_2(NT_PRINTER_INFO_LEVEL *printer, NT_PRINTER_PARA NT_DEVICEMODE *tmp_devmode = printer->info_2->devmode; /* - * Set devmode on printer info, so entire printer initialization can be - * saved to tdb. + * When the DEVMODE is already set on the printer, don't try to unpack it. */ - if ((ctx = talloc_init()) == NULL) - return WERR_NOMEM; - if ((nt_devmode = (NT_DEVICEMODE*)malloc(sizeof(NT_DEVICEMODE))) == NULL) { - status = WERR_NOMEM; - goto done; - } + if (!printer->info_2->devmode) { + /* + * Set devmode on printer info, so entire printer initialization can be + * saved to tdb. + */ + + if ((ctx = talloc_init()) == NULL) + return WERR_NOMEM; + + if ((nt_devmode = (NT_DEVICEMODE*)malloc(sizeof(NT_DEVICEMODE))) == NULL) { + status = WERR_NOMEM; + goto done; + } - ZERO_STRUCTP(nt_devmode); + ZERO_STRUCTP(nt_devmode); - /* - * The DEVMODE is held in the 'data' component of the param in raw binary. - * Convert it to to a devmode structure - */ - if (!convert_driver_init(param, ctx, nt_devmode)) { - DEBUG(10,("save_driver_init_2: error converting DEVMODE\n")); - status = WERR_INVALID_PARAM; - goto done; + /* + * The DEVMODE is held in the 'data' component of the param in raw binary. + * Convert it to to a devmode structure + */ + if (!convert_driver_init(param, ctx, nt_devmode)) { + DEBUG(10,("save_driver_init_2: error converting DEVMODE\n")); + status = WERR_INVALID_PARAM; + goto done; + } + + printer->info_2->devmode = nt_devmode; } /* @@ -2974,7 +3075,7 @@ static WERROR save_driver_init_2(NT_PRINTER_INFO_LEVEL *printer, NT_PRINTER_PARA * a 'driver init' element in the tdb * */ - printer->info_2->devmode = nt_devmode; + if (update_driver_init(*printer, 2)!=0) { DEBUG(10,("save_driver_init_2: error updating DEVMODE\n")); status = WERR_NOMEM; @@ -2991,6 +3092,10 @@ static WERROR save_driver_init_2(NT_PRINTER_INFO_LEVEL *printer, NT_PRINTER_PARA DEBUG(10,("save_driver_init_2: error setting DEVMODE on printer [%s]\n", printer->info_2->printername)); } + +#if 0 /* JERRY */ + srv_spoolss_sendnotify(p, handle); +#endif done: talloc_destroy(ctx); @@ -3488,6 +3593,7 @@ WERROR nt_printing_setsec(char *printername, SEC_DESC_BUF *secdesc_ctr) static SEC_DESC_BUF *construct_default_printer_sdb(TALLOC_CTX *ctx) { + extern DOM_SID global_sam_sid; SEC_ACE ace[3]; SEC_ACCESS sa; SEC_ACL *psa = NULL; @@ -3508,9 +3614,10 @@ static SEC_DESC_BUF *construct_default_printer_sdb(TALLOC_CTX *ctx) if (secrets_fetch_domain_sid(lp_workgroup(), &owner_sid)) { sid_append_rid(&owner_sid, DOMAIN_USER_RID_ADMIN); } else { + /* Backup plan - make printer owned by admins. - This should emulate a lanman printer as security - settings can't be changed. */ + This should emulate a lanman printer as security + settings can't be changed. */ sid_copy(&owner_sid, &global_sam_sid); sid_append_rid(&owner_sid, DOMAIN_USER_RID_ADMIN); @@ -3537,7 +3644,7 @@ static SEC_DESC_BUF *construct_default_printer_sdb(TALLOC_CTX *ctx) } if (!psd) { - DEBUG(0,("construct_default_printer_sdb: Failed to make SEC_DESC.\n")); + DEBUG(0,("construct_default_printer_sd: Failed to make SEC_DESC.\n")); return NULL; } @@ -3576,22 +3683,21 @@ BOOL nt_printing_getsec(TALLOC_CTX *ctx, char *printername, SEC_DESC_BUF **secde return False; } - /* Save default security descriptor for later */ + /* Save default security descriptor for later */ - prs_init(&ps, (uint32)sec_desc_size((*secdesc_ctr)->sec) + - sizeof(SEC_DESC_BUF), ctx, MARSHALL); + prs_init(&ps, (uint32)sec_desc_size((*secdesc_ctr)->sec) + + sizeof(SEC_DESC_BUF), ctx, MARSHALL); - if (sec_io_desc_buf("nt_printing_setsec", secdesc_ctr, &ps, 1)) - tdb_prs_store(tdb_printers, key, &ps); + if (sec_io_desc_buf("nt_printing_setsec", secdesc_ctr, &ps, 1)) + tdb_prs_store(tdb_printers, key, &ps); - prs_mem_free(&ps); + prs_mem_free(&ps); return True; } - /* If security descriptor is owned by S-1-1-0 and we can now read our - domain sid (from secrets.tdb). The current security descriptor must of been - created under the old code that didn't talk to winbind properly or when winbindd was + /* If security descriptor is owned by S-1-1-0 and winbindd is up, + this security descriptor has been created when winbindd was down. Take ownership of security descriptor. */ if (sid_equal((*secdesc_ctr)->sec->owner_sid, &global_sid_World)) { diff --git a/source3/rpc_server/srv_spoolss_nt.c b/source3/rpc_server/srv_spoolss_nt.c index 69ecf5cc77..f76b78f116 100644 --- a/source3/rpc_server/srv_spoolss_nt.c +++ b/source3/rpc_server/srv_spoolss_nt.c @@ -1,12 +1,12 @@ /* - * Unix SMB/CIFS implementation. + * Unix SMB/Netbios implementation. + * Version 1.9. * RPC Pipe client / server routines * Copyright (C) Andrew Tridgell 1992-2000, * Copyright (C) Luke Kenneth Casson Leighton 1996-2000, * Copyright (C) Jean François Micouleau 1998-2000. * Copyright (C) Jeremy Allison 2001. * Copyright (C) Gerald Carter 2000-2001. - * Copyright (C) Tim Potter 2001. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -32,6 +32,7 @@ #define MAX_OPEN_PRINTER_EXS 50 #endif +#define MAGIC_DISPLAY_FREQUENCY 0xfade2bad #define PHANTOM_DEVMODE_KEY "_p_f_a_n_t_0_m_" #define PRINTER_HANDLE_IS_PRINTER 0 #define PRINTER_HANDLE_IS_PRINTSERVER 1 @@ -48,9 +49,10 @@ struct table_node { /* and the notify info asked about */ /* that's the central struct */ typedef struct _Printer{ + struct _Printer *prev, *next; BOOL document_started; BOOL page_started; - int jobid; /* jobid in printing backend */ + int jobid; /* jobid in printing backend */ BOOL printer_type; union { fstring handlename; @@ -73,6 +75,8 @@ typedef struct _Printer{ } client; } Printer_entry; +static Printer_entry *printers_list; + typedef struct _counter_printer_0 { ubi_dlNode Next; ubi_dlNode Prev; @@ -86,7 +90,8 @@ static ubi_dlList counter_list; static struct cli_state cli; static uint32 smb_connections=0; -#define OUR_HANDLE(hnd) ((hnd==NULL)?"NULL":(IVAL(hnd->data5,4)==(uint32)sys_getpid()?"OURS":"OTHER")) +#define OUR_HANDLE(hnd) (((hnd)==NULL)?"NULL":(IVAL((hnd)->data5,4)==(uint32)sys_getpid()?"OURS":"OTHER")), \ +((unsigned int)IVAL((hnd)->data5,4)),((unsigned int)sys_getpid()) /* translate between internal status numbers and NT status numbers */ static int nt_printj_status(int v) @@ -193,6 +198,9 @@ static void free_printer_entry(void *ptr) Printer->notify.option=NULL; Printer->notify.client_connected=False; + /* Remove from the internal list. */ + DLIST_REMOVE(printers_list, Printer); + SAFE_FREE(Printer); } @@ -234,7 +242,7 @@ static Printer_entry *find_printer_index_by_hnd(pipes_struct *p, POLICY_HND *hnd Printer_entry *find_printer = NULL; if(!find_policy_by_hnd(p,hnd,(void **)&find_printer)) { - DEBUG(3,("find_printer_index_by_hnd: Printer handle not found: ")); + DEBUG(2,("find_printer_index_by_hnd: Printer handle not found: ")); return NULL; } @@ -242,7 +250,7 @@ static Printer_entry *find_printer_index_by_hnd(pipes_struct *p, POLICY_HND *hnd } /**************************************************************************** - close printer index by handle + Close printer index by handle. ****************************************************************************/ static BOOL close_printer_handle(pipes_struct *p, POLICY_HND *hnd) @@ -250,7 +258,7 @@ static BOOL close_printer_handle(pipes_struct *p, POLICY_HND *hnd) Printer_entry *Printer = find_printer_index_by_hnd(p, hnd); if (!Printer) { - DEBUG(0,("close_printer_handle: Invalid handle (%s)\n", OUR_HANDLE(hnd))); + DEBUG(2,("close_printer_handle: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(hnd))); return False; } @@ -260,14 +268,15 @@ static BOOL close_printer_handle(pipes_struct *p, POLICY_HND *hnd) } /**************************************************************************** - delete a printer given a handle + Delete a printer given a handle. ****************************************************************************/ + static WERROR delete_printer_handle(pipes_struct *p, POLICY_HND *hnd) { Printer_entry *Printer = find_printer_index_by_hnd(p, hnd); if (!Printer) { - DEBUG(0,("delete_printer_handle: Invalid handle (%s)\n", OUR_HANDLE(hnd))); + DEBUG(2,("delete_printer_handle: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(hnd))); return WERR_BADFID; } @@ -325,7 +334,7 @@ static BOOL get_printer_snum(pipes_struct *p, POLICY_HND *hnd, int *number) Printer_entry *Printer = find_printer_index_by_hnd(p, hnd); if (!Printer) { - DEBUG(0,("get_printer_snum: Invalid handle (%s)\n", OUR_HANDLE(hnd))); + DEBUG(2,("get_printer_snum: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(hnd))); return False; } @@ -349,7 +358,7 @@ static BOOL set_printer_hnd_accesstype(pipes_struct *p, POLICY_HND *hnd, uint32 Printer_entry *Printer = find_printer_index_by_hnd(p, hnd); if (!Printer) { - DEBUG(0,("set_printer_hnd_accesstype: Invalid handle (%s)", OUR_HANDLE(hnd))); + DEBUG(2,("set_printer_hnd_accesstype: Invalid handle (%s:%u:%u)", OUR_HANDLE(hnd))); return False; } @@ -532,6 +541,9 @@ static BOOL open_printer_hnd(pipes_struct *p, POLICY_HND *hnd, char *name) new_printer->notify.option=NULL; + /* Add to the internal list. */ + DLIST_ADD(printers_list, new_printer); + if (!create_policy_hnd(p, hnd, free_printer_entry, new_printer)) { SAFE_FREE(new_printer); return False; @@ -553,7 +565,7 @@ static BOOL open_printer_hnd(pipes_struct *p, POLICY_HND *hnd, char *name) } /******************************************************************** - Return True is the handle is a print server. + Return True if the handle is a print server. ********************************************************************/ static BOOL handle_is_printserver(pipes_struct *p, POLICY_HND *handle) @@ -604,91 +616,62 @@ static BOOL alloc_buffer_size(NEW_BUFFER *buffer, uint32 buffer_size) } /*************************************************************************** - receive the notify message + Receive the notify message. ****************************************************************************/ static void srv_spoolss_receive_message(int msg_type, pid_t src, void *buf, size_t len) { - fstring printer; + Printer_entry *find_printer; WERROR status; - struct pipes_struct *p; - struct policy *pol; - struct handle_list *hl; - - *printer = '\0'; - fstrcpy(printer,buf); + char msg[8]; + uint32 low, high; - if (len == 0) { - DEBUG(0,("srv_spoolss_receive_message: got null message !\n")); + if (len != sizeof(msg)) { + DEBUG(2,("srv_spoolss_receive_message: got incorrect message size (%u)!\n", (unsigned int)len)); return; } - DEBUG(10,("srv_spoolss_receive_message: Got message about printer %s\n", printer )); - - /* - * We need to enumerate all printers. The handle list is shared - * across pipes of the same name, so just find the first open - * spoolss pipe. - */ - - hl = NULL; - for ( p = get_first_internal_pipe(); p; get_next_internal_pipe(p)) { - if (strequal(p->name, "spoolss")) { - hl = p->pipe_handles; - break; - } - } + memcpy(msg, buf, len); + low = IVAL(msg,0); + high = IVAL(msg,4); - if (!hl) { - DEBUG(0,("srv_spoolss_receive_message: no handle list on spoolss pipe !\n")); - return; - } + DEBUG(10,("srv_spoolss_receive_message: Got message printer change low=0x%x high=0x%x\n", (unsigned int)low, + (unsigned int)high )); - /* Iterate the printer list on this pipe. */ - for (pol = hl->Policy; pol; pol = pol->next ) { - Printer_entry *find_printer = (Printer_entry *)pol->data_ptr; + find_printer = printers_list; - if (!find_printer) - continue; + /* Iterate the printer list */ + for(; find_printer; find_printer = find_printer->next) { /* - * if the entry is the given printer or if it's a printerserver - * we send the message + * If the entry has a connected client we send the message. */ - if (find_printer->printer_type==PRINTER_HANDLE_IS_PRINTER) - if (strcmp(find_printer->dev.handlename, printer)) - continue; - if (find_printer->notify.client_connected==True) - cli_spoolss_reply_rrpcn(&cli, &find_printer->notify.client_hnd, PRINTER_CHANGE_ALL, 0x0, &status); + if (find_printer->notify.client_connected==True) { + DEBUG(10,("srv_spoolss_receive_message: printerserver [%s]\n", find_printer->dev.printerservername )); + if (cli_spoolss_reply_rrpcn(&cli, &find_printer->notify.client_hnd, low, high, &status)) + DEBUG(10,("srv_spoolss_receive_message: cli_spoolss_reply_rrpcn status = 0x%x\n", + (unsigned int)W_ERROR_V(status))); + else + DEBUG(10,("srv_spoolss_receive_message: cli_spoolss_reply_rrpcn failed\n")); + } } } /*************************************************************************** - send a notify event + Send a notify event. ****************************************************************************/ -static BOOL srv_spoolss_sendnotify(pipes_struct *p, POLICY_HND *handle) -{ - fstring printer; - - Printer_entry *Printer=find_printer_index_by_hnd(p, handle); - - if (!Printer) { - DEBUG(0,("srv_spoolss_sendnotify: Invalid handle (%s).\n", OUR_HANDLE(handle))); - return False; - } - if (Printer->printer_type==PRINTER_HANDLE_IS_PRINTER) - fstrcpy(printer, Printer->dev.handlename); - else - fstrcpy(printer, ""); - - /*srv_spoolss_receive_message(printer);*/ - DEBUG(10,("srv_spoolss_sendnotify: Sending message about printer %s\n", printer )); +static BOOL srv_spoolss_sendnotify(uint32 high, uint32 low) +{ + char msg[8]; - broadcast_printer_notify(printer); + SIVAL(msg,0,low); + SIVAL(msg,4,high); + DEBUG(10,("srv_spoolss_sendnotify: printer change low=0x%x high=0x%x\n", low, high)); + message_send_all(conn_tdb_ctx(), MSG_PRINTER_NOTIFY, msg, sizeof(msg), False, NULL); return True; } @@ -1021,7 +1004,7 @@ static WERROR _spoolss_enddocprinter_internal(pipes_struct *p, POLICY_HND *handl Printer_entry *Printer=find_printer_index_by_hnd(p, handle); if (!Printer) { - DEBUG(0,("_spoolss_enddocprinter_internal: Invalid handle (%s)\n", OUR_HANDLE(handle))); + DEBUG(2,("_spoolss_enddocprinter_internal: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle))); return WERR_BADFID; } @@ -1045,11 +1028,16 @@ WERROR _spoolss_closeprinter(pipes_struct *p, SPOOL_Q_CLOSEPRINTER *q_u, SPOOL_R if (Printer && Printer->document_started) _spoolss_enddocprinter_internal(p, handle); /* print job was not closed */ - memcpy(&r_u->handle, &q_u->handle, sizeof(r_u->handle)); - if (!close_printer_handle(p, handle)) return WERR_BADFID; + /* clear the returned printer handle. Observed behavior + from Win2k server. Don't think this really matters. + Previous code just copied the value of the closed + handle. --jerry */ + + memset(&r_u->handle, '\0', sizeof(r_u->handle)); + return WERR_OK; } @@ -1071,8 +1059,10 @@ WERROR _spoolss_deleteprinter(pipes_struct *p, SPOOL_Q_DELETEPRINTER *q_u, SPOOL result = delete_printer_handle(p, handle); + update_c_setprinter(FALSE); + if (W_ERROR_IS_OK(result)) { - srv_spoolss_sendnotify(p, handle); + srv_spoolss_sendnotify(0, PRINTER_CHANGE_DELETE_PRINTER); } return result; @@ -1160,6 +1150,14 @@ static BOOL getprinterdata_printer_server(TALLOC_CTX *ctx, fstring value, uint32 DEBUG(8,("getprinterdata_printer_server:%s\n", value)); + if (!strcmp(value, "W3SvcInstalled")) { + *type = 0x4; + if((*data = (uint8 *)talloc_zero(ctx, 4*sizeof(uint8) )) == NULL) + return False; + *needed = 0x4; + return True; + } + if (!strcmp(value, "BeepEnabled")) { *type = 0x4; if((*data = (uint8 *)talloc(ctx, 4*sizeof(uint8) )) == NULL) @@ -1245,7 +1243,7 @@ static BOOL getprinterdata_printer(pipes_struct *p, TALLOC_CTX *ctx, POLICY_HND DEBUG(5,("getprinterdata_printer\n")); if (!Printer) { - DEBUG(0,("getprinterdata_printer: Invalid handle (%s).\n", OUR_HANDLE(handle))); + DEBUG(2,("getprinterdata_printer: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle))); return False; } @@ -1321,7 +1319,7 @@ WERROR _spoolss_getprinterdata(pipes_struct *p, SPOOL_Q_GETPRINTERDATA *q_u, SPO if (!Printer) { if((*data=(uint8 *)talloc_zero(p->mem_ctx, 4*sizeof(uint8))) == NULL) return WERR_NOMEM; - DEBUG(0,("_spoolss_getprinterdata: Invalid handle (%s).\n", OUR_HANDLE(handle))); + DEBUG(2,("_spoolss_getprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle))); return WERR_BADFID; } @@ -1407,7 +1405,7 @@ WERROR _spoolss_rffpcnex(pipes_struct *p, SPOOL_Q_RFFPCNEX *q_u, SPOOL_R_RFFPCNE Printer_entry *Printer=find_printer_index_by_hnd(p, handle); if (!Printer) { - DEBUG(0,("_spoolss_rffpcnex: Invalid handle (%s).\n", OUR_HANDLE(handle))); + DEBUG(2,("_spoolss_rffpcnex: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle))); return WERR_BADFID; } @@ -1448,7 +1446,7 @@ static void spoolss_notify_server_name(int snum, len = rpcstr_push(temp, temp_name, sizeof(temp)-2, STR_TERMINATE); - data->notify_data.data.length = len / 2; + data->notify_data.data.length = len / 2 - 1; data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len); if (!data->notify_data.data.string) { @@ -1472,7 +1470,7 @@ static void spoolss_notify_printer_name(int snum, uint32 len; /* the notify name should not contain the \\server\ part */ - char *p = strrchr_m(printer->info_2->printername, '\\'); + char *p = strrchr(printer->info_2->printername, '\\'); if (!p) { p = printer->info_2->printername; @@ -1481,7 +1479,8 @@ static void spoolss_notify_printer_name(int snum, } len = rpcstr_push(temp, p, sizeof(temp)-2, STR_TERMINATE); - data->notify_data.data.length = len / 2; + + data->notify_data.data.length = len / 2 - 1; data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len); if (!data->notify_data.data.string) { @@ -1506,7 +1505,7 @@ static void spoolss_notify_share_name(int snum, len = rpcstr_push(temp, lp_servicename(snum), sizeof(temp)-2, STR_TERMINATE); - data->notify_data.data.length = len / 2; + data->notify_data.data.length = len / 2 - 1; data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len); if (!data->notify_data.data.string) { @@ -1533,7 +1532,7 @@ static void spoolss_notify_port_name(int snum, len = rpcstr_push(temp, printer->info_2->portname, sizeof(temp)-2, STR_TERMINATE); - data->notify_data.data.length = len / 2; + data->notify_data.data.length = len / 2 - 1; data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len); if (!data->notify_data.data.string) { @@ -1559,7 +1558,7 @@ static void spoolss_notify_driver_name(int snum, uint32 len; len = rpcstr_push(temp, printer->info_2->drivername, sizeof(temp)-2, STR_TERMINATE); - data->notify_data.data.length = len / 2; + data->notify_data.data.length = len / 2 - 1; data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len); if (!data->notify_data.data.string) { @@ -1584,11 +1583,10 @@ static void spoolss_notify_comment(int snum, if (*printer->info_2->comment == '\0') len = rpcstr_push(temp, lp_comment(snum), sizeof(temp)-2, STR_TERMINATE); - else len = rpcstr_push(temp, printer->info_2->comment, sizeof(temp)-2, STR_TERMINATE); - data->notify_data.data.length = len / 2; + data->notify_data.data.length = len / 2 - 1; data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len); if (!data->notify_data.data.string) { @@ -1615,7 +1613,7 @@ static void spoolss_notify_location(int snum, len = rpcstr_push(temp, printer->info_2->location,sizeof(temp)-2, STR_TERMINATE); - data->notify_data.data.length = len / 2; + data->notify_data.data.length = len / 2 - 1; data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len); if (!data->notify_data.data.string) { @@ -1654,7 +1652,7 @@ static void spoolss_notify_sepfile(int snum, len = rpcstr_push(temp, printer->info_2->sepfile, sizeof(temp)-2, STR_TERMINATE); - data->notify_data.data.length = len / 2; + data->notify_data.data.length = len / 2 - 1; data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len); if (!data->notify_data.data.string) { @@ -1680,7 +1678,7 @@ static void spoolss_notify_print_processor(int snum, len = rpcstr_push(temp, printer->info_2->printprocessor, sizeof(temp)-2, STR_TERMINATE); - data->notify_data.data.length = len / 2; + data->notify_data.data.length = len / 2 - 1; data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len); if (!data->notify_data.data.string) { @@ -1706,7 +1704,7 @@ static void spoolss_notify_parameters(int snum, len = rpcstr_push(temp, printer->info_2->parameters, sizeof(temp)-2, STR_TERMINATE); - data->notify_data.data.length = len / 2; + data->notify_data.data.length = len / 2 - 1; data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len); if (!data->notify_data.data.string) { @@ -1732,7 +1730,7 @@ static void spoolss_notify_datatype(int snum, len = rpcstr_push(temp, printer->info_2->datatype, sizeof(pstring)-2, STR_TERMINATE); - data->notify_data.data.length = len / 2; + data->notify_data.data.length = len / 2 - 1; data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len); if (!data->notify_data.data.string) { @@ -1882,8 +1880,7 @@ static void spoolss_notify_username(int snum, len = rpcstr_push(temp, queue->user, sizeof(temp)-2, STR_TERMINATE); - - data->notify_data.data.length = len / 2; + data->notify_data.data.length = len / 2 - 1; data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len); if (!data->notify_data.data.string) { @@ -1920,8 +1917,8 @@ static void spoolss_notify_job_name(int snum, uint32 len; len = rpcstr_push(temp, queue->file, sizeof(temp)-2, STR_TERMINATE); - - data->notify_data.data.length = len / 2; + + data->notify_data.data.length = len / 2 - 1; data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len); if (!data->notify_data.data.string) { @@ -1970,7 +1967,7 @@ static void spoolss_notify_job_status_string(int snum, len = rpcstr_push(temp, p, sizeof(temp) - 2, STR_TERMINATE); - data->notify_data.data.length = len / 2; + data->notify_data.data.length = len / 2 - 1; data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len); if (!data->notify_data.data.string) { @@ -2248,7 +2245,7 @@ static BOOL construct_notify_printer_info(SPOOL_NOTIFY_INFO *info, int continue; if((tid=(SPOOL_NOTIFY_INFO_DATA *)Realloc(info->data, (info->count+1)*sizeof(SPOOL_NOTIFY_INFO_DATA))) == NULL) { - DEBUG(0,("construct_notify_printer_info: failed to enlarge buffer info->data!\n")); + DEBUG(2,("construct_notify_printer_info: failed to enlarge buffer info->data!\n")); return False; } else info->data = tid; @@ -2303,7 +2300,7 @@ static BOOL construct_notify_jobs_info(print_queue_struct *queue, continue; if((tid=Realloc(info->data, (info->count+1)*sizeof(SPOOL_NOTIFY_INFO_DATA))) == NULL) { - DEBUG(0,("construct_notify_jobs_info: failed to enlarg buffer info->data!\n")); + DEBUG(2,("construct_notify_jobs_info: failed to enlarg buffer info->data!\n")); return False; } else info->data = tid; @@ -2363,6 +2360,9 @@ static WERROR printserver_notify_info(pipes_struct *p, POLICY_HND *hnd, DEBUG(4,("printserver_notify_info\n")); + if (!Printer) + return WERR_BADFID; + option=Printer->notify.option; id=1; info->version=2; @@ -2420,6 +2420,9 @@ static WERROR printer_notify_info(pipes_struct *p, POLICY_HND *hnd, SPOOL_NOTIFY DEBUG(4,("printer_notify_info\n")); + if (!Printer) + return WERR_BADFID; + option=Printer->notify.option; id=0xffffffff; info->version=2; @@ -2500,7 +2503,7 @@ WERROR _spoolss_rfnpcnex( pipes_struct *p, SPOOL_Q_RFNPCNEX *q_u, SPOOL_R_RFNPCN r_u->info_ptr=0x1; if (!Printer) { - DEBUG(0,("_spoolss_rfnpcnex: Invalid handle (%s).\n", + DEBUG(2,("_spoolss_rfnpcnex: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle))); goto done; } @@ -2624,7 +2627,7 @@ static BOOL construct_printer_info_0(PRINTER_INFO_0 *printer, int snum) printer->unknown18 = 0x0; printer->status = nt_printq_status(status.status); printer->unknown20 = 0x0; - printer->c_setprinter = ntprinter->info_2->c_setprinter; /* how many times setprinter has been called */ + printer->c_setprinter = get_c_setprinter(); /* monotonically increasing sum of delta printer counts */ printer->unknown22 = 0x0; printer->unknown23 = 0x6; /* 6 ???*/ printer->unknown24 = 0; /* unknown 24 to 26 are always 0 */ @@ -2683,7 +2686,7 @@ static void free_dev_mode(DEVICEMODE *dev) if (dev == NULL) return; - SAFE_FREE(dev->private); + SAFE_FREE(dev->private); SAFE_FREE(dev); } @@ -2704,7 +2707,7 @@ static DEVICEMODE *construct_dev_mode(int snum) DEBUGADD(8,("getting printer characteristics\n")); if ((devmode = (DEVICEMODE *)malloc(sizeof(DEVICEMODE))) == NULL) { - DEBUG(0,("construct_dev_mode: malloc fail.\n")); + DEBUG(2,("construct_dev_mode: malloc fail.\n")); return NULL; } @@ -2849,7 +2852,7 @@ static BOOL construct_printer_info_3(PRINTER_INFO_3 **pp_printer, int snum) *pp_printer = NULL; if ((printer = (PRINTER_INFO_3 *)malloc(sizeof(PRINTER_INFO_3))) == NULL) { - DEBUG(0,("construct_printer_info_3: malloc fail.\n")); + DEBUG(2,("construct_printer_info_3: malloc fail.\n")); return False; } @@ -2951,7 +2954,7 @@ static WERROR enum_all_printers_info_1(uint32 flags, NEW_BUFFER *buffer, uint32 if (construct_printer_info_1(flags, ¤t_prt, snum)) { if((tp=Realloc(printers, (*returned +1)*sizeof(PRINTER_INFO_1))) == NULL) { - DEBUG(0,("enum_all_printers_info_1: failed to enlarge printers buffer!\n")); + DEBUG(2,("enum_all_printers_info_1: failed to enlarge printers buffer!\n")); SAFE_FREE(printers); *returned=0; return WERR_NOMEM; @@ -3007,7 +3010,7 @@ static WERROR enum_all_printers_info_1_name(fstring name, NEW_BUFFER *buffer, ui if ((name[0] == '\\') && (name[1] == '\\')) s = name + 2; - + if (is_myname_or_ipaddr(s)) { return enum_all_printers_info_1(PRINTER_ENUM_ICON8, buffer, offered, needed, returned); } @@ -3100,7 +3103,7 @@ static WERROR enum_all_printers_info_2(NEW_BUFFER *buffer, uint32 offered, uint3 if (construct_printer_info_2(¤t_prt, snum)) { if((tp=Realloc(printers, (*returned +1)*sizeof(PRINTER_INFO_2))) == NULL) { - DEBUG(0,("enum_all_printers_info_2: failed to enlarge printers buffer!\n")); + DEBUG(2,("enum_all_printers_info_2: failed to enlarge printers buffer!\n")); SAFE_FREE(printers); *returned = 0; return WERR_NOMEM; @@ -3613,10 +3616,10 @@ static void init_unistr_array(uint16 **uni_array, fstring *char_array, char *ser slprintf(line, sizeof(line)-1, "\\\\%s%s", servername, v); DEBUGADD(6,("%d:%s:%d\n", i, line, strlen(line))); if((tuary=Realloc(*uni_array, (j+strlen(line)+2)*sizeof(uint16))) == NULL) { - DEBUG(0,("init_unistr_array: Realloc error\n" )); + DEBUG(2,("init_unistr_array: Realloc error\n" )); return; - } - else *uni_array = tuary; + } else + *uni_array = tuary; j += (rpcstr_push((*uni_array+j), line, sizeof(uint16)*strlen(line)+2, 0)/ sizeof(uint16)); i++; } @@ -3692,10 +3695,38 @@ static WERROR construct_printer_driver_info_3(DRIVER_INFO_3 *info, int snum, fst status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version); DEBUG(8,("construct_printer_driver_info_3: status: %s\n", werror_str(status))); + +#if 0 /* JERRY */ + + /* + * I put this code in during testing. Helpful when commenting out the + * support for DRIVER_INFO_6 in regards to win2k. Not needed in general + * as win2k always queries the driver using an infor level of 6. + * I've left it in (but ifdef'd out) because I'll probably + * use it in experimentation again in the future. --jerry 22/01/2002 + */ + if (!W_ERROR_IS_OK(status)) { - free_a_printer(&printer,2); - return WERR_UNKNOWN_PRINTER_DRIVER; + /* + * Is this a W2k client ? + */ + if (version == 3) { + /* Yes - try again with a WinNT driver. */ + version = 2; + status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version); + DEBUG(8,("construct_printer_driver_info_3: status: %s\n", werror_str(status))); + } +#endif + + if (!W_ERROR_IS_OK(status)) { + free_a_printer(&printer,2); + return WERR_UNKNOWN_PRINTER_DRIVER; + } + +#if 0 /* JERRY */ } +#endif + fill_printer_driver_info_3(info, driver, servername); @@ -4046,7 +4077,7 @@ WERROR _spoolss_endpageprinter(pipes_struct *p, SPOOL_Q_ENDPAGEPRINTER *q_u, SPO Printer_entry *Printer = find_printer_index_by_hnd(p, handle); if (!Printer) { - DEBUG(0,("_spoolss_endpageprinter: Invalid handle (%s).\n",OUR_HANDLE(handle))); + DEBUG(2,("_spoolss_endpageprinter: Invalid handle (%s:%u:%u).\n",OUR_HANDLE(handle))); return WERR_BADFID; } @@ -4076,7 +4107,7 @@ WERROR _spoolss_startdocprinter(pipes_struct *p, SPOOL_Q_STARTDOCPRINTER *q_u, S struct current_user user; if (!Printer) { - DEBUG(0,("_spoolss_startdocprinter: Invalid handle (%s)\n", OUR_HANDLE(handle))); + DEBUG(2,("_spoolss_startdocprinter: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle))); return WERR_BADFID; } @@ -4150,7 +4181,7 @@ WERROR _spoolss_writeprinter(pipes_struct *p, SPOOL_Q_WRITEPRINTER *q_u, SPOOL_R Printer_entry *Printer = find_printer_index_by_hnd(p, handle); if (!Printer) { - DEBUG(0,("_spoolss_writeprinter: Invalid handle (%s)\n",OUR_HANDLE(handle))); + DEBUG(2,("_spoolss_writeprinter: Invalid handle (%s:%u:%u)\n",OUR_HANDLE(handle))); r_u->buffer_written = q_u->buffer_size2; return WERR_BADFID; } @@ -4179,7 +4210,7 @@ static WERROR control_printer(POLICY_HND *handle, uint32 command, get_current_user(&user, p); if (!Printer) { - DEBUG(0,("control_printer: Invalid handle (%s)\n", OUR_HANDLE(handle))); + DEBUG(2,("control_printer: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle))); return WERR_BADFID; } @@ -4237,7 +4268,7 @@ static WERROR update_printer_sec(POLICY_HND *handle, uint32 level, Printer_entry *Printer = find_printer_index_by_hnd(p, handle); if (!Printer || !get_printer_snum(p, handle, &snum)) { - DEBUG(0,("update_printer_sec: Invalid handle (%s)\n", + DEBUG(2,("update_printer_sec: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle))); result = WERR_BADFID; @@ -4331,10 +4362,7 @@ static BOOL check_printer_ok(NT_PRINTER_INFO_LEVEL_2 *info, int snum) slprintf(info->printername, sizeof(info->printername)-1, "\\\\%s\\%s", get_called_name(), lp_servicename(snum)); fstrcpy(info->sharename, lp_servicename(snum)); - info->attributes = PRINTER_ATTRIBUTE_SHARED \ - | PRINTER_ATTRIBUTE_LOCAL \ - | PRINTER_ATTRIBUTE_RAW_ONLY \ - | PRINTER_ATTRIBUTE_QUEUED ; + info->attributes = PRINTER_ATTRIBUTE_SHARED | PRINTER_ATTRIBUTE_NETWORK; return True; } @@ -4350,6 +4378,7 @@ static BOOL add_printer_hook(NT_PRINTER_INFO_LEVEL *printer) int numlines; int ret; int fd; + fstring remote_machine = "%m"; /* build driver path... only 9X architecture is needed for legacy reasons */ slprintf(driverlocation, sizeof(driverlocation)-1, "\\\\%s\\print$\\WIN40\\0", @@ -4357,11 +4386,12 @@ static BOOL add_printer_hook(NT_PRINTER_INFO_LEVEL *printer) /* change \ to \\ for the shell */ all_string_sub(driverlocation,"\\","\\\\",sizeof(pstring)); - slprintf(command, sizeof(command)-1, "%s \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\"", + slprintf(command, sizeof(command)-1, "%s \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\"", cmd, printer->info_2->printername, printer->info_2->sharename, printer->info_2->portname, printer->info_2->drivername, - printer->info_2->location, driverlocation); + printer->info_2->location, driverlocation, remote_machine); + /* Convert script args to unix-codepage */ DEBUG(10,("Running [%s]\n", command)); ret = smbrun(command, &fd); DEBUGADD(10,("returned [%d]\n", ret)); @@ -4633,8 +4663,8 @@ static BOOL nt_printer_info_level_equal(NT_PRINTER_INFO_LEVEL *p1, } /******************************************************************** - * called by spoolss_api_setprinter - * when updating a printer description + * Called by spoolss_api_setprinter + * when updating a printer description. ********************************************************************/ static WERROR update_printer(pipes_struct *p, POLICY_HND *handle, uint32 level, @@ -4651,7 +4681,7 @@ static WERROR update_printer(pipes_struct *p, POLICY_HND *handle, uint32 level, result = WERR_OK; if (level!=2) { - DEBUG(0,("Send a mail to samba@samba.org\n")); + DEBUG(0,("update_printer: Send a mail to samba@samba.org\n")); DEBUGADD(0,("with the following message: update_printer: level!=2\n")); result = WERR_UNKNOWN_LEVEL; goto done; @@ -4690,7 +4720,7 @@ static WERROR update_printer(pipes_struct *p, POLICY_HND *handle, uint32 level, /* we have a valid devmode convert it and link it*/ - DEBUGADD(8,("Converting the devicemode struct\n")); + DEBUGADD(8,("update_printer: Converting the devicemode struct\n")); if (!convert_devicemode(printer->info_2->printername, devmode, &printer->info_2->devmode)) { result = WERR_NOMEM; @@ -4710,7 +4740,7 @@ static WERROR update_printer(pipes_struct *p, POLICY_HND *handle, uint32 level, annoying permission denied dialog box. */ if (nt_printer_info_level_equal(printer, old_printer)) { - DEBUG(3, ("printer info has not changed\n")); + DEBUG(3, ("update_printer: printer info has not changed\n")); result = WERR_OK; goto done; } @@ -4718,8 +4748,7 @@ static WERROR update_printer(pipes_struct *p, POLICY_HND *handle, uint32 level, /* Check calling user has permission to update printer description */ if (!print_access_check(NULL, snum, PRINTER_ACCESS_ADMINISTER)) { - DEBUG(3, ("printer property change denied by security " - "descriptor\n")); + DEBUG(3, ("update_printer: printer property change denied by security descriptor\n")); result = WERR_ACCESS_DENIED; goto done; } @@ -4727,12 +4756,38 @@ static WERROR update_printer(pipes_struct *p, POLICY_HND *handle, uint32 level, /* Call addprinter hook */ if (*lp_addprinter_cmd()) { - if (!add_printer_hook(printer)) { + if ( !add_printer_hook(printer) ) { result = WERR_ACCESS_DENIED; goto done; } } + /* + * Set the DRIVER_INIT info in the tdb; trigger on magic value for the + * DEVMODE.displayfrequency, which is not used for printer drivers. This + * requires Win32 client code (see other notes elsewhere in the code). + */ + if (printer->info_2->devmode && + printer->info_2->devmode->displayfrequency == MAGIC_DISPLAY_FREQUENCY) { + + DEBUG(10,("update_printer: Save printer driver init data\n")); + printer->info_2->devmode->displayfrequency = 0; + + if (update_driver_init(*printer, 2)!=0) { + DEBUG(10,("update_printer: error updating printer driver init DEVMODE\n")); + result = WERR_ACCESS_DENIED; + goto done; + } + } else { + /* + * When a *new* driver is bound to a printer, the drivername is used to + * lookup previously saved driver initialization info, which is then + * bound to the printer, simulating what happens in the Windows arch. + */ + if (strequal(printer->info_2->drivername, old_printer->info_2->drivername)) + set_driver_init(printer, 2); + } + /* Update printer info */ result = mod_a_printer(*printer, 2); @@ -4740,7 +4795,7 @@ static WERROR update_printer(pipes_struct *p, POLICY_HND *handle, uint32 level, free_a_printer(&printer, 2); free_a_printer(&old_printer, 2); - srv_spoolss_sendnotify(p, handle); + srv_spoolss_sendnotify(0, PRINTER_CHANGE_SET_PRINTER); return result; } @@ -4760,7 +4815,7 @@ WERROR _spoolss_setprinter(pipes_struct *p, SPOOL_Q_SETPRINTER *q_u, SPOOL_R_SET Printer_entry *Printer = find_printer_index_by_hnd(p, handle); if (!Printer) { - DEBUG(0,("_spoolss_setprinter: Invalid handle (%s)\n", OUR_HANDLE(handle))); + DEBUG(2,("_spoolss_setprinter: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle))); return WERR_BADFID; } @@ -4788,7 +4843,7 @@ WERROR _spoolss_fcpn(pipes_struct *p, SPOOL_Q_FCPN *q_u, SPOOL_R_FCPN *r_u) Printer_entry *Printer= find_printer_index_by_hnd(p, handle); if (!Printer) { - DEBUG(0,("_spoolss_fcpn: Invalid handle (%s)\n", OUR_HANDLE(handle))); + DEBUG(2,("_spoolss_fcpn: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle))); return WERR_BADFID; } @@ -5902,11 +5957,24 @@ static WERROR spoolss_addprinterex_level_2( pipes_struct *p, const UNISTR2 *uni_ return WERR_INVALID_PARAM; } - /* + /* * When a printer is created, the drivername bound to the printer is used * to lookup previously saved driver initialization info, which is then * bound to the new printer, simulating what happens in the Windows arch. */ + + if (!devmode) + set_driver_init(printer, 2); + else { + /* A valid devmode was included, convert and link it + */ + DEBUGADD(10, ("spoolss_addprinterex_level_2: devmode included, converting\n")); + + if (!convert_devicemode(printer->info_2->printername, devmode, + &printer->info_2->devmode)) + return WERR_NOMEM; + } + set_driver_init(printer, 2); /* write the ASCII on disk */ @@ -5925,7 +5993,9 @@ static WERROR spoolss_addprinterex_level_2( pipes_struct *p, const UNISTR2 *uni_ free_a_printer(&printer,2); - srv_spoolss_sendnotify(p, handle); + update_c_setprinter(False); + + srv_spoolss_sendnotify(0, PRINTER_CHANGE_ADD_PRINTER); return WERR_OK; } @@ -6016,7 +6086,9 @@ static WERROR getprinterdriverdir_level_1(UNISTR2 *name, UNISTR2 *uni_environmen pstring long_archi; pstring short_archi; DRIVER_DIRECTORY_1 *info=NULL; - +#if 0 + fstring asc_name, servername; +#endif unistr2_to_ascii(long_archi, uni_environment, sizeof(long_archi)-1); if (get_short_archi(short_archi, long_archi)==False) @@ -6025,6 +6097,20 @@ static WERROR getprinterdriverdir_level_1(UNISTR2 *name, UNISTR2 *uni_environmen if((info=(DRIVER_DIRECTORY_1 *)malloc(sizeof(DRIVER_DIRECTORY_1))) == NULL) return WERR_NOMEM; +#if 0 /* JERRY */ + /* use the name the client sent us */ + + unistr2_to_ascii(asc_name, name, sizeof(asc_name)-1); + if (asc_name[0] == '\\' && asc_name[1] == '\\') + fstrcpy(servername, asc_name); + else { + fstrcpy(servername, "\\\\"); + fstrcat(servername, asc_name); + } + + slprintf(path, sizeof(path)-1, "%s\\print$\\%s", servername, short_archi); +#endif + slprintf(path, sizeof(path)-1, "\\\\%s\\print$\\%s", get_called_name(), short_archi); DEBUG(4,("printer driver directory: [%s]\n", path)); @@ -6118,7 +6204,7 @@ WERROR _spoolss_enumprinterdata(pipes_struct *p, SPOOL_Q_ENUMPRINTERDATA *q_u, S DEBUG(5,("spoolss_enumprinterdata\n")); if (!Printer) { - DEBUG(0,("_spoolss_enumprinterdata: Invalid handle (%s).\n", OUR_HANDLE(handle))); + DEBUG(2,("_spoolss_enumprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle))); return WERR_BADFID; } @@ -6194,20 +6280,17 @@ WERROR _spoolss_enumprinterdata(pipes_struct *p, SPOOL_Q_ENUMPRINTERDATA *q_u, S problems unmarshalling the response */ *out_max_value_len=(in_value_len/sizeof(uint16)); - if((*out_value=(uint16 *)malloc(in_value_len*sizeof(uint8))) == NULL) + if((*out_value=(uint16 *)talloc_zero(p->mem_ctx, in_value_len*sizeof(uint8))) == NULL) return WERR_NOMEM; - ZERO_STRUCTP(*out_value); *out_value_len = rpcstr_push((char *)*out_value, "", in_value_len, 0); /* the data is counted in bytes */ *out_max_data_len = in_data_len; *out_data_len = in_data_len; - if((*data_out=(uint8 *)malloc(in_data_len*sizeof(uint8))) == NULL) + if((*data_out=(uint8 *)talloc_zero(p->mem_ctx, in_data_len*sizeof(uint8))) == NULL) return WERR_NOMEM; - memset(*data_out,'\0',in_data_len); - return WERR_NO_MORE_ITEMS; } @@ -6269,7 +6352,7 @@ WERROR _spoolss_setprinterdata( pipes_struct *p, SPOOL_Q_SETPRINTERDATA *q_u, SP DEBUG(5,("spoolss_setprinterdata\n")); if (!Printer) { - DEBUG(0,("_spoolss_setprinterdata: Invalid handle (%s).\n", OUR_HANDLE(handle))); + DEBUG(2,("_spoolss_setprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle))); return WERR_BADFID; } @@ -6305,6 +6388,8 @@ WERROR _spoolss_setprinterdata( pipes_struct *p, SPOOL_Q_SETPRINTERDATA *q_u, SP convert_specific_param(¶m, value , type, data, real_len); #if 0 + /* JRA. W2K always changes changeid. */ + if (get_specific_param(*printer, 2, param->value, &old_param.data, &old_param.type, (uint32 *)&old_param.data_len)) { @@ -6344,6 +6429,11 @@ WERROR _spoolss_setprinterdata( pipes_struct *p, SPOOL_Q_SETPRINTERDATA *q_u, SP free_nt_printer_param(¶m); SAFE_FREE(old_param.data); +#if 0 + /* Is this correct. JRA ? */ + srv_spoolss_sendnotify(0, PRINTER_CHANGE_SET_PRINTER); +#endif + return status; } @@ -6364,7 +6454,7 @@ WERROR _spoolss_deleteprinterdata(pipes_struct *p, SPOOL_Q_DELETEPRINTERDATA *q_ DEBUG(5,("spoolss_deleteprinterdata\n")); if (!Printer) { - DEBUG(0,("_spoolss_deleteprinterdata: Invalid handle (%s).\n", OUR_HANDLE(handle))); + DEBUG(2,("_spoolss_deleteprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle))); return WERR_BADFID; } @@ -6402,40 +6492,60 @@ WERROR _spoolss_addform( pipes_struct *p, SPOOL_Q_ADDFORM *q_u, SPOOL_R_ADDFORM /* uint32 level = q_u->level; - notused. */ FORM *form = &q_u->form; nt_forms_struct tmpForm; - int count=0, snum; + int snum; + WERROR status = WERR_OK; + NT_PRINTER_INFO_LEVEL *printer = NULL; + + int count=0; nt_forms_struct *list=NULL; Printer_entry *Printer = find_printer_index_by_hnd(p, handle); DEBUG(5,("spoolss_addform\n")); if (!Printer) { - DEBUG(0,("_spoolss_addform: Invalid handle (%s).\n", OUR_HANDLE(handle))); + DEBUG(2,("_spoolss_addform: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle))); return WERR_BADFID; } - /* Must be administrator to add a form */ - - if (!get_printer_snum(p, handle, &snum)) - return WERR_BADFID; + /* + * FIXME!! Feels like there should be an access check here, but haven't + * had time to verify. --jerry + */ - if (!print_access_check(NULL, snum, PRINTER_ACCESS_ADMINISTER)) { - DEBUG(0, ("_spoolss_addform: Access denied\n")); - return WERR_ACCESS_DENIED; - } + if (!get_printer_snum(p,handle, &snum)) + return WERR_BADFID; + /* can't add if builtin */ if (get_a_builtin_ntform(&form->name,&tmpForm)) { - return WERR_FILE_EXISTS; + return WERR_ALREADY_EXISTS; } count=get_ntforms(&list); if(!add_a_form(&list, form, &count)) return WERR_NOMEM; write_ntforms(&list, count); + + /* + * ChangeID must always be set + */ + + if (!get_printer_snum(p,handle, &snum)) + return WERR_BADFID; + status = get_a_printer(&printer, 2, lp_servicename(snum)); + if (!W_ERROR_IS_OK(status)) + goto done; + + status = mod_a_printer(*printer, 2); + if (!W_ERROR_IS_OK(status)) + goto done; + +done: + free_a_printer(&printer, 2); SAFE_FREE(list); - return WERR_OK; + return status; } /**************************************************************************** @@ -6446,25 +6556,27 @@ WERROR _spoolss_deleteform( pipes_struct *p, SPOOL_Q_DELETEFORM *q_u, SPOOL_R_DE POLICY_HND *handle = &q_u->handle; UNISTR2 *form_name = &q_u->name; nt_forms_struct tmpForm; - int count=0, snum; + int count=0; WERROR ret = WERR_OK; nt_forms_struct *list=NULL; Printer_entry *Printer = find_printer_index_by_hnd(p, handle); + int snum; + WERROR status = WERR_OK; + NT_PRINTER_INFO_LEVEL *printer = NULL; DEBUG(5,("spoolss_deleteform\n")); if (!Printer) { - DEBUG(0,("_spoolss_deleteform: Invalid handle (%s).\n", OUR_HANDLE(handle))); + DEBUG(2,("_spoolss_deleteform: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle))); return WERR_BADFID; } - /* Must be administrator to set a form */ - - if (!get_printer_snum(p, handle, &snum)) + if (!get_printer_snum(p, handle, &snum)) return WERR_BADFID; if (!print_access_check(NULL, snum, PRINTER_ACCESS_ADMINISTER)) { - DEBUG(0, ("_spoolss_addform: Access denied\n")); + DEBUG(3, ("security descriptor change denied by existing " + "security descriptor\n")); return WERR_ACCESS_DENIED; } @@ -6477,6 +6589,23 @@ WERROR _spoolss_deleteform( pipes_struct *p, SPOOL_Q_DELETEFORM *q_u, SPOOL_R_DE if(!delete_a_form(&list, form_name, &count, &ret)) return WERR_INVALID_PARAM; + /* + * ChangeID must always be set + */ + + if (!get_printer_snum(p,handle, &snum)) + return WERR_BADFID; + + status = get_a_printer(&printer, 2, lp_servicename(snum)); + if (!W_ERROR_IS_OK(status)) + goto done; + + status = mod_a_printer(*printer, 2); + if (!W_ERROR_IS_OK(status)) + goto done; + +done: + free_a_printer(&printer, 2); SAFE_FREE(list); return ret; @@ -6492,24 +6621,27 @@ WERROR _spoolss_setform(pipes_struct *p, SPOOL_Q_SETFORM *q_u, SPOOL_R_SETFORM * /* uint32 level = q_u->level; - notused. */ FORM *form = &q_u->form; nt_forms_struct tmpForm; - int count=0, snum; + int snum; + WERROR status = WERR_OK; + NT_PRINTER_INFO_LEVEL *printer = NULL; + + int count=0; nt_forms_struct *list=NULL; Printer_entry *Printer = find_printer_index_by_hnd(p, handle); DEBUG(5,("spoolss_setform\n")); if (!Printer) { - DEBUG(0,("_spoolss_setform: Invalid handle (%s).\n", OUR_HANDLE(handle))); + DEBUG(2,("_spoolss_setform: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle))); return WERR_BADFID; } - /* Must be administrator to set a form */ - if (!get_printer_snum(p, handle, &snum)) return WERR_BADFID; if (!print_access_check(NULL, snum, PRINTER_ACCESS_ADMINISTER)) { - DEBUG(0, ("_spoolss_addform: Access denied\n")); + DEBUG(3, ("security descriptor change denied by existing " + "security descriptor\n")); return WERR_ACCESS_DENIED; } @@ -6522,6 +6654,23 @@ WERROR _spoolss_setform(pipes_struct *p, SPOOL_Q_SETFORM *q_u, SPOOL_R_SETFORM * update_a_form(&list, form, count); write_ntforms(&list, count); + /* + * ChangeID must always be set + */ + + if (!get_printer_snum(p,handle, &snum)) + return WERR_BADFID; + + status = get_a_printer(&printer, 2, lp_servicename(snum)); + if (!W_ERROR_IS_OK(status)) + goto done; + + status = mod_a_printer(*printer, 2); + if (!W_ERROR_IS_OK(status)) + goto done; + +done: + free_a_printer(&printer, 2); SAFE_FREE(list); return WERR_OK; @@ -6943,7 +7092,7 @@ WERROR _spoolss_getprinterdataex(pipes_struct *p, SPOOL_Q_GETPRINTERDATAEX *q_u, if (!Printer) { if((*data=(uint8 *)talloc_zero(p->mem_ctx, 4*sizeof(uint8))) == NULL) return WERR_NOMEM; - DEBUG(0,("_spoolss_getprinterdata: Invalid handle (%s).\n", OUR_HANDLE(handle))); + DEBUG(2,("_spoolss_getprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle))); return WERR_BADFID; } @@ -7122,7 +7271,7 @@ WERROR _spoolss_enumprinterdataex(pipes_struct *p, SPOOL_Q_ENUMPRINTERDATAEX *q_ DEBUG(4,("_spoolss_enumprinterdataex\n")); if (!Printer) { - DEBUG(0,("_spoolss_enumprinterdata: Invalid handle (%s).\n", OUR_HANDLE(handle))); + DEBUG(2,("_spoolss_enumprinterdata: Invalid handle (%s:%u:%u1<).\n", OUR_HANDLE(handle))); return WERR_BADFID; } @@ -7259,7 +7408,7 @@ static WERROR getprintprocessordirectory_level_1(UNISTR2 *name, unistr2_to_ascii(long_archi, environment, sizeof(long_archi)-1); - if (get_short_archi(short_archi, long_archi)==False) + if (get_short_archi(short_archi, long_archi)==FALSE) return WERR_INVALID_ENVIRONMENT; if((info=(PRINTPROCESSOR_DIRECTORY_1 *)malloc(sizeof(PRINTPROCESSOR_DIRECTORY_1))) == NULL) |