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
;
244 DEBUG(8,("print_subpath_values_environments: Enter key => [%s]\n", key
? key
: "NULL"));
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
257 key2
= strdup( key
);
259 reg_split_path( keystr
, &base
, &new_path
);
260 if ( !base
|| !new_path
)
262 fstrcpy( env
, base
);
267 reg_split_path( keystr
, &base
, &new_path
);
268 if ( !base
|| !new_path
)
270 version
= atoi( base
);
272 /* printer driver name */
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
)
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
) )
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
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 );
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 );
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 );
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
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 */
369 /**********************************************************************
370 handle enumeration of values below KEY_PRINTING\Forms
371 *********************************************************************/
373 static int print_subpath_values_forms( char *key
, REGVAL_CTR
*val
)
379 DEBUG(10,("print_values_forms: key=>[%s]\n", key
? key
: "NULL" ));
381 /* handle ..\Forms\ */
385 nt_forms_struct
*forms_list
= NULL
;
386 nt_forms_struct
*form
= NULL
;
389 if ( (num_values
= get_ntforms( &forms_list
)) == 0 )
392 DEBUG(10,("print_subpath_values_forms: [%d] user defined forms returned\n",
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
;
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
);
417 /* handle built-on forms */
419 if ( (num_values
= get_builtin_ntforms( &forms_list
)) == 0 )
422 DEBUG(10,("print_subpath_values_forms: [%d] built-in forms returned\n",
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
;
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
);
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();
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" ));
466 /* enumerate all printers */
468 for (snum
=0; snum
<n_services
; snum
++) {
469 if ( !(lp_snum_ok(snum
) && lp_print_ok(snum
) ) )
472 fstrcpy( sname
, lp_servicename(snum
) );
474 regsubkey_ctr_addkey( subkeys
, sname
);
477 num_subkeys
= regsubkey_ctr_numkeys( subkeys
);
481 /* get information for a specific printer */
483 key2
= strdup( key
);
485 reg_split_path( keystr
, &base
, &new_path
);
489 /* sanity check on the printer name */
490 if ( !W_ERROR_IS_OK( get_a_printer(&printer
, 2, base
) ) )
493 free_a_printer( &printer
, 2 );
495 regsubkey_ctr_addkey( subkeys
, "PrinterDriverData" );
498 /* no other subkeys below here */
505 /**********************************************************************
506 handle enumeration of values below KEY_PRINTING\Printers
507 *********************************************************************/
509 static int print_subpath_values_printers( char *key
, REGVAL_CTR
*val
)
512 char *keystr
, *key2
= NULL
;
513 char *base
, *new_path
;
514 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
515 NT_PRINTER_INFO_LEVEL_2
*info2
;
523 uint32 type
, data_len
;
527 * There are tw cases to deal with here
528 * (1) enumeration of printer_info_2 values
529 * (2) enumeration of the PrinterDriverData subney
533 /* top level key has no values */
537 key2
= strdup( key
);
539 reg_split_path( keystr
, &base
, &new_path
);
541 fstrcpy( printername
, base
);
545 /* we are dealing with the printer itself */
547 if ( !W_ERROR_IS_OK( get_a_printer(&printer
, 2, printername
) ) )
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
);
619 reg_split_path( keystr
, &base
, &new_path
);
621 /* here should be no more path components here */
623 if ( new_path
|| strcmp(base
, "PrinterDriverData") )
626 /* now enumerate the PrinterDriverData key */
627 if ( !W_ERROR_IS_OK( get_a_printer(&printer
, 2, printername
) ) )
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
);
650 /**********************************************************************
651 Routine to handle enumeration of subkeys and values
652 below KEY_PRINTING (depending on whether or not subkeys/val are
654 *********************************************************************/
656 static int handle_printing_subpath( char *key
, REGSUBKEY_CTR
*subkeys
, REGVAL_CTR
*val
)
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 )
677 DEBUG(10,("handle_printing_subpath: base=>[%s], i==[%d]\n", base
, i
));
679 if ( !(i
< MAX_TOP_LEVEL_KEYS
) )
682 /* Call routine to handle each top level key */
685 case KEY_INDEX_ENVIR
:
687 print_subpath_environments( p
, subkeys
);
689 print_subpath_values_environments( p
, val
);
692 case KEY_INDEX_FORMS
:
694 print_subpath_forms( p
, subkeys
);
696 print_subpath_values_forms( p
, val
);
699 case KEY_INDEX_PRINTER
:
701 print_subpath_printers( p
, subkeys
);
703 print_subpath_values_printers( p
, val
);
706 /* default case for top level key that has no handler */
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
)
725 BOOL top_level
= False
;
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 */
738 for ( num_subkeys
=0; num_subkeys
<MAX_TOP_LEVEL_KEYS
; num_subkeys
++ )
739 regsubkey_ctr_addkey( subkey_ctr
, top_level_keys
[num_subkeys
] );
742 num_subkeys
= handle_printing_subpath( path
, subkey_ctr
, NULL
);
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
)
757 BOOL top_level
= False
;
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 */
769 /* fill in values from the getprinterdata_printer_server() */
773 num_values
= handle_printing_subpath( path
, NULL
, val
);
779 /**********************************************************************
780 Stub function which always returns failure since we don't want
781 people storing printing information directly via regostry calls
783 *********************************************************************/
785 BOOL
printing_store_subkey( char *key
, REGSUBKEY_CTR
*subkeys
)
790 /**********************************************************************
791 Stub function which always returns failure since we don't want
792 people storing printing information directly via regostry calls
794 *********************************************************************/
796 BOOL
printing_store_value( char *key
, REGVAL_CTR
*val
)
802 * Table of function pointers for accessing printing data
805 REGISTRY_OPS printing_ops
= {
806 printing_subkey_info
,
808 printing_store_subkey
,