1/* 2 * Unix SMB/CIFS implementation. 3 * Virtual Windows Registry Layer 4 * Copyright (C) Gerald Carter 2002-2005 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 3 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, see <http://www.gnu.org/licenses/>. 18 */ 19 20/* Implementation of registry virtual views for printing information */ 21 22#include "includes.h" 23 24#undef DBGC_CLASS 25#define DBGC_CLASS DBGC_REGISTRY 26 27/* registrt paths used in the print_registry[] */ 28 29#define KEY_MONITORS "HKLM/SYSTEM/CURRENTCONTROLSET/CONTROL/PRINT/MONITORS" 30#define KEY_FORMS "HKLM/SYSTEM/CURRENTCONTROLSET/CONTROL/PRINT/FORMS" 31#define KEY_CONTROL_PRINTERS "HKLM/SYSTEM/CURRENTCONTROLSET/CONTROL/PRINT/PRINTERS" 32#define KEY_ENVIRONMENTS "HKLM/SYSTEM/CURRENTCONTROLSET/CONTROL/PRINT/ENVIRONMENTS" 33#define KEY_CONTROL_PRINT "HKLM/SYSTEM/CURRENTCONTROLSET/CONTROL/PRINT" 34#define KEY_WINNT_PRINTERS "HKLM/SOFTWARE/MICROSOFT/WINDOWS NT/CURRENTVERSION/PRINT/PRINTERS" 35#define KEY_WINNT_PRINT "HKLM/SOFTWARE/MICROSOFT/WINDOWS NT/CURRENTVERSION/PRINT" 36#define KEY_PORTS "HKLM/SOFTWARE/MICROSOFT/WINDOWS NT/CURRENTVERSION/PORTS" 37 38/* callback table for various registry paths below the ones we service in this module */ 39 40struct reg_dyn_tree { 41 /* full key path in normalized form */ 42 const char *path; 43 44 /* callbscks for fetch/store operations */ 45 int ( *fetch_subkeys) ( const char *path, struct regsubkey_ctr *subkeys ); 46 bool (*store_subkeys) ( const char *path, struct regsubkey_ctr *subkeys ); 47 int (*fetch_values) ( const char *path, struct regval_ctr *values ); 48 bool (*store_values) ( const char *path, struct regval_ctr *values ); 49}; 50 51/********************************************************************* 52 ********************************************************************* 53 ** Utility Functions 54 ********************************************************************* 55 *********************************************************************/ 56 57/*********************************************************************** 58 simple function to prune a pathname down to the basename of a file 59 **********************************************************************/ 60 61static const char *dos_basename(const char *path) 62{ 63 const char *p; 64 65 if (!(p = strrchr( path, '\\'))) { 66 p = path; 67 } else { 68 p++; 69 } 70 71 return p; 72} 73 74/********************************************************************* 75 ********************************************************************* 76 ** "HKLM/SYSTEM/CURRENTCONTROLSET/CONTROL/PRINT/FORMS" 77 ********************************************************************* 78 *********************************************************************/ 79 80static int key_forms_fetch_keys(const char *key, struct regsubkey_ctr *subkeys) 81{ 82 char *p = reg_remaining_path(talloc_tos(), key + strlen(KEY_FORMS)); 83 84 /* no keys below Forms */ 85 86 if (p) { 87 return -1; 88 } 89 90 return 0; 91} 92 93/********************************************************************** 94 *********************************************************************/ 95 96static int key_forms_fetch_values(const char *key, struct regval_ctr *values) 97{ 98 uint32 data[8]; 99 int i, num_values, form_index = 1; 100 nt_forms_struct *forms_list = NULL; 101 nt_forms_struct *form; 102 103 DEBUG(10,("print_values_forms: key=>[%s]\n", key ? key : "NULL" )); 104 105 num_values = get_ntforms( &forms_list ); 106 107 DEBUG(10,("hive_forms_fetch_values: [%d] user defined forms returned\n", 108 num_values)); 109 110 /* handle user defined forms */ 111 112 for ( i=0; i<num_values; i++ ) { 113 form = &forms_list[i]; 114 115 data[0] = form->width; 116 data[1] = form->length; 117 data[2] = form->left; 118 data[3] = form->top; 119 data[4] = form->right; 120 data[5] = form->bottom; 121 data[6] = form_index++; 122 data[7] = form->flag; 123 124 regval_ctr_addvalue( values, form->name, REG_BINARY, (char*)data, sizeof(data) ); 125 } 126 127 SAFE_FREE( forms_list ); 128 forms_list = NULL; 129 130 /* handle built-on forms */ 131 132 num_values = get_builtin_ntforms( &forms_list ); 133 134 DEBUG(10,("print_subpath_values_forms: [%d] built-in forms returned\n", 135 num_values)); 136 137 for ( i=0; i<num_values; i++ ) { 138 form = &forms_list[i]; 139 140 data[0] = form->width; 141 data[1] = form->length; 142 data[2] = form->left; 143 data[3] = form->top; 144 data[4] = form->right; 145 data[5] = form->bottom; 146 data[6] = form_index++; 147 data[7] = form->flag; 148 149 regval_ctr_addvalue(values, form->name, REG_BINARY, (char*)data, sizeof(data) ); 150 } 151 152 SAFE_FREE(forms_list); 153 154 return regval_ctr_numvals(values); 155} 156 157/********************************************************************* 158 ********************************************************************* 159 ** "HKLM/SYSTEM/CURRENTCONTROLSET/CONTROL/PRINT/PRINTERS" 160 ** "HKLM/SOFTWARE/MICROSOFT/WINDOWS NT/CURRENTVERSION/PRINT/PRINTERS" 161 ********************************************************************* 162 *********************************************************************/ 163 164/********************************************************************* 165 strip off prefix for printers key. DOes return a pointer to static 166 memory. 167 *********************************************************************/ 168 169static char *strip_printers_prefix(const char *key) 170{ 171 char *subkeypath = NULL; 172 char *path = NULL; 173 TALLOC_CTX *ctx = talloc_tos(); 174 175 path = talloc_strdup(ctx, key); 176 if (!path) { 177 return NULL; 178 } 179 path = normalize_reg_path(ctx, path); 180 if (!path) { 181 return NULL; 182 } 183 184 /* normalizing the path does not change length, just key delimiters and case */ 185 186 if (strncmp(path, KEY_WINNT_PRINTERS, strlen(KEY_WINNT_PRINTERS)) == 0) { 187 subkeypath = reg_remaining_path(ctx, key + strlen(KEY_WINNT_PRINTERS)); 188 } else { 189 subkeypath = reg_remaining_path(ctx, key + strlen(KEY_CONTROL_PRINTERS)); 190 } 191 192 TALLOC_FREE(path); 193 return subkeypath; 194} 195 196/********************************************************************* 197 *********************************************************************/ 198 199static int key_printers_fetch_keys( const char *key, struct regsubkey_ctr *subkeys ) 200{ 201 int n_services = lp_numservices(); 202 int snum; 203 fstring sname; 204 int i; 205 int num_subkeys = 0; 206 char *printers_key; 207 char *printername, *printerdatakey; 208 NT_PRINTER_INFO_LEVEL *printer = NULL; 209 fstring *subkey_names = NULL; 210 211 DEBUG(10,("key_printers_fetch_keys: key=>[%s]\n", key ? key : "NULL" )); 212 213 printers_key = strip_printers_prefix( key ); 214 215 if ( !printers_key ) { 216 /* enumerate all printers */ 217 218 for (snum=0; snum<n_services; snum++) { 219 if ( !(lp_snum_ok(snum) && lp_print_ok(snum) ) ) 220 continue; 221 222 /* don't report the [printers] share */ 223 224 if ( strequal( lp_servicename(snum), PRINTERS_NAME ) ) 225 continue; 226 227 fstrcpy( sname, lp_servicename(snum) ); 228 229 regsubkey_ctr_addkey( subkeys, sname ); 230 } 231 232 num_subkeys = regsubkey_ctr_numkeys( subkeys ); 233 goto done; 234 } 235 236 /* get information for a specific printer */ 237 238 if (!reg_split_path( printers_key, &printername, &printerdatakey )) { 239 return -1; 240 } 241 242 /* validate the printer name */ 243 244 for (snum=0; snum<n_services; snum++) { 245 if ( !lp_snum_ok(snum) || !lp_print_ok(snum) ) 246 continue; 247 if (strequal( lp_servicename(snum), printername ) ) 248 break; 249 } 250 251 if ( snum>=n_services 252 || !W_ERROR_IS_OK( get_a_printer(NULL, &printer, 2, printername) ) ) 253 { 254 return -1; 255 } 256 257 num_subkeys = get_printer_subkeys( printer->info_2->data, printerdatakey?printerdatakey:"", &subkey_names ); 258 259 for ( i=0; i<num_subkeys; i++ ) 260 regsubkey_ctr_addkey( subkeys, subkey_names[i] ); 261 262 free_a_printer( &printer, 2 ); 263 264 /* no other subkeys below here */ 265 266done: 267 SAFE_FREE( subkey_names ); 268 269 return num_subkeys; 270} 271 272/********************************************************************** 273 Take a list of names and call add_printer_hook() if necessary 274 Note that we do this a little differently from Windows since the 275 keyname is the sharename and not the printer name. 276 *********************************************************************/ 277 278static bool add_printers_by_registry( struct regsubkey_ctr *subkeys ) 279{ 280 int i, num_keys, snum; 281 char *printername; 282 NT_PRINTER_INFO_LEVEL_2 info2; 283 NT_PRINTER_INFO_LEVEL printer; 284 285 ZERO_STRUCT( info2 ); 286 printer.info_2 = &info2; 287 288 num_keys = regsubkey_ctr_numkeys( subkeys ); 289 290 become_root(); 291 for ( i=0; i<num_keys; i++ ) { 292 printername = regsubkey_ctr_specific_key( subkeys, i ); 293 snum = find_service( printername ); 294 295 /* just verify a valied snum for now */ 296 if ( snum == -1 ) { 297 fstrcpy( info2.printername, printername ); 298 fstrcpy( info2.sharename, printername ); 299 if ( !add_printer_hook(talloc_tos(), NULL, &printer ) ) { 300 DEBUG(0,("add_printers_by_registry: Failed to add printer [%s]\n", 301 printername)); 302 } 303 } 304 } 305 unbecome_root(); 306 307 return True; 308} 309 310/********************************************************************** 311 *********************************************************************/ 312 313static bool key_printers_store_keys( const char *key, struct regsubkey_ctr *subkeys ) 314{ 315 char *printers_key; 316 char *printername, *printerdatakey; 317 NT_PRINTER_INFO_LEVEL *printer = NULL; 318 int i, num_subkeys, num_existing_keys; 319 char *subkeyname; 320 fstring *existing_subkeys = NULL; 321 322 printers_key = strip_printers_prefix( key ); 323 324 if ( !printers_key ) { 325 /* have to deal with some new or deleted printer */ 326 return add_printers_by_registry( subkeys ); 327 } 328 329 if (!reg_split_path( printers_key, &printername, &printerdatakey )) { 330 return False; 331 } 332 333 /* lookup the printer */ 334 335 if ( !W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, printername)) ) { 336 DEBUG(0,("key_printers_store_keys: Tried to store subkey for bad printername %s\n", 337 printername)); 338 return False; 339 } 340 341 /* get the top level printer keys */ 342 343 num_existing_keys = get_printer_subkeys( printer->info_2->data, "", &existing_subkeys ); 344 345 for ( i=0; i<num_existing_keys; i++ ) { 346 347 /* remove the key if it has been deleted */ 348 349 if ( !regsubkey_ctr_key_exists( subkeys, existing_subkeys[i] ) ) { 350 DEBUG(5,("key_printers_store_keys: deleting key %s\n", 351 existing_subkeys[i])); 352 delete_printer_key( printer->info_2->data, existing_subkeys[i] ); 353 } 354 } 355 356 num_subkeys = regsubkey_ctr_numkeys( subkeys ); 357 for ( i=0; i<num_subkeys; i++ ) { 358 subkeyname = regsubkey_ctr_specific_key(subkeys, i); 359 /* add any missing printer keys */ 360 if ( lookup_printerkey(printer->info_2->data, subkeyname) == -1 ) { 361 DEBUG(5,("key_printers_store_keys: adding key %s\n", 362 existing_subkeys[i])); 363 if ( add_new_printer_key( printer->info_2->data, subkeyname ) == -1 ) { 364 SAFE_FREE( existing_subkeys ); 365 return False; 366 } 367 } 368 } 369 370 /* write back to disk */ 371 372 mod_a_printer( printer, 2 ); 373 374 /* cleanup */ 375 376 free_a_printer( &printer, 2 ); 377 378 SAFE_FREE( existing_subkeys ); 379 380 return True; 381} 382 383/********************************************************************** 384 *********************************************************************/ 385 386static void fill_in_printer_values(NT_PRINTER_INFO_LEVEL_2 *info2, struct regval_ctr *values) 387{ 388 struct spoolss_DeviceMode *devmode; 389 char *p; 390 uint32 printer_status = PRINTER_STATUS_OK; 391 392 regval_ctr_addvalue( values, "Attributes", REG_DWORD, (char*)&info2->attributes, sizeof(info2->attributes) ); 393 regval_ctr_addvalue( values, "Priority", REG_DWORD, (char*)&info2->priority, sizeof(info2->attributes) ); 394 regval_ctr_addvalue( values, "ChangeID", REG_DWORD, (char*)&info2->changeid, sizeof(info2->changeid) ); 395 regval_ctr_addvalue( values, "Default Priority", REG_DWORD, (char*)&info2->default_priority, sizeof(info2->default_priority) ); 396 397 /* lie and say everything is ok since we don't want to call print_queue_length() to get the real status */ 398 regval_ctr_addvalue( values, "Status", REG_DWORD, (char*)&printer_status, sizeof(info2->status) ); 399 400 regval_ctr_addvalue( values, "StartTime", REG_DWORD, (char*)&info2->starttime, sizeof(info2->starttime) ); 401 regval_ctr_addvalue( values, "UntilTime", REG_DWORD, (char*)&info2->untiltime, sizeof(info2->untiltime) ); 402 403 /* strip the \\server\ from this string */ 404 if ( !(p = strrchr( info2->printername, '\\' ) ) ) 405 p = info2->printername; 406 else 407 p++; 408 409 regval_ctr_addvalue_sz(values, "Name", p); 410 regval_ctr_addvalue_sz(values, "Location", info2->location); 411 regval_ctr_addvalue_sz(values, "Description", info2->comment); 412 regval_ctr_addvalue_sz(values, "Parameters", info2->parameters); 413 regval_ctr_addvalue_sz(values, "Port", info2->portname); 414 regval_ctr_addvalue_sz(values, "Share Name", info2->sharename); 415 regval_ctr_addvalue_sz(values, "Printer Driver", info2->drivername); 416 regval_ctr_addvalue_sz(values, "Separator File", info2->sepfile); 417 regval_ctr_addvalue_sz(values, "Print Processor", "WinPrint"); 418 regval_ctr_addvalue_sz(values, "Datatype", "RAW"); 419 420 /* stream the device mode */ 421 422 devmode = construct_dev_mode(values,info2->sharename); 423 if (devmode) { 424 DATA_BLOB blob; 425 enum ndr_err_code ndr_err; 426 427 ndr_err = ndr_push_struct_blob(&blob, values, NULL, devmode, 428 (ndr_push_flags_fn_t)ndr_push_spoolss_DeviceMode); 429 430 if (NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { 431 regval_ctr_addvalue(values, "Default Devmode", REG_BINARY, 432 (const char *)blob.data, blob.length); 433 } 434 } 435 436 /* stream the printer security descriptor */ 437 438 if (info2->secdesc_buf && 439 info2->secdesc_buf->sd && 440 info2->secdesc_buf->sd_size) 441 { 442 NTSTATUS status; 443 DATA_BLOB blob; 444 445 status = marshall_sec_desc(values, info2->secdesc_buf->sd, 446 &blob.data, &blob.length); 447 if (NT_STATUS_IS_OK(status)) { 448 regval_ctr_addvalue(values, "Security", REG_BINARY, 449 (const char *)blob.data, blob.length); 450 } 451 } 452 453 return; 454} 455 456/********************************************************************** 457 *********************************************************************/ 458 459static int key_printers_fetch_values(const char *key, struct regval_ctr *values) 460{ 461 int num_values; 462 char *printers_key; 463 char *printername, *printerdatakey; 464 NT_PRINTER_INFO_LEVEL *printer = NULL; 465 NT_PRINTER_DATA *p_data; 466 int i, key_index; 467 468 printers_key = strip_printers_prefix( key ); 469 470 /* top level key values stored in the registry has no values */ 471 472 if ( !printers_key ) { 473 /* normalize to the 'HKLM\SOFTWARE\...\Print\Printers' key */ 474 return regdb_fetch_values( KEY_WINNT_PRINTERS, values ); 475 } 476 477 /* lookup the printer object */ 478 479 if (!reg_split_path( printers_key, &printername, &printerdatakey )) { 480 return -1; 481 } 482 483 if ( !W_ERROR_IS_OK( get_a_printer(NULL, &printer, 2, printername) ) ) 484 goto done; 485 486 if ( !printerdatakey ) { 487 fill_in_printer_values( printer->info_2, values ); 488 goto done; 489 } 490 491 /* iterate over all printer data keys and fill the regval container */ 492 493 p_data = printer->info_2->data; 494 if ( (key_index = lookup_printerkey( p_data, printerdatakey )) == -1 ) { 495 /* failure....should never happen if the client has a valid open handle first */ 496 DEBUG(10,("key_printers_fetch_values: Unknown keyname [%s]\n", printerdatakey)); 497 free_a_printer( &printer, 2 ); 498 return -1; 499 } 500 501 num_values = regval_ctr_numvals( p_data->keys[key_index].values ); 502 for ( i=0; i<num_values; i++ ) 503 regval_ctr_copyvalue( values, regval_ctr_specific_value(p_data->keys[key_index].values, i) ); 504 505 506done: 507 if ( printer ) 508 free_a_printer( &printer, 2 ); 509 510 return regval_ctr_numvals( values ); 511} 512 513/********************************************************************** 514 *********************************************************************/ 515 516#define REG_IDX_ATTRIBUTES 1 517#define REG_IDX_PRIORITY 2 518#define REG_IDX_DEFAULT_PRIORITY 3 519#define REG_IDX_CHANGEID 4 520#define REG_IDX_STATUS 5 521#define REG_IDX_STARTTIME 6 522#define REG_IDX_NAME 7 523#define REG_IDX_LOCATION 8 524#define REG_IDX_DESCRIPTION 9 525#define REG_IDX_PARAMETERS 10 526#define REG_IDX_PORT 12 527#define REG_IDX_SHARENAME 13 528#define REG_IDX_DRIVER 14 529#define REG_IDX_SEP_FILE 15 530#define REG_IDX_PRINTPROC 16 531#define REG_IDX_DATATYPE 17 532#define REG_IDX_DEVMODE 18 533#define REG_IDX_SECDESC 19 534#define REG_IDX_UNTILTIME 20 535 536struct { 537 const char *name; 538 int index; 539} printer_values_map[] = { 540 { "Attributes", REG_IDX_ATTRIBUTES }, 541 { "Priority", REG_IDX_PRIORITY }, 542 { "Default Priority", REG_IDX_DEFAULT_PRIORITY }, 543 { "ChangeID", REG_IDX_CHANGEID }, 544 { "Status", REG_IDX_STATUS }, 545 { "StartTime", REG_IDX_STARTTIME }, 546 { "UntilTime", REG_IDX_UNTILTIME }, 547 { "Name", REG_IDX_NAME }, 548 { "Location", REG_IDX_LOCATION }, 549 { "Description", REG_IDX_DESCRIPTION }, 550 { "Parameters", REG_IDX_PARAMETERS }, 551 { "Port", REG_IDX_PORT }, 552 { "Share Name", REG_IDX_SHARENAME }, 553 { "Printer Driver", REG_IDX_DRIVER }, 554 { "Separator File", REG_IDX_SEP_FILE }, 555 { "Print Processor", REG_IDX_PRINTPROC }, 556 { "Datatype", REG_IDX_DATATYPE }, 557 { "Default Devmode", REG_IDX_DEVMODE }, 558 { "Security", REG_IDX_SECDESC }, 559 { NULL, -1 } 560}; 561 562 563static int find_valuename_index( const char *valuename ) 564{ 565 int i; 566 567 for ( i=0; printer_values_map[i].name; i++ ) { 568 if ( strequal( valuename, printer_values_map[i].name ) ) 569 return printer_values_map[i].index; 570 } 571 572 return -1; 573} 574 575/********************************************************************** 576 *********************************************************************/ 577 578static void pull_reg_sz_fstring(TALLOC_CTX *mem_ctx, const DATA_BLOB *blob, fstring s) 579{ 580 const char *str; 581 pull_reg_sz(mem_ctx, blob, &str); 582 fstrcpy(s, str); 583} 584 585static void convert_values_to_printer_info_2(TALLOC_CTX *mem_ctx, 586 NT_PRINTER_INFO_LEVEL_2 *printer2, 587 struct regval_ctr *values) 588{ 589 int num_values = regval_ctr_numvals( values ); 590 uint32 value_index; 591 struct regval_blob *val; 592 int i; 593 594 for ( i=0; i<num_values; i++ ) { 595 DATA_BLOB blob; 596 val = regval_ctr_specific_value( values, i ); 597 value_index = find_valuename_index( regval_name( val ) ); 598 599 blob = data_blob_const(regval_data_p(val), regval_size(val)); 600 601 switch( value_index ) { 602 case REG_IDX_ATTRIBUTES: 603 printer2->attributes = (uint32)(*regval_data_p(val)); 604 break; 605 case REG_IDX_PRIORITY: 606 printer2->priority = (uint32)(*regval_data_p(val)); 607 break; 608 case REG_IDX_DEFAULT_PRIORITY: 609 printer2->default_priority = (uint32)(*regval_data_p(val)); 610 break; 611 case REG_IDX_CHANGEID: 612 printer2->changeid = (uint32)(*regval_data_p(val)); 613 break; 614 case REG_IDX_STARTTIME: 615 printer2->starttime = (uint32)(*regval_data_p(val)); 616 break; 617 case REG_IDX_UNTILTIME: 618 printer2->untiltime = (uint32)(*regval_data_p(val)); 619 break; 620 case REG_IDX_NAME: 621 pull_reg_sz_fstring(mem_ctx, &blob, printer2->printername); 622 break; 623 case REG_IDX_LOCATION: 624 pull_reg_sz_fstring(mem_ctx, &blob, printer2->location); 625 break; 626 case REG_IDX_DESCRIPTION: 627 pull_reg_sz_fstring(mem_ctx, &blob, printer2->comment); 628 break; 629 case REG_IDX_PARAMETERS: 630 pull_reg_sz_fstring(mem_ctx, &blob, printer2->parameters); 631 break; 632 case REG_IDX_PORT: 633 pull_reg_sz_fstring(mem_ctx, &blob, printer2->portname); 634 break; 635 case REG_IDX_SHARENAME: 636 pull_reg_sz_fstring(mem_ctx, &blob, printer2->sharename); 637 break; 638 case REG_IDX_DRIVER: 639 pull_reg_sz_fstring(mem_ctx, &blob, printer2->drivername); 640 break; 641 case REG_IDX_SEP_FILE: 642 pull_reg_sz_fstring(mem_ctx, &blob, printer2->sepfile); 643 break; 644 case REG_IDX_PRINTPROC: 645 pull_reg_sz_fstring(mem_ctx, &blob, printer2->printprocessor); 646 break; 647 case REG_IDX_DATATYPE: 648 pull_reg_sz_fstring(mem_ctx, &blob, printer2->datatype); 649 break; 650 case REG_IDX_DEVMODE: 651 break; 652 case REG_IDX_SECDESC: 653 break; 654 default: 655 /* unsupported value...throw away */ 656 DEBUG(8,("convert_values_to_printer_info_2: Unsupported registry value [%s]\n", 657 regval_name( val ) )); 658 } 659 } 660 661 return; 662} 663 664/********************************************************************** 665 *********************************************************************/ 666 667static bool key_printers_store_values(const char *key, struct regval_ctr *values) 668{ 669 char *printers_key; 670 char *printername, *keyname; 671 NT_PRINTER_INFO_LEVEL *printer = NULL; 672 WERROR result; 673 TALLOC_CTX *mem_ctx = talloc_init("key_printers_store_values"); 674 675 printers_key = strip_printers_prefix( key ); 676 677 /* values in the top level key get stored in the registry */ 678 679 if ( !printers_key ) { 680 /* normalize on the 'HKLM\SOFTWARE\....\Print\Printers' key */ 681 return regdb_store_values( KEY_WINNT_PRINTERS, values ); 682 } 683 684 if (!reg_split_path( printers_key, &printername, &keyname )) { 685 return False; 686 } 687 688 if ( !W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, printername) ) ) 689 return False; 690 691 /* deal with setting values directly under the printername */ 692 693 if ( !keyname ) { 694 convert_values_to_printer_info_2(mem_ctx, printer->info_2, values ); 695 } 696 else { 697 int num_values = regval_ctr_numvals( values ); 698 int i; 699 struct regval_blob *val; 700 701 delete_printer_key( printer->info_2->data, keyname ); 702 703 /* deal with any subkeys */ 704 for ( i=0; i<num_values; i++ ) { 705 val = regval_ctr_specific_value( values, i ); 706 result = set_printer_dataex( printer, keyname, 707 regval_name( val ), 708 regval_type( val ), 709 regval_data_p( val ), 710 regval_size( val ) ); 711 if ( !W_ERROR_IS_OK(result) ) { 712 DEBUG(0,("key_printers_store_values: failed to set printer data [%s]!\n", 713 keyname)); 714 free_a_printer( &printer, 2 ); 715 talloc_destroy(mem_ctx); 716 return False; 717 } 718 } 719 } 720 721 result = mod_a_printer( printer, 2 ); 722 723 free_a_printer( &printer, 2 ); 724 talloc_destroy(mem_ctx); 725 726 return W_ERROR_IS_OK(result); 727} 728 729/********************************************************************* 730 ********************************************************************* 731 ** "HKLM/SYSTEM/CURRENTCONTROLSET/CONTROL/PRINT/ENVIRONMENTS" 732 ********************************************************************* 733 *********************************************************************/ 734 735static int key_driver_fetch_keys( const char *key, struct regsubkey_ctr *subkeys ) 736{ 737 const char *environments[] = { 738 "Windows 4.0", 739 "Windows NT x86", 740 "Windows NT R4000", 741 "Windows NT Alpha_AXP", 742 "Windows NT PowerPC", 743 "Windows IA64", 744 "Windows x64", 745 NULL }; 746 fstring *drivers = NULL; 747 int i, env_index, num_drivers; 748 char *keystr, *base, *subkeypath; 749 char *key2 = NULL; 750 int num_subkeys = -1; 751 int version; 752 TALLOC_CTX *ctx = talloc_tos(); 753 754 DEBUG(10,("key_driver_fetch_keys key=>[%s]\n", key ? key : "NULL" )); 755 756 keystr = reg_remaining_path(ctx, key + strlen(KEY_ENVIRONMENTS) ); 757 758 /* list all possible architectures */ 759 760 if ( !keystr ) { 761 for ( num_subkeys=0; environments[num_subkeys]; num_subkeys++ ) 762 regsubkey_ctr_addkey( subkeys, environments[num_subkeys] ); 763 764 return num_subkeys; 765 } 766 767 /* we are dealing with a subkey of "Environments */ 768 key2 = talloc_strdup(ctx, keystr); 769 if (!key2) { 770 return -1; 771 } 772 keystr = key2; 773 if (!reg_split_path(keystr, &base, &subkeypath )) { 774 return -1; 775 } 776 777 /* sanity check */ 778 779 for ( env_index=0; environments[env_index]; env_index++ ) { 780 if ( strequal( environments[env_index], base ) ) 781 break; 782 } 783 if ( !environments[env_index] ) 784 return -1; 785 786 /* ...\Print\Environements\...\ */ 787 788 if ( !subkeypath ) { 789 regsubkey_ctr_addkey( subkeys, "Drivers" ); 790 regsubkey_ctr_addkey( subkeys, "Print Processors" ); 791 792 return 2; 793 } 794 795 /* more of the key path to process */ 796 797 keystr = subkeypath; 798 if (!reg_split_path( keystr, &base, &subkeypath )) { 799 return -1; 800 } 801 802 /* ...\Print\Environements\...\Drivers\ */ 803 804 if ( !subkeypath ) { 805 if ( strequal(base, "Drivers") ) { 806 switch ( env_index ) { 807 case 0: /* Win9x */ 808 regsubkey_ctr_addkey( subkeys, "Version-0" ); 809 break; 810 default: /* Windows NT based systems */ 811 regsubkey_ctr_addkey( subkeys, "Version-2" ); 812 regsubkey_ctr_addkey( subkeys, "Version-3" ); 813 break; 814 } 815 816 return regsubkey_ctr_numkeys( subkeys ); 817 } else if ( strequal(base, "Print Processors") ) { 818 if ( env_index == 1 || env_index == 5 || env_index == 6 ) 819 820 821 return regsubkey_ctr_numkeys( subkeys ); 822 } else 823 return -1; /* bad path */ 824 } 825 826 /* we finally get to enumerate the drivers */ 827 828 /* only one possible subkey below PrintProc key */ 829 830 if ( strequal(base, "Print Processors") ) { 831 keystr = subkeypath; 832 if (!reg_split_path( keystr, &base, &subkeypath )) { 833 return -1; 834 } 835 836 /* no subkeys below this point */ 837 838 if ( subkeypath ) 839 return -1; 840 841 /* only allow one keyname here -- 'winprint' */ 842 843 return strequal( base, "winprint" ) ? 0 : -1; 844 } 845 846 /* only dealing with drivers from here on out */ 847 848 keystr = subkeypath; 849 if (!reg_split_path( keystr, &base, &subkeypath )) { 850 return -1; 851 } 852 853 version = atoi(&base[strlen(base)-1]); 854 855 switch (env_index) { 856 case 0: 857 if ( version != 0 ) 858 return -1; 859 break; 860 default: 861 if ( version != 2 && version != 3 ) 862 return -1; 863 break; 864 } 865 866 867 if ( !subkeypath ) { 868 num_drivers = get_ntdrivers( &drivers, environments[env_index], version ); 869 for ( i=0; i<num_drivers; i++ ) 870 regsubkey_ctr_addkey( subkeys, drivers[i] ); 871 872 return regsubkey_ctr_numkeys( subkeys ); 873 } 874 875 /* if anything else left, just say if has no subkeys */ 876 877 DEBUG(1,("key_driver_fetch_keys unhandled key [%s] (subkey == %s)\n", 878 key, subkeypath )); 879 880 return 0; 881} 882 883 884/********************************************************************** 885 *********************************************************************/ 886 887static void fill_in_driver_values(const struct spoolss_DriverInfo8 *r, 888 struct regval_ctr *values) 889{ 890 char *buffer = NULL; 891 int buffer_size = 0; 892 int i, length; 893 const char *filename; 894 DATA_BLOB data; 895 896 filename = dos_basename(r->driver_path); 897 regval_ctr_addvalue_sz(values, "Driver", filename); 898 899 filename = dos_basename(r->config_file); 900 regval_ctr_addvalue_sz(values, "Configuration File", filename); 901 902 filename = dos_basename(r->data_file); 903 regval_ctr_addvalue_sz(values, "Data File", filename); 904 905 filename = dos_basename(r->help_file); 906 regval_ctr_addvalue_sz(values, "Help File", filename); 907 908 regval_ctr_addvalue_sz(values, "Data Type", r->default_datatype); 909 910 regval_ctr_addvalue( values, "Version", REG_DWORD, (char*)&r->version, 911 sizeof(r->version) ); 912 913 if (r->dependent_files) { 914 /* place the list of dependent files in a single 915 character buffer, separating each file name by 916 a NULL */ 917 918 for (i=0; r->dependent_files[i] && strcmp(r->dependent_files[i], ""); i++) { 919 /* strip the path to only the file's base name */ 920 921 filename = dos_basename(r->dependent_files[i]); 922 923 length = strlen(filename); 924 925 buffer = (char *)SMB_REALLOC( buffer, buffer_size + (length + 1)*sizeof(uint16) ); 926 if ( !buffer ) { 927 break; 928 } 929 930 push_reg_sz(talloc_tos(), &data, filename); 931 memcpy( buffer+buffer_size, (char*)data.data, data.length); 932 933 buffer_size += (length + 1)*sizeof(uint16); 934 } 935 936 /* terminated by double NULL. Add the final one here */ 937 938 buffer = (char *)SMB_REALLOC( buffer, buffer_size + 2 ); 939 if ( !buffer ) { 940 buffer_size = 0; 941 } else { 942 buffer[buffer_size++] = '\0'; 943 buffer[buffer_size++] = '\0'; 944 } 945 } 946 947 regval_ctr_addvalue( values, "Dependent Files", REG_MULTI_SZ, buffer, buffer_size ); 948 949 SAFE_FREE( buffer ); 950 951 return; 952} 953 954/********************************************************************** 955 *********************************************************************/ 956 957static int driver_arch_fetch_values(char *key, struct regval_ctr *values) 958{ 959 char *keystr, *base, *subkeypath; 960 fstring arch_environment; 961 fstring driver; 962 int version; 963 struct spoolss_DriverInfo8 *driver_ctr; 964 WERROR w_result; 965 966 if (!reg_split_path( key, &base, &subkeypath )) { 967 return -1; 968 } 969 970 /* no values in 'Environments\Drivers\Windows NT x86' */ 971 972 if ( !subkeypath ) 973 return 0; 974 975 /* We have the Architecture string and some subkey name: 976 Currently we only support 977 * Drivers 978 * Print Processors 979 Anything else is an error. 980 */ 981 982 fstrcpy( arch_environment, base ); 983 984 keystr = subkeypath; 985 if (!reg_split_path( keystr, &base, &subkeypath )) { 986 return -1; 987 } 988 989 if ( strequal(base, "Print Processors") ) 990 return 0; 991 992 /* only Drivers key can be left */ 993 994 if ( !strequal(base, "Drivers") ) 995 return -1; 996 997 if ( !subkeypath ) 998 return 0; 999 1000 /* We know that we have Architechure\Drivers with some subkey name 1001 The subkey name has to be Version-XX */ 1002 1003 keystr = subkeypath; 1004 if (!reg_split_path( keystr, &base, &subkeypath )) { 1005 return -1; 1006 } 1007 1008 if ( !subkeypath ) 1009 return 0; 1010 1011 version = atoi(&base[strlen(base)-1]); 1012 1013 /* BEGIN PRINTER DRIVER NAME BLOCK */ 1014 1015 keystr = subkeypath; 1016 if (!reg_split_path( keystr, &base, &subkeypath )) { 1017 return -1; 1018 } 1019 1020 /* don't go any deeper for now */ 1021 1022 fstrcpy( driver, base ); 1023 1024 w_result = get_a_printer_driver(talloc_tos(), &driver_ctr, driver, arch_environment, version); 1025 1026 if ( !W_ERROR_IS_OK(w_result) ) 1027 return -1; 1028 1029 fill_in_driver_values(driver_ctr, values); 1030 1031 free_a_printer_driver(driver_ctr); 1032 1033 /* END PRINTER DRIVER NAME BLOCK */ 1034 1035 1036 DEBUG(8,("key_driver_fetch_values: Exit\n")); 1037 1038 return regval_ctr_numvals( values ); 1039} 1040 1041/********************************************************************** 1042 *********************************************************************/ 1043 1044static int key_driver_fetch_values(const char *key, struct regval_ctr *values) 1045{ 1046 char *keystr = NULL; 1047 char *subkey = NULL; 1048 TALLOC_CTX *ctx = talloc_tos(); 1049 1050 DEBUG(8,("key_driver_fetch_values: Enter key => [%s]\n", key ? key : "NULL")); 1051 1052 /* no values in the Environments key */ 1053 1054 if (!(keystr = reg_remaining_path(ctx, key + strlen(KEY_ENVIRONMENTS)))) 1055 return 0; 1056 1057 subkey = talloc_strdup(ctx, keystr); 1058 if (!subkey) { 1059 return 0; 1060 } 1061 1062 /* pass off to handle subkeys */ 1063 1064 return driver_arch_fetch_values( subkey, values ); 1065} 1066 1067/********************************************************************* 1068 ********************************************************************* 1069 ** "HKLM/SYSTEM/CURRENTCONTROLSET/CONTROL/PRINT" 1070 ********************************************************************* 1071 *********************************************************************/ 1072 1073static int key_print_fetch_keys( const char *key, struct regsubkey_ctr *subkeys ) 1074{ 1075 int key_len = strlen(key); 1076 1077 /* no keys below 'Print' handled here */ 1078 1079 if ( (key_len != strlen(KEY_CONTROL_PRINT)) && (key_len != strlen(KEY_WINNT_PRINT)) ) 1080 return -1; 1081 1082 regsubkey_ctr_addkey( subkeys, "Environments" ); 1083 regsubkey_ctr_addkey( subkeys, "Monitors" ); 1084 regsubkey_ctr_addkey( subkeys, "Forms" ); 1085 regsubkey_ctr_addkey( subkeys, "Printers" ); 1086 1087 return regsubkey_ctr_numkeys( subkeys ); 1088} 1089 1090/********************************************************************** 1091 ********************************************************************* 1092 ** Structure to hold dispatch table of ops for various printer keys. 1093 ** Make sure to always store deeper keys along the same path first so 1094 ** we ge a more specific match. 1095 ********************************************************************* 1096 *********************************************************************/ 1097 1098static struct reg_dyn_tree print_registry[] = { 1099/* just pass the monitor onto the registry tdb */ 1100{ KEY_MONITORS, 1101 ®db_fetch_keys, 1102 ®db_store_keys, 1103 ®db_fetch_values, 1104 ®db_store_values }, 1105{ KEY_FORMS, 1106 &key_forms_fetch_keys, 1107 NULL, 1108 &key_forms_fetch_values, 1109 NULL }, 1110{ KEY_CONTROL_PRINTERS, 1111 &key_printers_fetch_keys, 1112 &key_printers_store_keys, 1113 &key_printers_fetch_values, 1114 &key_printers_store_values }, 1115{ KEY_ENVIRONMENTS, 1116 &key_driver_fetch_keys, 1117 NULL, 1118 &key_driver_fetch_values, 1119 NULL }, 1120{ KEY_CONTROL_PRINT, 1121 &key_print_fetch_keys, 1122 NULL, 1123 NULL, 1124 NULL }, 1125{ KEY_WINNT_PRINTERS, 1126 &key_printers_fetch_keys, 1127 &key_printers_store_keys, 1128 &key_printers_fetch_values, 1129 &key_printers_store_values }, 1130{ KEY_PORTS, 1131 ®db_fetch_keys, 1132 ®db_store_keys, 1133 ®db_fetch_values, 1134 ®db_store_values }, 1135 1136{ NULL, NULL, NULL, NULL, NULL } 1137}; 1138 1139 1140/********************************************************************** 1141 ********************************************************************* 1142 ** Main reg_printing interface functions 1143 ********************************************************************* 1144 *********************************************************************/ 1145 1146/*********************************************************************** 1147 Lookup a key in the print_registry table, returning its index. 1148 -1 on failure 1149 **********************************************************************/ 1150 1151static int match_registry_path(const char *key) 1152{ 1153 int i; 1154 char *path = NULL; 1155 TALLOC_CTX *ctx = talloc_tos(); 1156 1157 if ( !key ) 1158 return -1; 1159 1160 path = talloc_strdup(ctx, key); 1161 if (!path) { 1162 return -1; 1163 } 1164 path = normalize_reg_path(ctx, path); 1165 if (!path) { 1166 return -1; 1167 } 1168 1169 for ( i=0; print_registry[i].path; i++ ) { 1170 if (strncmp( path, print_registry[i].path, strlen(print_registry[i].path) ) == 0 ) 1171 return i; 1172 } 1173 1174 return -1; 1175} 1176 1177/*********************************************************************** 1178 **********************************************************************/ 1179 1180static int regprint_fetch_reg_keys( const char *key, struct regsubkey_ctr *subkeys ) 1181{ 1182 int i = match_registry_path( key ); 1183 1184 if ( i == -1 ) 1185 return -1; 1186 1187 if ( !print_registry[i].fetch_subkeys ) 1188 return -1; 1189 1190 return print_registry[i].fetch_subkeys( key, subkeys ); 1191} 1192 1193/********************************************************************** 1194 *********************************************************************/ 1195 1196static bool regprint_store_reg_keys( const char *key, struct regsubkey_ctr *subkeys ) 1197{ 1198 int i = match_registry_path( key ); 1199 1200 if ( i == -1 ) 1201 return False; 1202 1203 if ( !print_registry[i].store_subkeys ) 1204 return False; 1205 1206 return print_registry[i].store_subkeys( key, subkeys ); 1207} 1208 1209/********************************************************************** 1210 *********************************************************************/ 1211 1212static int regprint_fetch_reg_values(const char *key, struct regval_ctr *values) 1213{ 1214 int i = match_registry_path( key ); 1215 1216 if ( i == -1 ) 1217 return -1; 1218 1219 /* return 0 values by default since we know the key had 1220 to exist because the client opened a handle */ 1221 1222 if ( !print_registry[i].fetch_values ) 1223 return 0; 1224 1225 return print_registry[i].fetch_values( key, values ); 1226} 1227 1228/********************************************************************** 1229 *********************************************************************/ 1230 1231static bool regprint_store_reg_values(const char *key, struct regval_ctr *values) 1232{ 1233 int i = match_registry_path( key ); 1234 1235 if ( i == -1 ) 1236 return False; 1237 1238 if ( !print_registry[i].store_values ) 1239 return False; 1240 1241 return print_registry[i].store_values( key, values ); 1242} 1243 1244/* 1245 * Table of function pointers for accessing printing data 1246 */ 1247 1248struct registry_ops printing_ops = { 1249 .fetch_subkeys = regprint_fetch_reg_keys, 1250 .fetch_values = regprint_fetch_reg_values, 1251 .store_subkeys = regprint_store_reg_keys, 1252 .store_values = regprint_store_reg_values, 1253}; 1254