* Fix DeletePrinterDataEx() to work with arbitrary registry keys
authorGerald Carter <jerry@samba.org>
Sun, 18 Aug 2002 16:52:51 +0000 (16:52 +0000)
committerGerald Carter <jerry@samba.org>
Sun, 18 Aug 2002 16:52:51 +0000 (16:52 +0000)
* Fix delete_all_printer_data() to accept a key name for partial tree
  deletions

* Fix EnumPrinterKey() to work with subkeys

* Fix DeletePrinterKey() to work with ful or partial registry
  trees

* Fix get_printer_subkeys() to return a list of unique keynames
  ( some were getting added twice due to subkeys names )

* fix a couple of typos for good measure
(This used to be commit b6ceb8c2e50b7fcdc614a3b6782db05b60689a85)

source3/printing/nt_printing.c
source3/rpc_server/srv_spoolss_nt.c

index 6cfc9aac5aa7c243e23f8db161500b76610947f1..1761064584bda726a9079d6aebf6aad806f97e85 100644 (file)
@@ -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);
 
index 7286fef5283a4ec9bb0ba93e5e53f8df8c69b02b..2cf73d71185c3cfdbfd675c98e77da8f52d054ca 100644 (file)
@@ -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;
 }