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