From 669a39fae36f8bc60753c9b352556ef8ffaeb568 Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij Date: Sat, 17 Aug 2002 16:31:24 +0000 Subject: Sync 3.0 branch with HEAD (This used to be commit eac75549c398f208484ae735d5a5931fed6d0e99) --- source3/printing/nt_printing.c | 882 ++++++++++++++++++----------------------- 1 file changed, 387 insertions(+), 495 deletions(-) (limited to 'source3/printing/nt_printing.c') diff --git a/source3/printing/nt_printing.c b/source3/printing/nt_printing.c index ff08b99eb0..3b85fce020 100644 --- a/source3/printing/nt_printing.c +++ b/source3/printing/nt_printing.c @@ -319,7 +319,17 @@ BOOL nt_printing_init(void) * register callback to handle updating printers as new * drivers are installed */ - message_register(MSG_PRINTER_DRVUPGRADE, do_drv_upgrade_printer); + + message_register( MSG_PRINTER_DRVUPGRADE, do_drv_upgrade_printer ); + + /* + * register callback to handle updating printer data + * when a driver is initialized + */ + + message_register( MSG_PRINTERDATA_INIT_RESET, reset_all_printerdata ); + + return True; } @@ -435,25 +445,29 @@ int get_ntforms(nt_forms_struct **list) for (kbuf = tdb_firstkey(tdb_forms); kbuf.dptr; - newkey = tdb_nextkey(tdb_forms, kbuf), safe_free(kbuf.dptr), kbuf=newkey) { - if (strncmp(kbuf.dptr, FORMS_PREFIX, strlen(FORMS_PREFIX)) != 0) continue; + newkey = tdb_nextkey(tdb_forms, kbuf), safe_free(kbuf.dptr), kbuf=newkey) + { + if (strncmp(kbuf.dptr, FORMS_PREFIX, strlen(FORMS_PREFIX)) != 0) + continue; dbuf = tdb_fetch(tdb_forms, kbuf); - if (!dbuf.dptr) continue; + if (!dbuf.dptr) + continue; fstrcpy(form.name, kbuf.dptr+strlen(FORMS_PREFIX)); ret = tdb_unpack(dbuf.dptr, dbuf.dsize, "dddddddd", &i, &form.flag, &form.width, &form.length, &form.left, &form.top, &form.right, &form.bottom); SAFE_FREE(dbuf.dptr); - if (ret != dbuf.dsize) continue; + if (ret != dbuf.dsize) + continue; tl = Realloc(*list, sizeof(nt_forms_struct)*(n+1)); if (!tl) { DEBUG(0,("get_ntforms: Realloc fail.\n")); return 0; } - *list = tl; + *list = tl; (*list)[n] = form; n++; } @@ -998,7 +1012,7 @@ static int file_version_is_newer(connection_struct *conn, fstring new_file, } close_file(fsp, True); - if (use_version) { + if (use_version && (new_major != old_major || new_minor != old_minor)) { /* Compare versions and choose the larger version number */ if (new_major > old_major || (new_major == old_major && new_minor > old_minor)) { @@ -1218,8 +1232,7 @@ static WERROR clean_up_driver_struct_level_3(NT_PRINTER_DRIVER_INFO_LEVEL_3 *dri /**************************************************************************** ****************************************************************************/ -static WERROR clean_up_driver_struct_level_6(NT_PRINTER_DRIVER_INFO_LEVEL_6 *driver, - struct current_user *user) +static WERROR clean_up_driver_struct_level_6(NT_PRINTER_DRIVER_INFO_LEVEL_6 *driver, struct current_user *user) { fstring architecture; fstring new_name; @@ -1274,8 +1287,7 @@ static WERROR clean_up_driver_struct_level_6(NT_PRINTER_DRIVER_INFO_LEVEL_6 *dri * NT 4: cversion=2 * NT2K: cversion=3 */ - if ((driver->version = get_correct_cversion(architecture, - driver->driverpath, user, &err)) == -1) + if ((driver->version = get_correct_cversion(architecture, driver->driverpath, user, &err)) == -1) return err; return WERR_OK; @@ -1747,7 +1759,8 @@ static WERROR get_a_printer_driver_3(NT_PRINTER_DRIVER_INFO_LEVEL_3 **info_ptr, driver.defaultdatatype); i=0; - while (len < dbuf.dsize) { + while (len < dbuf.dsize) + { fstring *tddfs; tddfs = (fstring *)Realloc(driver.dependentfiles, @@ -1762,13 +1775,15 @@ static WERROR get_a_printer_driver_3(NT_PRINTER_DRIVER_INFO_LEVEL_3 **info_ptr, &driver.dependentfiles[i]); i++; } + if (driver.dependentfiles != NULL) fstrcpy(driver.dependentfiles[i], ""); SAFE_FREE(dbuf.dptr); - if (len != dbuf.dsize) { - SAFE_FREE(driver.dependentfiles); + if (len != dbuf.dsize) + { + SAFE_FREE(driver.dependentfiles); return get_a_printer_driver_3_default(info_ptr, drivername, arch); } @@ -1950,22 +1965,52 @@ static int pack_devicemode(NT_DEVICEMODE *nt_devmode, char *buf, int buflen) } /**************************************************************************** -****************************************************************************/ -static int pack_specifics(NT_PRINTER_PARAM *param, char *buf, int buflen) + Pack all values in all printer keys + ***************************************************************************/ + +static int pack_values(NT_PRINTER_DATA *data, char *buf, int buflen) { - int len = 0; + int len = 0; + int i, j; + REGISTRY_VALUE *val; + REGVAL_CTR *val_ctr; + pstring path; + int num_values; - while (param != NULL) { - len += tdb_pack(buf+len, buflen-len, "pfdB", - param, - param->value, - param->type, - param->data_len, - param->data); - param=param->next; + if ( !data ) + return 0; + + /* loop over all keys */ + + for ( i=0; inum_keys; i++ ) + { + val_ctr = &data->keys[i].values; + num_values = regval_ctr_numvals( val_ctr ); + + /* loop over all values */ + + for ( j=0; j\ */ + + val = regval_ctr_specific_value( val_ctr, j ); + pstrcpy( path, data->keys[i].name ); + pstrcat( path, "\\" ); + pstrcat( path, regval_name(val) ); + + len += tdb_pack(buf+len, buflen-len, "pPdB", + val, + path, + regval_type(val), + regval_size(val), + regval_data_p(val) ); + } + } - len += tdb_pack(buf+len, buflen-len, "p", param); + /* terminator */ + + len += tdb_pack(buf+len, buflen-len, "p", NULL); return len; } @@ -2059,7 +2104,7 @@ static WERROR update_a_printer_2(NT_PRINTER_INFO_LEVEL_2 *info) len += pack_devicemode(info->devmode, buf+len, buflen-len); - len += pack_specifics(info->specific, buf+len, buflen-len); + len += pack_values( &info->data, buf+len, buflen-len ); if (buflen != len) { char *tb; @@ -2098,89 +2143,6 @@ done: } -/**************************************************************************** -****************************************************************************/ -void add_a_specific_param(NT_PRINTER_INFO_LEVEL_2 *info_2, NT_PRINTER_PARAM **param) -{ - NT_PRINTER_PARAM *current; - - DEBUG(108,("add_a_specific_param\n")); - - (*param)->next=NULL; - - if (info_2->specific == NULL) - { - info_2->specific=*param; - } - else - { - current=info_2->specific; - while (current->next != NULL) { - current=current->next; - } - current->next=*param; - } - - *param = NULL; -} - -/**************************************************************************** -****************************************************************************/ -BOOL unlink_specific_param_if_exist(NT_PRINTER_INFO_LEVEL_2 *info_2, NT_PRINTER_PARAM *param) -{ - NT_PRINTER_PARAM *current; - NT_PRINTER_PARAM *previous; - - current=info_2->specific; - previous=current; - - if (current==NULL) return (False); - - if ( !strcmp(current->value, param->value) && - (strlen(current->value)==strlen(param->value)) ) { - DEBUG(109,("deleting first value\n")); - info_2->specific=current->next; - SAFE_FREE(current->data); - SAFE_FREE(current); - DEBUG(109,("deleted first value\n")); - return (True); - } - - current=previous->next; - - while ( current!=NULL ) { - if (!strcmp(current->value, param->value) && - strlen(current->value)==strlen(param->value) ) { - DEBUG(109,("deleting current value\n")); - previous->next=current->next; - SAFE_FREE(current->data); - SAFE_FREE(current); - DEBUG(109,("deleted current value\n")); - return(True); - } - - previous=previous->next; - current=current->next; - } - return (False); -} - -/**************************************************************************** - Clean up and deallocate a (maybe partially) allocated NT_PRINTER_PARAM. -****************************************************************************/ -void free_nt_printer_param(NT_PRINTER_PARAM **param_ptr) -{ - NT_PRINTER_PARAM *param = *param_ptr; - - if(param == NULL) - return; - - DEBUG(106,("free_nt_printer_param: deleting param [%s]\n", param->value)); - - SAFE_FREE(param->data); - SAFE_FREE(*param_ptr); -} - /**************************************************************************** Malloc and return an NT devicemode. ****************************************************************************/ @@ -2282,7 +2244,7 @@ void free_nt_devicemode(NT_DEVICEMODE **devmode_ptr) DEBUG(106,("free_nt_devicemode: deleting DEVMODE\n")); - SAFE_FREE(nt_devmode->private); + SAFE_FREE(nt_devmode->private); SAFE_FREE(*devmode_ptr); } @@ -2292,23 +2254,29 @@ void free_nt_devicemode(NT_DEVICEMODE **devmode_ptr) static void free_nt_printer_info_level_2(NT_PRINTER_INFO_LEVEL_2 **info_ptr) { NT_PRINTER_INFO_LEVEL_2 *info = *info_ptr; - NT_PRINTER_PARAM *param_ptr; + NT_PRINTER_DATA *data; + int i; - if(info == NULL) + if ( !info ) return; DEBUG(106,("free_nt_printer_info_level_2: deleting info\n")); free_nt_devicemode(&info->devmode); - for(param_ptr = info->specific; param_ptr; ) { - NT_PRINTER_PARAM *tofree = param_ptr; - - param_ptr = param_ptr->next; - free_nt_printer_param(&tofree); + /* clean up all registry keys */ + + data = &info->data; + for ( i=0; inum_keys; i++ ) + { + SAFE_FREE( data->keys[i].name ); + regval_ctr_destroy( &data->keys[i].values ); } + SAFE_FREE( data->keys ); - SAFE_FREE(*info_ptr); + /* finally the top level structure */ + + SAFE_FREE( *info_ptr ); } @@ -2388,32 +2356,257 @@ static int unpack_devicemode(NT_DEVICEMODE **nt_devmode, char *buf, int buflen) } /**************************************************************************** -****************************************************************************/ -static int unpack_specifics(NT_PRINTER_PARAM **list, char *buf, int buflen) + allocate and initialize a new slot in + ***************************************************************************/ + +static int add_new_printer_key( NT_PRINTER_DATA *data, char *name ) { - int len = 0; - NT_PRINTER_PARAM param, *p; + NT_PRINTER_KEY *d; + int key_index; + + if ( !data || !name ) + return -1; + + /* allocate another slot in the NT_PRINTER_KEY array */ + + d = Realloc( data->keys, sizeof(NT_PRINTER_KEY)*(data->num_keys+1) ); + if ( d ) + data->keys = d; + + key_index = data->num_keys; + + /* initialze new key */ + + data->num_keys++; + data->keys[key_index].name = strdup( name ); + + ZERO_STRUCTP( &data->keys[key_index].values ); + + regval_ctr_init( &data->keys[key_index].values ); + + DEBUG(10,("add_new_printer_key: Inserted new data key [%s]\n", name )); + + return key_index; +} - *list = NULL; +/**************************************************************************** + search for a registry key name in the existing printer data + ***************************************************************************/ + +int lookup_printerkey( NT_PRINTER_DATA *data, char *name ) +{ + int key_index = -1; + int i; + + if ( !data || !name ) + return -1; - while (1) { - len += tdb_unpack(buf+len, buflen-len, "p", &p); - if (!p) break; + DEBUG(12,("lookup_printerkey: Looking for [%s]\n", name)); + /* loop over all existing keys */ + + for ( i=0; inum_keys; i++ ) + { + if ( strcmp(data->keys[i].name, name) == 0 ) { + DEBUG(12,("lookup_printerkey: Found [%s]!\n", name)); + key_index = i; + break; + + } + } + + return key_index; +} + +/**************************************************************************** + ***************************************************************************/ + +WERROR delete_all_printer_data( NT_PRINTER_INFO_LEVEL_2 *p2 ) +{ + WERROR result = WERR_OK; + NT_PRINTER_DATA *data; + int i; + + data = &p2->data; + + for ( i=0; inum_keys; i++ ) + { + DEBUG(8,("delete_all_printer_data: Removed all Printer Data from key [%s]\n", + data->keys[i].name)); + + SAFE_FREE( data->keys[i].name ); + regval_ctr_destroy( &data->keys[i].values ); + } + + SAFE_FREE( data->keys ); + + DEBUG(8,("delete_all_printer_data: Removed all Printer Data from printer [%s]\n", + p2->printername )); + + ZERO_STRUCTP( data ); + + return result; +} + +/**************************************************************************** + ***************************************************************************/ + +WERROR delete_printer_data( NT_PRINTER_INFO_LEVEL_2 *p2, char *key, char *value ) +{ + WERROR result = WERR_OK; + int key_index; + + /* we must have names on non-zero length */ + + if ( !key || !*key|| !value || !*value ) + return WERR_INVALID_NAME; + + /* find the printer key first */ + + key_index = lookup_printerkey( &p2->data, key ); + if ( key_index == -1 ) + key_index = add_new_printer_key( &p2->data, key ); + + if ( key_index == -1 ) + return WERR_NOMEM; + + regval_ctr_delvalue( &p2->data.keys[key_index].values, value ); + + DEBUG(8,("delete_printer_data: Removed key => [%s], value => [%s]\n", + key, value )); + + return result; +} + +/**************************************************************************** + ***************************************************************************/ + +WERROR add_printer_data( NT_PRINTER_INFO_LEVEL_2 *p2, char *key, char *value, + uint32 type, uint8 *data, int real_len ) +{ + WERROR result = WERR_OK; + int key_index; + + /* we must have names on non-zero length */ + + if ( !key || !*key|| !value || !*value ) + return WERR_INVALID_NAME; + + /* find the printer key first */ + + key_index = lookup_printerkey( &p2->data, key ); + if ( key_index == -1 ) + key_index = add_new_printer_key( &p2->data, key ); + + if ( key_index == -1 ) + return WERR_NOMEM; + + regval_ctr_addvalue( &p2->data.keys[key_index].values, value, + type, data, real_len ); + + DEBUG(8,("add_printer_data: Added key => [%s], value => [%s], size => [%d]\n", + key, value, real_len )); + + return result; +} + +/**************************************************************************** + ***************************************************************************/ + +REGISTRY_VALUE* get_printer_data( NT_PRINTER_INFO_LEVEL_2 *p2, char *key, char *value ) +{ + int key_index; + + if ( (key_index = lookup_printerkey( &p2->data, key )) == -1 ) + return NULL; + + DEBUG(8,("get_printer_data: Attempting to lookup key => [%s], value => [%s]\n", + key, value )); + + return regval_ctr_getvalue( &p2->data.keys[key_index].values, value ); +} + +/**************************************************************************** + Unpack a list of registry values frem the TDB + ***************************************************************************/ + +static int unpack_values(NT_PRINTER_DATA *printer_data, char *buf, int buflen) +{ + int len = 0; + uint32 type; + pstring string, valuename, keyname; + char *str; + int size; + uint8 *data_p; + REGISTRY_VALUE *regval_p; + int key_index; + + /* add the "PrinterDriverData" key first for performance reasons */ + + add_new_printer_key( printer_data, SPOOL_PRINTERDATA_KEY ); + + /* loop and unpack the rest of the registry values */ + + while ( True ) + { + + /* check to see if there are any more registry values */ + + len += tdb_unpack(buf+len, buflen-len, "p", ®val_p); + if ( !regval_p ) + break; + + /* unpack the next regval */ + len += tdb_unpack(buf+len, buflen-len, "fdB", - param.value, - ¶m.type, - ¶m.data_len, - ¶m.data); - param.next = *list; - *list = memdup(¶m, sizeof(param)); - - DEBUG(8,("specific: [%s], len: %d\n", param.value, param.data_len)); + string, + &type, + &size, + &data_p); + + /* + * break of the keyname from the value name. + * Should only be one '\' in the string returned. + */ + + str = strchr( string, '\\'); + + /* Put in "PrinterDriverData" is no key specified */ + + if ( !str ) { + pstrcpy( keyname, SPOOL_PRINTERDATA_KEY ); + pstrcpy( valuename, string ); + } + else { + *str = '\0'; + pstrcpy( keyname, string ); + pstrcpy( valuename, str+1 ); + } + + /* see if we need a new key */ + + if ( (key_index=lookup_printerkey( printer_data, keyname )) == -1 ) + key_index = add_new_printer_key( printer_data, keyname ); + + if ( key_index == -1 ) { + DEBUG(0,("unpack_values: Failed to allocate a new key [%s]!\n", + keyname)); + break; + } + + /* add the new value */ + + regval_ctr_addvalue( &printer_data->keys[key_index].values, valuename, type, data_p, size ); + + DEBUG(8,("specific: [%s\\%s], len: %d\n", keyname, valuename, size)); } return len; } +/**************************************************************************** + ***************************************************************************/ + static void map_to_os2_driver(fstring drivername) { static BOOL initialised=False; @@ -2647,10 +2840,10 @@ static WERROR get_a_printer_2(NT_PRINTER_INFO_LEVEL_2 **info_ptr, fstring sharen info.devmode = construct_nt_devicemode(printername); } - len += unpack_specifics(&info.specific,dbuf.dptr+len, dbuf.dsize-len); + len += unpack_values( &info.data, dbuf.dptr+len, dbuf.dsize-len ); /* This will get the current RPC talloc context, but we should be - passing this as a parameter... fixme... JRA ! */ + passing this as a parameter... fixme... JRA ! */ nt_printing_getsec(get_talloc_ctx(), sharename, &info.secdesc_buf); @@ -2837,34 +3030,31 @@ WERROR mod_a_printer(NT_PRINTER_INFO_LEVEL printer, uint32 level) Initialize printer devmode & data with previously saved driver init values. ****************************************************************************/ -static BOOL set_driver_init_2(NT_PRINTER_INFO_LEVEL_2 *info_ptr) +static BOOL set_driver_init_2( NT_PRINTER_INFO_LEVEL_2 *info_ptr ) { int len = 0; pstring key; TDB_DATA kbuf, dbuf; - NT_PRINTER_PARAM *current; NT_PRINTER_INFO_LEVEL_2 info; + + ZERO_STRUCT(info); + /* - * Delete any printer data 'specifics' already set. When called for driver + * Delete any printer data 'values' already set. When called for driver * replace, there will generally be some, but during an add printer, there * should not be any (if there are delete them). */ - while ( (current=info_ptr->specific) != NULL ) { - info_ptr->specific=current->next; - SAFE_FREE(current->data); - SAFE_FREE(current); - } - - ZERO_STRUCT(info); - + + delete_all_printer_data( info_ptr ); + slprintf(key, sizeof(key)-1, "%s%s", DRIVER_INIT_PREFIX, info_ptr->drivername); kbuf.dptr = key; kbuf.dsize = strlen(key)+1; dbuf = tdb_fetch(tdb_drivers, kbuf); - if (!dbuf.dptr) { + if (!dbuf.dptr) { /* * When changing to a driver that has no init info in the tdb, remove * the previous drivers init info and leave the new on blank. @@ -2872,16 +3062,18 @@ static BOOL set_driver_init_2(NT_PRINTER_INFO_LEVEL_2 *info_ptr) free_nt_devicemode(&info_ptr->devmode); return False; } - + /* * Get the saved DEVMODE.. */ + len += unpack_devicemode(&info.devmode,dbuf.dptr+len, dbuf.dsize-len); /* * The saved DEVMODE contains the devicename from the printer used during * the initialization save. Change it to reflect the new printer. */ + ZERO_STRUCT(info.devmode->devicename); fstrcpy(info.devmode->devicename, info_ptr->printername); @@ -2897,45 +3089,20 @@ static BOOL set_driver_init_2(NT_PRINTER_INFO_LEVEL_2 *info_ptr) * --jerry */ -#if 1 /* JERRY */ - /* - * Bind the saved DEVMODE to the new the printer. - */ + /* Bind the saved DEVMODE to the new the printer */ + free_nt_devicemode(&info_ptr->devmode); info_ptr->devmode = info.devmode; -#else - /* copy the entire devmode if we currently don't have one */ - - if (!info_ptr->devmode) { - DEBUG(10,("set_driver_init_2: Current Devmode is NULL. Copying entire Device Mode\n")); - info_ptr->devmode = info.devmode; - } - else { - /* only set the necessary fields */ - DEBUG(10,("set_driver_init_2: Setting driverversion [0x%x] and private data [0x%x]\n", - info.devmode->driverversion, info.devmode->driverextra)); - - info_ptr->devmode->driverversion = info.devmode->driverversion; - - SAFE_FREE(info_ptr->devmode->private); - info_ptr->devmode->private = NULL; - - if (info.devmode->driverversion) - info_ptr->devmode->private = memdup(info.devmode->private, info.devmode->driverversion); - - free_nt_devicemode(&info.devmode); - } -#endif DEBUG(10,("set_driver_init_2: Set printer [%s] init DEVMODE for driver [%s]\n", info_ptr->printername, info_ptr->drivername)); - /* - * Add the printer data 'specifics' to the new printer - */ - len += unpack_specifics(&info_ptr->specific,dbuf.dptr+len, dbuf.dsize-len); + /* Add the printer data 'values' to the new printer */ + + len += unpack_values( &info_ptr->data, dbuf.dptr+len, dbuf.dsize-len ); + SAFE_FREE(dbuf.dptr); @@ -2956,7 +3123,7 @@ BOOL set_driver_init(NT_PRINTER_INFO_LEVEL *printer, uint32 level) switch (level) { case 2: - result=set_driver_init_2(printer->info_2); + result = set_driver_init_2(printer->info_2); break; default: @@ -2993,7 +3160,7 @@ BOOL del_driver_init(char *drivername) } /**************************************************************************** - Pack up the DEVMODE and specifics for a printer into a 'driver init' entry + Pack up the DEVMODE and values for a printer into a 'driver init' entry in the tdb. Note: this is different from the driver entry and the printer entry. There should be a single driver init entry for each driver regardless of whether it was installed from NT or 2K. Technically, they should be @@ -3014,7 +3181,7 @@ static uint32 update_driver_init_2(NT_PRINTER_INFO_LEVEL_2 *info) len = 0; len += pack_devicemode(info->devmode, buf+len, buflen-len); - len += pack_specifics(info->specific, buf+len, buflen-len); + len += pack_values( &info->data, buf+len, buflen-len ); if (buflen != len) { char *tb; @@ -3045,14 +3212,14 @@ done: SAFE_FREE(buf); - DEBUG(10,("update_driver_init_2: Saved printer [%s] init DEVMODE & specifics for driver [%s]\n", + DEBUG(10,("update_driver_init_2: Saved printer [%s] init DEVMODE & values for driver [%s]\n", info->sharename, info->drivername)); return ret; } /**************************************************************************** - Update (i.e. save) the driver init info (DEVMODE and specifics) for a printer + Update (i.e. save) the driver init info (DEVMODE and values) for a printer ****************************************************************************/ uint32 update_driver_init(NT_PRINTER_INFO_LEVEL printer, uint32 level) @@ -3076,154 +3243,6 @@ uint32 update_driver_init(NT_PRINTER_INFO_LEVEL printer, uint32 level) return result; } -/**************************************************************************** - Convert the printer data value, a REG_BINARY array, into an initialization - DEVMODE. Note: the array must be parsed as if it was a DEVMODE in an rpc... - got to keep the endians happy :). -****************************************************************************/ - -static BOOL convert_driver_init(NT_PRINTER_PARAM *param, TALLOC_CTX *ctx, NT_DEVICEMODE *nt_devmode) -{ - BOOL result = False; - prs_struct ps; - DEVICEMODE devmode; - - ZERO_STRUCT(devmode); - - prs_init(&ps, 0, ctx, UNMARSHALL); - ps.data_p = (char *)param->data; - ps.buffer_size = param->data_len; - - if (spoolss_io_devmode("phantom DEVMODE", &ps, 0, &devmode)) - result = convert_devicemode("", &devmode, &nt_devmode); - else - DEBUG(10,("convert_driver_init: error parsing DEVMODE\n")); - - return result; -} - -/**************************************************************************** - Set the DRIVER_INIT info in the tdb. Requires Win32 client code that: - - 1. Use the driver's config DLL to this UNC printername and: - a. Call DrvPrintEvent with PRINTER_EVENT_INITIALIZE - b. Call DrvConvertDevMode with CDM_DRIVER_DEFAULT to get default DEVMODE - 2. Call SetPrinterData with the 'magic' key and the DEVMODE as data. - - The last step triggers saving the "driver initialization" information for - this printer into the tdb. Later, new printers that use this driver will - have this initialization information bound to them. This simulates the - driver initialization, as if it had run on the Samba server (as it would - have done on NT). - - The Win32 client side code requirement sucks! But until we can run arbitrary - Win32 printer driver code on any Unix that Samba runs on, we are stuck with it. - - It would have been easier to use SetPrinter because all the UNMARSHALLING of - the DEVMODE is done there, but 2K/XP clients do not set the DEVMODE... think - about it and you will realize why. JRR 010720 -****************************************************************************/ - -static WERROR save_driver_init_2(NT_PRINTER_INFO_LEVEL *printer, NT_PRINTER_PARAM *param) -{ - WERROR status = WERR_OK; - TALLOC_CTX *ctx = NULL; - NT_DEVICEMODE *nt_devmode = NULL; - NT_DEVICEMODE *tmp_devmode = printer->info_2->devmode; - - /* - * When the DEVMODE is already set on the printer, don't try to unpack it. - */ - - if (!printer->info_2->devmode && param->data_len) { - /* - * Set devmode on printer info, so entire printer initialization can be - * saved to tdb. - */ - - if ((ctx = talloc_init()) == NULL) - return WERR_NOMEM; - - if ((nt_devmode = (NT_DEVICEMODE*)malloc(sizeof(NT_DEVICEMODE))) == NULL) { - status = WERR_NOMEM; - goto done; - } - - ZERO_STRUCTP(nt_devmode); - - /* - * The DEVMODE is held in the 'data' component of the param in raw binary. - * Convert it to to a devmode structure - */ - if (!convert_driver_init(param, ctx, nt_devmode)) { - DEBUG(10,("save_driver_init_2: error converting DEVMODE\n")); - status = WERR_INVALID_PARAM; - goto done; - } - - printer->info_2->devmode = nt_devmode; - } - - /* - * Pack up and add (or update) the DEVMODE and any current printer data to - * a 'driver init' element in the tdb - * - */ - - if (update_driver_init(*printer, 2)!=0) { - DEBUG(10,("save_driver_init_2: error updating DEVMODE\n")); - status = WERR_NOMEM; - goto done; - } - - /* - * If driver initialization info was successfully saved, set the current - * printer to match it. This allows initialization of the current printer - * as well as the driver. - */ - status = mod_a_printer(*printer, 2); - if (!W_ERROR_IS_OK(status)) { - DEBUG(10,("save_driver_init_2: error setting DEVMODE on printer [%s]\n", - printer->info_2->printername)); - } - -#if 0 /* JERRY */ - srv_spoolss_sendnotify(p, handle); -#endif - - done: - talloc_destroy(ctx); - if (nt_devmode) - SAFE_FREE(nt_devmode->private); - SAFE_FREE(nt_devmode); - printer->info_2->devmode = tmp_devmode; - - return status; -} - -/**************************************************************************** - Update the driver init info (DEVMODE and specifics) for a printer -****************************************************************************/ - -WERROR save_driver_init(NT_PRINTER_INFO_LEVEL *printer, uint32 level, NT_PRINTER_PARAM *param) -{ - WERROR status = WERR_OK; - - switch (level) - { - case 2: - { - status=save_driver_init_2(printer, param); - break; - } - default: - status=WERR_UNKNOWN_LEVEL; - break; - } - - return status; -} - /**************************************************************************** Get a NT_PRINTER_INFO_LEVEL struct. It returns malloced memory. ****************************************************************************/ @@ -3752,7 +3771,7 @@ static WERROR delete_printer_driver_internal( NT_PRINTER_DRIVER_INFO_LEVEL_3 *i, { pstring key; fstring arch; - TDB_DATA kbuf; + TDB_DATA kbuf, dbuf; NT_PRINTER_DRIVER_INFO_LEVEL ctr; /* delete the tdb data first */ @@ -3770,8 +3789,20 @@ static WERROR delete_printer_driver_internal( NT_PRINTER_DRIVER_INFO_LEVEL_3 *i, kbuf.dptr=key; kbuf.dsize=strlen(key)+1; + /* check if the driver actually exists for this environment */ + + dbuf = tdb_fetch( tdb_drivers, kbuf ); + if ( !dbuf.dptr ) { + DEBUG(8,("delete_printer_driver_internal: Driver unknown [%s]\n", key)); + return WERR_UNKNOWN_PRINTER_DRIVER; + } + + SAFE_FREE( dbuf.dptr ); + + /* ok... the driver exists so the delete should return success */ + if (tdb_delete(tdb_drivers, kbuf) == -1) { - DEBUG (0,("delete_printer_driver: fail to delete %s!\n", key)); + DEBUG (0,("delete_printer_driver_internal: fail to delete %s!\n", key)); return WERR_ACCESS_DENIED; } @@ -3784,8 +3815,8 @@ static WERROR delete_printer_driver_internal( NT_PRINTER_DRIVER_INFO_LEVEL_3 *i, if ( delete_files ) delete_driver_files( i, user ); - DEBUG(5,("delete_printer_driver: [%s] driver delete successful.\n", - i->name)); + + DEBUG(5,("delete_printer_driver_internal: driver delete successful [%s]\n", key)); return WERR_OK; } @@ -3798,99 +3829,33 @@ static WERROR delete_printer_driver_internal( NT_PRINTER_DRIVER_INFO_LEVEL_3 *i, WERROR delete_printer_driver( NT_PRINTER_DRIVER_INFO_LEVEL_3 *i, struct current_user *user, uint32 version, BOOL delete_files ) { - int ver; WERROR err; - /* see if we should delete all versions of this driver */ + /* + * see if we should delete all versions of this driver + * (DRIVER_ANY_VERSION uis only set for "Windows NT x86") + */ - if ( version == DRIVER_ANY_VERSION ) { - for ( ver=0; verspecific; - - while (param != NULL && i < param_index) { - param=param->next; - i++; } - if (param == NULL) - return False; - - /* exited because it exist */ - *type=param->type; - StrnCpy(value, param->value, sizeof(fstring)-1); - *data=(uint8 *)malloc(param->data_len*sizeof(uint8)); - if(*data == NULL) - return False; - ZERO_STRUCTP(*data); - memcpy(*data, param->data, param->data_len); - *len=param->data_len; - return True; -} - -/**************************************************************************** -****************************************************************************/ -BOOL get_specific_param(NT_PRINTER_INFO_LEVEL printer, uint32 level, - fstring value, uint8 **data, uint32 *type, uint32 *len) -{ - /* right now that's enough ! */ - NT_PRINTER_PARAM *param; - - DEBUG(10, ("get_specific_param\n")); - - param=printer.info_2->specific; - - while (param != NULL) - { -#if 1 /* JRA - I think this should be case insensitive.... */ - if ( strequal(value, param->value) -#else - if ( !strcmp(value, param->value) -#endif - && strlen(value)==strlen(param->value)) - break; - - param=param->next; - } + /* just delete what they asked for */ - if (param != NULL) - { - DEBUGADD(10, ("get_specific_param: found one param\n")); - /* exited because it exist */ - *type=param->type; - - *data=(uint8 *)malloc(param->data_len*sizeof(uint8)); - if(*data == NULL) - return False; - memcpy(*data, param->data, param->data_len); - *len=param->data_len; - - DEBUGADD(10, ("get_specific_param: exit true\n")); - return (True); - } - DEBUGADD(10, ("get_specific_param: exit false\n")); - return (False); + return delete_printer_driver_internal(i, user, version, delete_files ); } /**************************************************************************** @@ -4328,76 +4293,3 @@ BOOL print_time_access_check(int snum) return ok; } -#if 0 /* JERRY - not used */ -/**************************************************************************** - Attempt to write a default device. -*****************************************************************************/ - -WERROR printer_write_default_dev(int snum, const PRINTER_DEFAULT *printer_default) -{ - NT_PRINTER_INFO_LEVEL *printer = NULL; - WERROR result; - - /* - * Don't bother if no default devicemode was sent. - */ - - if (printer_default->devmode_cont.devmode == NULL) - return WERR_OK; - - result = get_a_printer(&printer, 2, lp_servicename(snum)); - if (!W_ERROR_IS_OK(result)) return result; - - /* - * Just ignore it if we already have a devmode. - */ -#if 0 - if (printer->info_2->devmode != NULL) - goto done; -#endif - /* - * We don't have a devicemode and we're trying to write - * one. Check we have the access needed. - */ - DEBUG(5,("printer_write_default_dev: access: %x\n", printer_default->access_required)); - - if ( (printer_default->access_required & PRINTER_ACCESS_ADMINISTER) != - PRINTER_ACCESS_ADMINISTER) { - DEBUG(5,("printer_write_default_dev: invalid request access to update: %x\n", printer_default->access_required)); - result = WERR_ACCESS_DENIED; - goto done; - } - - if (!print_access_check(NULL, snum, PRINTER_ACCESS_ADMINISTER)) { - DEBUG(5,("printer_write_default_dev: Access denied for printer %s\n", - lp_servicename(snum) )); - result = WERR_ACCESS_DENIED; - /*result = NT_STATUS_NO_PROBLEMO;*/ - goto done; - } - - DEBUG(5,("printer_write_default_dev: updating, check OK.\n")); - - /* - * Convert the on the wire devicemode format to the internal one. - */ - - if (!convert_devicemode(printer->info_2->printername, - printer_default->devmode_cont.devmode, - &printer->info_2->devmode)) { - result = WERR_NOMEM; - goto done; - } - - /* - * Finally write back to the tdb. - */ - - result = mod_a_printer(*printer, 2); - - done: - - free_a_printer(&printer, 2); - return result; -} -#endif /* JERRY */ -- cgit