done! printer_info_2, devicemode, sec_desc, & printer data all enumerate
[Samba.git] / source / registry / reg_printing.c
blob145b8230c9800b949886146bd7bec35a549dd9b2
1 /*
2 * Unix SMB/CIFS implementation.
3 * RPC Pipe client / server routines
4 * Copyright (C) Gerald Carter 2002.
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
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.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
21 /* Implementation of registry virtual views for printing information */
23 #include "includes.h"
25 #undef DBGC_CLASS
26 #define DBGC_CLASS DBGC_RPC_SRV
28 #define MAX_TOP_LEVEL_KEYS 3
30 /* some symbolic indexes into the top_level_keys */
32 #define KEY_INDEX_ENVIR 0
33 #define KEY_INDEX_FORMS 1
34 #define KEY_INDEX_PRINTER 2
36 static char *top_level_keys[MAX_TOP_LEVEL_KEYS] = {
37 "Environments",
38 "Forms",
39 "Printers"
43 /**********************************************************************
44 It is safe to assume that every registry path passed into on of
45 the exported functions here begins with KEY_PRINTING else
46 these functions would have never been called. This is a small utility
47 function to strip the beginning of the path and make a copy that the
48 caller can modify. Note that the caller is responsible for releasing
49 the memory allocated here.
50 **********************************************************************/
52 static char* trim_reg_path( char *path )
54 char *p;
55 uint16 key_len = strlen(KEY_PRINTING);
57 /*
58 * sanity check...this really should never be True.
59 * It is only here to prevent us from accessing outside
60 * the path buffer in the extreme case.
63 if ( strlen(path) < key_len ) {
64 DEBUG(0,("trim_reg_path: Registry path too short! [%s]\n", path));
65 DEBUG(0,("trim_reg_path: KEY_PRINTING => [%s]!\n", KEY_PRINTING));
66 return NULL;
70 p = path + strlen( KEY_PRINTING );
72 if ( *p == '\\' )
73 p++;
75 if ( *p )
76 return strdup(p);
77 else
78 return NULL;
81 /**********************************************************************
82 handle enumeration of subkeys below KEY_PRINTING\Environments
83 *********************************************************************/
85 static int print_subpath_environments( char *key, REGSUBKEY_CTR *subkeys )
87 char *environments[] = {
88 "Windows 4.0",
89 "Windows NT x86",
90 "Windows NT R4000",
91 "Windows NT Alpha_AXP",
92 "Windows NT PowerPC",
93 NULL };
94 fstring *drivers = NULL;
95 int i, env_index, num_drivers;
96 BOOL valid_env = False;
97 char *base, *new_path;
98 char *keystr;
99 char *key2 = NULL;
100 int num_subkeys = -1;
102 DEBUG(10,("print_subpath_environments: key=>[%s]\n", key ? key : "NULL" ));
104 /* listed architectures of installed drivers */
106 if ( !key )
108 /* Windows 9x drivers */
110 if ( get_ntdrivers( &drivers, environments[0], 0 ) )
111 regsubkey_ctr_addkey( subkeys, environments[0] );
112 SAFE_FREE( drivers );
114 /* Windows NT/2k intel drivers */
116 if ( get_ntdrivers( &drivers, environments[1], 2 )
117 || get_ntdrivers( &drivers, environments[1], 3 ) )
119 regsubkey_ctr_addkey( subkeys, environments[1] );
121 SAFE_FREE( drivers );
123 /* Windows NT 4.0; non-intel drivers */
124 for ( i=2; environments[i]; i++ ) {
125 if ( get_ntdrivers( &drivers, environments[i], 2 ) )
126 regsubkey_ctr_addkey( subkeys, environments[i] );
129 SAFE_FREE( drivers );
131 num_subkeys = regsubkey_ctr_numkeys( subkeys );
132 goto done;
135 /* we are dealing with a subkey of "Environments */
137 key2 = strdup( key );
138 keystr = key2;
139 reg_split_path( keystr, &base, &new_path );
141 /* sanity check */
143 for ( env_index=0; environments[env_index]; env_index++ ) {
144 if ( StrCaseCmp( environments[env_index], base ) == 0 ) {
145 valid_env = True;
146 break;
150 if ( !valid_env )
151 return -1;
153 /* enumerate driver versions; environment is environments[env_index] */
155 if ( !new_path ) {
156 switch ( env_index ) {
157 case 0: /* Win9x */
158 if ( get_ntdrivers( &drivers, environments[0], 0 ) ) {
159 regsubkey_ctr_addkey( subkeys, "0" );
160 SAFE_FREE( drivers );
162 break;
163 case 1: /* Windows NT/2k - intel */
164 if ( get_ntdrivers( &drivers, environments[1], 2 ) ) {
165 regsubkey_ctr_addkey( subkeys, "2" );
166 SAFE_FREE( drivers );
168 if ( get_ntdrivers( &drivers, environments[1], 3 ) ) {
169 regsubkey_ctr_addkey( subkeys, "3" );
170 SAFE_FREE( drivers );
172 break;
173 default: /* Windows NT - nonintel */
174 if ( get_ntdrivers( &drivers, environments[env_index], 2 ) ) {
175 regsubkey_ctr_addkey( subkeys, "2" );
176 SAFE_FREE( drivers );
181 num_subkeys = regsubkey_ctr_numkeys( subkeys );
182 goto done;
185 /* we finally get to enumerate the drivers */
187 keystr = new_path;
188 reg_split_path( keystr, &base, &new_path );
190 if ( !new_path ) {
191 num_drivers = get_ntdrivers( &drivers, environments[env_index], atoi(base) );
192 for ( i=0; i<num_drivers; i++ )
193 regsubkey_ctr_addkey( subkeys, drivers[i] );
195 num_subkeys = regsubkey_ctr_numkeys( subkeys );
196 goto done;
199 done:
200 SAFE_FREE( key2 );
202 return num_subkeys;
205 /***********************************************************************
206 simple function to prune a pathname down to the basename of a file
207 **********************************************************************/
209 static char* dos_basename ( char *path )
211 char *p;
213 p = strrchr( path, '\\' );
214 if ( p )
215 p++;
216 else
217 p = path;
219 return p;
222 /**********************************************************************
223 handle enumeration of values below
224 KEY_PRINTING\Environments\<arch>\<version>\<drivername>
225 *********************************************************************/
227 static int print_subpath_values_environments( char *key, REGVAL_CTR *val )
229 char *keystr;
230 char *key2 = NULL;
231 char *base, *new_path;
232 fstring env;
233 fstring driver;
234 int version;
235 NT_PRINTER_DRIVER_INFO_LEVEL driver_ctr;
236 NT_PRINTER_DRIVER_INFO_LEVEL_3 *info3;
237 WERROR w_result;
238 char *buffer = NULL;
239 char *buffer2 = NULL;
240 int buffer_size = 0;
241 int i, length;
242 char *filename;
244 DEBUG(8,("print_subpath_values_environments: Enter key => [%s]\n", key ? key : "NULL"));
246 if ( !key )
247 return 0;
250 * The only key below KEY_PRINTING\Environments that
251 * posseses values is each specific printer driver
252 * First get the arch, version, & driver name
255 /* env */
257 key2 = strdup( key );
258 keystr = key2;
259 reg_split_path( keystr, &base, &new_path );
260 if ( !base || !new_path )
261 return 0;
262 fstrcpy( env, base );
264 /* version */
266 keystr = new_path;
267 reg_split_path( keystr, &base, &new_path );
268 if ( !base || !new_path )
269 return 0;
270 version = atoi( base );
272 /* printer driver name */
274 keystr = new_path;
275 reg_split_path( keystr, &base, &new_path );
276 /* new_path should be NULL here since this must be the last key */
277 if ( !base || new_path )
278 return 0;
279 fstrcpy( driver, base );
281 w_result = get_a_printer_driver( &driver_ctr, 3, driver, env, version );
283 if ( !W_ERROR_IS_OK(w_result) )
284 return -1;
286 /* build the values out of the driver information */
287 info3 = driver_ctr.info_3;
289 filename = dos_basename( info3->driverpath );
290 regval_ctr_addvalue( val, "Driver", REG_SZ, filename, strlen(filename)+1 );
291 filename = dos_basename( info3->configfile );
292 regval_ctr_addvalue( val, "Configuration File", REG_SZ, filename, strlen(filename)+1 );
293 filename = dos_basename( info3->datafile );
294 regval_ctr_addvalue( val, "Data File", REG_SZ, filename, strlen(filename)+1 );
295 filename = dos_basename( info3->helpfile );
296 regval_ctr_addvalue( val, "Help File", REG_SZ, filename, strlen(filename)+1 );
298 regval_ctr_addvalue( val, "Data Type", REG_SZ, info3->defaultdatatype, strlen(info3->defaultdatatype)+1 );
300 regval_ctr_addvalue( val, "Version", REG_DWORD, (char*)&info3->cversion, sizeof(info3->cversion) );
302 if ( info3->dependentfiles )
304 /* place the list of dependent files in a single
305 character buffer, separating each file name by
306 a NULL */
308 for ( i=0; strcmp(info3->dependentfiles[i], ""); i++ )
310 /* strip the path to only the file's base name */
312 filename = dos_basename( info3->dependentfiles[i] );
314 length = strlen(filename);
316 buffer2 = Realloc( buffer, buffer_size + length + 1 );
317 if ( !buffer2 )
318 break;
319 buffer = buffer2;
321 memcpy( buffer+buffer_size, filename, length+1 );
323 buffer_size += length + 1;
326 /* terminated by double NULL. Add the final one here */
328 buffer2 = Realloc( buffer, buffer_size + 1 );
329 if ( !buffer2 ) {
330 SAFE_FREE( buffer );
331 buffer_size = 0;
333 else {
334 buffer = buffer2;
335 buffer[buffer_size++] = '\0';
339 regval_ctr_addvalue( val, "Dependent Files", REG_MULTI_SZ, buffer, buffer_size );
341 free_a_printer_driver( driver_ctr, 3 );
342 SAFE_FREE( key2 );
343 SAFE_FREE( buffer );
345 DEBUG(8,("print_subpath_values_environments: Exit\n"));
347 return regval_ctr_numvals( val );
351 /**********************************************************************
352 handle enumeration of subkeys below KEY_PRINTING\Forms
353 Really just a stub function, but left here in case it needs to
354 be expanded later on
355 *********************************************************************/
357 static int print_subpath_forms( char *key, REGSUBKEY_CTR *subkeys )
359 DEBUG(10,("print_subpath_forms: key=>[%s]\n", key ? key : "NULL" ));
361 /* there are no subkeys */
363 if ( key )
364 return -1;
366 return 0;
369 /**********************************************************************
370 handle enumeration of values below KEY_PRINTING\Forms
371 *********************************************************************/
373 static int print_subpath_values_forms( char *key, REGVAL_CTR *val )
375 int num_values = 0;
376 uint32 data[8];
377 int form_index = 1;
379 DEBUG(10,("print_values_forms: key=>[%s]\n", key ? key : "NULL" ));
381 /* handle ..\Forms\ */
383 if ( !key )
385 nt_forms_struct *forms_list = NULL;
386 nt_forms_struct *form = NULL;
387 int i;
389 if ( (num_values = get_ntforms( &forms_list )) == 0 )
390 return 0;
392 DEBUG(10,("print_subpath_values_forms: [%d] user defined forms returned\n",
393 num_values));
395 /* handle user defined forms */
397 for ( i=0; i<num_values; i++ )
399 form = &forms_list[i];
401 data[0] = form->width;
402 data[1] = form->length;
403 data[2] = form->left;
404 data[3] = form->top;
405 data[4] = form->right;
406 data[5] = form->bottom;
407 data[6] = form_index++;
408 data[7] = form->flag;
410 regval_ctr_addvalue( val, form->name, REG_BINARY, (char*)data, sizeof(data) );
414 SAFE_FREE( forms_list );
415 forms_list = NULL;
417 /* handle built-on forms */
419 if ( (num_values = get_builtin_ntforms( &forms_list )) == 0 )
420 return 0;
422 DEBUG(10,("print_subpath_values_forms: [%d] built-in forms returned\n",
423 num_values));
425 for ( i=0; i<num_values; i++ )
427 form = &forms_list[i];
429 data[0] = form->width;
430 data[1] = form->length;
431 data[2] = form->left;
432 data[3] = form->top;
433 data[4] = form->right;
434 data[5] = form->bottom;
435 data[6] = form_index++;
436 data[7] = form->flag;
438 regval_ctr_addvalue( val, form->name, REG_BINARY, (char*)data, sizeof(data) );
441 SAFE_FREE( forms_list );
444 return num_values;
447 /**********************************************************************
448 handle enumeration of subkeys below KEY_PRINTING\Printers
449 *********************************************************************/
451 static int print_subpath_printers( char *key, REGSUBKEY_CTR *subkeys )
453 int n_services = lp_numservices();
454 int snum;
455 fstring sname;
456 int num_subkeys = 0;
457 char *keystr, *key2 = NULL;
458 char *base, *new_path;
459 NT_PRINTER_INFO_LEVEL *printer = NULL;
462 DEBUG(10,("print_subpath_printers: key=>[%s]\n", key ? key : "NULL" ));
464 if ( !key )
466 /* enumerate all printers */
468 for (snum=0; snum<n_services; snum++) {
469 if ( !(lp_snum_ok(snum) && lp_print_ok(snum) ) )
470 continue;
472 fstrcpy( sname, lp_servicename(snum) );
474 regsubkey_ctr_addkey( subkeys, sname );
477 num_subkeys = regsubkey_ctr_numkeys( subkeys );
478 goto done;
481 /* get information for a specific printer */
483 key2 = strdup( key );
484 keystr = key2;
485 reg_split_path( keystr, &base, &new_path );
488 if ( !new_path ) {
489 /* sanity check on the printer name */
490 if ( !W_ERROR_IS_OK( get_a_printer(&printer, 2, base) ) )
491 goto done;
493 free_a_printer( &printer, 2 );
495 regsubkey_ctr_addkey( subkeys, "PrinterDriverData" );
498 /* no other subkeys below here */
500 done:
501 SAFE_FREE( key2 );
502 return num_subkeys;
505 /**********************************************************************
506 handle enumeration of values below KEY_PRINTING\Printers
507 *********************************************************************/
509 static int print_subpath_values_printers( char *key, REGVAL_CTR *val )
511 int num_values = 0;
512 char *keystr, *key2 = NULL;
513 char *base, *new_path;
514 NT_PRINTER_INFO_LEVEL *printer = NULL;
515 NT_PRINTER_INFO_LEVEL_2 *info2;
516 DEVICEMODE *devmode;
517 prs_struct prs;
518 uint32 offset;
519 int snum;
520 int i;
521 fstring valuename;
522 uint8 *data;
523 uint32 type, data_len;
524 fstring printername;
527 * There are tw cases to deal with here
528 * (1) enumeration of printer_info_2 values
529 * (2) enumeration of the PrinterDriverData subney
532 if ( !key ) {
533 /* top level key has no values */
534 goto done;
537 key2 = strdup( key );
538 keystr = key2;
539 reg_split_path( keystr, &base, &new_path );
541 fstrcpy( printername, base );
543 if ( !new_path )
545 /* we are dealing with the printer itself */
547 if ( !W_ERROR_IS_OK( get_a_printer(&printer, 2, printername) ) )
548 goto done;
550 info2 = printer->info_2;
553 regval_ctr_addvalue( val, "Attributes", REG_DWORD, (char*)&info2->attributes, sizeof(info2->attributes) );
554 regval_ctr_addvalue( val, "Priority", REG_DWORD, (char*)&info2->priority, sizeof(info2->attributes) );
555 regval_ctr_addvalue( val, "ChangeID", REG_DWORD, (char*)&info2->changeid, sizeof(info2->changeid) );
556 regval_ctr_addvalue( val, "Default Priority", REG_DWORD, (char*)&info2->default_priority, sizeof(info2->default_priority) );
557 regval_ctr_addvalue( val, "Status", REG_DWORD, (char*)&info2->status, sizeof(info2->status) );
558 regval_ctr_addvalue( val, "StartTime", REG_DWORD, (char*)&info2->starttime, sizeof(info2->starttime) );
559 regval_ctr_addvalue( val, "UntilTime", REG_DWORD, (char*)&info2->untiltime, sizeof(info2->untiltime) );
560 regval_ctr_addvalue( val, "cjobs", REG_DWORD, (char*)&info2->cjobs, sizeof(info2->cjobs) );
561 regval_ctr_addvalue( val, "AveragePPM", REG_DWORD, (char*)&info2->averageppm, sizeof(info2->averageppm) );
563 regval_ctr_addvalue( val, "Name", REG_SZ, info2->printername, sizeof(info2->printername)+1 );
564 regval_ctr_addvalue( val, "Location", REG_SZ, info2->location, sizeof(info2->location)+1 );
565 regval_ctr_addvalue( val, "Comment", REG_SZ, info2->comment, sizeof(info2->comment)+1 );
566 regval_ctr_addvalue( val, "Parameters", REG_SZ, info2->parameters, sizeof(info2->parameters)+1 );
567 regval_ctr_addvalue( val, "Port", REG_SZ, info2->portname, sizeof(info2->portname)+1 );
568 regval_ctr_addvalue( val, "Server", REG_SZ, info2->servername, sizeof(info2->servername)+1 );
569 regval_ctr_addvalue( val, "Share", REG_SZ, info2->sharename, sizeof(info2->sharename)+1 );
570 regval_ctr_addvalue( val, "Driver", REG_SZ, info2->drivername, sizeof(info2->drivername)+1 );
571 regval_ctr_addvalue( val, "Separator File", REG_SZ, info2->sepfile, sizeof(info2->sepfile)+1 );
572 regval_ctr_addvalue( val, "Print Processor", REG_SZ, info2->printprocessor, sizeof(info2->printprocessor)+1 );
575 /* use a prs_struct for converting the devmode and security
576 descriptor to REG_BIARY */
578 prs_init( &prs, MAX_PDU_FRAG_LEN, regval_ctr_getctx(val), MARSHALL);
580 /* stream the device mode */
582 snum = lp_servicenumber(info2->sharename);
583 if ( (devmode = construct_dev_mode( snum )) != NULL )
585 if ( spoolss_io_devmode( "devmode", &prs, 0, devmode ) ) {
587 offset = prs_offset( &prs );
589 regval_ctr_addvalue( val, "Default Devmode", REG_BINARY, prs_data_p(&prs), offset );
595 prs_mem_clear( &prs );
596 prs_set_offset( &prs, 0 );
598 if ( info2->secdesc_buf && info2->secdesc_buf->len )
600 if ( sec_io_desc("sec_desc", &info2->secdesc_buf->sec, &prs, 0 ) ) {
602 offset = prs_offset( &prs );
604 regval_ctr_addvalue( val, "Security", REG_BINARY, prs_data_p(&prs), offset );
609 prs_mem_free( &prs );
610 free_a_printer( &printer, 2 );
612 num_values = regval_ctr_numvals( val );
613 goto done;
618 keystr = new_path;
619 reg_split_path( keystr, &base, &new_path );
621 /* here should be no more path components here */
623 if ( new_path || strcmp(base, "PrinterDriverData") )
624 goto done;
626 /* now enumerate the PrinterDriverData key */
627 if ( !W_ERROR_IS_OK( get_a_printer(&printer, 2, printername) ) )
628 goto done;
630 info2 = printer->info_2;
633 /* iterate over all printer data and fill the regval container */
635 for ( i=0; get_specific_param_by_index(*printer, 2, i, valuename, &data, &type, &data_len); i++ )
637 regval_ctr_addvalue( val, valuename, type, data, data_len );
640 free_a_printer( &printer, 2 );
642 num_values = regval_ctr_numvals( val );
644 done:
645 SAFE_FREE( key2 );
647 return num_values;
650 /**********************************************************************
651 Routine to handle enumeration of subkeys and values
652 below KEY_PRINTING (depending on whether or not subkeys/val are
653 valid pointers.
654 *********************************************************************/
656 static int handle_printing_subpath( char *key, REGSUBKEY_CTR *subkeys, REGVAL_CTR *val )
658 int result = 0;
659 char *p, *base;
660 int i;
662 DEBUG(10,("handle_printing_subpath: key=>[%s]\n", key ));
665 * break off the first part of the path
666 * topmost base **must** be one of the strings
667 * in top_level_keys[]
670 reg_split_path( key, &base, &p);
672 for ( i=0; i<MAX_TOP_LEVEL_KEYS; i++ ) {
673 if ( StrCaseCmp( top_level_keys[i], base ) == 0 )
674 break;
677 DEBUG(10,("handle_printing_subpath: base=>[%s], i==[%d]\n", base, i));
679 if ( !(i < MAX_TOP_LEVEL_KEYS) )
680 return -1;
682 /* Call routine to handle each top level key */
683 switch ( i )
685 case KEY_INDEX_ENVIR:
686 if ( subkeys )
687 print_subpath_environments( p, subkeys );
688 if ( val )
689 print_subpath_values_environments( p, val );
690 break;
692 case KEY_INDEX_FORMS:
693 if ( subkeys )
694 print_subpath_forms( p, subkeys );
695 if ( val )
696 print_subpath_values_forms( p, val );
697 break;
699 case KEY_INDEX_PRINTER:
700 if ( subkeys )
701 print_subpath_printers( p, subkeys );
702 if ( val )
703 print_subpath_values_printers( p, val );
704 break;
706 /* default case for top level key that has no handler */
708 default:
709 break;
714 return result;
717 /**********************************************************************
718 Enumerate registry subkey names given a registry path.
719 Caller is responsible for freeing memory to **subkeys
720 *********************************************************************/
722 int printing_subkey_info( char *key, REGSUBKEY_CTR *subkey_ctr )
724 char *path;
725 BOOL top_level = False;
726 int num_subkeys = 0;
728 DEBUG(10,("printing_subkey_info: key=>[%s]\n", key));
730 path = trim_reg_path( key );
732 /* check to see if we are dealing with the top level key */
734 if ( !path )
735 top_level = True;
737 if ( top_level ) {
738 for ( num_subkeys=0; num_subkeys<MAX_TOP_LEVEL_KEYS; num_subkeys++ )
739 regsubkey_ctr_addkey( subkey_ctr, top_level_keys[num_subkeys] );
741 else
742 num_subkeys = handle_printing_subpath( path, subkey_ctr, NULL );
744 SAFE_FREE( path );
746 return num_subkeys;
749 /**********************************************************************
750 Enumerate registry values given a registry path.
751 Caller is responsible for freeing memory
752 *********************************************************************/
754 int printing_value_info( char *key, REGVAL_CTR *val )
756 char *path;
757 BOOL top_level = False;
758 int num_values = 0;
760 DEBUG(10,("printing_value_info: key=>[%s]\n", key));
762 path = trim_reg_path( key );
764 /* check to see if we are dealing with the top level key */
766 if ( !path )
767 top_level = True;
769 /* fill in values from the getprinterdata_printer_server() */
770 if ( top_level )
771 num_values = 0;
772 else
773 num_values = handle_printing_subpath( path, NULL, val );
776 return num_values;
779 /**********************************************************************
780 Stub function which always returns failure since we don't want
781 people storing printing information directly via regostry calls
782 (for now at least)
783 *********************************************************************/
785 BOOL printing_store_subkey( char *key, REGSUBKEY_CTR *subkeys )
787 return False;
790 /**********************************************************************
791 Stub function which always returns failure since we don't want
792 people storing printing information directly via regostry calls
793 (for now at least)
794 *********************************************************************/
796 BOOL printing_store_value( char *key, REGVAL_CTR *val )
798 return False;
802 * Table of function pointers for accessing printing data
805 REGISTRY_OPS printing_ops = {
806 printing_subkey_info,
807 printing_value_info,
808 printing_store_subkey,
809 printing_store_value