1
0
mirror of https://github.com/samba-team/samba.git synced 2025-08-03 04:22:09 +03:00

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 commit is contained in:
Gerald Carter
-
parent bc9e9e3e2e
commit 7ba7c04c0e
6 changed files with 676 additions and 958 deletions

View File

@ -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;

View File

@ -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; i<data->num_keys; i++ )
{
val_ctr = &data->keys[i].values;
num_values = regval_ctr_numvals( val_ctr );
/* loop over all values */
for ( j=0; j<num_values; j++ )
{
/* pathname should be stored as <key>\<value> */
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; i<data->num_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;
}
*list = NULL;
/****************************************************************************
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;
while (1) {
len += tdb_unpack(buf+len, buflen-len, "p", &p);
if (!p) break;
DEBUG(12,("lookup_printerkey: Looking for [%s]\n", name));
/* loop over all existing keys */
for ( i=0; i<data->num_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; i<data->num_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;
/* 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", &regval_p);
if ( !regval_p )
break;
/* unpack the next regval */
len += tdb_unpack(buf+len, buflen-len, "fdB",
param.value,
&param.type,
&param.data_len,
&param.data);
param.next = *list;
*list = memdup(&param, 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 */

View File

@ -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; i<ctr->num_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; i<ctr->num_values; i++ ) {
if ( strcmp( ctr->values[i]->valuename, name ) == 0)
return ctr->values[i];
}
return NULL;
}
/***********************************************************************
free memory held by a REGVAL_CTR structure
**********************************************************************/

View File

@ -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 );

View File

@ -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;
}
/*******************************************************************
********************************************************************/

View File

@ -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; i<num_values; i++ )
{
val = regval_ctr_specific_value( &p_data->keys[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;
}
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
*/
/* 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, regval_name(val), in_value_len, 0);
/* type */
*out_type = regval_type( val );
/* data - 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)
{
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;
}
done:
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
*/
*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;
}
*out_value_len = (uint32)rpcstr_push((char *)*out_value,value, in_value_len, 0);
*out_type=type;
/* 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;
}
memcpy(*data_out, data, (size_t)data_len);
*out_data_len=data_len;
SAFE_FREE(data);
return WERR_OK;
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(&param, value , type, data, real_len);
unlink_specific_param_if_exist(printer->info_2, param);
/* save the registry data */
/*
* 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, &param);
status = mod_a_printer(*printer, 2);
}
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 );
done:
/* write the **entire** printer out to disk.... :-( */
status = mod_a_printer(*printer, 2);
done:
free_a_printer(&printer, 2);
if (param)
free_nt_printer_param(&param);
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(&param);
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, &param))
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;
/* 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;
needed = 0;
/* allocate the memory for the array of pointers -- if necessary */
num_entries = regval_ctr_numvals( &p_data->keys[key_index].values );
if ( num_entries )
{
if ( (enum_values=talloc(p->mem_ctx, num_entries*sizeof(PRINTER_ENUM_VALUES))) == NULL )
{
DEBUG(0,("_spoolss_enumprinterdataex: talloc() failed to allocate memory for [%d] bytes!\n",
num_entries*sizeof(PRINTER_ENUM_VALUES)));
result = WERR_NOMEM;
goto done;
}
memset( enum_values, 0x0, num_entries*sizeof(PRINTER_ENUM_VALUES) );
}
/*
* loop through all params and build the array to pass
* back to the client
*/
result = WERR_OK;
param_index = 0;
needed = 0;
num_entries = 0;
while (get_specific_param_by_index(*printer, 2, param_index, value, &data, &type, &data_len))
for ( i=0; i<num_entries; i++ )
{
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)
{
DEBUG(0,("talloc_realloc failed to allocate more memory!\n"));
result = WERR_NOMEM;
goto done;
}
enum_values = ptr;
/* lookup the registry value */
ZERO_STRUCTP( &enum_values[num_entries] );
val = regval_ctr_specific_value( &p_data->keys[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;