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