s3:registry: printing backend: use regdb options via ops struct, not directly
[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
27 #undef DBGC_CLASS
28 #define DBGC_CLASS DBGC_REGISTRY
29
30 extern struct registry_ops regdb_ops;
31
32 /* registry paths used in the print_registry[] */
33 #define KEY_CONTROL_PRINTERS    "HKLM\\SYSTEM\\CURRENTCONTROLSET\\CONTROL\\PRINT\\PRINTERS"
34 #define KEY_WINNT_PRINTERS      "HKLM\\SOFTWARE\\MICROSOFT\\WINDOWS NT\\CURRENTVERSION\\PRINT\\PRINTERS"
35
36 /* callback table for various registry paths below the ones we service in this module */
37
38 struct reg_dyn_tree {
39         /* full key path in normalized form */
40         const char *path;
41
42         /* callbscks for fetch/store operations */
43         int ( *fetch_subkeys) ( const char *path, struct regsubkey_ctr *subkeys );
44         bool (*store_subkeys) ( const char *path, struct regsubkey_ctr *subkeys );
45         int  (*fetch_values)  ( const char *path, struct regval_ctr *values );
46         bool (*store_values)  ( const char *path, struct regval_ctr *values );
47 };
48
49 /*********************************************************************
50  *********************************************************************
51  ** "HKLM/SYSTEM/CURRENTCONTROLSET/CONTROL/PRINT/PRINTERS"
52  ** "HKLM/SOFTWARE/MICROSOFT/WINDOWS NT/CURRENTVERSION/PRINT/PRINTERS"
53  *********************************************************************
54  *********************************************************************/
55
56 static char *create_printer_registry_path(TALLOC_CTX *mem_ctx, const char *key) {
57         char *path;
58         char *subkey = NULL;
59
60         path = talloc_strdup(mem_ctx, key);
61         if (path == NULL) {
62                 return NULL;
63         }
64
65         path = normalize_reg_path(mem_ctx, path);
66         if (path == NULL) {
67                 return NULL;
68         }
69
70         if (strncmp(path, KEY_CONTROL_PRINTERS, strlen(KEY_CONTROL_PRINTERS)) == 0) {
71                 subkey = reg_remaining_path(mem_ctx, key + strlen(KEY_CONTROL_PRINTERS));
72                 if (subkey == NULL) {
73                         return NULL;
74                 }
75                 return talloc_asprintf(mem_ctx, "%s\\%s", KEY_WINNT_PRINTERS, subkey);
76         }
77
78         return NULL;
79 }
80
81 /*********************************************************************
82  *********************************************************************/
83
84 static int key_printers_fetch_keys( const char *key, struct regsubkey_ctr *subkeys )
85 {
86         TALLOC_CTX *ctx = talloc_tos();
87         char *printers_key;
88
89         printers_key = create_printer_registry_path(ctx, key);
90         if (printers_key == NULL) {
91                 /* normalize on the 'HKLM\SOFTWARE\....\Print\Printers' key */
92                 return regdb_ops.fetch_subkeys(KEY_WINNT_PRINTERS, subkeys);
93         }
94
95         return regdb_ops.fetch_subkeys(printers_key, subkeys);
96 }
97
98 /**********************************************************************
99  *********************************************************************/
100
101 static bool key_printers_store_keys( const char *key, struct regsubkey_ctr *subkeys )
102 {
103         TALLOC_CTX *ctx = talloc_tos();
104         char *printers_key;
105
106         printers_key = create_printer_registry_path(ctx, key);
107         if (printers_key == NULL) {
108                 /* normalize on the 'HKLM\SOFTWARE\....\Print\Printers' key */
109                 return regdb_ops.store_subkeys(KEY_WINNT_PRINTERS, subkeys);
110         }
111
112         return regdb_ops.store_subkeys(printers_key, subkeys);
113 }
114
115 /**********************************************************************
116  *********************************************************************/
117
118 static int key_printers_fetch_values(const char *key, struct regval_ctr *values)
119 {
120         TALLOC_CTX *ctx = talloc_tos();
121         char *printers_key;
122
123         printers_key = create_printer_registry_path(ctx, key);
124         if (printers_key == NULL) {
125                 /* normalize on the 'HKLM\SOFTWARE\....\Print\Printers' key */
126                 return regdb_ops.fetch_values(KEY_WINNT_PRINTERS, values);
127         }
128
129         return regdb_ops.fetch_values(printers_key, values);
130 }
131
132 /**********************************************************************
133  *********************************************************************/
134
135 static bool key_printers_store_values(const char *key, struct regval_ctr *values)
136 {
137         TALLOC_CTX *ctx = talloc_tos();
138         char *printers_key;
139
140         printers_key = create_printer_registry_path(ctx, key);
141         if (printers_key == NULL) {
142                 /* normalize on the 'HKLM\SOFTWARE\....\Print\Printers' key */
143                 return regdb_ops.store_values(KEY_WINNT_PRINTERS, values);
144         }
145
146         return regdb_ops.store_values(printers_key, values);
147 }
148
149 /**********************************************************************
150  *********************************************************************
151  ** Structure to hold dispatch table of ops for various printer keys.
152  ** Make sure to always store deeper keys along the same path first so
153  ** we ge a more specific match.
154  *********************************************************************
155  *********************************************************************/
156
157 static struct reg_dyn_tree print_registry[] = {
158 { KEY_CONTROL_PRINTERS,
159         &key_printers_fetch_keys,
160         &key_printers_store_keys,
161         &key_printers_fetch_values,
162         &key_printers_store_values },
163
164 { NULL, NULL, NULL, NULL, NULL }
165 };
166
167
168 /**********************************************************************
169  *********************************************************************
170  ** Main reg_printing interface functions
171  *********************************************************************
172  *********************************************************************/
173
174 /***********************************************************************
175  Lookup a key in the print_registry table, returning its index.
176  -1 on failure
177  **********************************************************************/
178
179 static int match_registry_path(const char *key)
180 {
181         int i;
182         char *path = NULL;
183         TALLOC_CTX *ctx = talloc_tos();
184
185         if ( !key )
186                 return -1;
187
188         path = talloc_strdup(ctx, key);
189         if (!path) {
190                 return -1;
191         }
192         path = normalize_reg_path(ctx, path);
193         if (!path) {
194                 return -1;
195         }
196
197         for ( i=0; print_registry[i].path; i++ ) {
198                 if (strncmp( path, print_registry[i].path, strlen(print_registry[i].path) ) == 0 )
199                         return i;
200         }
201
202         return -1;
203 }
204
205 /***********************************************************************
206  **********************************************************************/
207
208 static int regprint_fetch_reg_keys( const char *key, struct regsubkey_ctr *subkeys )
209 {
210         int i = match_registry_path( key );
211
212         if ( i == -1 )
213                 return -1;
214
215         if ( !print_registry[i].fetch_subkeys )
216                 return -1;
217
218         return print_registry[i].fetch_subkeys( key, subkeys );
219 }
220
221 /**********************************************************************
222  *********************************************************************/
223
224 static bool regprint_store_reg_keys( const char *key, struct regsubkey_ctr *subkeys )
225 {
226         int i = match_registry_path( key );
227
228         if ( i == -1 )
229                 return False;
230
231         if ( !print_registry[i].store_subkeys )
232                 return False;
233
234         return print_registry[i].store_subkeys( key, subkeys );
235 }
236
237 /**********************************************************************
238  *********************************************************************/
239
240 static int regprint_fetch_reg_values(const char *key, struct regval_ctr *values)
241 {
242         int i = match_registry_path( key );
243
244         if ( i == -1 )
245                 return -1;
246
247         /* return 0 values by default since we know the key had
248            to exist because the client opened a handle */
249
250         if ( !print_registry[i].fetch_values )
251                 return 0;
252
253         return print_registry[i].fetch_values( key, values );
254 }
255
256 /**********************************************************************
257  *********************************************************************/
258
259 static bool regprint_store_reg_values(const char *key, struct regval_ctr *values)
260 {
261         int i = match_registry_path( key );
262
263         if ( i == -1 )
264                 return False;
265
266         if ( !print_registry[i].store_values )
267                 return False;
268
269         return print_registry[i].store_values( key, values );
270 }
271
272 /*
273  * Table of function pointers for accessing printing data
274  */
275
276 struct registry_ops printing_ops = {
277         .fetch_subkeys = regprint_fetch_reg_keys,
278         .fetch_values = regprint_fetch_reg_values,
279         .store_subkeys = regprint_store_reg_keys,
280         .store_values = regprint_store_reg_values,
281 };