s3-registry: Redirect KEY_CONTROL_PRINTERS to KEY_WINNT_PRINTERS.
[kai/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  *  Copyright (c) Andreas Schneider <asn@samba.org> 2010
6  *
7  *  This program is free software; you can redistribute it and/or modify
8  *  it under the terms of the GNU General Public License as published by
9  *  the Free Software Foundation; either version 3 of the License, or
10  *  (at your option) any later version.
11  *
12  *  This program is distributed in the hope that it will be useful,
13  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
14  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  *  GNU General Public License for more details.
16  *
17  *  You should have received a copy of the GNU General Public License
18  *  along with this program; if not, see <http://www.gnu.org/licenses/>.
19  */
20
21 /* Implementation of registry virtual views for printing information */
22
23 #include "includes.h"
24 #include "registry.h"
25 #include "reg_util_internal.h"
26 #include "reg_backend_db.h"
27 #include "reg_objects.h"
28 #include "../librpc/gen_ndr/ndr_spoolss.h"
29
30 #undef DBGC_CLASS
31 #define DBGC_CLASS DBGC_REGISTRY
32
33 /* registry paths used in the print_registry[] */
34 #define KEY_CONTROL_PRINTERS    "HKLM\\SYSTEM\\CURRENTCONTROLSET\\CONTROL\\PRINT\\PRINTERS"
35 #define KEY_WINNT_PRINTERS      "HKLM\\SOFTWARE\\MICROSOFT\\WINDOWS NT\\CURRENTVERSION\\PRINT\\PRINTERS"
36
37 /* callback table for various registry paths below the ones we service in this module */
38
39 struct reg_dyn_tree {
40         /* full key path in normalized form */
41         const char *path;
42
43         /* callbscks for fetch/store operations */
44         int ( *fetch_subkeys) ( const char *path, struct regsubkey_ctr *subkeys );
45         bool (*store_subkeys) ( const char *path, struct regsubkey_ctr *subkeys );
46         int  (*fetch_values)  ( const char *path, struct regval_ctr *values );
47         bool (*store_values)  ( const char *path, struct regval_ctr *values );
48 };
49
50 /*********************************************************************
51  *********************************************************************
52  ** "HKLM/SYSTEM/CURRENTCONTROLSET/CONTROL/PRINT/PRINTERS"
53  ** "HKLM/SOFTWARE/MICROSOFT/WINDOWS NT/CURRENTVERSION/PRINT/PRINTERS"
54  *********************************************************************
55  *********************************************************************/
56
57 static char *create_printer_registry_path(TALLOC_CTX *mem_ctx, const char *key) {
58         char *path;
59         char *subkey = NULL;
60
61         path = talloc_strdup(mem_ctx, key);
62         if (path == NULL) {
63                 return NULL;
64         }
65
66         path = normalize_reg_path(mem_ctx, path);
67         if (path == NULL) {
68                 return NULL;
69         }
70
71         if (strncmp(path, KEY_CONTROL_PRINTERS, strlen(KEY_CONTROL_PRINTERS)) == 0) {
72                 subkey = reg_remaining_path(mem_ctx, key + strlen(KEY_CONTROL_PRINTERS));
73                 if (subkey == NULL) {
74                         return NULL;
75                 }
76                 return talloc_asprintf(mem_ctx, "%s\\%s", KEY_WINNT_PRINTERS, subkey);
77         }
78
79         return NULL;
80 }
81
82 /*********************************************************************
83  *********************************************************************/
84
85 static int key_printers_fetch_keys( const char *key, struct regsubkey_ctr *subkeys )
86 {
87         TALLOC_CTX *ctx = talloc_tos();
88         char *printers_key;
89
90         printers_key = create_printer_registry_path(ctx, key);
91         if (printers_key == NULL) {
92                 /* normalize on the 'HKLM\SOFTWARE\....\Print\Printers' key */
93                 return regdb_fetch_keys(KEY_WINNT_PRINTERS, subkeys);
94         }
95
96         return regdb_fetch_keys(printers_key, subkeys);
97 }
98
99 /**********************************************************************
100  *********************************************************************/
101
102 static bool key_printers_store_keys( const char *key, struct regsubkey_ctr *subkeys )
103 {
104         TALLOC_CTX *ctx = talloc_tos();
105         char *printers_key;
106
107         printers_key = create_printer_registry_path(ctx, key);
108         if (printers_key == NULL) {
109                 /* normalize on the 'HKLM\SOFTWARE\....\Print\Printers' key */
110                 return regdb_store_keys(KEY_WINNT_PRINTERS, subkeys);
111         }
112
113         return regdb_store_keys(printers_key, subkeys);
114 }
115
116 /**********************************************************************
117  *********************************************************************/
118
119 static int key_printers_fetch_values(const char *key, struct regval_ctr *values)
120 {
121         TALLOC_CTX *ctx = talloc_tos();
122         char *printers_key;
123
124         printers_key = create_printer_registry_path(ctx, key);
125         if (printers_key == NULL) {
126                 /* normalize on the 'HKLM\SOFTWARE\....\Print\Printers' key */
127                 return regdb_fetch_values(KEY_WINNT_PRINTERS, values);
128         }
129
130         return regdb_fetch_values(printers_key, values);
131 }
132
133 /**********************************************************************
134  *********************************************************************/
135
136 static bool key_printers_store_values(const char *key, struct regval_ctr *values)
137 {
138         TALLOC_CTX *ctx = talloc_tos();
139         char *printers_key;
140
141         printers_key = create_printer_registry_path(ctx, key);
142         if (printers_key == NULL) {
143                 /* normalize on the 'HKLM\SOFTWARE\....\Print\Printers' key */
144                 return regdb_store_values(KEY_WINNT_PRINTERS, values);
145         }
146
147         return regdb_store_values(printers_key, values);
148 }
149
150 /**********************************************************************
151  *********************************************************************
152  ** Structure to hold dispatch table of ops for various printer keys.
153  ** Make sure to always store deeper keys along the same path first so
154  ** we ge a more specific match.
155  *********************************************************************
156  *********************************************************************/
157
158 static struct reg_dyn_tree print_registry[] = {
159 { KEY_CONTROL_PRINTERS,
160         &key_printers_fetch_keys,
161         &key_printers_store_keys,
162         &key_printers_fetch_values,
163         &key_printers_store_values },
164
165 { NULL, NULL, NULL, NULL, NULL }
166 };
167
168
169 /**********************************************************************
170  *********************************************************************
171  ** Main reg_printing interface functions
172  *********************************************************************
173  *********************************************************************/
174
175 /***********************************************************************
176  Lookup a key in the print_registry table, returning its index.
177  -1 on failure
178  **********************************************************************/
179
180 static int match_registry_path(const char *key)
181 {
182         int i;
183         char *path = NULL;
184         TALLOC_CTX *ctx = talloc_tos();
185
186         if ( !key )
187                 return -1;
188
189         path = talloc_strdup(ctx, key);
190         if (!path) {
191                 return -1;
192         }
193         path = normalize_reg_path(ctx, path);
194         if (!path) {
195                 return -1;
196         }
197
198         for ( i=0; print_registry[i].path; i++ ) {
199                 if (strncmp( path, print_registry[i].path, strlen(print_registry[i].path) ) == 0 )
200                         return i;
201         }
202
203         return -1;
204 }
205
206 /***********************************************************************
207  **********************************************************************/
208
209 static int regprint_fetch_reg_keys( const char *key, struct regsubkey_ctr *subkeys )
210 {
211         int i = match_registry_path( key );
212
213         if ( i == -1 )
214                 return -1;
215
216         if ( !print_registry[i].fetch_subkeys )
217                 return -1;
218
219         return print_registry[i].fetch_subkeys( key, subkeys );
220 }
221
222 /**********************************************************************
223  *********************************************************************/
224
225 static bool regprint_store_reg_keys( const char *key, struct regsubkey_ctr *subkeys )
226 {
227         int i = match_registry_path( key );
228
229         if ( i == -1 )
230                 return False;
231
232         if ( !print_registry[i].store_subkeys )
233                 return False;
234
235         return print_registry[i].store_subkeys( key, subkeys );
236 }
237
238 /**********************************************************************
239  *********************************************************************/
240
241 static int regprint_fetch_reg_values(const char *key, struct regval_ctr *values)
242 {
243         int i = match_registry_path( key );
244
245         if ( i == -1 )
246                 return -1;
247
248         /* return 0 values by default since we know the key had
249            to exist because the client opened a handle */
250
251         if ( !print_registry[i].fetch_values )
252                 return 0;
253
254         return print_registry[i].fetch_values( key, values );
255 }
256
257 /**********************************************************************
258  *********************************************************************/
259
260 static bool regprint_store_reg_values(const char *key, struct regval_ctr *values)
261 {
262         int i = match_registry_path( key );
263
264         if ( i == -1 )
265                 return False;
266
267         if ( !print_registry[i].store_values )
268                 return False;
269
270         return print_registry[i].store_values( key, values );
271 }
272
273 /*
274  * Table of function pointers for accessing printing data
275  */
276
277 struct registry_ops printing_ops = {
278         .fetch_subkeys = regprint_fetch_reg_keys,
279         .fetch_values = regprint_fetch_reg_values,
280         .store_subkeys = regprint_store_reg_keys,
281         .store_values = regprint_store_reg_values,
282 };