diff options
-rw-r--r-- | source3/printing/nt_printing.c | 125 | ||||
-rw-r--r-- | source3/rpc_server/srv_spoolss_nt.c | 101 |
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; } |