summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--source3/printing/nt_printing.c125
-rw-r--r--source3/rpc_server/srv_spoolss_nt.c101
2 files changed, 173 insertions, 53 deletions
diff --git a/source3/printing/nt_printing.c b/source3/printing/nt_printing.c
index 6cfc9aac5a..1761064584 100644
--- a/source3/printing/nt_printing.c
+++ b/source3/printing/nt_printing.c
@@ -2423,11 +2423,12 @@ int lookup_printerkey( NT_PRINTER_DATA *data, char *name )
uint32 get_printer_subkeys( NT_PRINTER_DATA *data, char* key, fstring **subkeys )
{
- int i;
+ int i, j;
int key_len;
int num_subkeys = 0;
char *p;
fstring *ptr, *subkeys_ptr = NULL;
+ fstring subkeyname;
if ( !data )
return 0;
@@ -2445,7 +2446,22 @@ uint32 get_printer_subkeys( NT_PRINTER_DATA *data, char* key, fstring **subkeys
/* get subkey path */
p = data->keys[i].name + key_len;
+ if ( *p == '\\' )
+ p++;
+ fstrcpy( subkeyname, p );
+ if ( (p = strchr( subkeyname, '\\' )) )
+ *p = '\0';
+
+ /* don't add a key more than once */
+
+ for ( j=0; j<num_subkeys; j++ ) {
+ if ( strequal( subkeys_ptr[j], subkeyname ) )
+ break;
+ }
+ if ( j != num_subkeys )
+ continue;
+
/* found a match, so allocate space and copy the name */
if ( !(ptr = Realloc( subkeys_ptr, (num_subkeys+2)*sizeof(fstring))) ) {
@@ -2456,14 +2472,7 @@ uint32 get_printer_subkeys( NT_PRINTER_DATA *data, char* key, fstring **subkeys
}
subkeys_ptr = ptr;
-
- /* copy the subkey name and trim off any trailing
- subkeys below it */
-
- fstrcpy( subkeys_ptr[num_subkeys], p );
- p = strchr( subkeys_ptr[num_subkeys], '\\' );
- if ( p )
- *p = '\0';
+ fstrcpy( subkeys_ptr[num_subkeys], subkeyname );
num_subkeys++;
}
@@ -2481,31 +2490,99 @@ uint32 get_printer_subkeys( NT_PRINTER_DATA *data, char* key, fstring **subkeys
/****************************************************************************
***************************************************************************/
-WERROR delete_all_printer_data( NT_PRINTER_INFO_LEVEL_2 *p2 )
+WERROR delete_all_printer_data( NT_PRINTER_INFO_LEVEL_2 *p2, char *key )
{
- WERROR result = WERR_OK;
NT_PRINTER_DATA *data;
int i;
+ int removed_keys = 0;
+ int empty_slot;
data = &p2->data;
+ empty_slot = data->num_keys;
+
+ if ( !key )
+ return WERR_INVALID_PARAM;
- for ( i=0; i<data->num_keys; i++ )
+ /* remove all keys */
+
+ if ( !strlen(key) )
{
- DEBUG(8,("delete_all_printer_data: Removed all Printer Data from key [%s]\n",
- data->keys[i].name));
+ 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[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 ));
+
+ SAFE_FREE( data->keys );
+ ZERO_STRUCTP( data );
- DEBUG(8,("delete_all_printer_data: Removed all Printer Data from printer [%s]\n",
- p2->printername ));
+ return WERR_OK;
+ }
+
+ /* remove a specific key (and all subkeys) */
- ZERO_STRUCTP( data );
+ for ( i=0; i<data->num_keys; i++ )
+ {
+ if ( StrnCaseCmp( data->keys[i].name, key, strlen(key)) == 0 )
+ {
+ 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 );
+
+ /* mark the slot as empty */
+
+ ZERO_STRUCTP( &data->keys[i] );
+ }
+ }
+
+ /* find the first empty slot */
+
+ for ( i=0; i<data->num_keys; i++ ) {
+ if ( !data->keys[i].name ) {
+ empty_slot = i;
+ removed_keys++;
+ break;
+ }
+ }
+
+ if ( i == data->num_keys )
+ /* nothing was removed */
+ return WERR_INVALID_PARAM;
+
+ /* move everything down */
- return result;
+ for ( i=empty_slot+1; i<data->num_keys; i++ ) {
+ if ( data->keys[i].name ) {
+ memcpy( &data->keys[empty_slot], &data->keys[i], sizeof(NT_PRINTER_KEY) );
+ ZERO_STRUCTP( &data->keys[i] );
+ empty_slot++;
+ removed_keys++;
+ }
+ }
+
+ /* update count */
+
+ data->num_keys -= removed_keys;
+
+ /* sanity check to see if anything is left */
+
+ if ( !data->num_keys )
+ {
+ DEBUG(8,("delete_all_printer_data: No keys left for printer [%s]\n", p2->printername ));
+
+ SAFE_FREE( data->keys );
+ ZERO_STRUCTP( data );
+ }
+
+ return WERR_OK;
}
/****************************************************************************
@@ -2655,7 +2732,7 @@ static int unpack_values(NT_PRINTER_DATA *printer_data, char *buf, int buflen)
regval_ctr_addvalue( &printer_data->keys[key_index].values, valuename, type, data_p, size );
- DEBUG(8,("specific: [%s\\%s], len: %d\n", keyname, valuename, size));
+ DEBUG(8,("specific: [%s:%s], len: %d\n", keyname, valuename, size));
}
return len;
@@ -3103,7 +3180,7 @@ static BOOL set_driver_init_2( NT_PRINTER_INFO_LEVEL_2 *info_ptr )
* should not be any (if there are delete them).
*/
- delete_all_printer_data( info_ptr );
+ delete_all_printer_data( info_ptr, "" );
slprintf(key, sizeof(key)-1, "%s%s", DRIVER_INIT_PREFIX, info_ptr->drivername);
diff --git a/source3/rpc_server/srv_spoolss_nt.c b/source3/rpc_server/srv_spoolss_nt.c
index 7286fef528..2cf73d7118 100644
--- a/source3/rpc_server/srv_spoolss_nt.c
+++ b/source3/rpc_server/srv_spoolss_nt.c
@@ -1297,7 +1297,7 @@ Can't find printer handle we created for printer %s\n", name ));
printer_default->access_required = PRINTER_ACCESS_USE;
DEBUG(4,("Setting printer access = %s\n", (printer_default->access_required == PRINTER_ACCESS_ADMINISTER)
- ? "PRINTER_ACCESS_ADMINSTER" : "PRINTER_ACCESS_USE" ));
+ ? "PRINTER_ACCESS_ADMINISTER" : "PRINTER_ACCESS_USE" ));
Printer->access_granted = printer_default->access_required;
@@ -7211,7 +7211,7 @@ WERROR _spoolss_deleteprinterdata(pipes_struct *p, SPOOL_Q_DELETEPRINTERDATA *q_
unistr2_to_ascii( valuename, value, sizeof(valuename)-1 );
status = delete_printer_data( printer->info_2, SPOOL_PRINTERDATA_KEY, valuename );
- if ( NT_STATUS_IS_OK(status) )
+ if ( W_ERROR_IS_OK(status) )
status = mod_a_printer(*printer, 2);
free_a_printer(&printer, 2);
@@ -7960,26 +7960,46 @@ WERROR _spoolss_setprinterdataex(pipes_struct *p, SPOOL_Q_SETPRINTERDATAEX *q_u,
WERROR _spoolss_deleteprinterdataex(pipes_struct *p, SPOOL_Q_DELETEPRINTERDATAEX *q_u, SPOOL_R_DELETEPRINTERDATAEX *r_u)
{
- SPOOL_Q_DELETEPRINTERDATA q_u_local;
- SPOOL_R_DELETEPRINTERDATA r_u_local;
- fstring key;
-
- /* From MSDN documentation of SetPrinterDataEx: pass request to
- SetPrinterData if key is "PrinterDriverData" */
-
- unistr2_to_ascii(key, &q_u->keyname, sizeof(key) - 1);
+ POLICY_HND *handle = &q_u->handle;
+ UNISTR2 *value = &q_u->valuename;
+ UNISTR2 *key = &q_u->keyname;
- if (strcmp(key, SPOOL_PRINTERDATA_KEY) != 0)
- return WERR_INVALID_PARAM;
+ 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, keyname;
- memcpy(&q_u_local.handle, &q_u->handle, sizeof(POLICY_HND));
- copy_unistr2(&q_u_local.valuename, &q_u->valuename);
+ DEBUG(5,("spoolss_deleteprinterdataex\n"));
- return _spoolss_deleteprinterdata( p, &q_u_local, &r_u_local );
-}
+ if (!Printer) {
+ DEBUG(2,("_spoolss_deleteprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
+ return WERR_BADFID;
+ }
+ if (!get_printer_snum(p, handle, &snum))
+ return WERR_BADFID;
+
+ if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
+ DEBUG(3, ("_spoolss_deleteprinterdataex: printer properties change denied by handle\n"));
+ return WERR_ACCESS_DENIED;
+ }
+ status = get_a_printer(&printer, 2, lp_servicename(snum));
+ if (!W_ERROR_IS_OK(status))
+ return status;
+
+ unistr2_to_ascii( valuename, value, sizeof(valuename)-1 );
+ unistr2_to_ascii( keyname, key, sizeof(keyname)-1 );
+
+ status = delete_printer_data( printer->info_2, keyname, valuename );
+ if ( W_ERROR_IS_OK(status) )
+ status = mod_a_printer(*printer, 2);
+
+ free_a_printer(&printer, 2);
+ return status;
+}
/********************************************************************
* spoolss_enumprinterkey
@@ -8059,25 +8079,48 @@ done:
WERROR _spoolss_deleteprinterkey(pipes_struct *p, SPOOL_Q_DELETEPRINTERKEY *q_u, SPOOL_R_DELETEPRINTERKEY *r_u)
{
- Printer_entry *Printer = find_printer_index_by_hnd(p, &q_u->handle);
- fstring key;
+ POLICY_HND *handle = &q_u->handle;
+ Printer_entry *Printer = find_printer_index_by_hnd(p, &q_u->handle);
+ fstring key;
+ NT_PRINTER_INFO_LEVEL *printer = NULL;
+ int snum=0;
+ WERROR status;
+
+ DEBUG(5,("spoolss_deleteprinterkey\n"));
if (!Printer) {
- DEBUG(2,("_spoolss_deleteprinterkey: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(&q_u->handle)));
+ DEBUG(2,("_spoolss_deleteprinterkey: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
return WERR_BADFID;
}
-
- unistr2_to_ascii(key, &q_u->keyname, sizeof(key) - 1);
- if (strcmp(key, SPOOL_PRINTERDATA_KEY) != 0)
- return WERR_INVALID_PARAM;
+ /* if keyname == NULL, return error */
+
+ if ( !q_u->keyname.buffer )
+ return WERR_INVALID_PARAM;
- /*
- * this is what 2k returns when you try to delete the "PrinterDriverData"
- * key
- */
-
- return WERR_ACCESS_DENIED;
+ if (!get_printer_snum(p, handle, &snum))
+ return WERR_BADFID;
+
+ if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
+ DEBUG(3, ("_spoolss_deleteprinterkey: printer properties change denied by handle\n"));
+ return WERR_ACCESS_DENIED;
+ }
+
+ status = get_a_printer(&printer, 2, lp_servicename(snum));
+ if (!W_ERROR_IS_OK(status))
+ return status;
+
+ /* delete the key and all subneys */
+
+ unistr2_to_ascii(key, &q_u->keyname, sizeof(key) - 1);
+
+ status = delete_all_printer_data( printer->info_2, key );
+ if ( W_ERROR_IS_OK(status) )
+ status = mod_a_printer(*printer, 2);
+
+ free_a_printer( &printer, 2 );
+
+ return status;
}