From 4ed429481c6aa2517b8b1615f95900d7db372cd6 Mon Sep 17 00:00:00 2001 From: Gerald Carter Date: Fri, 16 Aug 2002 15:36:37 +0000 Subject: Fairly large change to printing code. * removed support for PHANTOM_DEVMODE printer data * s/NT_PRINTER_PARAM/REGISTRY_VALUE/g - This was a good bit of work. Everything seems stable, but is not complete. * support for printer data keys other than PrinterDriverData in the store and fetch routines. Still needs to be plugged into the XxxPrinterDataEx() calls. Tested against NT4.0 & 2k. Like I said, it's not done, but doesn't crash so it shouldn't upset anyone (unless you're trying to build a Samba printer server off of HEAD). More work to come. Should settle by Monday. jerry (This used to be commit 7ba7c04c0e961618c82c2112b9627af114c6cc42) --- source3/include/nt_printing.h | 31 +- source3/printing/nt_printing.c | 746 +++++++++++++++--------------------- source3/registry/reg_frontend.c | 91 ++++- source3/registry/reg_printing.c | 6 +- source3/rpc_parse/parse_spoolss.c | 36 -- source3/rpc_server/srv_spoolss_nt.c | 710 ++++++++++++---------------------- 6 files changed, 669 insertions(+), 951 deletions(-) (limited to 'source3') diff --git a/source3/include/nt_printing.h b/source3/include/nt_printing.h index 57181c6659..6303136894 100644 --- a/source3/include/nt_printing.h +++ b/source3/include/nt_printing.h @@ -174,14 +174,26 @@ typedef struct nt_printer_driver_info_level NT_PRINTER_DRIVER_INFO_LEVEL_6 *info_6; } NT_PRINTER_DRIVER_INFO_LEVEL; -typedef struct nt_printer_param -{ - fstring value; - uint32 type; - uint8 *data; - int data_len; - struct nt_printer_param *next; -} NT_PRINTER_PARAM; +/* predefined registry key names for printer data */ + +#define SPOOL_PRINTERDATA_KEY "PrinterDriverData" +#define SPOOL_DSSPOOLER_KEY "DsSpooler" +#define SPOOL_DSDRIVER_KEY "DsDriver" +#define SPOOL_DSUSER_KEY "DsUser" + +/* container for a single registry key */ + +typedef struct { + char *name; + REGVAL_CTR values; +} NT_PRINTER_KEY; + +/* container for all printer data */ + +typedef struct { + int num_keys; + NT_PRINTER_KEY *keys; +} NT_PRINTER_DATA; typedef struct ntdevicemode { @@ -246,9 +258,8 @@ typedef struct nt_printer_info_level_2 fstring printprocessor; fstring datatype; fstring parameters; - NT_PRINTER_PARAM *specific; + NT_PRINTER_DATA data; SEC_DESC_BUF *secdesc_buf; - /* not used but ... and how ??? */ uint32 changeid; uint32 c_setprinter; uint32 setuptime; diff --git a/source3/printing/nt_printing.c b/source3/printing/nt_printing.c index e9ebb89d60..c497c65bfe 100644 --- a/source3/printing/nt_printing.c +++ b/source3/printing/nt_printing.c @@ -1962,22 +1962,52 @@ static int pack_devicemode(NT_DEVICEMODE *nt_devmode, char *buf, int buflen) } /**************************************************************************** -****************************************************************************/ -static int pack_specifics(NT_PRINTER_PARAM *param, char *buf, int buflen) + Pack all values in all printer keys + ***************************************************************************/ + +static int pack_values(NT_PRINTER_DATA *data, char *buf, int buflen) { - int len = 0; + int len = 0; + int i, j; + REGISTRY_VALUE *val; + REGVAL_CTR *val_ctr; + pstring path; + int num_values; - while (param != NULL) { - len += tdb_pack(buf+len, buflen-len, "pfdB", - param, - param->value, - param->type, - param->data_len, - param->data); - param=param->next; + if ( !data ) + return 0; + + /* loop over all keys */ + + for ( i=0; inum_keys; i++ ) + { + val_ctr = &data->keys[i].values; + num_values = regval_ctr_numvals( val_ctr ); + + /* loop over all values */ + + for ( j=0; j\ */ + + val = regval_ctr_specific_value( val_ctr, j ); + pstrcpy( path, data->keys[i].name ); + pstrcat( path, "\\" ); + pstrcat( path, regval_name(val) ); + + len += tdb_pack(buf+len, buflen-len, "pPdB", + val, + path, + regval_type(val), + regval_size(val), + regval_data_p(val) ); + } + } - len += tdb_pack(buf+len, buflen-len, "p", param); + /* terminator */ + + len += tdb_pack(buf+len, buflen-len, "p", NULL); return len; } @@ -2071,7 +2101,7 @@ static WERROR update_a_printer_2(NT_PRINTER_INFO_LEVEL_2 *info) len += pack_devicemode(info->devmode, buf+len, buflen-len); - len += pack_specifics(info->specific, buf+len, buflen-len); + len += pack_values( &info->data, buf+len, buflen-len ); if (buflen != len) { char *tb; @@ -2110,89 +2140,6 @@ done: } -/**************************************************************************** -****************************************************************************/ -void add_a_specific_param(NT_PRINTER_INFO_LEVEL_2 *info_2, NT_PRINTER_PARAM **param) -{ - NT_PRINTER_PARAM *current; - - DEBUG(108,("add_a_specific_param\n")); - - (*param)->next=NULL; - - if (info_2->specific == NULL) - { - info_2->specific=*param; - } - else - { - current=info_2->specific; - while (current->next != NULL) { - current=current->next; - } - current->next=*param; - } - - *param = NULL; -} - -/**************************************************************************** -****************************************************************************/ -BOOL unlink_specific_param_if_exist(NT_PRINTER_INFO_LEVEL_2 *info_2, NT_PRINTER_PARAM *param) -{ - NT_PRINTER_PARAM *current; - NT_PRINTER_PARAM *previous; - - current=info_2->specific; - previous=current; - - if (current==NULL) return (False); - - if ( !strcmp(current->value, param->value) && - (strlen(current->value)==strlen(param->value)) ) { - DEBUG(109,("deleting first value\n")); - info_2->specific=current->next; - SAFE_FREE(current->data); - SAFE_FREE(current); - DEBUG(109,("deleted first value\n")); - return (True); - } - - current=previous->next; - - while ( current!=NULL ) { - if (!strcmp(current->value, param->value) && - strlen(current->value)==strlen(param->value) ) { - DEBUG(109,("deleting current value\n")); - previous->next=current->next; - SAFE_FREE(current->data); - SAFE_FREE(current); - DEBUG(109,("deleted current value\n")); - return(True); - } - - previous=previous->next; - current=current->next; - } - return (False); -} - -/**************************************************************************** - Clean up and deallocate a (maybe partially) allocated NT_PRINTER_PARAM. -****************************************************************************/ -void free_nt_printer_param(NT_PRINTER_PARAM **param_ptr) -{ - NT_PRINTER_PARAM *param = *param_ptr; - - if(param == NULL) - return; - - DEBUG(106,("free_nt_printer_param: deleting param [%s]\n", param->value)); - - SAFE_FREE(param->data); - SAFE_FREE(*param_ptr); -} - /**************************************************************************** Malloc and return an NT devicemode. ****************************************************************************/ @@ -2294,7 +2241,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); } @@ -2304,23 +2251,29 @@ void free_nt_devicemode(NT_DEVICEMODE **devmode_ptr) static void free_nt_printer_info_level_2(NT_PRINTER_INFO_LEVEL_2 **info_ptr) { NT_PRINTER_INFO_LEVEL_2 *info = *info_ptr; - NT_PRINTER_PARAM *param_ptr; + NT_PRINTER_DATA *data; + int i; - if(info == NULL) + if ( !info ) return; DEBUG(106,("free_nt_printer_info_level_2: deleting info\n")); free_nt_devicemode(&info->devmode); - for(param_ptr = info->specific; param_ptr; ) { - NT_PRINTER_PARAM *tofree = param_ptr; - - param_ptr = param_ptr->next; - free_nt_printer_param(&tofree); + /* clean up all registry keys */ + + data = &info->data; + for ( i=0; inum_keys; i++ ) + { + SAFE_FREE( data->keys[i].name ); + regval_ctr_destroy( &data->keys[i].values ); } + SAFE_FREE( data->keys ); - SAFE_FREE(*info_ptr); + /* finally the top level structure */ + + SAFE_FREE( *info_ptr ); } @@ -2400,32 +2353,257 @@ static int unpack_devicemode(NT_DEVICEMODE **nt_devmode, char *buf, int buflen) } /**************************************************************************** -****************************************************************************/ -static int unpack_specifics(NT_PRINTER_PARAM **list, char *buf, int buflen) + allocate and initialize a new slot in + ***************************************************************************/ + +static int add_new_printer_key( NT_PRINTER_DATA *data, char *name ) { - int len = 0; - NT_PRINTER_PARAM param, *p; + NT_PRINTER_KEY *d; + int key_index; + + if ( !data || !name ) + return -1; + + /* allocate another slot in the NT_PRINTER_KEY array */ + + d = Realloc( data->keys, sizeof(NT_PRINTER_KEY)*(data->num_keys+1) ); + if ( d ) + data->keys = d; + + key_index = data->num_keys; + + /* initialze new key */ + + data->num_keys++; + data->keys[key_index].name = strdup( name ); + + ZERO_STRUCTP( &data->keys[key_index].values ); + + regval_ctr_init( &data->keys[key_index].values ); + + DEBUG(10,("add_new_printer_key: Inserted new data key [%s]\n", name )); + + return key_index; +} + +/**************************************************************************** + search for a registry key name in the existing printer data + ***************************************************************************/ + +int lookup_printerkey( NT_PRINTER_DATA *data, char *name ) +{ + int key_index = -1; + int i; + + if ( !data || !name ) + return -1; + + DEBUG(12,("lookup_printerkey: Looking for [%s]\n", name)); - *list = NULL; + /* loop over all existing keys */ + + for ( i=0; inum_keys; i++ ) + { + if ( strcmp(data->keys[i].name, name) == 0 ) { + DEBUG(12,("lookup_printerkey: Found [%s]!\n", name)); + key_index = i; + break; + + } + } + + return key_index; +} + +/**************************************************************************** + ***************************************************************************/ + +WERROR delete_all_printer_data( NT_PRINTER_INFO_LEVEL_2 *p2 ) +{ + WERROR result = WERR_OK; + NT_PRINTER_DATA *data; + int i; + + data = &p2->data; + + for ( i=0; inum_keys; i++ ) + { + DEBUG(8,("delete_all_printer_data: Removed all Printer Data from key [%s]\n", + data->keys[i].name)); + + SAFE_FREE( data->keys[i].name ); + regval_ctr_destroy( &data->keys[i].values ); + } + + SAFE_FREE( data->keys ); + + DEBUG(8,("delete_all_printer_data: Removed all Printer Data from printer [%s]\n", + p2->printername )); + + ZERO_STRUCTP( data ); + + return result; +} + +/**************************************************************************** + ***************************************************************************/ + +WERROR delete_printer_data( NT_PRINTER_INFO_LEVEL_2 *p2, char *key, char *value ) +{ + WERROR result = WERR_OK; + int key_index; + + /* we must have names on non-zero length */ + + if ( !key || !*key|| !value || !*value ) + return WERR_INVALID_NAME; + + /* find the printer key first */ + + key_index = lookup_printerkey( &p2->data, key ); + if ( key_index == -1 ) + key_index = add_new_printer_key( &p2->data, key ); + + if ( key_index == -1 ) + return WERR_NOMEM; + + regval_ctr_delvalue( &p2->data.keys[key_index].values, value ); + + DEBUG(8,("delete_printer_data: Removed key => [%s], value => [%s]\n", + key, value )); + + return result; +} + +/**************************************************************************** + ***************************************************************************/ + +WERROR add_printer_data( NT_PRINTER_INFO_LEVEL_2 *p2, char *key, char *value, + uint32 type, uint8 *data, int real_len ) +{ + WERROR result = WERR_OK; + int key_index; - while (1) { - len += tdb_unpack(buf+len, buflen-len, "p", &p); - if (!p) break; + /* we must have names on non-zero length */ + + if ( !key || !*key|| !value || !*value ) + return WERR_INVALID_NAME; + + /* find the printer key first */ + + key_index = lookup_printerkey( &p2->data, key ); + if ( key_index == -1 ) + key_index = add_new_printer_key( &p2->data, key ); + + if ( key_index == -1 ) + return WERR_NOMEM; + + regval_ctr_addvalue( &p2->data.keys[key_index].values, value, + type, data, real_len ); + + DEBUG(8,("add_printer_data: Added key => [%s], value => [%s], size => [%d]\n", + key, value, real_len )); + + return result; +} + +/**************************************************************************** + ***************************************************************************/ + +REGISTRY_VALUE* get_printer_data( NT_PRINTER_INFO_LEVEL_2 *p2, char *key, char *value ) +{ + int key_index; + + if ( (key_index = lookup_printerkey( &p2->data, key )) == -1 ) + return NULL; + DEBUG(8,("get_printer_data: Attempting to lookup key => [%s], value => [%s]\n", + key, value )); + + return regval_ctr_getvalue( &p2->data.keys[key_index].values, value ); +} + +/**************************************************************************** + Unpack a list of registry values frem the TDB + ***************************************************************************/ + +static int unpack_values(NT_PRINTER_DATA *printer_data, char *buf, int buflen) +{ + int len = 0; + uint32 type; + pstring string, valuename, keyname; + char *str; + int size; + uint8 *data_p; + REGISTRY_VALUE *regval_p; + int key_index; + + /* add the "PrinterDriverData" key first for performance reasons */ + + add_new_printer_key( printer_data, SPOOL_PRINTERDATA_KEY ); + + /* loop and unpack the rest of the registry values */ + + while ( True ) + { + + /* check to see if there are any more registry values */ + + len += tdb_unpack(buf+len, buflen-len, "p", ®val_p); + if ( !regval_p ) + break; + + /* unpack the next regval */ + len += tdb_unpack(buf+len, buflen-len, "fdB", - param.value, - ¶m.type, - ¶m.data_len, - ¶m.data); - param.next = *list; - *list = memdup(¶m, sizeof(param)); + string, + &type, + &size, + &data_p); + + /* + * break of the keyname from the value name. + * Should only be one '\' in the string returned. + */ + + str = strchr( string, '\\'); + + /* Put in "PrinterDriverData" is no key specified */ + + if ( !str ) { + pstrcpy( keyname, SPOOL_PRINTERDATA_KEY ); + pstrcpy( valuename, string ); + } + else { + *str = '\0'; + pstrcpy( keyname, string ); + pstrcpy( valuename, str+1 ); + } + + /* see if we need a new key */ + + if ( (key_index=lookup_printerkey( printer_data, keyname )) == -1 ) + key_index = add_new_printer_key( printer_data, keyname ); + + if ( key_index == -1 ) { + DEBUG(0,("unpack_values: Failed to allocate a new key [%s]!\n", + keyname)); + break; + } + + /* add the new value */ + + regval_ctr_addvalue( &printer_data->keys[key_index].values, valuename, type, data_p, size ); - DEBUG(8,("specific: [%s], len: %d\n", param.value, param.data_len)); + DEBUG(8,("specific: [%s\\%s], len: %d\n", keyname, valuename, size)); } return len; } +/**************************************************************************** + ***************************************************************************/ + static void map_to_os2_driver(fstring drivername) { static BOOL initialised=False; @@ -2659,10 +2837,10 @@ static WERROR get_a_printer_2(NT_PRINTER_INFO_LEVEL_2 **info_ptr, fstring sharen info.devmode = construct_nt_devicemode(printername); } - len += unpack_specifics(&info.specific,dbuf.dptr+len, dbuf.dsize-len); + len += unpack_values( &info.data, dbuf.dptr+len, dbuf.dsize-len ); /* This will get the current RPC talloc context, but we should be - passing this as a parameter... fixme... JRA ! */ + passing this as a parameter... fixme... JRA ! */ nt_printing_getsec(get_talloc_ctx(), sharename, &info.secdesc_buf); @@ -2849,24 +3027,19 @@ WERROR mod_a_printer(NT_PRINTER_INFO_LEVEL printer, uint32 level) Initialize printer devmode & data with previously saved driver init values. ****************************************************************************/ -static BOOL set_driver_init_2(NT_PRINTER_INFO_LEVEL_2 *info_ptr) +static BOOL set_driver_init_2( NT_PRINTER_INFO_LEVEL_2 *info_ptr ) { int len = 0; pstring key; TDB_DATA kbuf, dbuf; - NT_PRINTER_PARAM *current; NT_PRINTER_INFO_LEVEL_2 info; /* - * Delete any printer data 'specifics' already set. When called for driver + * Delete any printer data 'values' 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); - } + delete_all_printer_data( info_ptr ); ZERO_STRUCT(info); @@ -2876,7 +3049,7 @@ static BOOL 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. @@ -2945,9 +3118,10 @@ static BOOL set_driver_init_2(NT_PRINTER_INFO_LEVEL_2 *info_ptr) info_ptr->printername, info_ptr->drivername)); /* - * Add the printer data 'specifics' to the new printer + * Add the printer data 'values' to the new printer */ - len += unpack_specifics(&info_ptr->specific,dbuf.dptr+len, dbuf.dsize-len); + len += unpack_values( &info_ptr->data, dbuf.dptr+len, dbuf.dsize-len ); + SAFE_FREE(dbuf.dptr); @@ -3005,7 +3179,7 @@ BOOL del_driver_init(char *drivername) } /**************************************************************************** - Pack up the DEVMODE and specifics for a printer into a 'driver init' entry + Pack up the DEVMODE and values for a printer into a 'driver init' entry in the tdb. Note: this is different from the driver entry and the printer entry. There should be a single driver init entry for each driver regardless of whether it was installed from NT or 2K. Technically, they should be @@ -3026,7 +3200,7 @@ static uint32 update_driver_init_2(NT_PRINTER_INFO_LEVEL_2 *info) len = 0; len += pack_devicemode(info->devmode, buf+len, buflen-len); - len += pack_specifics(info->specific, buf+len, buflen-len); + len += pack_values( &info->data, buf+len, buflen-len ); if (buflen != len) { char *tb; @@ -3057,14 +3231,14 @@ done: SAFE_FREE(buf); - DEBUG(10,("update_driver_init_2: Saved printer [%s] init DEVMODE & specifics for driver [%s]\n", + DEBUG(10,("update_driver_init_2: Saved printer [%s] init DEVMODE & values for driver [%s]\n", info->sharename, info->drivername)); return ret; } /**************************************************************************** - Update (i.e. save) the driver init info (DEVMODE and specifics) for a printer + Update (i.e. save) the driver init info (DEVMODE and values) for a printer ****************************************************************************/ uint32 update_driver_init(NT_PRINTER_INFO_LEVEL printer, uint32 level) @@ -3088,154 +3262,6 @@ uint32 update_driver_init(NT_PRINTER_INFO_LEVEL printer, uint32 level) return result; } -/**************************************************************************** - Convert the printer data value, a REG_BINARY array, into an initialization - DEVMODE. Note: the array must be parsed as if it was a DEVMODE in an rpc... - got to keep the endians happy :). -****************************************************************************/ - -static BOOL convert_driver_init(NT_PRINTER_PARAM *param, TALLOC_CTX *ctx, NT_DEVICEMODE *nt_devmode) -{ - BOOL result = False; - prs_struct ps; - DEVICEMODE devmode; - - ZERO_STRUCT(devmode); - - prs_init(&ps, 0, ctx, UNMARSHALL); - ps.data_p = (char *)param->data; - ps.buffer_size = param->data_len; - - if (spoolss_io_devmode("phantom DEVMODE", &ps, 0, &devmode)) - result = convert_devicemode("", &devmode, &nt_devmode); - else - DEBUG(10,("convert_driver_init: error parsing DEVMODE\n")); - - return result; -} - -/**************************************************************************** - Set the DRIVER_INIT info in the tdb. Requires Win32 client code that: - - 1. Use the driver's config DLL to this UNC printername and: - a. Call DrvPrintEvent with PRINTER_EVENT_INITIALIZE - b. Call DrvConvertDevMode with CDM_DRIVER_DEFAULT to get default DEVMODE - 2. Call SetPrinterData with the 'magic' key and the DEVMODE as data. - - The last step triggers saving the "driver initialization" information for - this printer into the tdb. Later, new printers that use this driver will - have this initialization information bound to them. This simulates the - driver initialization, as if it had run on the Samba server (as it would - have done on NT). - - The Win32 client side code requirement sucks! But until we can run arbitrary - Win32 printer driver code on any Unix that Samba runs on, we are stuck with it. - - It would have been easier to use SetPrinter because all the UNMARSHALLING of - the DEVMODE is done there, but 2K/XP clients do not set the DEVMODE... think - about it and you will realize why. JRR 010720 -****************************************************************************/ - -static WERROR save_driver_init_2(NT_PRINTER_INFO_LEVEL *printer, NT_PRINTER_PARAM *param) -{ - WERROR status = WERR_OK; - TALLOC_CTX *ctx = NULL; - NT_DEVICEMODE *nt_devmode = NULL; - NT_DEVICEMODE *tmp_devmode = printer->info_2->devmode; - - /* - * When the DEVMODE is already set on the printer, don't try to unpack it. - */ - - if (!printer->info_2->devmode && param->data_len) { - /* - * 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); - - /* - * 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; - } - - /* - * Pack up and add (or update) the DEVMODE and any current printer data to - * a 'driver init' element in the tdb - * - */ - - if (update_driver_init(*printer, 2)!=0) { - DEBUG(10,("save_driver_init_2: error updating DEVMODE\n")); - status = WERR_NOMEM; - goto done; - } - - /* - * If driver initialization info was successfully saved, set the current - * printer to match it. This allows initialization of the current printer - * as well as the driver. - */ - status = mod_a_printer(*printer, 2); - if (!W_ERROR_IS_OK(status)) { - DEBUG(10,("save_driver_init_2: error setting DEVMODE on printer [%s]\n", - printer->info_2->printername)); - } - -#if 0 /* JERRY */ - srv_spoolss_sendnotify(p, handle); -#endif - - done: - talloc_destroy(ctx); - if (nt_devmode) - SAFE_FREE(nt_devmode->private); - SAFE_FREE(nt_devmode); - printer->info_2->devmode = tmp_devmode; - - return status; -} - -/**************************************************************************** - Update the driver init info (DEVMODE and specifics) for a printer -****************************************************************************/ - -WERROR save_driver_init(NT_PRINTER_INFO_LEVEL *printer, uint32 level, NT_PRINTER_PARAM *param) -{ - WERROR status = WERR_OK; - - switch (level) - { - case 2: - { - status=save_driver_init_2(printer, param); - break; - } - default: - status=WERR_UNKNOWN_LEVEL; - break; - } - - return status; -} - /**************************************************************************** Get a NT_PRINTER_INFO_LEVEL struct. It returns malloced memory. ****************************************************************************/ @@ -3851,83 +3877,6 @@ WERROR delete_printer_driver( NT_PRINTER_DRIVER_INFO_LEVEL_3 *i, struct current_ return delete_printer_driver_internal(i, user, version, delete_files ); } - -/**************************************************************************** -****************************************************************************/ - -BOOL get_specific_param_by_index(NT_PRINTER_INFO_LEVEL printer, uint32 level, uint32 param_index, - fstring value, uint8 **data, uint32 *type, uint32 *len) -{ - /* right now that's enough ! */ - NT_PRINTER_PARAM *param; - int i=0; - - param=printer.info_2->specific; - - while (param != NULL && i < param_index) { - param=param->next; - i++; - } - - if (param == NULL) - return False; - - /* exited because it exist */ - *type=param->type; - StrnCpy(value, param->value, sizeof(fstring)-1); - *data=(uint8 *)malloc(param->data_len*sizeof(uint8)); - if(*data == NULL) - return False; - ZERO_STRUCTP(*data); - memcpy(*data, param->data, param->data_len); - *len=param->data_len; - return True; -} - -/**************************************************************************** -****************************************************************************/ -BOOL get_specific_param(NT_PRINTER_INFO_LEVEL printer, uint32 level, - fstring value, uint8 **data, uint32 *type, uint32 *len) -{ - /* right now that's enough ! */ - NT_PRINTER_PARAM *param; - - DEBUG(10, ("get_specific_param\n")); - - param=printer.info_2->specific; - - while (param != NULL) - { -#if 1 /* JRA - I think this should be case insensitive.... */ - if ( strequal(value, param->value) -#else - if ( !strcmp(value, param->value) -#endif - && strlen(value)==strlen(param->value)) - break; - - param=param->next; - } - - if (param != NULL) - { - DEBUGADD(10, ("get_specific_param: found one param\n")); - /* exited because it exist */ - *type=param->type; - - *data=(uint8 *)malloc(param->data_len*sizeof(uint8)); - if(*data == NULL) - return False; - memcpy(*data, param->data, param->data_len); - *len=param->data_len; - - DEBUGADD(10, ("get_specific_param: exit true\n")); - return (True); - } - DEBUGADD(10, ("get_specific_param: exit false\n")); - return (False); -} - /**************************************************************************** Store a security desc for a printer. ****************************************************************************/ @@ -4363,76 +4312,3 @@ BOOL print_time_access_check(int snum) return ok; } -#if 0 /* JERRY - not used */ -/**************************************************************************** - Attempt to write a default device. -*****************************************************************************/ - -WERROR printer_write_default_dev(int snum, const PRINTER_DEFAULT *printer_default) -{ - NT_PRINTER_INFO_LEVEL *printer = NULL; - WERROR result; - - /* - * Don't bother if no default devicemode was sent. - */ - - if (printer_default->devmode_cont.devmode == NULL) - return WERR_OK; - - result = get_a_printer(&printer, 2, lp_servicename(snum)); - if (!W_ERROR_IS_OK(result)) return result; - - /* - * Just ignore it if we already have a devmode. - */ -#if 0 - if (printer->info_2->devmode != NULL) - goto done; -#endif - /* - * We don't have a devicemode and we're trying to write - * one. Check we have the access needed. - */ - DEBUG(5,("printer_write_default_dev: access: %x\n", printer_default->access_required)); - - if ( (printer_default->access_required & PRINTER_ACCESS_ADMINISTER) != - PRINTER_ACCESS_ADMINISTER) { - DEBUG(5,("printer_write_default_dev: invalid request access to update: %x\n", printer_default->access_required)); - result = WERR_ACCESS_DENIED; - goto done; - } - - if (!print_access_check(NULL, snum, PRINTER_ACCESS_ADMINISTER)) { - DEBUG(5,("printer_write_default_dev: Access denied for printer %s\n", - lp_servicename(snum) )); - result = WERR_ACCESS_DENIED; - /*result = NT_STATUS_NO_PROBLEMO;*/ - goto done; - } - - DEBUG(5,("printer_write_default_dev: updating, check OK.\n")); - - /* - * Convert the on the wire devicemode format to the internal one. - */ - - if (!convert_devicemode(printer->info_2->printername, - printer_default->devmode_cont.devmode, - &printer->info_2->devmode)) { - result = WERR_NOMEM; - goto done; - } - - /* - * Finally write back to the tdb. - */ - - result = mod_a_printer(*printer, 2); - - done: - - free_a_printer(&printer, 2); - return result; -} -#endif /* JERRY */ diff --git a/source3/registry/reg_frontend.c b/source3/registry/reg_frontend.c index c0788c1b75..45c1f24001 100644 --- a/source3/registry/reg_frontend.c +++ b/source3/registry/reg_frontend.c @@ -188,6 +188,38 @@ void free_registry_value( REGISTRY_VALUE *val ) return; } +/********************************************************************** + *********************************************************************/ + +uint8* regval_data_p( REGISTRY_VALUE *val ) +{ + return val->data_p; +} + +/********************************************************************** + *********************************************************************/ + +int regval_size( REGISTRY_VALUE *val ) +{ + return val->size; +} + +/********************************************************************** + *********************************************************************/ + +char* regval_name( REGISTRY_VALUE *val ) +{ + return val->valuename; +} + +/********************************************************************** + *********************************************************************/ + +uint32 regval_type( REGISTRY_VALUE *val ) +{ + return val->type; +} + /*********************************************************************** Retreive a pointer to a specific value. Caller shoud dup the structure since this memory may go away with a regval_ctr_destroy() @@ -214,7 +246,7 @@ TALLOC_CTX* regval_ctr_getctx( REGVAL_CTR *val ) } /*********************************************************************** - Add a new regostry value to the array + Add a new registry value to the array **********************************************************************/ int regval_ctr_addvalue( REGVAL_CTR *ctr, char *name, uint16 type, @@ -237,7 +269,7 @@ int regval_ctr_addvalue( REGVAL_CTR *ctr, char *name, uint16 type, ctr->values = ppreg; } - /* allocate a new valuie and store the pointer in the arrya */ + /* allocate a new value and store the pointer in the arrya */ ctr->values[ctr->num_values] = talloc( ctr->ctx, sizeof(REGISTRY_VALUE) ); @@ -253,6 +285,61 @@ int regval_ctr_addvalue( REGVAL_CTR *ctr, char *name, uint16 type, return ctr->num_values; } +/*********************************************************************** + Delete a single value from the registry container. + No need to free memory since it is talloc'd. + **********************************************************************/ + +int regval_ctr_delvalue( REGVAL_CTR *ctr, char *name ) +{ + int i; + + /* search for the value */ + + for ( i=0; inum_values; i++ ) { + if ( strcmp( ctr->values[i]->valuename, name ) == 0) + break; + } + + /* just return if we don't find it */ + + if ( i == ctr->num_values ) + return ctr->num_values; + + /* just shift everything down one */ + + for ( /* use previous i */; i<(ctr->num_values-1); i++ ) + memcpy( ctr->values[i], ctr->values[i+1], sizeof(REGISTRY_VALUE) ); + + /* paranoia */ + + ZERO_STRUCTP( ctr->values[i] ); + + ctr->num_values--; + + return ctr->num_values; +} + +/*********************************************************************** + Delete a single value from the registry container. + No need to free memory since it is talloc'd. + **********************************************************************/ + +REGISTRY_VALUE* regval_ctr_getvalue( REGVAL_CTR *ctr, char *name ) +{ + int i; + + /* search for the value */ + + for ( i=0; inum_values; i++ ) { + if ( strcmp( ctr->values[i]->valuename, name ) == 0) + return ctr->values[i]; + + } + + return NULL; +} + /*********************************************************************** free memory held by a REGVAL_CTR structure **********************************************************************/ diff --git a/source3/registry/reg_printing.c b/source3/registry/reg_printing.c index 3fd3680489..8f53fe9ea5 100644 --- a/source3/registry/reg_printing.c +++ b/source3/registry/reg_printing.c @@ -492,7 +492,7 @@ static int print_subpath_printers( char *key, REGSUBKEY_CTR *subkeys ) free_a_printer( &printer, 2 ); - regsubkey_ctr_addkey( subkeys, "PrinterDriverData" ); + regsubkey_ctr_addkey( subkeys, SPOOL_PRINTERDATA_KEY ); } /* no other subkeys below here */ @@ -620,7 +620,7 @@ static int print_subpath_values_printers( char *key, REGVAL_CTR *val ) /* here should be no more path components here */ - if ( new_path || strcmp(base, "PrinterDriverData") ) + if ( new_path || strcmp(base, SPOOL_PRINTERDATA_KEY) ) goto done; /* now enumerate the PrinterDriverData key */ @@ -632,10 +632,12 @@ static int print_subpath_values_printers( char *key, REGVAL_CTR *val ) /* iterate over all printer data and fill the regval container */ +#if 0 /* JERRY */ for ( i=0; get_specific_param_by_index(*printer, 2, i, valuename, &data, &type, &data_len); i++ ) { regval_ctr_addvalue( val, valuename, type, data, data_len ); } +#endif free_a_printer( &printer, 2 ); diff --git a/source3/rpc_parse/parse_spoolss.c b/source3/rpc_parse/parse_spoolss.c index 79760ff37e..ac41a81a5a 100644 --- a/source3/rpc_parse/parse_spoolss.c +++ b/source3/rpc_parse/parse_spoolss.c @@ -6186,42 +6186,6 @@ BOOL spoolss_io_r_resetprinter(char *desc, SPOOL_R_RESETPRINTER *r_u, prs_struct return True; } -/******************************************************************* -********************************************************************/ -BOOL convert_specific_param(NT_PRINTER_PARAM **param, const UNISTR2 *value, - uint32 type, const uint8 *data, uint32 len) -{ - DEBUG(5,("converting a specific param struct\n")); - - if (*param == NULL) - { - *param=(NT_PRINTER_PARAM *)malloc(sizeof(NT_PRINTER_PARAM)); - if(*param == NULL) - return False; - memset((char *)*param, '\0', sizeof(NT_PRINTER_PARAM)); - DEBUGADD(6,("Allocated a new PARAM struct\n")); - } - unistr2_to_ascii((*param)->value, value, sizeof((*param)->value)-1); - (*param)->type = type; - - /* le champ data n'est pas NULL termine */ - /* on stocke donc la longueur */ - - (*param)->data_len=len; - - if (len) { - (*param)->data=(uint8 *)malloc(len * sizeof(uint8)); - if((*param)->data == NULL) - return False; - memcpy((*param)->data, data, len); - } - - DEBUGADD(6,("\tvalue:[%s], len:[%d]\n",(*param)->value, (*param)->data_len)); - dump_data(10, (char *)(*param)->data, (*param)->data_len); - - return True; -} - /******************************************************************* ********************************************************************/ diff --git a/source3/rpc_server/srv_spoolss_nt.c b/source3/rpc_server/srv_spoolss_nt.c index d04aff8b15..2aa11530f8 100644 --- a/source3/rpc_server/srv_spoolss_nt.c +++ b/source3/rpc_server/srv_spoolss_nt.c @@ -1798,51 +1798,56 @@ static BOOL getprinterdata_printer(pipes_struct *p, TALLOC_CTX *ctx, POLICY_HND uint8 **data, uint32 *needed, uint32 in_size ) { NT_PRINTER_INFO_LEVEL *printer = NULL; - int snum=0; - uint8 *idata=NULL; - uint32 len; - Printer_entry *Printer = find_printer_index_by_hnd(p, handle); + int snum=0; + Printer_entry *Printer = find_printer_index_by_hnd(p, handle); + REGISTRY_VALUE *val; + int size = 0; DEBUG(5,("getprinterdata_printer\n")); - if (!Printer) { + if ( !Printer ) { DEBUG(2,("getprinterdata_printer: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle))); return False; } - if(!get_printer_snum(p, handle, &snum)) + if ( !get_printer_snum(p, handle, &snum) ) return False; - if (!W_ERROR_IS_OK(get_a_printer(&printer, 2, lp_servicename(snum)))) + if ( !W_ERROR_IS_OK(get_a_printer(&printer, 2, lp_servicename(snum))) ) return False; - if (!get_specific_param(*printer, 2, value, &idata, type, &len)) { + if ( !(val = get_printer_data( printer->info_2, SPOOL_PRINTERDATA_KEY, value)) ) + { free_a_printer(&printer, 2); return False; } + + *type = regval_type( val ); - free_a_printer(&printer, 2); DEBUG(5,("getprinterdata_printer:allocating %d\n", in_size)); - if (in_size) { - if((*data = (uint8 *)talloc(ctx, in_size *sizeof(uint8) )) == NULL) { + if (in_size) + { + if ( (*data = (uint8 *)talloc(ctx, in_size * sizeof(uint8))) == NULL ) return False; - } - memset(*data, 0, in_size *sizeof(uint8)); + memset( *data, 0, in_size *sizeof(uint8) ); + /* copy the min(in_size, len) */ - memcpy(*data, idata, (len>in_size)?in_size:len *sizeof(uint8)); - } else { - *data = NULL; + + size = regval_size( val ); + memcpy( *data, regval_data_p(val), (size > in_size) ? in_size : size*sizeof(uint8) ); } + else + *data = NULL; - *needed = len; + *needed = size; DEBUG(5,("getprinterdata_printer:copy done\n")); - SAFE_FREE(idata); + free_a_printer(&printer, 2); return True; } @@ -1871,11 +1876,12 @@ WERROR _spoolss_getprinterdata(pipes_struct *p, SPOOL_Q_GETPRINTERDATA *q_u, SPO * JFM, 4/19/1999 */ - *out_size=in_size; + *out_size = in_size; /* in case of problem, return some default values */ - *needed=0; - *type=0; + + *needed = 0; + *type = 0; DEBUG(4,("_spoolss_getprinterdata\n")); @@ -1889,13 +1895,16 @@ WERROR _spoolss_getprinterdata(pipes_struct *p, SPOOL_Q_GETPRINTERDATA *q_u, SPO unistr2_to_ascii(value, valuename, sizeof(value)-1); if (Printer->printer_type == PRINTER_HANDLE_IS_PRINTSERVER) - found=getprinterdata_printer_server(p->mem_ctx, value, type, data, needed, *out_size); + found = getprinterdata_printer_server(p->mem_ctx, value, type, data, needed, *out_size); else - found= getprinterdata_printer(p, p->mem_ctx, handle, value, type, data, needed, *out_size); + found = getprinterdata_printer(p, p->mem_ctx, handle, value, type, data, needed, *out_size); - if (found==False) { + if ( !found ) + { DEBUG(5, ("value not found, allocating %d\n", *out_size)); + /* reply this param doesn't exist */ + if (*out_size) { if((*data=(uint8 *)talloc_zero(p->mem_ctx, *out_size*sizeof(uint8))) == NULL) return WERR_NOMEM; @@ -5219,254 +5228,6 @@ static BOOL add_printer_hook(NT_PRINTER_INFO_LEVEL *printer) return True; } -#if 0 /* JERRY */ - -/* Return true if two devicemodes are equal */ - -#define DEVMODE_CHECK_INT(field) \ - if (d1->field != d2->field) { \ - DEBUG(10, ("nt_devicemode_equal(): " #field " not equal (%d != %d)\n", \ - d1->field, d2->field)); \ - return False; \ - } - -/************************************************************************ - Handy, but currently unused functions - ***********************************************************************/ - -static BOOL nt_devicemode_equal(NT_DEVICEMODE *d1, NT_DEVICEMODE *d2) -{ - if (!d1 && !d2) goto equal; /* if both are NULL they are equal */ - - if (!d1 ^ !d2) { - DEBUG(10, ("nt_devicemode_equal(): pointers not equal\n")); - return False; /* if either is exclusively NULL are not equal */ - } - - if (!strequal(d1->devicename, d2->devicename)) { - DEBUG(10, ("nt_devicemode_equal(): device not equal (%s != %s)\n", d1->devicename, d2->devicename)); - return False; - } - - if (!strequal(d1->formname, d2->formname)) { - DEBUG(10, ("nt_devicemode_equal(): formname not equal (%s != %s)\n", d1->formname, d2->formname)); - return False; - } - - DEVMODE_CHECK_INT(specversion); - DEVMODE_CHECK_INT(driverversion); - DEVMODE_CHECK_INT(driverextra); - DEVMODE_CHECK_INT(orientation); - DEVMODE_CHECK_INT(papersize); - DEVMODE_CHECK_INT(paperlength); - DEVMODE_CHECK_INT(paperwidth); - DEVMODE_CHECK_INT(scale); - DEVMODE_CHECK_INT(copies); - DEVMODE_CHECK_INT(defaultsource); - DEVMODE_CHECK_INT(printquality); - DEVMODE_CHECK_INT(color); - DEVMODE_CHECK_INT(duplex); - DEVMODE_CHECK_INT(yresolution); - DEVMODE_CHECK_INT(ttoption); - DEVMODE_CHECK_INT(collate); - DEVMODE_CHECK_INT(logpixels); - - DEVMODE_CHECK_INT(fields); - DEVMODE_CHECK_INT(bitsperpel); - DEVMODE_CHECK_INT(pelswidth); - DEVMODE_CHECK_INT(pelsheight); - DEVMODE_CHECK_INT(displayflags); - DEVMODE_CHECK_INT(displayfrequency); - DEVMODE_CHECK_INT(icmmethod); - DEVMODE_CHECK_INT(icmintent); - DEVMODE_CHECK_INT(mediatype); - DEVMODE_CHECK_INT(dithertype); - DEVMODE_CHECK_INT(reserved1); - DEVMODE_CHECK_INT(reserved2); - DEVMODE_CHECK_INT(panningwidth); - DEVMODE_CHECK_INT(panningheight); - - /* compare the private data if it exists */ - if (!d1->driverextra && !d2->driverextra) goto equal; - - - DEVMODE_CHECK_INT(driverextra); - - if (memcmp(d1->private, d2->private, d1->driverextra)) { - DEBUG(10, ("nt_devicemode_equal(): private data not equal\n")); - return False; - } - - equal: - DEBUG(10, ("nt_devicemode_equal(): devicemodes identical\n")); - return True; -} - -/* Return true if two NT_PRINTER_PARAM structures are equal */ - -static BOOL nt_printer_param_equal(NT_PRINTER_PARAM *p1, - NT_PRINTER_PARAM *p2) -{ - if (!p1 && !p2) goto equal; - - if ((!p1 && p2) || (p1 && !p2)) { - DEBUG(10, ("nt_printer_param_equal(): pointers differ\n")); - return False; - } - - /* Compare lists of printer parameters */ - - while (p1) { - BOOL found = False; - NT_PRINTER_PARAM *q = p1; - - /* Find the parameter in the second structure */ - - while(q) { - - if (strequal(p1->value, q->value)) { - - if (p1->type != q->type) { - DEBUG(10, ("nt_printer_param_equal():" - "types for %s differ (%d != %d)\n", - p1->value, p1->type, - q->type)); - break; - } - - if (p1->data_len != q->data_len) { - DEBUG(10, ("nt_printer_param_equal():" - "len for %s differs (%d != %d)\n", - p1->value, p1->data_len, - q->data_len)); - break; - } - - if (memcmp(p1->data, q->data, p1->data_len) == 0) { - found = True; - } else { - DEBUG(10, ("nt_printer_param_equal():" - "data for %s differs\n", p1->value)); - } - - break; - } - - q = q->next; - } - - if (!found) { - DEBUG(10, ("nt_printer_param_equal(): param %s " - "does not exist\n", p1->value)); - return False; - } - - p1 = p1->next; - } - - equal: - - DEBUG(10, ("nt_printer_param_equal(): printer params identical\n")); - return True; -} - -/******************************************************************** - * Called by update_printer when trying to work out whether to - * actually update printer info. - ********************************************************************/ - -#define PI_CHECK_INT(field) \ - if (pi1->field != pi2->field) { \ - DEBUG(10, ("nt_printer_info_level_equal(): " #field " not equal (%d != %d)\n", \ - pi1->field, pi2->field)); \ - return False; \ - } - -#define PI_CHECK_STR(field) \ - if (!strequal(pi1->field, pi2->field)) { \ - DEBUG(10, ("nt_printer_info_level_equal(): " #field " not equal (%s != %s)\n", \ - pi1->field, pi2->field)); \ - return False; \ - } - -static BOOL nt_printer_info_level_equal(NT_PRINTER_INFO_LEVEL *p1, - NT_PRINTER_INFO_LEVEL *p2) -{ - NT_PRINTER_INFO_LEVEL_2 *pi1, *pi2; - - /* Trivial conditions */ - - if ((!p1 && !p2) || (!p1->info_2 && !p2->info_2)) { - goto equal; - } - - if ((!p1 && p2) || (p1 && !p2) || - (!p1->info_2 && p2->info_2) || - (p1->info_2 && !p2->info_2)) { - DEBUG(10, ("nt_printer_info_level_equal(): info levels " - "differ\n")); - return False; - } - - /* Compare two nt_printer_info_level structures. Don't compare - status or cjobs as they seem to have something to do with the - printer queue. */ - - pi1 = p1->info_2; - pi2 = p2->info_2; - - /* Don't check the attributes as we stomp on the value in - check_printer_ok() anyway. */ - -#if 0 - PI_CHECK_INT(attributes); -#endif - - PI_CHECK_INT(priority); - PI_CHECK_INT(default_priority); - PI_CHECK_INT(starttime); - PI_CHECK_INT(untiltime); - PI_CHECK_INT(averageppm); - - /* Yuck - don't check the printername or servername as the - mod_a_printer() code plays games with them. You can't - change the printername or the sharename through this interface - in Samba. */ - - PI_CHECK_STR(sharename); - PI_CHECK_STR(portname); - PI_CHECK_STR(drivername); - PI_CHECK_STR(comment); - PI_CHECK_STR(location); - - if (!nt_devicemode_equal(pi1->devmode, pi2->devmode)) { - return False; - } - - PI_CHECK_STR(sepfile); - PI_CHECK_STR(printprocessor); - PI_CHECK_STR(datatype); - PI_CHECK_STR(parameters); - - if (!nt_printer_param_equal(pi1->specific, pi2->specific)) { - return False; - } - - if (!sec_desc_equal(pi1->secdesc_buf->sec, pi2->secdesc_buf->sec)) { - return False; - } - - PI_CHECK_INT(changeid); - PI_CHECK_INT(c_setprinter); - PI_CHECK_INT(setuptime); - - equal: - DEBUG(10, ("nt_printer_info_level_equal(): infos are identical\n")); - return True; -} - -#endif - /******************************************************************** * Called by spoolss_api_setprinter * when updating a printer description. @@ -7121,38 +6882,38 @@ WERROR _spoolss_getprinterdriverdirectory(pipes_struct *p, SPOOL_Q_GETPRINTERDRI WERROR _spoolss_enumprinterdata(pipes_struct *p, SPOOL_Q_ENUMPRINTERDATA *q_u, SPOOL_R_ENUMPRINTERDATA *r_u) { POLICY_HND *handle = &q_u->handle; - uint32 idx = q_u->index; - uint32 in_value_len = q_u->valuesize; - uint32 in_data_len = q_u->datasize; - uint32 *out_max_value_len = &r_u->valuesize; - uint16 **out_value = &r_u->value; - uint32 *out_value_len = &r_u->realvaluesize; - uint32 *out_type = &r_u->type; + uint32 idx = q_u->index; + uint32 in_value_len = q_u->valuesize; + uint32 in_data_len = q_u->datasize; + uint32 *out_max_value_len= &r_u->valuesize; + uint16 **out_value = &r_u->value; + uint32 *out_value_len = &r_u->realvaluesize; + uint32 *out_type = &r_u->type; uint32 *out_max_data_len = &r_u->datasize; - uint8 **data_out = &r_u->data; - uint32 *out_data_len = &r_u->realdatasize; + uint8 **data_out = &r_u->data; + uint32 *out_data_len = &r_u->realdatasize; NT_PRINTER_INFO_LEVEL *printer = NULL; - fstring value; + uint32 param_index; + uint32 biggest_valuesize; + uint32 biggest_datasize; + uint32 data_len; + Printer_entry *Printer = find_printer_index_by_hnd(p, handle); + int snum; + WERROR result; + REGISTRY_VALUE *val; + NT_PRINTER_DATA *p_data; + int i, key_index, num_values; + int name_length; - uint32 param_index; - uint32 biggest_valuesize; - uint32 biggest_datasize; - uint32 data_len; - Printer_entry *Printer = find_printer_index_by_hnd(p, handle); - int snum; - uint8 *data=NULL; - uint32 type; - WERROR result; - - ZERO_STRUCT(printer); + ZERO_STRUCT( printer ); - *out_type=0; + *out_type = 0; - *out_max_data_len=0; - *data_out=NULL; - *out_data_len=0; + *out_max_data_len = 0; + *data_out = NULL; + *out_data_len = 0; DEBUG(5,("spoolss_enumprinterdata\n")); @@ -7167,103 +6928,133 @@ WERROR _spoolss_enumprinterdata(pipes_struct *p, SPOOL_Q_ENUMPRINTERDATA *q_u, S result = get_a_printer(&printer, 2, lp_servicename(snum)); if (!W_ERROR_IS_OK(result)) return result; + + p_data = &printer->info_2->data; + key_index = lookup_printerkey( p_data, SPOOL_PRINTERDATA_KEY ); + + result = WERR_OK; /* * The NT machine wants to know the biggest size of value and data * * cf: MSDN EnumPrinterData remark section */ - if ( (in_value_len==0) && (in_data_len==0) ) { + + if ( !in_value_len && !in_data_len ) + { DEBUGADD(6,("Activating NT mega-hack to find sizes\n")); - SAFE_FREE(data); - - param_index=0; - biggest_valuesize=0; - biggest_datasize=0; + param_index = 0; + biggest_valuesize = 0; + biggest_datasize = 0; + + num_values = regval_ctr_numvals( &p_data->keys[key_index].values ); - while (get_specific_param_by_index(*printer, 2, param_index, value, &data, &type, &data_len)) { - if (strlen(value) > biggest_valuesize) biggest_valuesize=strlen(value); - if (data_len > biggest_datasize) biggest_datasize=data_len; - - DEBUG(6,("current values: [%d], [%d]\n", biggest_valuesize, biggest_datasize)); - - SAFE_FREE(data); - param_index++; + for ( i=0; ikeys[key_index].values, i ); + + name_length = strlen(val->valuename); + if ( strlen(val->valuename) > biggest_valuesize ) + biggest_valuesize = name_length; + + if ( val->size > biggest_datasize ) + biggest_datasize = val->size; + + DEBUG(6,("current values: [%d], [%d]\n", biggest_valuesize, + biggest_datasize)); } - /* the value is an UNICODE string but realvaluesize is the length in bytes including the leading 0 */ - *out_value_len=2*(1+biggest_valuesize); - *out_data_len=biggest_datasize; + /* the value is an UNICODE string but real_value_size is the length + in bytes including the trailing 0 */ + + *out_value_len = 2 * (1+biggest_valuesize); + *out_data_len = biggest_datasize; DEBUG(6,("final values: [%d], [%d]\n", *out_value_len, *out_data_len)); - free_a_printer(&printer, 2); - return WERR_OK; + goto done; } /* * the value len is wrong in NT sp3 * that's the number of bytes not the number of unicode chars */ + + val = regval_ctr_specific_value( &p_data->keys[key_index].values, idx ); - if (!get_specific_param_by_index(*printer, 2, idx, value, &data, &type, &data_len)) { - - SAFE_FREE(data); - free_a_printer(&printer, 2); + if ( !val ) + { /* out_value should default to "" or else NT4 has problems unmarshalling the response */ - *out_max_value_len=(in_value_len/sizeof(uint16)); - if((*out_value=(uint16 *)talloc_zero(p->mem_ctx, in_value_len*sizeof(uint8))) == NULL) - return WERR_NOMEM; + *out_max_value_len = (in_value_len/sizeof(uint16)); + + if ( (*out_value=(uint16 *)talloc_zero(p->mem_ctx, in_value_len*sizeof(uint8))) == NULL ) + { + result = WERR_NOMEM; + goto done; + } *out_value_len = (uint32)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 *)talloc_zero(p->mem_ctx, in_data_len*sizeof(uint8))) == NULL) - return WERR_NOMEM; + *out_data_len = in_data_len; + + /* only allocate when given a non-zero data_len */ + + if ( in_data_len && ((*data_out=(uint8 *)talloc_zero(p->mem_ctx, in_data_len*sizeof(uint8))) == NULL) ) + { + result = WERR_NOMEM; + goto done; + } - return WERR_NO_MORE_ITEMS; + result = WERR_NO_MORE_ITEMS; } - - free_a_printer(&printer, 2); - - /* - * the value is: - * - counted in bytes in the request - * - counted in UNICODE chars in the max reply - * - counted in bytes in the real size - * - * take a pause *before* coding not *during* coding - */ + else + { + /* + * the value is: + * - counted in bytes in the request + * - counted in UNICODE chars in the max reply + * - counted in bytes in the real size + * + * take a pause *before* coding not *during* coding + */ - *out_max_value_len=(in_value_len/sizeof(uint16)); - if((*out_value=(uint16 *)talloc_zero(p->mem_ctx,in_value_len*sizeof(uint8))) == NULL) { - SAFE_FREE(data); - return WERR_NOMEM; - } + /* name */ + *out_max_value_len = ( in_value_len / sizeof(uint16) ); + if ( (*out_value = (uint16 *)talloc_zero(p->mem_ctx, in_value_len*sizeof(uint8))) == NULL ) + { + result = WERR_NOMEM; + goto done; + } - *out_value_len = (uint32)rpcstr_push((char *)*out_value,value, in_value_len, 0); + *out_value_len = (uint32)rpcstr_push((char *)*out_value, regval_name(val), in_value_len, 0); + + /* type */ + + *out_type = regval_type( val ); - *out_type=type; + /* data - counted in bytes */ - /* the data is counted in bytes */ - *out_max_data_len=in_data_len; - if((*data_out=(uint8 *)talloc_zero(p->mem_ctx, in_data_len*sizeof(uint8))) == NULL) { - SAFE_FREE(data); - return WERR_NOMEM; + *out_max_data_len = in_data_len; + if ( (*data_out = (uint8 *)talloc_zero(p->mem_ctx, in_data_len*sizeof(uint8))) == NULL) + { + result = WERR_NOMEM; + goto done; + } + data_len = (size_t)regval_size(val); + memcpy( *data_out, regval_data_p(val), data_len ); + *out_data_len = data_len; } - - memcpy(*data_out, data, (size_t)data_len); - *out_data_len=data_len; - SAFE_FREE(data); - - return WERR_OK; +done: + free_a_printer(&printer, 2); + return result; } /**************************************************************************** @@ -7271,17 +7062,17 @@ WERROR _spoolss_enumprinterdata(pipes_struct *p, SPOOL_Q_ENUMPRINTERDATA *q_u, S WERROR _spoolss_setprinterdata( pipes_struct *p, SPOOL_Q_SETPRINTERDATA *q_u, SPOOL_R_SETPRINTERDATA *r_u) { - POLICY_HND *handle = &q_u->handle; - UNISTR2 *value = &q_u->value; - uint32 type = q_u->type; - uint8 *data = q_u->data; - uint32 real_len = q_u->real_len; + POLICY_HND *handle = &q_u->handle; + UNISTR2 *value = &q_u->value; + uint32 type = q_u->type; + uint8 *data = q_u->data; + uint32 real_len = q_u->real_len; - NT_PRINTER_INFO_LEVEL *printer = NULL; - NT_PRINTER_PARAM *param = NULL, old_param; - int snum=0; - WERROR status = WERR_OK; - Printer_entry *Printer=find_printer_index_by_hnd(p, handle); + NT_PRINTER_INFO_LEVEL *printer = NULL; + int snum=0; + WERROR status = WERR_OK; + Printer_entry *Printer=find_printer_index_by_hnd(p, handle); + fstring valuename; DEBUG(5,("spoolss_setprinterdata\n")); @@ -7293,8 +7084,6 @@ WERROR _spoolss_setprinterdata( pipes_struct *p, SPOOL_Q_SETPRINTERDATA *q_u, SP if (!get_printer_snum(p,handle, &snum)) return WERR_BADFID; - ZERO_STRUCT(old_param); - /* * Access check : NT returns "access denied" if you make a * SetPrinterData call without the necessary privildge. @@ -7309,40 +7098,22 @@ WERROR _spoolss_setprinterdata( pipes_struct *p, SPOOL_Q_SETPRINTERDATA *q_u, SP goto done; } - /* Check if we are making any changes or not. Return true if - nothing is actually changing. This is not needed anymore but - has been left in as an optimization to keep from from - writing to disk as often --jerry */ - status = get_a_printer(&printer, 2, lp_servicename(snum)); if (!W_ERROR_IS_OK(status)) return status; - convert_specific_param(¶m, value , type, data, real_len); + /* save the registry data */ + + unistr2_to_ascii( valuename, value, sizeof(valuename)-1 ); + delete_printer_data( printer->info_2, SPOOL_PRINTERDATA_KEY, valuename ); + add_printer_data( printer->info_2, SPOOL_PRINTERDATA_KEY, valuename, type, data, real_len ); - unlink_specific_param_if_exist(printer->info_2, param); + /* write the **entire** printer out to disk.... :-( */ - /* - * When client side code sets a magic printer data key, detect it and save - * the current printer data and the magic key's data (its the DEVMODE) for - * future printer/driver initializations. - */ - if (param->type==3 && !strcmp( param->value, PHANTOM_DEVMODE_KEY)) { - /* - * Set devmode and printer initialization info - */ - status = save_driver_init(printer, 2, param); - } - else { - add_a_specific_param(printer->info_2, ¶m); - status = mod_a_printer(*printer, 2); - } + status = mod_a_printer(*printer, 2); - done: +done: free_a_printer(&printer, 2); - if (param) - free_nt_printer_param(¶m); - SAFE_FREE(old_param.data); return status; } @@ -7352,9 +7123,9 @@ WERROR _spoolss_setprinterdata( pipes_struct *p, SPOOL_Q_SETPRINTERDATA *q_u, SP WERROR _spoolss_resetprinter(pipes_struct *p, SPOOL_Q_RESETPRINTER *q_u, SPOOL_R_RESETPRINTER *r_u) { - POLICY_HND *handle = &q_u->handle; - Printer_entry *Printer=find_printer_index_by_hnd(p, handle); - int snum; + POLICY_HND *handle = &q_u->handle; + Printer_entry *Printer=find_printer_index_by_hnd(p, handle); + int snum; DEBUG(5,("_spoolss_resetprinter\n")); @@ -7378,16 +7149,19 @@ WERROR _spoolss_resetprinter(pipes_struct *p, SPOOL_Q_RESETPRINTER *q_u, SPOOL_R } +/**************************************************************************** +****************************************************************************/ + WERROR _spoolss_deleteprinterdata(pipes_struct *p, SPOOL_Q_DELETEPRINTERDATA *q_u, SPOOL_R_DELETEPRINTERDATA *r_u) { - POLICY_HND *handle = &q_u->handle; - UNISTR2 *value = &q_u->valuename; + POLICY_HND *handle = &q_u->handle; + UNISTR2 *value = &q_u->valuename; - NT_PRINTER_INFO_LEVEL *printer = NULL; - NT_PRINTER_PARAM param; - int snum=0; - WERROR status = WERR_OK; - Printer_entry *Printer=find_printer_index_by_hnd(p, handle); + NT_PRINTER_INFO_LEVEL *printer = NULL; + int snum=0; + WERROR status = WERR_OK; + Printer_entry *Printer=find_printer_index_by_hnd(p, handle); + pstring valuename; DEBUG(5,("spoolss_deleteprinterdata\n")); @@ -7408,15 +7182,14 @@ WERROR _spoolss_deleteprinterdata(pipes_struct *p, SPOOL_Q_DELETEPRINTERDATA *q_ if (!W_ERROR_IS_OK(status)) return status; - ZERO_STRUCTP(¶m); - unistr2_to_ascii(param.value, value, sizeof(param.value)-1); + unistr2_to_ascii( valuename, value, sizeof(valuename)-1 ); - if(!unlink_specific_param_if_exist(printer->info_2, ¶m)) - status = WERR_INVALID_PARAM; - else + status = delete_printer_data( printer->info_2, SPOOL_PRINTERDATA_KEY, valuename ); + if ( NT_STATUS_IS_OK(status) ) status = mod_a_printer(*printer, 2); free_a_printer(&printer, 2); + return status; } @@ -7426,7 +7199,6 @@ WERROR _spoolss_deleteprinterdata(pipes_struct *p, SPOOL_Q_DELETEPRINTERDATA *q_ WERROR _spoolss_addform( pipes_struct *p, SPOOL_Q_ADDFORM *q_u, SPOOL_R_ADDFORM *r_u) { POLICY_HND *handle = &q_u->handle; -/* uint32 level = q_u->level; - notused. */ FORM *form = &q_u->form; nt_forms_struct tmpForm; int snum; @@ -8045,9 +7817,10 @@ WERROR _spoolss_getprinterdataex(pipes_struct *p, SPOOL_Q_GETPRINTERDATAEX *q_u, * (a) DsDriver * (b) DsSpooler * (c) PnPData + * (d) DsUser */ - if (strcmp(key, "PrinterDriverData") != 0) + if (strcmp(key, SPOOL_PRINTERDATA_KEY) != 0) return WERR_BADFILE; DEBUG(10, ("_spoolss_getprinterdataex: pass me to getprinterdata\n")); @@ -8093,7 +7866,7 @@ WERROR _spoolss_setprinterdataex(pipes_struct *p, SPOOL_Q_SETPRINTERDATAEX *q_u, unistr2_to_ascii(key, &q_u->key, sizeof(key) - 1); - if (strcmp(key, "PrinterDriverData") != 0) + if (strcmp(key, SPOOL_PRINTERDATA_KEY) != 0) return WERR_INVALID_PARAM; ZERO_STRUCT(q_u_local); @@ -8128,7 +7901,7 @@ WERROR _spoolss_deleteprinterdataex(pipes_struct *p, SPOOL_Q_DELETEPRINTERDATAEX unistr2_to_ascii(key, &q_u->keyname, sizeof(key) - 1); - if (strcmp(key, "PrinterDriverData") != 0) + if (strcmp(key, SPOOL_PRINTERDATA_KEY) != 0) return WERR_INVALID_PARAM; memcpy(&q_u_local.handle, &q_u->handle, sizeof(POLICY_HND)); @@ -8153,7 +7926,7 @@ WERROR _spoolss_enumprinterkey(pipes_struct *p, SPOOL_Q_ENUMPRINTERKEY *q_u, SPO uint16 enumkeys[ENUMERATED_KEY_SIZE+1]; char* ptr = NULL; int i; - char *PrinterKey = "PrinterDriverData"; + char *PrinterKey = SPOOL_PRINTERDATA_KEY; DEBUG(4,("_spoolss_enumprinterkey\n")); @@ -8222,7 +7995,7 @@ WERROR _spoolss_deleteprinterkey(pipes_struct *p, SPOOL_Q_DELETEPRINTERKEY *q_u, unistr2_to_ascii(key, &q_u->keyname, sizeof(key) - 1); - if (strcmp(key, "PrinterDriverData") != 0) + if (strcmp(key, SPOOL_PRINTERDATA_KEY) != 0) return WERR_INVALID_PARAM; /* @@ -8246,14 +8019,16 @@ WERROR _spoolss_enumprinterdataex(pipes_struct *p, SPOOL_Q_ENUMPRINTERDATAEX *q_ needed; NT_PRINTER_INFO_LEVEL *printer = NULL; PRINTER_ENUM_VALUES *enum_values = NULL; - fstring key, value; + NT_PRINTER_DATA *p_data; + fstring key; Printer_entry *Printer = find_printer_index_by_hnd(p, handle); int snum; - uint32 param_index, - data_len, - type; WERROR result; - uint8 *data=NULL; + int key_index; + int i; + REGISTRY_VALUE *val; + char *value_name; + int data_len; DEBUG(4,("_spoolss_enumprinterdataex\n")); @@ -8264,20 +8039,8 @@ WERROR _spoolss_enumprinterdataex(pipes_struct *p, SPOOL_Q_ENUMPRINTERDATAEX *q_ } - /* - * The only key we support is "PrinterDriverData". This should return - > an array of all the key/value pairs returned by EnumPrinterDataSee - * _spoolss_getprinterdataex() for details --jerry - */ - - unistr2_to_ascii(key, &q_u->key, sizeof(key) - 1); - if (strcmp(key, "PrinterDriverData") != 0) - { - DEBUG(10,("_spoolss_enumprinterdataex: Unknown keyname [%s]\n", key)); - return WERR_INVALID_PARAM; - } - - + /* first get the printer off of disk */ + if (!get_printer_snum(p,handle, &snum)) return WERR_BADFID; @@ -8285,61 +8048,76 @@ WERROR _spoolss_enumprinterdataex(pipes_struct *p, SPOOL_Q_ENUMPRINTERDATAEX *q_ result = get_a_printer(&printer, 2, lp_servicename(snum)); if (!W_ERROR_IS_OK(result)) return result; - - /* - * loop through all params and build the array to pass - * back to the client - */ + /* now look for a match on the key name */ + + p_data = &printer->info_2->data; + + unistr2_to_ascii(key, &q_u->key, sizeof(key) - 1); + if ( (key_index = lookup_printerkey( p_data, key)) == -1 ) + { + DEBUG(10,("_spoolss_enumprinterdataex: Unknown keyname [%s]\n", key)); + result = WERR_INVALID_PARAM; + goto done; + } + result = WERR_OK; - param_index = 0; - needed = 0; - num_entries = 0; + needed = 0; - while (get_specific_param_by_index(*printer, 2, param_index, value, &data, &type, &data_len)) + /* allocate the memory for the array of pointers -- if necessary */ + + num_entries = regval_ctr_numvals( &p_data->keys[key_index].values ); + if ( num_entries ) { - PRINTER_ENUM_VALUES *ptr; - - DEBUG(10,("retrieved value number [%d] [%s]\n", num_entries, value)); - - if ((ptr=talloc_realloc(p->mem_ctx, enum_values, (num_entries+1) * sizeof(PRINTER_ENUM_VALUES))) == NULL) + if ( (enum_values=talloc(p->mem_ctx, num_entries*sizeof(PRINTER_ENUM_VALUES))) == NULL ) { - DEBUG(0,("talloc_realloc failed to allocate more memory!\n")); + DEBUG(0,("_spoolss_enumprinterdataex: talloc() failed to allocate memory for [%d] bytes!\n", + num_entries*sizeof(PRINTER_ENUM_VALUES))); result = WERR_NOMEM; goto done; } - enum_values = ptr; + + memset( enum_values, 0x0, num_entries*sizeof(PRINTER_ENUM_VALUES) ); + } + + /* + * loop through all params and build the array to pass + * back to the client + */ + + for ( i=0; ikeys[key_index].values, i ); + DEBUG(10,("retrieved value number [%d] [%s]\n", i, regval_name(val) )); /* copy the data */ - init_unistr(&enum_values[num_entries].valuename, value); - enum_values[num_entries].value_len = (strlen(value)+1) * 2; - enum_values[num_entries].type = type; + value_name = regval_name( val ); + init_unistr( &enum_values[i].valuename, value_name ); + enum_values[i].value_len = (strlen(value_name)+1) * 2; + enum_values[i].type = regval_type( val ); - if ( data_len ) - { - if ( !(enum_values[num_entries].data = talloc_zero(p->mem_ctx, data_len)) ) { - DEBUG(0,("talloc_realloc failed to allocate more memory [data_len=%d] for data!\n", data_len )); + data_len = regval_size( val ); + if ( data_len ) { + if ( !(enum_values[i].data = talloc_memdup(p->mem_ctx, regval_data_p(val), data_len)) ) + { + DEBUG(0,("talloc_memdup failed to allocate memory [data_len=%d] for data!\n", + data_len )); result = WERR_NOMEM; goto done; } - memcpy(enum_values[num_entries].data, data, data_len); } - - enum_values[num_entries].data_len = data_len; + enum_values[i].data_len = data_len; /* keep track of the size of the array in bytes */ needed += spoolss_size_printer_enum_values(&enum_values[num_entries]); - - num_entries++; - param_index++; } - r_u->needed = needed; - r_u->returned = num_entries; + r_u->needed = needed; + r_u->returned = num_entries; if (needed > in_size) { result = WERR_MORE_DATA; -- cgit