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