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:
@ -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;
|
||||
|
@ -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", ®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 */
|
||||
|
@ -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
|
||||
**********************************************************************/
|
||||
|
@ -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 );
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
/*******************************************************************
|
||||
********************************************************************/
|
||||
|
||||
|
@ -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(¶m, 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, ¶m);
|
||||
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(¶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;
|
||||
|
||||
|
||||
/* 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;
|
||||
|
Reference in New Issue
Block a user