1/* 2 * Unix SMB/CIFS implementation. 3 * RPC Pipe client / server routines 4 * Copyright (C) Gerald Carter 2002. 5 * 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. 10 * 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. 15 * 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. 19 */ 20 21/* Implementation of registry virtual views for printing information */ 22 23#include "includes.h" 24 25#undef DBGC_CLASS 26#define DBGC_CLASS DBGC_RPC_SRV 27 28#define MAX_TOP_LEVEL_KEYS 3 29 30/* some symbolic indexes into the top_level_keys */ 31 32#define KEY_INDEX_ENVIR 0 33#define KEY_INDEX_FORMS 1 34#define KEY_INDEX_PRINTER 2 35 36static const char *top_level_keys[MAX_TOP_LEVEL_KEYS] = { 37 "Environments", 38 "Forms", 39 "Printers" 40}; 41 42 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 **********************************************************************/ 51 52static char* trim_reg_path( char *path ) 53{ 54 char *p; 55 uint16 key_len = strlen(KEY_PRINTING); 56 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. 61 */ 62 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; 67 } 68 69 70 p = path + strlen( KEY_PRINTING ); 71 72 if ( *p == '\\' ) 73 p++; 74 75 if ( *p ) 76 return strdup(p); 77 else 78 return NULL; 79} 80 81/********************************************************************** 82 handle enumeration of subkeys below KEY_PRINTING\Environments 83 *********************************************************************/ 84 85static int print_subpath_environments( char *key, REGSUBKEY_CTR *subkeys ) 86{ 87 const 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; 101 102 DEBUG(10,("print_subpath_environments: key=>[%s]\n", key ? key : "NULL" )); 103 104 /* listed architectures of installed drivers */ 105 106 if ( !key ) 107 { 108 /* Windows 9x drivers */ 109 110 if ( get_ntdrivers( &drivers, environments[0], 0 ) ) 111 regsubkey_ctr_addkey( subkeys, environments[0] ); 112 SAFE_FREE( drivers ); 113 114 /* Windows NT/2k intel drivers */ 115 116 if ( get_ntdrivers( &drivers, environments[1], 2 ) 117 || get_ntdrivers( &drivers, environments[1], 3 ) ) 118 { 119 regsubkey_ctr_addkey( subkeys, environments[1] ); 120 } 121 SAFE_FREE( drivers ); 122 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] ); 127 128 } 129 SAFE_FREE( drivers ); 130 131 num_subkeys = regsubkey_ctr_numkeys( subkeys ); 132 goto done; 133 } 134 135 /* we are dealing with a subkey of "Environments */ 136 137 key2 = strdup( key ); 138 keystr = key2; 139 reg_split_path( keystr, &base, &new_path ); 140 141 /* sanity check */ 142 143 for ( env_index=0; environments[env_index]; env_index++ ) { 144 if ( StrCaseCmp( environments[env_index], base ) == 0 ) { 145 valid_env = True; 146 break; 147 } 148 } 149 150 if ( !valid_env ) 151 return -1; 152 153 /* enumerate driver versions; environment is environments[env_index] */ 154 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 ); 161 } 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 ); 167 } 168 if ( get_ntdrivers( &drivers, environments[1], 3 ) ) { 169 regsubkey_ctr_addkey( subkeys, "3" ); 170 SAFE_FREE( drivers ); 171 } 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 ); 177 } 178 179 } 180 181 num_subkeys = regsubkey_ctr_numkeys( subkeys ); 182 goto done; 183 } 184 185 /* we finally get to enumerate the drivers */ 186 187 keystr = new_path; 188 reg_split_path( keystr, &base, &new_path ); 189 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] ); 194 195 num_subkeys = regsubkey_ctr_numkeys( subkeys ); 196 goto done; 197 } 198 199done: 200 SAFE_FREE( key2 ); 201 202 return num_subkeys; 203} 204 205/*********************************************************************** 206 simple function to prune a pathname down to the basename of a file 207 **********************************************************************/ 208 209static char* dos_basename ( char *path ) 210{ 211 char *p; 212 213 p = strrchr( path, '\\' ); 214 if ( p ) 215 p++; 216 else 217 p = path; 218 219 return p; 220} 221 222/********************************************************************** 223 handle enumeration of values below 224 KEY_PRINTING\Environments\<arch>\<version>\<drivername> 225 *********************************************************************/ 226 227static int print_subpath_values_environments( char *key, REGVAL_CTR *val ) 228{ 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; 243 UNISTR2 data;; 244 245 DEBUG(8,("print_subpath_values_environments: Enter key => [%s]\n", key ? key : "NULL")); 246 247 if ( !key ) 248 return 0; 249 250 /* 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 254 */ 255 256 /* env */ 257 258 key2 = strdup( key ); 259 keystr = key2; 260 reg_split_path( keystr, &base, &new_path ); 261 if ( !base || !new_path ) 262 return 0; 263 fstrcpy( env, base ); 264 265 /* version */ 266 267 keystr = new_path; 268 reg_split_path( keystr, &base, &new_path ); 269 if ( !base || !new_path ) 270 return 0; 271 version = atoi( base ); 272 273 /* printer driver name */ 274 275 keystr = new_path; 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 ) 279 return 0; 280 fstrcpy( driver, base ); 281 282 w_result = get_a_printer_driver( &driver_ctr, 3, driver, env, version ); 283 284 if ( !W_ERROR_IS_OK(w_result) ) 285 return -1; 286 287 /* build the values out of the driver information */ 288 info3 = driver_ctr.info_3; 289 290 filename = dos_basename( info3->driverpath ); 291 init_unistr2( &data, filename, UNI_STR_TERMINATE); 292 regval_ctr_addvalue( val, "Driver", REG_SZ, (char*)data.buffer, data.uni_str_len*sizeof(uint16) ); 293 294 filename = dos_basename( info3->configfile ); 295 init_unistr2( &data, filename, UNI_STR_TERMINATE); 296 regval_ctr_addvalue( val, "Configuration File", REG_SZ, (char*)data.buffer, data.uni_str_len*sizeof(uint16) ); 297 298 filename = dos_basename( info3->datafile ); 299 init_unistr2( &data, filename, UNI_STR_TERMINATE); 300 regval_ctr_addvalue( val, "Data File", REG_SZ, (char*)data.buffer, data.uni_str_len*sizeof(uint16) ); 301 302 filename = dos_basename( info3->helpfile ); 303 init_unistr2( &data, filename, UNI_STR_TERMINATE); 304 regval_ctr_addvalue( val, "Help File", REG_SZ, (char*)data.buffer, data.uni_str_len*sizeof(uint16) ); 305 306 init_unistr2( &data, info3->defaultdatatype, UNI_STR_TERMINATE); 307 regval_ctr_addvalue( val, "Data Type", REG_SZ, (char*)data.buffer, data.uni_str_len*sizeof(uint16) ); 308 309 regval_ctr_addvalue( val, "Version", REG_DWORD, (char*)&info3->cversion, sizeof(info3->cversion) ); 310 311 if ( info3->dependentfiles ) { 312 /* place the list of dependent files in a single 313 character buffer, separating each file name by 314 a NULL */ 315 316 for ( i=0; strcmp(info3->dependentfiles[i], ""); i++ ) { 317 /* strip the path to only the file's base name */ 318 319 filename = dos_basename( info3->dependentfiles[i] ); 320 321 length = strlen(filename); 322 323 buffer2 = Realloc( buffer, buffer_size + (length + 1)*sizeof(uint16) ); 324 if ( !buffer2 ) 325 break; 326 buffer = buffer2; 327 328 init_unistr2( &data, filename, UNI_STR_TERMINATE); 329 memcpy( buffer+buffer_size, (char*)data.buffer, data.uni_str_len*sizeof(uint16) ); 330 331 buffer_size += (length + 1)*sizeof(uint16); 332 } 333 334 /* terminated by double NULL. Add the final one here */ 335 336 buffer2 = Realloc( buffer, buffer_size + 2 ); 337 if ( !buffer2 ) { 338 SAFE_FREE( buffer ); 339 buffer_size = 0; 340 } else { 341 buffer = buffer2; 342 buffer[buffer_size++] = '\0'; 343 buffer[buffer_size++] = '\0'; 344 } 345 } 346 347 regval_ctr_addvalue( val, "Dependent Files", REG_MULTI_SZ, buffer, buffer_size ); 348 349 free_a_printer_driver( driver_ctr, 3 ); 350 351 SAFE_FREE( key2 ); 352 SAFE_FREE( buffer ); 353 354 DEBUG(8,("print_subpath_values_environments: Exit\n")); 355 356 return regval_ctr_numvals( val ); 357} 358 359 360/********************************************************************** 361 handle enumeration of subkeys below KEY_PRINTING\Forms 362 Really just a stub function, but left here in case it needs to 363 be expanded later on 364 *********************************************************************/ 365 366static int print_subpath_forms( char *key, REGSUBKEY_CTR *subkeys ) 367{ 368 DEBUG(10,("print_subpath_forms: key=>[%s]\n", key ? key : "NULL" )); 369 370 /* there are no subkeys */ 371 372 if ( key ) 373 return -1; 374 375 return 0; 376} 377 378/********************************************************************** 379 handle enumeration of values below KEY_PRINTING\Forms 380 *********************************************************************/ 381 382static int print_subpath_values_forms( char *key, REGVAL_CTR *val ) 383{ 384 int num_values = 0; 385 uint32 data[8]; 386 int form_index = 1; 387 388 DEBUG(10,("print_values_forms: key=>[%s]\n", key ? key : "NULL" )); 389 390 /* handle ..\Forms\ */ 391 392 if ( !key ) 393 { 394 nt_forms_struct *forms_list = NULL; 395 nt_forms_struct *form = NULL; 396 int i; 397 398 if ( (num_values = get_ntforms( &forms_list )) == 0 ) 399 return 0; 400 401 DEBUG(10,("print_subpath_values_forms: [%d] user defined forms returned\n", 402 num_values)); 403 404 /* handle user defined forms */ 405 406 for ( i=0; i<num_values; i++ ) 407 { 408 form = &forms_list[i]; 409 410 data[0] = form->width; 411 data[1] = form->length; 412 data[2] = form->left; 413 data[3] = form->top; 414 data[4] = form->right; 415 data[5] = form->bottom; 416 data[6] = form_index++; 417 data[7] = form->flag; 418 419 regval_ctr_addvalue( val, form->name, REG_BINARY, (char*)data, sizeof(data) ); 420 421 } 422 423 SAFE_FREE( forms_list ); 424 forms_list = NULL; 425 426 /* handle built-on forms */ 427 428 if ( (num_values = get_builtin_ntforms( &forms_list )) == 0 ) 429 return 0; 430 431 DEBUG(10,("print_subpath_values_forms: [%d] built-in forms returned\n", 432 num_values)); 433 434 for ( i=0; i<num_values; i++ ) 435 { 436 form = &forms_list[i]; 437 438 data[0] = form->width; 439 data[1] = form->length; 440 data[2] = form->left; 441 data[3] = form->top; 442 data[4] = form->right; 443 data[5] = form->bottom; 444 data[6] = form_index++; 445 data[7] = form->flag; 446 447 regval_ctr_addvalue( val, form->name, REG_BINARY, (char*)data, sizeof(data) ); 448 } 449 450 SAFE_FREE( forms_list ); 451 } 452 453 return num_values; 454} 455 456/********************************************************************** 457 handle enumeration of subkeys below KEY_PRINTING\Printers 458 *********************************************************************/ 459 460static int print_subpath_printers( char *key, REGSUBKEY_CTR *subkeys ) 461{ 462 int n_services = lp_numservices(); 463 int snum; 464 fstring sname; 465 int i; 466 int num_subkeys = 0; 467 char *keystr, *key2 = NULL; 468 char *base, *new_path; 469 NT_PRINTER_INFO_LEVEL *printer = NULL; 470 fstring *subkey_names = NULL; 471 472 DEBUG(10,("print_subpath_printers: key=>[%s]\n", key ? key : "NULL" )); 473 474 if ( !key ) 475 { 476 /* enumerate all printers */ 477 478 for (snum=0; snum<n_services; snum++) { 479 if ( !(lp_snum_ok(snum) && lp_print_ok(snum) ) ) 480 continue; 481 482 fstrcpy( sname, lp_servicename(snum) ); 483 484 regsubkey_ctr_addkey( subkeys, sname ); 485 } 486 487 num_subkeys = regsubkey_ctr_numkeys( subkeys ); 488 goto done; 489 } 490 491 /* get information for a specific printer */ 492 493 key2 = strdup( key ); 494 keystr = key2; 495 reg_split_path( keystr, &base, &new_path ); 496 497 if ( !W_ERROR_IS_OK( get_a_printer(NULL, &printer, 2, base) ) ) 498 goto done; 499 500 num_subkeys = get_printer_subkeys( &printer->info_2->data, new_path?new_path:"", &subkey_names ); 501 502 for ( i=0; i<num_subkeys; i++ ) 503 regsubkey_ctr_addkey( subkeys, subkey_names[i] ); 504 505 free_a_printer( &printer, 2 ); 506 507 /* no other subkeys below here */ 508 509done: 510 SAFE_FREE( key2 ); 511 SAFE_FREE( subkey_names ); 512 513 return num_subkeys; 514} 515 516/********************************************************************** 517 handle enumeration of values below KEY_PRINTING\Printers 518 *********************************************************************/ 519 520static int print_subpath_values_printers( char *key, REGVAL_CTR *val ) 521{ 522 int num_values = 0; 523 char *keystr, *key2 = NULL; 524 char *base, *new_path; 525 NT_PRINTER_INFO_LEVEL *printer = NULL; 526 NT_PRINTER_INFO_LEVEL_2 *info2; 527 DEVICEMODE *devmode; 528 prs_struct prs; 529 uint32 offset; 530 int snum; 531 fstring printername; 532 NT_PRINTER_DATA *p_data; 533 int i, key_index; 534 UNISTR2 data; 535 536 /* 537 * Theres are tw cases to deal with here 538 * (1) enumeration of printer_info_2 values 539 * (2) enumeration of the PrinterDriverData subney 540 */ 541 542 if ( !key ) { 543 /* top level key has no values */ 544 goto done; 545 } 546 547 key2 = strdup( key ); 548 keystr = key2; 549 reg_split_path( keystr, &base, &new_path ); 550 551 fstrcpy( printername, base ); 552 553 if ( !new_path ) 554 { 555 /* we are dealing with the printer itself */ 556 557 if ( !W_ERROR_IS_OK( get_a_printer(NULL, &printer, 2, printername) ) ) 558 goto done; 559 560 info2 = printer->info_2; 561 562 563 regval_ctr_addvalue( val, "Attributes", REG_DWORD, (char*)&info2->attributes, sizeof(info2->attributes) ); 564 regval_ctr_addvalue( val, "Priority", REG_DWORD, (char*)&info2->priority, sizeof(info2->attributes) ); 565 regval_ctr_addvalue( val, "ChangeID", REG_DWORD, (char*)&info2->changeid, sizeof(info2->changeid) ); 566 regval_ctr_addvalue( val, "Default Priority", REG_DWORD, (char*)&info2->default_priority, sizeof(info2->default_priority) ); 567 regval_ctr_addvalue( val, "Status", REG_DWORD, (char*)&info2->status, sizeof(info2->status) ); 568 regval_ctr_addvalue( val, "StartTime", REG_DWORD, (char*)&info2->starttime, sizeof(info2->starttime) ); 569 regval_ctr_addvalue( val, "UntilTime", REG_DWORD, (char*)&info2->untiltime, sizeof(info2->untiltime) ); 570 regval_ctr_addvalue( val, "cjobs", REG_DWORD, (char*)&info2->cjobs, sizeof(info2->cjobs) ); 571 regval_ctr_addvalue( val, "AveragePPM", REG_DWORD, (char*)&info2->averageppm, sizeof(info2->averageppm) ); 572 573 init_unistr2( &data, info2->printername, UNI_STR_TERMINATE); 574 regval_ctr_addvalue( val, "Name", REG_SZ, (char*)data.buffer, data.uni_str_len*sizeof(uint16) ); 575 init_unistr2( &data, info2->location, UNI_STR_TERMINATE); 576 regval_ctr_addvalue( val, "Location", REG_SZ, (char*)data.buffer, data.uni_str_len*sizeof(uint16) ); 577 init_unistr2( &data, info2->comment, UNI_STR_TERMINATE); 578 regval_ctr_addvalue( val, "Comment", REG_SZ, (char*)data.buffer, data.uni_str_len*sizeof(uint16) ); 579 init_unistr2( &data, info2->parameters, UNI_STR_TERMINATE); 580 regval_ctr_addvalue( val, "Parameters", REG_SZ, (char*)data.buffer, data.uni_str_len*sizeof(uint16) ); 581 init_unistr2( &data, info2->portname, UNI_STR_TERMINATE); 582 regval_ctr_addvalue( val, "Port", REG_SZ, (char*)data.buffer, data.uni_str_len*sizeof(uint16) ); 583 init_unistr2( &data, info2->servername, UNI_STR_TERMINATE); 584 regval_ctr_addvalue( val, "Server", REG_SZ, (char*)data.buffer, data.uni_str_len*sizeof(uint16) ); 585 init_unistr2( &data, info2->sharename, UNI_STR_TERMINATE); 586 regval_ctr_addvalue( val, "Share", REG_SZ, (char*)data.buffer, data.uni_str_len*sizeof(uint16) ); 587 init_unistr2( &data, info2->drivername, UNI_STR_TERMINATE); 588 regval_ctr_addvalue( val, "Driver", REG_SZ, (char*)data.buffer, data.uni_str_len*sizeof(uint16) ); 589 init_unistr2( &data, info2->sepfile, UNI_STR_TERMINATE); 590 regval_ctr_addvalue( val, "Separator File", REG_SZ, (char*)data.buffer, data.uni_str_len*sizeof(uint16) ); 591 init_unistr2( &data, "winprint", UNI_STR_TERMINATE); 592 regval_ctr_addvalue( val, "Print Processor", REG_SZ, (char*)data.buffer, data.uni_str_len*sizeof(uint16) ); 593 594 595 /* use a prs_struct for converting the devmode and security 596 descriptor to REG_BIARY */ 597 598 prs_init( &prs, MAX_PDU_FRAG_LEN, regval_ctr_getctx(val), MARSHALL); 599 600 /* stream the device mode */ 601 602 snum = lp_servicenumber(info2->sharename); 603 if ( (devmode = construct_dev_mode( snum )) != NULL ) 604 { 605 if ( spoolss_io_devmode( "devmode", &prs, 0, devmode ) ) { 606 607 offset = prs_offset( &prs ); 608 609 regval_ctr_addvalue( val, "Default Devmode", REG_BINARY, prs_data_p(&prs), offset ); 610 } 611 612 613 } 614 615 prs_mem_clear( &prs ); 616 prs_set_offset( &prs, 0 ); 617 618 if ( info2->secdesc_buf && info2->secdesc_buf->len ) 619 { 620 if ( sec_io_desc("sec_desc", &info2->secdesc_buf->sec, &prs, 0 ) ) { 621 622 offset = prs_offset( &prs ); 623 624 regval_ctr_addvalue( val, "Security", REG_BINARY, prs_data_p(&prs), offset ); 625 } 626 } 627 628 prs_mem_free( &prs ); 629 630 num_values = regval_ctr_numvals( val ); 631 632 goto done; 633 634 } 635 636 /* now enumerate the key */ 637 638 if ( !W_ERROR_IS_OK( get_a_printer(NULL, &printer, 2, printername) ) ) 639 goto done; 640 641 /* iterate over all printer data and fill the regval container */ 642 643 p_data = &printer->info_2->data; 644 if ( (key_index = lookup_printerkey( p_data, new_path )) == -1 ) { 645 DEBUG(10,("print_subpath_values_printer: Unknown keyname [%s]\n", new_path)); 646 goto done; 647 } 648 649 num_values = regval_ctr_numvals( &p_data->keys[key_index].values ); 650 651 for ( i=0; i<num_values; i++ ) 652 regval_ctr_copyvalue( val, regval_ctr_specific_value(&p_data->keys[key_index].values, i) ); 653 654 655done: 656 if ( printer ) 657 free_a_printer( &printer, 2 ); 658 659 SAFE_FREE( key2 ); 660 661 return num_values; 662} 663 664/********************************************************************** 665 Routine to handle enumeration of subkeys and values 666 below KEY_PRINTING (depending on whether or not subkeys/val are 667 valid pointers. 668 *********************************************************************/ 669 670static int handle_printing_subpath( char *key, REGSUBKEY_CTR *subkeys, REGVAL_CTR *val ) 671{ 672 int result = 0; 673 char *p, *base; 674 int i; 675 676 DEBUG(10,("handle_printing_subpath: key=>[%s]\n", key )); 677 678 /* 679 * break off the first part of the path 680 * topmost base **must** be one of the strings 681 * in top_level_keys[] 682 */ 683 684 reg_split_path( key, &base, &p); 685 686 for ( i=0; i<MAX_TOP_LEVEL_KEYS; i++ ) { 687 if ( StrCaseCmp( top_level_keys[i], base ) == 0 ) 688 break; 689 } 690 691 DEBUG(10,("handle_printing_subpath: base=>[%s], i==[%d]\n", base, i)); 692 693 if ( !(i < MAX_TOP_LEVEL_KEYS) ) 694 return -1; 695 696 /* Call routine to handle each top level key */ 697 switch ( i ) 698 { 699 case KEY_INDEX_ENVIR: 700 if ( subkeys ) 701 print_subpath_environments( p, subkeys ); 702 if ( val ) 703 print_subpath_values_environments( p, val ); 704 break; 705 706 case KEY_INDEX_FORMS: 707 if ( subkeys ) 708 print_subpath_forms( p, subkeys ); 709 if ( val ) 710 print_subpath_values_forms( p, val ); 711 break; 712 713 case KEY_INDEX_PRINTER: 714 if ( subkeys ) 715 print_subpath_printers( p, subkeys ); 716 if ( val ) 717 print_subpath_values_printers( p, val ); 718 break; 719 720 /* default case for top level key that has no handler */ 721 722 default: 723 break; 724 } 725 726 727 728 return result; 729 730} 731/********************************************************************** 732 Enumerate registry subkey names given a registry path. 733 Caller is responsible for freeing memory to **subkeys 734 *********************************************************************/ 735 736int printing_subkey_info( char *key, REGSUBKEY_CTR *subkey_ctr ) 737{ 738 char *path; 739 BOOL top_level = False; 740 int num_subkeys = 0; 741 742 DEBUG(10,("printing_subkey_info: key=>[%s]\n", key)); 743 744 path = trim_reg_path( key ); 745 746 /* check to see if we are dealing with the top level key */ 747 748 if ( !path ) 749 top_level = True; 750 751 if ( top_level ) { 752 for ( num_subkeys=0; num_subkeys<MAX_TOP_LEVEL_KEYS; num_subkeys++ ) 753 regsubkey_ctr_addkey( subkey_ctr, top_level_keys[num_subkeys] ); 754 } 755 else 756 num_subkeys = handle_printing_subpath( path, subkey_ctr, NULL ); 757 758 SAFE_FREE( path ); 759 760 return num_subkeys; 761} 762 763/********************************************************************** 764 Enumerate registry values given a registry path. 765 Caller is responsible for freeing memory 766 *********************************************************************/ 767 768int printing_value_info( char *key, REGVAL_CTR *val ) 769{ 770 char *path; 771 BOOL top_level = False; 772 int num_values = 0; 773 774 DEBUG(10,("printing_value_info: key=>[%s]\n", key)); 775 776 path = trim_reg_path( key ); 777 778 /* check to see if we are dealing with the top level key */ 779 780 if ( !path ) 781 top_level = True; 782 783 /* fill in values from the getprinterdata_printer_server() */ 784 if ( top_level ) 785 num_values = 0; 786 else 787 num_values = handle_printing_subpath( path, NULL, val ); 788 789 790 return num_values; 791} 792 793/********************************************************************** 794 Stub function which always returns failure since we don't want 795 people storing printing information directly via regostry calls 796 (for now at least) 797 *********************************************************************/ 798 799BOOL printing_store_subkey( char *key, REGSUBKEY_CTR *subkeys ) 800{ 801 return False; 802} 803 804/********************************************************************** 805 Stub function which always returns failure since we don't want 806 people storing printing information directly via regostry calls 807 (for now at least) 808 *********************************************************************/ 809 810BOOL printing_store_value( char *key, REGVAL_CTR *val ) 811{ 812 return False; 813} 814 815/* 816 * Table of function pointers for accessing printing data 817 */ 818 819REGISTRY_OPS printing_ops = { 820 printing_subkey_info, 821 printing_value_info, 822 printing_store_subkey, 823 printing_store_value 824}; 825 826 827