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 */
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
] = {
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
)
55 uint16 key_len
= strlen(KEY_PRINTING
);
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
));
70 p
= path
+ strlen( KEY_PRINTING
);
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
[] = {
91 "Windows NT Alpha_AXP",
94 fstring
*drivers
= NULL
;
95 int i
, env_index
, num_drivers
;
96 BOOL valid_env
= False
;
97 char *base
, *new_path
;
100 int num_subkeys
= -1;
102 DEBUG(10,("print_subpath_environments: key=>[%s]\n", key
? key
: "NULL" ));
104 /* listed architectures of installed drivers */
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
);
135 /* we are dealing with a subkey of "Environments */
137 key2
= strdup( key
);
139 reg_split_path( keystr
, &base
, &new_path
);
143 for ( env_index
=0; environments
[env_index
]; env_index
++ ) {
144 if ( StrCaseCmp( environments
[env_index
], base
) == 0 ) {
153 /* enumerate driver versions; environment is environments[env_index] */
156 switch ( env_index
) {
158 if ( get_ntdrivers( &drivers
, environments
[0], 0 ) ) {
159 regsubkey_ctr_addkey( subkeys
, "0" );
160 SAFE_FREE( drivers
);
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
);
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
);
185 /* we finally get to enumerate the drivers */
188 reg_split_path( keystr
, &base
, &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
);
205 /***********************************************************************
206 simple function to prune a pathname down to the basename of a file
207 **********************************************************************/
209 static char* dos_basename ( char *path
)
213 p
= strrchr( path
, '\\' );
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
)
231 char *base
, *new_path
;
235 NT_PRINTER_DRIVER_INFO_LEVEL driver_ctr
;
236 NT_PRINTER_DRIVER_INFO_LEVEL_3
*info3
;
239 char *buffer2
= NULL
;
245 DEBUG(8,("print_subpath_values_environments: Enter key => [%s]\n", key
? key
: "NULL"));
251 * The only key below KEY_PRINTING\Environments that
252 * posseses values is each specific printer driver
253 * First get the arch, version, & driver name
258 key2
= strdup( key
);
260 reg_split_path( keystr
, &base
, &new_path
);
261 if ( !base
|| !new_path
)
263 fstrcpy( env
, base
);
268 reg_split_path( keystr
, &base
, &new_path
);
269 if ( !base
|| !new_path
)
271 version
= atoi( base
);
273 /* printer driver name */
276 reg_split_path( keystr
, &base
, &new_path
);
277 /* new_path should be NULL here since this must be the last key */
278 if ( !base
|| new_path
)
280 fstrcpy( driver
, base
);
282 w_result
= get_a_printer_driver( &driver_ctr
, 3, driver
, env
, version
);
284 if ( !W_ERROR_IS_OK(w_result
) )
287 /* build the values out of the driver information */
288 info3
= driver_ctr
.info_3
;
290 filename
= dos_basename( info3
->driverpath
);
291 init_unistr2( &data
, filename
, strlen(filename
)+1 );
292 regval_ctr_addvalue( val
, "Driver", REG_SZ
, (char*)data
.buffer
, data
.uni_str_len
*sizeof(uint16
) );
294 filename
= dos_basename( info3
->configfile
);
295 init_unistr2( &data
, filename
, strlen(filename
)+1 );
296 regval_ctr_addvalue( val
, "Configuration File", REG_SZ
, (char*)data
.buffer
, data
.uni_str_len
*sizeof(uint16
) );
298 filename
= dos_basename( info3
->datafile
);
299 init_unistr2( &data
, filename
, strlen(filename
)+1 );
300 regval_ctr_addvalue( val
, "Data File", REG_SZ
, (char*)data
.buffer
, data
.uni_str_len
*sizeof(uint16
) );
302 filename
= dos_basename( info3
->helpfile
);
303 init_unistr2( &data
, filename
, strlen(filename
)+1 );
304 regval_ctr_addvalue( val
, "Help File", REG_SZ
, (char*)data
.buffer
, data
.uni_str_len
*sizeof(uint16
) );
306 init_unistr2( &data
, info3
->defaultdatatype
, strlen(info3
->defaultdatatype
)+1 );
307 regval_ctr_addvalue( val
, "Data Type", REG_SZ
, (char*)data
.buffer
, data
.uni_str_len
*sizeof(uint16
) );
309 regval_ctr_addvalue( val
, "Version", REG_DWORD
, (char*)&info3
->cversion
, sizeof(info3
->cversion
) );
311 if ( info3
->dependentfiles
)
313 /* place the list of dependent files in a single
314 character buffer, separating each file name by
317 for ( i
=0; strcmp(info3
->dependentfiles
[i
], ""); i
++ )
319 /* strip the path to only the file's base name */
321 filename
= dos_basename( info3
->dependentfiles
[i
] );
323 length
= strlen(filename
);
325 buffer2
= Realloc( buffer
, buffer_size
+ (length
+ 1)*sizeof(uint16
) );
330 init_unistr2( &data
, filename
, length
+1 );
331 memcpy( buffer
+buffer_size
, (char*)data
.buffer
, data
.uni_str_len
*sizeof(uint16
) );
333 buffer_size
+= (length
+ 1)*sizeof(uint16
);
336 /* terminated by double NULL. Add the final one here */
338 buffer2
= Realloc( buffer
, buffer_size
+ 2 );
345 buffer
[buffer_size
++] = '\0';
346 buffer
[buffer_size
++] = '\0';
350 regval_ctr_addvalue( val
, "Dependent Files", REG_MULTI_SZ
, buffer
, buffer_size
);
352 free_a_printer_driver( driver_ctr
, 3 );
357 DEBUG(8,("print_subpath_values_environments: Exit\n"));
359 return regval_ctr_numvals( val
);
363 /**********************************************************************
364 handle enumeration of subkeys below KEY_PRINTING\Forms
365 Really just a stub function, but left here in case it needs to
367 *********************************************************************/
369 static int print_subpath_forms( char *key
, REGSUBKEY_CTR
*subkeys
)
371 DEBUG(10,("print_subpath_forms: key=>[%s]\n", key
? key
: "NULL" ));
373 /* there are no subkeys */
381 /**********************************************************************
382 handle enumeration of values below KEY_PRINTING\Forms
383 *********************************************************************/
385 static int print_subpath_values_forms( char *key
, REGVAL_CTR
*val
)
391 DEBUG(10,("print_values_forms: key=>[%s]\n", key
? key
: "NULL" ));
393 /* handle ..\Forms\ */
397 nt_forms_struct
*forms_list
= NULL
;
398 nt_forms_struct
*form
= NULL
;
401 if ( (num_values
= get_ntforms( &forms_list
)) == 0 )
404 DEBUG(10,("print_subpath_values_forms: [%d] user defined forms returned\n",
407 /* handle user defined forms */
409 for ( i
=0; i
<num_values
; i
++ )
411 form
= &forms_list
[i
];
413 data
[0] = form
->width
;
414 data
[1] = form
->length
;
415 data
[2] = form
->left
;
417 data
[4] = form
->right
;
418 data
[5] = form
->bottom
;
419 data
[6] = form_index
++;
420 data
[7] = form
->flag
;
422 regval_ctr_addvalue( val
, form
->name
, REG_BINARY
, (char*)data
, sizeof(data
) );
426 SAFE_FREE( forms_list
);
429 /* handle built-on forms */
431 if ( (num_values
= get_builtin_ntforms( &forms_list
)) == 0 )
434 DEBUG(10,("print_subpath_values_forms: [%d] built-in forms returned\n",
437 for ( i
=0; i
<num_values
; i
++ )
439 form
= &forms_list
[i
];
441 data
[0] = form
->width
;
442 data
[1] = form
->length
;
443 data
[2] = form
->left
;
445 data
[4] = form
->right
;
446 data
[5] = form
->bottom
;
447 data
[6] = form_index
++;
448 data
[7] = form
->flag
;
450 regval_ctr_addvalue( val
, form
->name
, REG_BINARY
, (char*)data
, sizeof(data
) );
453 SAFE_FREE( forms_list
);
459 /**********************************************************************
460 handle enumeration of subkeys below KEY_PRINTING\Printers
461 *********************************************************************/
463 static int print_subpath_printers( char *key
, REGSUBKEY_CTR
*subkeys
)
465 int n_services
= lp_numservices();
470 char *keystr
, *key2
= NULL
;
471 char *base
, *new_path
;
472 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
473 fstring
*subkey_names
= NULL
;
475 DEBUG(10,("print_subpath_printers: key=>[%s]\n", key
? key
: "NULL" ));
479 /* enumerate all printers */
481 for (snum
=0; snum
<n_services
; snum
++) {
482 if ( !(lp_snum_ok(snum
) && lp_print_ok(snum
) ) )
485 fstrcpy( sname
, lp_servicename(snum
) );
487 regsubkey_ctr_addkey( subkeys
, sname
);
490 num_subkeys
= regsubkey_ctr_numkeys( subkeys
);
494 /* get information for a specific printer */
496 key2
= strdup( key
);
498 reg_split_path( keystr
, &base
, &new_path
);
500 if ( !W_ERROR_IS_OK( get_a_printer(&printer
, 2, base
) ) )
503 num_subkeys
= get_printer_subkeys( &printer
->info_2
->data
, new_path
?new_path
:"", &subkey_names
);
505 for ( i
=0; i
<num_subkeys
; i
++ )
506 regsubkey_ctr_addkey( subkeys
, subkey_names
[i
] );
508 free_a_printer( &printer
, 2 );
510 /* no other subkeys below here */
514 SAFE_FREE( subkey_names
);
519 /**********************************************************************
520 handle enumeration of values below KEY_PRINTING\Printers
521 *********************************************************************/
523 static int print_subpath_values_printers( char *key
, REGVAL_CTR
*val
)
526 char *keystr
, *key2
= NULL
;
527 char *base
, *new_path
;
528 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
529 NT_PRINTER_INFO_LEVEL_2
*info2
;
535 NT_PRINTER_DATA
*p_data
;
540 * Theres are tw cases to deal with here
541 * (1) enumeration of printer_info_2 values
542 * (2) enumeration of the PrinterDriverData subney
546 /* top level key has no values */
550 key2
= strdup( key
);
552 reg_split_path( keystr
, &base
, &new_path
);
554 fstrcpy( printername
, base
);
558 /* we are dealing with the printer itself */
560 if ( !W_ERROR_IS_OK( get_a_printer(&printer
, 2, printername
) ) )
563 info2
= printer
->info_2
;
566 regval_ctr_addvalue( val
, "Attributes", REG_DWORD
, (char*)&info2
->attributes
, sizeof(info2
->attributes
) );
567 regval_ctr_addvalue( val
, "Priority", REG_DWORD
, (char*)&info2
->priority
, sizeof(info2
->attributes
) );
568 regval_ctr_addvalue( val
, "ChangeID", REG_DWORD
, (char*)&info2
->changeid
, sizeof(info2
->changeid
) );
569 regval_ctr_addvalue( val
, "Default Priority", REG_DWORD
, (char*)&info2
->default_priority
, sizeof(info2
->default_priority
) );
570 regval_ctr_addvalue( val
, "Status", REG_DWORD
, (char*)&info2
->status
, sizeof(info2
->status
) );
571 regval_ctr_addvalue( val
, "StartTime", REG_DWORD
, (char*)&info2
->starttime
, sizeof(info2
->starttime
) );
572 regval_ctr_addvalue( val
, "UntilTime", REG_DWORD
, (char*)&info2
->untiltime
, sizeof(info2
->untiltime
) );
573 regval_ctr_addvalue( val
, "cjobs", REG_DWORD
, (char*)&info2
->cjobs
, sizeof(info2
->cjobs
) );
574 regval_ctr_addvalue( val
, "AveragePPM", REG_DWORD
, (char*)&info2
->averageppm
, sizeof(info2
->averageppm
) );
576 init_unistr2( &data
, info2
->printername
, strlen(info2
->printername
)+1 );
577 regval_ctr_addvalue( val
, "Name", REG_SZ
, (char*)data
.buffer
, data
.uni_str_len
*sizeof(uint16
) );
578 init_unistr2( &data
, info2
->location
, strlen(info2
->location
)+1 );
579 regval_ctr_addvalue( val
, "Location", REG_SZ
, (char*)data
.buffer
, data
.uni_str_len
*sizeof(uint16
) );
580 init_unistr2( &data
, info2
->comment
, strlen(info2
->comment
)+1 );
581 regval_ctr_addvalue( val
, "Comment", REG_SZ
, (char*)data
.buffer
, data
.uni_str_len
*sizeof(uint16
) );
582 init_unistr2( &data
, info2
->parameters
, strlen(info2
->parameters
)+1 );
583 regval_ctr_addvalue( val
, "Parameters", REG_SZ
, (char*)data
.buffer
, data
.uni_str_len
*sizeof(uint16
) );
584 init_unistr2( &data
, info2
->portname
, strlen(info2
->portname
)+1 );
585 regval_ctr_addvalue( val
, "Port", REG_SZ
, (char*)data
.buffer
, data
.uni_str_len
*sizeof(uint16
) );
586 init_unistr2( &data
, info2
->servername
, strlen(info2
->servername
)+1 );
587 regval_ctr_addvalue( val
, "Server", REG_SZ
, (char*)data
.buffer
, data
.uni_str_len
*sizeof(uint16
) );
588 init_unistr2( &data
, info2
->sharename
, strlen(info2
->sharename
)+1 );
589 regval_ctr_addvalue( val
, "Share", REG_SZ
, (char*)data
.buffer
, data
.uni_str_len
*sizeof(uint16
) );
590 init_unistr2( &data
, info2
->drivername
, strlen(info2
->drivername
)+1 );
591 regval_ctr_addvalue( val
, "Driver", REG_SZ
, (char*)data
.buffer
, data
.uni_str_len
*sizeof(uint16
) );
592 init_unistr2( &data
, info2
->sepfile
, strlen(info2
->sepfile
)+1 );
593 regval_ctr_addvalue( val
, "Separator File", REG_SZ
, (char*)data
.buffer
, data
.uni_str_len
*sizeof(uint16
) );
594 init_unistr2( &data
, "winprint", strlen("winprint")+1 );
595 regval_ctr_addvalue( val
, "Print Processor", REG_SZ
, (char*)data
.buffer
, data
.uni_str_len
*sizeof(uint16
) );
598 /* use a prs_struct for converting the devmode and security
599 descriptor to REG_BIARY */
601 prs_init( &prs
, MAX_PDU_FRAG_LEN
, regval_ctr_getctx(val
), MARSHALL
);
603 /* stream the device mode */
605 snum
= lp_servicenumber(info2
->sharename
);
606 if ( (devmode
= construct_dev_mode( snum
)) != NULL
)
608 if ( spoolss_io_devmode( "devmode", &prs
, 0, devmode
) ) {
610 offset
= prs_offset( &prs
);
612 regval_ctr_addvalue( val
, "Default Devmode", REG_BINARY
, prs_data_p(&prs
), offset
);
618 prs_mem_clear( &prs
);
619 prs_set_offset( &prs
, 0 );
621 if ( info2
->secdesc_buf
&& info2
->secdesc_buf
->len
)
623 if ( sec_io_desc("sec_desc", &info2
->secdesc_buf
->sec
, &prs
, 0 ) ) {
625 offset
= prs_offset( &prs
);
627 regval_ctr_addvalue( val
, "Security", REG_BINARY
, prs_data_p(&prs
), offset
);
632 prs_mem_free( &prs
);
634 num_values
= regval_ctr_numvals( val
);
640 /* now enumerate the key */
642 if ( !W_ERROR_IS_OK( get_a_printer(&printer
, 2, printername
) ) )
645 /* iterate over all printer data and fill the regval container */
647 p_data
= &printer
->info_2
->data
;
648 if ( (key_index
= lookup_printerkey( p_data
, new_path
)) == -1 ) {
649 DEBUG(10,("print_subpath_values_printer: Unknown keyname [%s]\n", new_path
));
653 num_values
= regval_ctr_numvals( &p_data
->keys
[key_index
].values
);
655 for ( i
=0; i
<num_values
; i
++ )
656 regval_ctr_copyvalue( val
, regval_ctr_specific_value(&p_data
->keys
[key_index
].values
, i
) );
661 free_a_printer( &printer
, 2 );
668 /**********************************************************************
669 Routine to handle enumeration of subkeys and values
670 below KEY_PRINTING (depending on whether or not subkeys/val are
672 *********************************************************************/
674 static int handle_printing_subpath( char *key
, REGSUBKEY_CTR
*subkeys
, REGVAL_CTR
*val
)
680 DEBUG(10,("handle_printing_subpath: key=>[%s]\n", key
));
683 * break off the first part of the path
684 * topmost base **must** be one of the strings
685 * in top_level_keys[]
688 reg_split_path( key
, &base
, &p
);
690 for ( i
=0; i
<MAX_TOP_LEVEL_KEYS
; i
++ ) {
691 if ( StrCaseCmp( top_level_keys
[i
], base
) == 0 )
695 DEBUG(10,("handle_printing_subpath: base=>[%s], i==[%d]\n", base
, i
));
697 if ( !(i
< MAX_TOP_LEVEL_KEYS
) )
700 /* Call routine to handle each top level key */
703 case KEY_INDEX_ENVIR
:
705 print_subpath_environments( p
, subkeys
);
707 print_subpath_values_environments( p
, val
);
710 case KEY_INDEX_FORMS
:
712 print_subpath_forms( p
, subkeys
);
714 print_subpath_values_forms( p
, val
);
717 case KEY_INDEX_PRINTER
:
719 print_subpath_printers( p
, subkeys
);
721 print_subpath_values_printers( p
, val
);
724 /* default case for top level key that has no handler */
735 /**********************************************************************
736 Enumerate registry subkey names given a registry path.
737 Caller is responsible for freeing memory to **subkeys
738 *********************************************************************/
740 int printing_subkey_info( char *key
, REGSUBKEY_CTR
*subkey_ctr
)
743 BOOL top_level
= False
;
746 DEBUG(10,("printing_subkey_info: key=>[%s]\n", key
));
748 path
= trim_reg_path( key
);
750 /* check to see if we are dealing with the top level key */
756 for ( num_subkeys
=0; num_subkeys
<MAX_TOP_LEVEL_KEYS
; num_subkeys
++ )
757 regsubkey_ctr_addkey( subkey_ctr
, top_level_keys
[num_subkeys
] );
760 num_subkeys
= handle_printing_subpath( path
, subkey_ctr
, NULL
);
767 /**********************************************************************
768 Enumerate registry values given a registry path.
769 Caller is responsible for freeing memory
770 *********************************************************************/
772 int printing_value_info( char *key
, REGVAL_CTR
*val
)
775 BOOL top_level
= False
;
778 DEBUG(10,("printing_value_info: key=>[%s]\n", key
));
780 path
= trim_reg_path( key
);
782 /* check to see if we are dealing with the top level key */
787 /* fill in values from the getprinterdata_printer_server() */
791 num_values
= handle_printing_subpath( path
, NULL
, val
);
797 /**********************************************************************
798 Stub function which always returns failure since we don't want
799 people storing printing information directly via regostry calls
801 *********************************************************************/
803 BOOL
printing_store_subkey( char *key
, REGSUBKEY_CTR
*subkeys
)
808 /**********************************************************************
809 Stub function which always returns failure since we don't want
810 people storing printing information directly via regostry calls
812 *********************************************************************/
814 BOOL
printing_store_value( char *key
, REGVAL_CTR
*val
)
820 * Table of function pointers for accessing printing data
823 REGISTRY_OPS printing_ops
= {
824 printing_subkey_info
,
826 printing_store_subkey
,