BIG merge from trunk. Features not copied over
[metze/old/v3-2-winbind-ndr.git] / source / registry / reg_printing.c
1 /* 
2  *  Unix SMB/CIFS implementation.
3  *  Virtual Windows Registry Layer
4  *  Copyright (C) Gerald Carter                     2002-2005
5  *
6  *  This program is free software; you can redistribute it and/or modify
7  *  it under the terms of the GNU General Public License as published by
8  *  the Free Software Foundation; either version 2 of the License, or
9  *  (at your option) any later version.
10  *  
11  *  This program is distributed in the hope that it will be useful,
12  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
13  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  *  GNU General Public License for more details.
15  *  
16  *  You should have received a copy of the GNU General Public License
17  *  along with this program; if not, write to the Free Software
18  *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19  */
20
21 /* Implementation of registry virtual views for printing information */
22
23 #include "includes.h"
24
25 #undef DBGC_CLASS
26 #define DBGC_CLASS DBGC_RPC_SRV
27
28 /* registrt paths used in the print_registry[] */
29
30 #define KEY_MONITORS            "HKLM/SYSTEM/CURRENTCONTROLSET/CONTROL/PRINT/MONITORS"
31 #define KEY_FORMS               "HKLM/SYSTEM/CURRENTCONTROLSET/CONTROL/PRINT/FORMS"
32 #define KEY_CONTROL_PRINTERS    "HKLM/SYSTEM/CURRENTCONTROLSET/CONTROL/PRINT/PRINTERS"
33 #define KEY_ENVIRONMENTS        "HKLM/SYSTEM/CURRENTCONTROLSET/CONTROL/PRINT/ENVIRONMENTS"
34 #define KEY_CONTROL_PRINT       "HKLM/SYSTEM/CURRENTCONTROLSET/CONTROL/PRINT"
35 #define KEY_WINNT_PRINTERS      "HKLM/SOFTWARE/MICROSOFT/WINDOWS NT/CURRENTVERSION/PRINT/PRINTERS"
36 #define KEY_WINNT_PRINT         "HKLM/SOFTWARE/MICROSOFT/WINDOWS NT/CURRENTVERSION/PRINT"
37 #define KEY_PORTS               "HKLM/SOFTWARE/MICROSOFT/WINDOWS NT/CURRENTVERSION/PORTS"
38
39 /* callback table for various registry paths below the ones we service in this module */
40         
41 struct reg_dyn_tree {
42         /* full key path in normalized form */
43         const char *path;
44         
45         /* callbscks for fetch/store operations */
46         int ( *fetch_subkeys) ( const char *path, REGSUBKEY_CTR *subkeys );
47         BOOL (*store_subkeys) ( const char *path, REGSUBKEY_CTR *subkeys );
48         int  (*fetch_values)  ( const char *path, REGVAL_CTR *values );
49         BOOL (*store_values)  ( const char *path, REGVAL_CTR *values );
50 };
51
52 /*********************************************************************
53  *********************************************************************
54  ** Utility Functions
55  *********************************************************************
56  *********************************************************************/
57
58 /***********************************************************************
59  simple function to prune a pathname down to the basename of a file 
60  **********************************************************************/
61  
62 static char* dos_basename ( char *path )
63 {
64         char *p;
65         
66         if ( !(p = strrchr( path, '\\' )) )
67                 p = path;
68         else
69                 p++;
70                 
71         return p;
72 }
73
74 /*********************************************************************
75  *********************************************************************
76  ** "HKLM/SYSTEM/CURRENTCONTROLSET/CONTROL/PRINT/FORMS"
77  *********************************************************************
78  *********************************************************************/
79
80 static int key_forms_fetch_keys( const char *key, REGSUBKEY_CTR *subkeys )
81 {
82         char *p = reg_remaining_path( key + strlen(KEY_FORMS) );
83         
84         /* no keys below Forms */
85         
86         if ( p )
87                 return -1;
88                 
89         return 0;
90 }
91
92 /**********************************************************************
93  *********************************************************************/
94
95 static int key_forms_fetch_values( const char *key, REGVAL_CTR *values )
96 {
97         uint32          data[8];
98         int             i, num_values, form_index = 1;
99         nt_forms_struct *forms_list = NULL;
100         nt_forms_struct *form;
101                 
102         DEBUG(10,("print_values_forms: key=>[%s]\n", key ? key : "NULL" ));
103         
104         num_values = get_ntforms( &forms_list );
105                 
106         DEBUG(10,("hive_forms_fetch_values: [%d] user defined forms returned\n",
107                 num_values));
108
109         /* handle user defined forms */
110                                 
111         for ( i=0; i<num_values; i++ ) {
112                 form = &forms_list[i];
113                         
114                 data[0] = form->width;
115                 data[1] = form->length;
116                 data[2] = form->left;
117                 data[3] = form->top;
118                 data[4] = form->right;
119                 data[5] = form->bottom;
120                 data[6] = form_index++;
121                 data[7] = form->flag;
122                         
123                 regval_ctr_addvalue( values, form->name, REG_BINARY, (char*)data, sizeof(data) );       
124         }
125                 
126         SAFE_FREE( forms_list );
127         forms_list = NULL;
128                 
129         /* handle built-on forms */
130                 
131         num_values = get_builtin_ntforms( &forms_list );
132                 
133         DEBUG(10,("print_subpath_values_forms: [%d] built-in forms returned\n",
134                 num_values));
135                         
136         for ( i=0; i<num_values; i++ ) {
137                 form = &forms_list[i];
138                         
139                 data[0] = form->width;
140                 data[1] = form->length;
141                 data[2] = form->left;
142                 data[3] = form->top;
143                 data[4] = form->right;
144                 data[5] = form->bottom;
145                 data[6] = form_index++;
146                 data[7] = form->flag;
147                                         
148                 regval_ctr_addvalue( values, form->name, REG_BINARY, (char*)data, sizeof(data) );
149         }
150                 
151         SAFE_FREE( forms_list );
152         
153         return regval_ctr_numvals( values );
154 }
155
156 /*********************************************************************
157  *********************************************************************
158  ** "HKLM/SYSTEM/CURRENTCONTROLSET/CONTROL/PRINT/PRINTERS"
159  ** "HKLM/SOFTWARE/MICROSOFT/WINDOWS NT/CURRENTVERSION/PRINT/PRINTERS"
160  *********************************************************************
161  *********************************************************************/
162
163 /*********************************************************************
164  strip off prefix for printers key.  DOes return a pointer to static 
165  memory.
166  *********************************************************************/
167
168 static char* strip_printers_prefix( const char *key )
169 {
170         char *subkeypath;
171         pstring path;
172         
173         pstrcpy( path, key );
174         normalize_reg_path( path );
175
176         /* normalizing the path does not change length, just key delimiters and case */
177
178         if ( strncmp( path, KEY_WINNT_PRINTERS, strlen(KEY_WINNT_PRINTERS) ) == 0 )
179                 subkeypath = reg_remaining_path( key + strlen(KEY_WINNT_PRINTERS) );
180         else
181                 subkeypath = reg_remaining_path( key + strlen(KEY_CONTROL_PRINTERS) );
182                 
183         return subkeypath;
184 }
185
186 /*********************************************************************
187  *********************************************************************/
188  
189 static int key_printers_fetch_keys( const char *key, REGSUBKEY_CTR *subkeys )
190 {
191         int n_services = lp_numservices();      
192         int snum;
193         fstring sname;
194         int i;
195         int num_subkeys = 0;
196         char *printers_key;
197         char *printername, *printerdatakey;
198         NT_PRINTER_INFO_LEVEL *printer = NULL;
199         fstring *subkey_names = NULL;
200         
201         DEBUG(10,("key_printers_fetch_keys: key=>[%s]\n", key ? key : "NULL" ));
202         
203         printers_key = strip_printers_prefix( key );    
204         
205         if ( !printers_key ) {
206                 /* enumerate all printers */
207                 
208                 for (snum=0; snum<n_services; snum++) {
209                         if ( !(lp_snum_ok(snum) && lp_print_ok(snum) ) )
210                                 continue;
211
212                         /* don't report the [printers] share */
213
214                         if ( strequal( lp_servicename(snum), PRINTERS_NAME ) )
215                                 continue;
216                                 
217                         fstrcpy( sname, lp_servicename(snum) );
218                                 
219                         regsubkey_ctr_addkey( subkeys, sname );
220                 }
221                 
222                 num_subkeys = regsubkey_ctr_numkeys( subkeys );
223                 goto done;
224         }
225
226         /* get information for a specific printer */
227         
228         reg_split_path( printers_key, &printername, &printerdatakey );
229
230         if ( find_service(printername) == -1
231                 || !W_ERROR_IS_OK( get_a_printer(NULL, &printer, 2, printername) ) ) 
232         {
233                 return -1;
234         }
235
236         num_subkeys = get_printer_subkeys( printer->info_2->data, printerdatakey?printerdatakey:"", &subkey_names );
237         
238         for ( i=0; i<num_subkeys; i++ )
239                 regsubkey_ctr_addkey( subkeys, subkey_names[i] );
240         
241         free_a_printer( &printer, 2 );
242                         
243         /* no other subkeys below here */
244
245 done:   
246         SAFE_FREE( subkey_names );
247         
248         return num_subkeys;
249 }
250
251 /**********************************************************************
252  Take a list of names and call add_printer_hook() if necessary
253  Note that we do this a little differently from Windows since the 
254  keyname is the sharename and not the printer name.
255  *********************************************************************/
256
257 static BOOL add_printers_by_registry( REGSUBKEY_CTR *subkeys )
258 {
259         int i, num_keys, snum;
260         char *printername;
261         NT_PRINTER_INFO_LEVEL_2 info2;
262         NT_PRINTER_INFO_LEVEL printer;
263         
264         ZERO_STRUCT( info2 );
265         printer.info_2 = &info2;
266         
267         num_keys = regsubkey_ctr_numkeys( subkeys );
268         
269         become_root();
270         for ( i=0; i<num_keys; i++ ) {
271                 printername = regsubkey_ctr_specific_key( subkeys, i );
272                 snum = find_service( printername );
273                 
274                 /* just verify a valied snum for now */
275                 if ( snum == -1 ) {
276                         fstrcpy( info2.printername, printername );
277                         fstrcpy( info2.sharename, printername );
278                         if ( !add_printer_hook( NULL, &printer ) ) {
279                                 DEBUG(0,("add_printers_by_registry: Failed to add printer [%s]\n",
280                                         printername));
281                         }       
282                 }
283         }
284         unbecome_root();
285
286         return True;
287 }
288
289 /**********************************************************************
290  *********************************************************************/
291
292 static BOOL key_printers_store_keys( const char *key, REGSUBKEY_CTR *subkeys )
293 {
294         char *printers_key;
295         char *printername, *printerdatakey;
296         NT_PRINTER_INFO_LEVEL *printer = NULL;
297         int i, num_subkeys, num_existing_keys;
298         char *subkeyname;
299         fstring *existing_subkeys = NULL;
300         
301         printers_key = strip_printers_prefix( key );
302         
303         if ( !printers_key ) {
304                 /* have to deal with some new or deleted printer */
305                 return add_printers_by_registry( subkeys );
306         }
307         
308         reg_split_path( printers_key, &printername, &printerdatakey );
309         
310         /* lookup the printer */
311         
312         if ( !W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, printername)) ) {
313                 DEBUG(0,("key_printers_store_keys: Tried to store subkey for bad printername %s\n", 
314                         printername));
315                 return False;
316         }
317         
318         /* get the top level printer keys */
319         
320         num_existing_keys = get_printer_subkeys( printer->info_2->data, "", &existing_subkeys );
321         
322         for ( i=0; i<num_existing_keys; i++ ) {
323         
324                 /* remove the key if it has been deleted */
325                 
326                 if ( !regsubkey_ctr_key_exists( subkeys, existing_subkeys[i] ) ) {
327                         DEBUG(5,("key_printers_store_keys: deleting key %s\n", 
328                                 existing_subkeys[i]));
329                         delete_printer_key( printer->info_2->data, existing_subkeys[i] );
330                 }
331         }
332
333         num_subkeys = regsubkey_ctr_numkeys( subkeys );
334         for ( i=0; i<num_subkeys; i++ ) {
335                 subkeyname = regsubkey_ctr_specific_key(subkeys, i);
336                 /* add any missing printer keys */
337                 if ( lookup_printerkey(printer->info_2->data, subkeyname) == -1 ) {
338                         DEBUG(5,("key_printers_store_keys: adding key %s\n", 
339                                 existing_subkeys[i]));
340                         if ( add_new_printer_key( printer->info_2->data, subkeyname ) == -1 ) 
341                                 return False;
342                 }
343         }
344         
345         /* write back to disk */
346         
347         mod_a_printer( printer, 2 );
348         
349         /* cleanup */
350         
351         if ( printer )
352                 free_a_printer( &printer, 2 );
353
354         return True;
355 }
356
357 /**********************************************************************
358  *********************************************************************/
359
360 static void fill_in_printer_values( NT_PRINTER_INFO_LEVEL_2 *info2, REGVAL_CTR *values )
361 {
362         DEVICEMODE      *devmode;
363         prs_struct      prs;
364         uint32          offset;
365         UNISTR2         data;
366         char            *p;
367         uint32 printer_status = PRINTER_STATUS_OK;
368         int snum;
369         
370         regval_ctr_addvalue( values, "Attributes",       REG_DWORD, (char*)&info2->attributes,       sizeof(info2->attributes) );
371         regval_ctr_addvalue( values, "Priority",         REG_DWORD, (char*)&info2->priority,         sizeof(info2->attributes) );
372         regval_ctr_addvalue( values, "ChangeID",         REG_DWORD, (char*)&info2->changeid,         sizeof(info2->changeid) );
373         regval_ctr_addvalue( values, "Default Priority", REG_DWORD, (char*)&info2->default_priority, sizeof(info2->default_priority) );
374         
375         /* lie and say everything is ok since we don't want to call print_queue_length() to get the real status */
376         regval_ctr_addvalue( values, "Status",           REG_DWORD, (char*)&printer_status,          sizeof(info2->status) );
377
378         regval_ctr_addvalue( values, "StartTime",        REG_DWORD, (char*)&info2->starttime,        sizeof(info2->starttime) );
379         regval_ctr_addvalue( values, "UntilTime",        REG_DWORD, (char*)&info2->untiltime,        sizeof(info2->untiltime) );
380
381         /* strip the \\server\ from this string */
382         if ( !(p = strrchr( info2->printername, '\\' ) ) )
383                 p = info2->printername;
384         else
385                 p++;
386         init_unistr2( &data, p, UNI_STR_TERMINATE);
387         regval_ctr_addvalue( values, "Name", REG_SZ, (char*)data.buffer, data.uni_str_len*sizeof(uint16) );
388
389         init_unistr2( &data, info2->location, UNI_STR_TERMINATE);
390         regval_ctr_addvalue( values, "Location", REG_SZ, (char*)data.buffer, data.uni_str_len*sizeof(uint16) );
391
392         init_unistr2( &data, info2->comment, UNI_STR_TERMINATE);
393         regval_ctr_addvalue( values, "Description", REG_SZ, (char*)data.buffer, data.uni_str_len*sizeof(uint16) );
394
395         init_unistr2( &data, info2->parameters, UNI_STR_TERMINATE);
396         regval_ctr_addvalue( values, "Parameters", REG_SZ, (char*)data.buffer, data.uni_str_len*sizeof(uint16) );
397
398         init_unistr2( &data, info2->portname, UNI_STR_TERMINATE);
399         regval_ctr_addvalue( values, "Port", REG_SZ, (char*)data.buffer, data.uni_str_len*sizeof(uint16) );
400
401         init_unistr2( &data, info2->sharename, UNI_STR_TERMINATE);
402         regval_ctr_addvalue( values, "Share Name", REG_SZ, (char*)data.buffer, data.uni_str_len*sizeof(uint16) );
403
404         init_unistr2( &data, info2->drivername, UNI_STR_TERMINATE);
405         regval_ctr_addvalue( values, "Printer Driver", REG_SZ, (char*)data.buffer, data.uni_str_len*sizeof(uint16) );
406
407         init_unistr2( &data, info2->sepfile, UNI_STR_TERMINATE);
408         regval_ctr_addvalue( values, "Separator File", REG_SZ, (char*)data.buffer, data.uni_str_len*sizeof(uint16) );
409
410         init_unistr2( &data, "WinPrint", UNI_STR_TERMINATE);
411         regval_ctr_addvalue( values, "Print Processor",  REG_SZ, (char*)data.buffer, data.uni_str_len*sizeof(uint16) );
412
413         init_unistr2( &data, "RAW", UNI_STR_TERMINATE);
414         regval_ctr_addvalue( values, "Datatype", REG_SZ, (char*)data.buffer, data.uni_str_len*sizeof(uint16) );
415
416                 
417         /* use a prs_struct for converting the devmode and security 
418            descriptor to REG_BINARY */
419         
420         prs_init( &prs, RPC_MAX_PDU_FRAG_LEN, values, MARSHALL);
421
422         /* stream the device mode */
423                 
424         snum = lp_servicenumber(info2->sharename);
425         if ( (devmode = construct_dev_mode( snum )) != NULL ) {                 
426                 if ( spoolss_io_devmode( "devmode", &prs, 0, devmode ) ) {
427                         offset = prs_offset( &prs );
428                         regval_ctr_addvalue( values, "Default Devmode", REG_BINARY, prs_data_p(&prs), offset );
429                 }
430         }
431                 
432         prs_mem_clear( &prs );
433         prs_set_offset( &prs, 0 );
434                 
435         /* stream the printer security descriptor */
436         
437         if ( info2->secdesc_buf && info2->secdesc_buf->len )  {
438                 if ( sec_io_desc("sec_desc", &info2->secdesc_buf->sec, &prs, 0 ) ) {
439                         offset = prs_offset( &prs );
440                         regval_ctr_addvalue( values, "Security", REG_BINARY, prs_data_p(&prs), offset );
441                 }
442         }
443
444         prs_mem_free( &prs );
445
446         return;         
447 }
448
449 /**********************************************************************
450  *********************************************************************/
451
452 static int key_printers_fetch_values( const char *key, REGVAL_CTR *values )
453 {
454         int             num_values;
455         char            *printers_key;
456         char            *printername, *printerdatakey;
457         NT_PRINTER_INFO_LEVEL   *printer = NULL;
458         NT_PRINTER_DATA *p_data;
459         int             i, key_index;
460         
461         printers_key = strip_printers_prefix( key );    
462         
463         /* top level key values stored in the registry has no values */
464         
465         if ( !printers_key ) {
466                 /* normalize to the 'HKLM\SOFTWARE\...\Print\Printers' ket */
467                 return regdb_fetch_values( KEY_WINNT_PRINTERS, values );
468         }
469         
470         /* lookup the printer object */
471         
472         reg_split_path( printers_key, &printername, &printerdatakey );
473         if ( !W_ERROR_IS_OK( get_a_printer(NULL, &printer, 2, printername) ) )
474                 goto done;
475                 
476         if ( !printerdatakey ) {
477                 fill_in_printer_values( printer->info_2, values );
478                 goto done;
479         }
480                 
481         /* iterate over all printer data keys and fill the regval container */
482         
483         p_data = printer->info_2->data;
484         if ( (key_index = lookup_printerkey( p_data, printerdatakey )) == -1  ) {
485                 /* failure....should never happen if the client has a valid open handle first */
486                 DEBUG(10,("key_printers_fetch_values: Unknown keyname [%s]\n", printerdatakey));
487                 if ( printer )
488                         free_a_printer( &printer, 2 );
489                 return -1;
490         }
491         
492         num_values = regval_ctr_numvals( p_data->keys[key_index].values );      
493         for ( i=0; i<num_values; i++ )
494                 regval_ctr_copyvalue( values, regval_ctr_specific_value(p_data->keys[key_index].values, i) );
495                         
496
497 done:
498         if ( printer )
499                 free_a_printer( &printer, 2 );
500                 
501         return regval_ctr_numvals( values );
502 }
503
504 /**********************************************************************
505  *********************************************************************/
506
507 #define REG_IDX_ATTRIBUTES              1
508 #define REG_IDX_PRIORITY                2
509 #define REG_IDX_DEFAULT_PRIORITY        3
510 #define REG_IDX_CHANGEID                4
511 #define REG_IDX_STATUS                  5
512 #define REG_IDX_STARTTIME               6
513 #define REG_IDX_NAME                    7
514 #define REG_IDX_LOCATION                8
515 #define REG_IDX_DESCRIPTION             9
516 #define REG_IDX_PARAMETERS              10
517 #define REG_IDX_PORT                    12
518 #define REG_IDX_SHARENAME               13
519 #define REG_IDX_DRIVER                  14
520 #define REG_IDX_SEP_FILE                15
521 #define REG_IDX_PRINTPROC               16
522 #define REG_IDX_DATATYPE                17
523 #define REG_IDX_DEVMODE                 18
524 #define REG_IDX_SECDESC                 19
525 #define REG_IDX_UNTILTIME               20
526
527 struct {
528         const char *name;
529         int index;      
530 } printer_values_map[] = {
531         { "Attributes",         REG_IDX_ATTRIBUTES },
532         { "Priority",           REG_IDX_PRIORITY },
533         { "Default Priority",   REG_IDX_DEFAULT_PRIORITY },
534         { "ChangeID",           REG_IDX_CHANGEID },
535         { "Status",             REG_IDX_STATUS },
536         { "StartTime",          REG_IDX_STARTTIME },
537         { "UntilTime",          REG_IDX_UNTILTIME },
538         { "Name",               REG_IDX_NAME },
539         { "Location",           REG_IDX_LOCATION },
540         { "Descrioption",       REG_IDX_DESCRIPTION },
541         { "Parameters",         REG_IDX_PARAMETERS },
542         { "Port",               REG_IDX_PORT },
543         { "Share Name",         REG_IDX_SHARENAME },
544         { "Printer Driver",     REG_IDX_DRIVER },
545         { "Separator File",     REG_IDX_SEP_FILE },
546         { "Print Processor",    REG_IDX_PRINTPROC },
547         { "Datatype",           REG_IDX_DATATYPE },
548         { "Default Devmode",    REG_IDX_DEVMODE },
549         { "Security",           REG_IDX_SECDESC },
550         { NULL, -1 }
551 };
552
553
554 static int find_valuename_index( const char *valuename )
555 {
556         int i;
557         
558         for ( i=0; printer_values_map[i].name; i++ ) {
559                 if ( strequal( valuename, printer_values_map[i].name ) )
560                         return printer_values_map[i].index;
561         }
562         
563         return -1;
564 }
565
566 /**********************************************************************
567  *********************************************************************/
568
569 static void convert_values_to_printer_info_2( NT_PRINTER_INFO_LEVEL_2 *printer2, REGVAL_CTR *values )
570 {
571         int num_values = regval_ctr_numvals( values );
572         uint32 value_index;
573         REGISTRY_VALUE *val;
574         int i;
575         
576         for ( i=0; i<num_values; i++ ) {
577                 val = regval_ctr_specific_value( values, i );
578                 value_index = find_valuename_index( regval_name( val ) );
579                 
580                 switch( value_index ) {
581                         case REG_IDX_ATTRIBUTES:
582                                 printer2->attributes = (uint32)(*regval_data_p(val));
583                                 break;
584                         case REG_IDX_PRIORITY:
585                                 printer2->priority = (uint32)(*regval_data_p(val));
586                                 break;
587                         case REG_IDX_DEFAULT_PRIORITY:
588                                 printer2->default_priority = (uint32)(*regval_data_p(val));
589                                 break;
590                         case REG_IDX_CHANGEID:
591                                 printer2->changeid = (uint32)(*regval_data_p(val));
592                                 break;
593                         case REG_IDX_STARTTIME:
594                                 printer2->starttime = (uint32)(*regval_data_p(val));
595                                 break;
596                         case REG_IDX_UNTILTIME:
597                                 printer2->untiltime = (uint32)(*regval_data_p(val));
598                                 break;
599                         case REG_IDX_NAME:
600                                 rpcstr_pull( printer2->printername, regval_data_p(val), sizeof(fstring), regval_size(val), 0 );
601                                 break;
602                         case REG_IDX_LOCATION:
603                                 rpcstr_pull( printer2->location, regval_data_p(val), sizeof(fstring), regval_size(val), 0 );
604                                 break;
605                         case REG_IDX_DESCRIPTION:
606                                 rpcstr_pull( printer2->comment, regval_data_p(val), sizeof(fstring), regval_size(val), 0 );
607                                 break;
608                         case REG_IDX_PARAMETERS:
609                                 rpcstr_pull( printer2->parameters, regval_data_p(val), sizeof(fstring), regval_size(val), 0 );
610                                 break;
611                         case REG_IDX_PORT:
612                                 rpcstr_pull( printer2->portname, regval_data_p(val), sizeof(fstring), regval_size(val), 0 );
613                                 break;
614                         case REG_IDX_SHARENAME:
615                                 rpcstr_pull( printer2->sharename, regval_data_p(val), sizeof(fstring), regval_size(val), 0 );
616                                 break;
617                         case REG_IDX_DRIVER:
618                                 rpcstr_pull( printer2->drivername, regval_data_p(val), sizeof(fstring), regval_size(val), 0 );
619                                 break;
620                         case REG_IDX_SEP_FILE:
621                                 rpcstr_pull( printer2->sepfile, regval_data_p(val), sizeof(fstring), regval_size(val), 0 );
622                                 break;
623                         case REG_IDX_PRINTPROC:
624                                 rpcstr_pull( printer2->printprocessor, regval_data_p(val), sizeof(fstring), regval_size(val), 0 );
625                                 break;
626                         case REG_IDX_DATATYPE:
627                                 rpcstr_pull( printer2->datatype, regval_data_p(val), sizeof(fstring), regval_size(val), 0 );
628                                 break;
629                         case REG_IDX_DEVMODE:
630                                 break;
631                         case REG_IDX_SECDESC:
632                                 break;          
633                         default:
634                                 /* unsupported value...throw away */
635                                 DEBUG(8,("convert_values_to_printer_info_2: Unsupported registry value [%s]\n", 
636                                         regval_name( val ) ));
637                 }
638         }
639         
640         return;
641 }       
642
643 /**********************************************************************
644  *********************************************************************/
645
646 static BOOL key_printers_store_values( const char *key, REGVAL_CTR *values )
647 {
648         char *printers_key;
649         char *printername, *keyname;
650         NT_PRINTER_INFO_LEVEL   *printer = NULL;
651         WERROR result;
652         
653         printers_key = strip_printers_prefix( key );
654         
655         /* values in the top level key get stored in the registry */
656
657         if ( !printers_key ) {
658                 /* normalize on the 'HKLM\SOFTWARE\....\Print\Printers' key */
659                 return regdb_store_values( KEY_WINNT_PRINTERS, values );
660         }
661         
662         reg_split_path( printers_key, &printername, &keyname );
663
664         if ( !W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, printername) ) )
665                 return False;
666
667         /* deal with setting values directly under the printername */
668
669         if ( !keyname ) {
670                 convert_values_to_printer_info_2( printer->info_2, values );
671         }
672         else {
673                 int num_values = regval_ctr_numvals( values );
674                 int i;
675                 REGISTRY_VALUE *val;
676                 
677                 delete_printer_key( printer->info_2->data, keyname );
678                 
679                 /* deal with any subkeys */
680                 for ( i=0; i<num_values; i++ ) {
681                         val = regval_ctr_specific_value( values, i );
682                         result = set_printer_dataex( printer, keyname, 
683                                 regval_name( val ),
684                                 regval_type( val ),
685                                 regval_data_p( val ),
686                                 regval_size( val ) );
687                         if ( !W_ERROR_IS_OK(result) ) {
688                                 DEBUG(0,("key_printers_store_values: failed to set printer data [%s]!\n",
689                                         keyname));
690                                 free_a_printer( &printer, 2 );
691                                 return False;
692                         }
693                 }
694         }
695
696         result = mod_a_printer( printer, 2 );
697
698         free_a_printer( &printer, 2 );
699
700         return W_ERROR_IS_OK(result);
701 }
702
703 /*********************************************************************
704  *********************************************************************
705  ** "HKLM/SYSTEM/CURRENTCONTROLSET/CONTROL/PRINT/ENVIRONMENTS"
706  *********************************************************************
707  *********************************************************************/
708
709 static int key_driver_fetch_keys( const char *key, REGSUBKEY_CTR *subkeys )
710 {
711         const char *environments[] = {
712                 "Windows 4.0",
713                 "Windows NT x86",
714                 "Windows NT R4000",
715                 "Windows NT Alpha_AXP",
716                 "Windows NT PowerPC",
717                 "Windows IA64",
718                 "Windows x64",
719                 NULL };
720         fstring *drivers = NULL;
721         int i, env_index, num_drivers;
722         char *keystr, *base, *subkeypath;
723         pstring key2;
724         int num_subkeys = -1;
725         int version;
726
727         DEBUG(10,("key_driver_fetch_keys key=>[%s]\n", key ? key : "NULL" ));
728         
729         keystr = reg_remaining_path( key + strlen(KEY_ENVIRONMENTS) );  
730         
731         /* list all possible architectures */
732         
733         if ( !keystr ) {
734                 for ( num_subkeys=0; environments[num_subkeys]; num_subkeys++ ) 
735                         regsubkey_ctr_addkey( subkeys,  environments[num_subkeys] );
736
737                 return num_subkeys;
738         }
739         
740         /* we are dealing with a subkey of "Environments */
741         
742         pstrcpy( key2, keystr );
743         keystr = key2;
744         reg_split_path( keystr, &base, &subkeypath );
745         
746         /* sanity check */
747         
748         for ( env_index=0; environments[env_index]; env_index++ ) {
749                 if ( strequal( environments[env_index], base ) )
750                         break;
751         }
752         if ( !environments[env_index] )
753                 return -1;
754         
755         /* ...\Print\Environements\...\ */
756         
757         if ( !subkeypath ) {
758                 regsubkey_ctr_addkey( subkeys, "Drivers" );
759                 regsubkey_ctr_addkey( subkeys, "Print Processors" );
760                                 
761                 return 2;
762         }
763         
764         /* more of the key path to process */
765         
766         keystr = subkeypath;
767         reg_split_path( keystr, &base, &subkeypath );   
768                 
769         /* ...\Print\Environements\...\Drivers\ */
770         
771         if ( !subkeypath ) {
772                 if ( strequal(base, "Drivers") ) {
773                         switch ( env_index ) {
774                                 case 0: /* Win9x */
775                                         regsubkey_ctr_addkey( subkeys, "Version-0" );
776                                         break;
777                                 default: /* Windows NT based systems */
778                                         regsubkey_ctr_addkey( subkeys, "Version-2" );
779                                         regsubkey_ctr_addkey( subkeys, "Version-3" );
780                                         break;                  
781                         }
782                 
783                         return regsubkey_ctr_numkeys( subkeys );
784                 } else if ( strequal(base, "Print Processors") ) {
785                         if ( env_index == 1 || env_index == 5 || env_index == 6 )
786                                 regsubkey_ctr_addkey( subkeys, "winprint" );
787                                 
788                         return regsubkey_ctr_numkeys( subkeys );
789                 } else
790                         return -1;      /* bad path */
791         }
792         
793         /* we finally get to enumerate the drivers */
794         
795         /* only one possible subkey below PrintProc key */
796
797         if ( strequal(base, "Print Processors") ) {
798                 keystr = subkeypath;
799                 reg_split_path( keystr, &base, &subkeypath );
800
801                 /* no subkeys below this point */
802
803                 if ( subkeypath )
804                         return -1;
805
806                 /* only allow one keyname here -- 'winprint' */
807
808                 return strequal( base, "winprint" ) ? 0 : -1;
809         }
810         
811         /* only dealing with drivers from here on out */
812
813         keystr = subkeypath;
814         reg_split_path( keystr, &base, &subkeypath );
815         version = atoi(&base[strlen(base)-1]);
816                         
817         switch (env_index) {
818         case 0:
819                 if ( version != 0 )
820                         return -1;
821                 break;
822         default:
823                 if ( version != 2 && version != 3 )
824                         return -1;
825                 break;
826         }
827
828         
829         if ( !subkeypath ) {
830                 num_drivers = get_ntdrivers( &drivers, environments[env_index], version );
831                 for ( i=0; i<num_drivers; i++ )
832                         regsubkey_ctr_addkey( subkeys, drivers[i] );
833                         
834                 return regsubkey_ctr_numkeys( subkeys );        
835         }       
836         
837         /* if anything else left, just say if has no subkeys */
838         
839         DEBUG(1,("key_driver_fetch_keys unhandled key [%s] (subkey == %s\n", 
840                 key, subkeypath ));
841         
842         return 0;
843 }
844
845
846 /**********************************************************************
847  *********************************************************************/
848
849 static void fill_in_driver_values( NT_PRINTER_DRIVER_INFO_LEVEL_3 *info3, REGVAL_CTR *values )
850 {
851         char *buffer = NULL;
852         char *buffer2 = NULL;
853         int buffer_size = 0;
854         int i, length;
855         char *filename;
856         UNISTR2 data;
857         
858         filename = dos_basename( info3->driverpath );
859         init_unistr2( &data, filename, UNI_STR_TERMINATE);
860         regval_ctr_addvalue( values, "Driver", REG_SZ, (char*)data.buffer, 
861                 data.uni_str_len*sizeof(uint16) );
862         
863         filename = dos_basename( info3->configfile );
864         init_unistr2( &data, filename, UNI_STR_TERMINATE);
865         regval_ctr_addvalue( values, "Configuration File", REG_SZ, (char*)data.buffer, 
866                 data.uni_str_len*sizeof(uint16) );
867         
868         filename = dos_basename( info3->datafile );
869         init_unistr2( &data, filename, UNI_STR_TERMINATE);
870         regval_ctr_addvalue( values, "Data File", REG_SZ, (char*)data.buffer, 
871                 data.uni_str_len*sizeof(uint16) );
872         
873         filename = dos_basename( info3->helpfile );
874         init_unistr2( &data, filename, UNI_STR_TERMINATE);
875         regval_ctr_addvalue( values, "Help File", REG_SZ, (char*)data.buffer, 
876                 data.uni_str_len*sizeof(uint16) );
877         
878         init_unistr2( &data, info3->defaultdatatype, UNI_STR_TERMINATE);
879         regval_ctr_addvalue( values, "Data Type", REG_SZ, (char*)data.buffer, 
880                 data.uni_str_len*sizeof(uint16) );
881         
882         regval_ctr_addvalue( values, "Version", REG_DWORD, (char*)&info3->cversion, 
883                 sizeof(info3->cversion) );
884         
885         if ( info3->dependentfiles ) {
886                 /* place the list of dependent files in a single 
887                    character buffer, separating each file name by
888                    a NULL */
889                    
890                 for ( i=0; strcmp(info3->dependentfiles[i], ""); i++ ) {
891                         /* strip the path to only the file's base name */
892                 
893                         filename = dos_basename( info3->dependentfiles[i] );
894                         
895                         length = strlen(filename);
896                 
897                         buffer2 = SMB_REALLOC( buffer, buffer_size + (length + 1)*sizeof(uint16) );
898                         if ( !buffer2 )
899                                 break;
900                         buffer = buffer2;
901                         
902                         init_unistr2( &data, filename, UNI_STR_TERMINATE);
903                         memcpy( buffer+buffer_size, (char*)data.buffer, data.uni_str_len*sizeof(uint16) );
904                 
905                         buffer_size += (length + 1)*sizeof(uint16);
906                 }
907                 
908                 /* terminated by double NULL.  Add the final one here */
909                 
910                 buffer2 = SMB_REALLOC( buffer, buffer_size + 2 );
911                 if ( !buffer2 ) {
912                         SAFE_FREE( buffer );
913                         buffer_size = 0;
914                 } else {
915                         buffer = buffer2;
916                         buffer[buffer_size++] = '\0';
917                         buffer[buffer_size++] = '\0';
918                 }
919         }
920         
921         regval_ctr_addvalue( values, "Dependent Files",    REG_MULTI_SZ, buffer, buffer_size );
922                 
923         SAFE_FREE( buffer );
924         
925         return;
926 }
927
928 /**********************************************************************
929  *********************************************************************/
930
931 static int driver_arch_fetch_values( char *key, REGVAL_CTR *values )
932 {
933         char            *keystr, *base, *subkeypath;
934         fstring         arch_environment;
935         fstring         driver;
936         int             version;
937         NT_PRINTER_DRIVER_INFO_LEVEL    driver_ctr;
938         WERROR          w_result;
939
940         reg_split_path( key, &base, &subkeypath );
941         
942         /* no values in 'Environments\Drivers\Windows NT x86' */
943         
944         if ( !subkeypath ) 
945                 return 0;
946                 
947         /* We have the Architecture string and some subkey name:
948            Currently we only support
949            * Drivers
950            * Print Processors
951            Anything else is an error.
952            */
953
954         fstrcpy( arch_environment, base );
955         
956         keystr = subkeypath;
957         reg_split_path( keystr, &base, &subkeypath );
958
959         if ( strequal(base, "Print Processors") )
960                 return 0;
961
962         /* only Drivers key can be left */
963                 
964         if ( !strequal(base, "Drivers") )
965                 return -1;
966                         
967         if ( !subkeypath )
968                 return 0;
969         
970         /* We know that we have Architechure\Drivers with some subkey name
971            The subkey name has to be Version-XX */
972         
973         keystr = subkeypath;
974         reg_split_path( keystr, &base, &subkeypath );
975
976         if ( !subkeypath )
977                 return 0;
978                 
979         version = atoi(&base[strlen(base)-1]);
980
981         /* BEGIN PRINTER DRIVER NAME BLOCK */
982         
983         keystr = subkeypath;
984         reg_split_path( keystr, &base, &subkeypath );
985         
986         /* don't go any deeper for now */
987         
988         fstrcpy( driver, base );
989         
990         w_result = get_a_printer_driver( &driver_ctr, 3, driver, arch_environment, version );
991
992         if ( !W_ERROR_IS_OK(w_result) )
993                 return -1;
994                 
995         fill_in_driver_values( driver_ctr.info_3, values ); 
996         
997         free_a_printer_driver( driver_ctr, 3 );
998
999         /* END PRINTER DRIVER NAME BLOCK */
1000
1001                                                 
1002         DEBUG(8,("key_driver_fetch_values: Exit\n"));
1003         
1004         return regval_ctr_numvals( values );
1005 }
1006
1007 /**********************************************************************
1008  *********************************************************************/
1009
1010 static int key_driver_fetch_values( const char *key, REGVAL_CTR *values )
1011 {
1012         char *keystr;
1013         pstring subkey;
1014         
1015         DEBUG(8,("key_driver_fetch_values: Enter key => [%s]\n", key ? key : "NULL"));
1016
1017         /* no values in the Environments key */
1018         
1019         if ( !(keystr = reg_remaining_path( key + strlen(KEY_ENVIRONMENTS) )) )
1020                 return 0;
1021         
1022         pstrcpy( subkey, keystr);
1023         
1024         /* pass off to handle subkeys */
1025         
1026         return driver_arch_fetch_values( subkey, values );
1027 }
1028
1029 /*********************************************************************
1030  *********************************************************************
1031  ** "HKLM/SYSTEM/CURRENTCONTROLSET/CONTROL/PRINT"
1032  *********************************************************************
1033  *********************************************************************/
1034
1035 static int key_print_fetch_keys( const char *key, REGSUBKEY_CTR *subkeys )
1036 {       
1037         int key_len = strlen(key);
1038         
1039         /* no keys below 'Print' handled here */
1040         
1041         if ( (key_len != strlen(KEY_CONTROL_PRINT)) && (key_len != strlen(KEY_WINNT_PRINT)) )
1042                 return -1;
1043
1044         regsubkey_ctr_addkey( subkeys, "Environments" );
1045         regsubkey_ctr_addkey( subkeys, "Monitors" );
1046         regsubkey_ctr_addkey( subkeys, "Forms" );
1047         regsubkey_ctr_addkey( subkeys, "Printers" );
1048         
1049         return regsubkey_ctr_numkeys( subkeys );
1050 }
1051
1052 /**********************************************************************
1053  *********************************************************************
1054  ** Structure to hold dispatch table of ops for various printer keys.
1055  ** Make sure to always store deeper keys along the same path first so 
1056  ** we ge a more specific match.
1057  *********************************************************************
1058  *********************************************************************/
1059
1060 static struct reg_dyn_tree print_registry[] = {
1061 /* just pass the monitor onto the registry tdb */
1062 { KEY_MONITORS,
1063         &regdb_fetch_keys, 
1064         &regdb_store_keys,
1065         &regdb_fetch_values,
1066         &regdb_store_values },
1067 { KEY_FORMS, 
1068         &key_forms_fetch_keys, 
1069         NULL, 
1070         &key_forms_fetch_values,
1071         NULL },
1072 { KEY_CONTROL_PRINTERS, 
1073         &key_printers_fetch_keys,
1074         &key_printers_store_keys,
1075         &key_printers_fetch_values,
1076         &key_printers_store_values },
1077 { KEY_ENVIRONMENTS,
1078         &key_driver_fetch_keys,
1079         NULL,
1080         &key_driver_fetch_values,
1081         NULL },
1082 { KEY_CONTROL_PRINT,
1083         &key_print_fetch_keys,
1084         NULL,
1085         NULL,
1086         NULL },
1087 { KEY_WINNT_PRINTERS,
1088         &key_printers_fetch_keys,
1089         &key_printers_store_keys,
1090         &key_printers_fetch_values,
1091         &key_printers_store_values },
1092 { KEY_PORTS,
1093         &regdb_fetch_keys, 
1094         &regdb_store_keys,
1095         &regdb_fetch_values,
1096         &regdb_store_values },
1097         
1098 { NULL, NULL, NULL, NULL, NULL }
1099 };
1100
1101
1102 /**********************************************************************
1103  *********************************************************************
1104  ** Main reg_printing interface functions
1105  *********************************************************************
1106  *********************************************************************/
1107
1108 /***********************************************************************
1109  Lookup a key in the print_registry table, returning its index.
1110  -1 on failure
1111  **********************************************************************/
1112
1113 static int match_registry_path( const char *key )
1114 {
1115         int i;
1116         pstring path;
1117         
1118         if ( !key )
1119                 return -1;
1120
1121         pstrcpy( path, key );
1122         normalize_reg_path( path );
1123         
1124         for ( i=0; print_registry[i].path; i++ ) {
1125                 if ( strncmp( path, print_registry[i].path, strlen(print_registry[i].path) ) == 0 )
1126                         return i;
1127         }
1128         
1129         return -1;
1130 }
1131
1132 /***********************************************************************
1133  **********************************************************************/
1134
1135 static int regprint_fetch_reg_keys( const char *key, REGSUBKEY_CTR *subkeys )
1136 {
1137         int i = match_registry_path( key );
1138         
1139         if ( i == -1 )
1140                 return -1;
1141                 
1142         if ( !print_registry[i].fetch_subkeys )
1143                 return -1;
1144                 
1145         return print_registry[i].fetch_subkeys( key, subkeys );
1146 }
1147
1148 /**********************************************************************
1149  *********************************************************************/
1150
1151 static BOOL regprint_store_reg_keys( const char *key, REGSUBKEY_CTR *subkeys )
1152 {
1153         int i = match_registry_path( key );
1154         
1155         if ( i == -1 )
1156                 return False;
1157         
1158         if ( !print_registry[i].store_subkeys )
1159                 return False;
1160                 
1161         return print_registry[i].store_subkeys( key, subkeys );
1162 }
1163
1164 /**********************************************************************
1165  *********************************************************************/
1166
1167 static int regprint_fetch_reg_values( const char *key, REGVAL_CTR *values )
1168 {
1169         int i = match_registry_path( key );
1170         
1171         if ( i == -1 )
1172                 return -1;
1173         
1174         /* return 0 values by default since we know the key had 
1175            to exist because the client opened a handle */
1176            
1177         if ( !print_registry[i].fetch_values )
1178                 return 0;
1179                 
1180         return print_registry[i].fetch_values( key, values );
1181 }
1182
1183 /**********************************************************************
1184  *********************************************************************/
1185
1186 static BOOL regprint_store_reg_values( const char *key, REGVAL_CTR *values )
1187 {
1188         int i = match_registry_path( key );
1189         
1190         if ( i == -1 )
1191                 return False;
1192         
1193         if ( !print_registry[i].store_values )
1194                 return False;
1195                 
1196         return print_registry[i].store_values( key, values );
1197 }
1198
1199 /* 
1200  * Table of function pointers for accessing printing data
1201  */
1202  
1203 REGISTRY_OPS printing_ops = {
1204         regprint_fetch_reg_keys,
1205         regprint_fetch_reg_values,
1206         regprint_store_reg_keys,
1207         regprint_store_reg_values,
1208         NULL
1209 };
1210
1211