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