diff options
Diffstat (limited to 'source/printing/nt_printing.c')
-rw-r--r-- | source/printing/nt_printing.c | 1488 |
1 files changed, 579 insertions, 909 deletions
diff --git a/source/printing/nt_printing.c b/source/printing/nt_printing.c index 58eba9d87e8..768373e5ad3 100644 --- a/source/printing/nt_printing.c +++ b/source/printing/nt_printing.c @@ -3,7 +3,6 @@ * RPC Pipe client / server routines * Copyright (C) Andrew Tridgell 1992-2000, * Copyright (C) Jean François Micouleau 1998-2000. - * Copyright (C) Gerald Carter 2002. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -315,20 +314,11 @@ BOOL nt_printing_init(void) update_c_setprinter(True); - /* + /* * register callback to handle updating printers as new - * drivers are installed - */ - - message_register( MSG_PRINTER_DRVUPGRADE, do_drv_upgrade_printer ); - - /* - * register callback to handle updating printer data - * when a driver is initialized + * drivers are installed */ - - message_register( MSG_PRINTERDATA_INIT_RESET, reset_all_printerdata ); - + message_register(MSG_PRINTER_DRVUPGRADE, do_drv_upgrade_printer); return True; } @@ -417,7 +407,7 @@ BOOL get_a_builtin_ntform(UNISTR2 *uni_formname,nt_forms_struct *form) { int i,count; fstring form_name; - unistr2_to_ascii(form_name, uni_formname, sizeof(form_name)-1); + unistr2_to_dos(form_name, uni_formname, sizeof(form_name)-1); DEBUGADD(6,("Looking for builtin form %s \n", form_name)); count = sizeof(default_forms) / sizeof(default_forms[0]); for (i=0;i<count;i++) { @@ -445,29 +435,25 @@ 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++; } @@ -494,6 +480,7 @@ int write_ntforms(nt_forms_struct **list, int number) (*list)[i].bottom); if (len > sizeof(buf)) break; slprintf(key, sizeof(key)-1, "%s%s", FORMS_PREFIX, (*list)[i].name); + dos_to_unix(key); /* Convert key to unix-codepage */ kbuf.dsize = strlen(key)+1; kbuf.dptr = key; dbuf.dsize = len; @@ -522,7 +509,7 @@ BOOL add_a_form(nt_forms_struct **list, const FORM *form, int *count) update=False; - unistr2_to_ascii(form_name, &form->name, sizeof(form_name)-1); + unistr2_to_dos(form_name, &form->name, sizeof(form_name)-1); for (n=0; n<*count; n++) { if (!strncmp((*list)[n].name, form_name, strlen(form_name))) { DEBUG(103, ("NT workaround, [%s] already exists\n", form_name)); @@ -537,7 +524,7 @@ BOOL add_a_form(nt_forms_struct **list, const FORM *form, int *count) return False; } *list = tl; - unistr2_to_ascii((*list)[n].name, &form->name, sizeof((*list)[n].name)-1); + unistr2_to_dos((*list)[n].name, &form->name, sizeof((*list)[n].name)-1); (*count)++; } @@ -564,7 +551,7 @@ BOOL delete_a_form(nt_forms_struct **list, UNISTR2 *del_name, int *count, WERROR *ret = WERR_OK; - unistr2_to_ascii(form_name, del_name, sizeof(form_name)-1); + unistr2_to_dos(form_name, del_name, sizeof(form_name)-1); for (n=0; n<*count; n++) { if (!strncmp((*list)[n].name, form_name, strlen(form_name))) { @@ -580,6 +567,7 @@ BOOL delete_a_form(nt_forms_struct **list, UNISTR2 *del_name, int *count, WERROR } slprintf(key, sizeof(key)-1, "%s%s", FORMS_PREFIX, (*list)[n].name); + dos_to_unix(key); /* Convert key to unix-codepage */ kbuf.dsize = strlen(key)+1; kbuf.dptr = key; if (tdb_delete(tdb_forms, kbuf) != 0) { @@ -597,7 +585,7 @@ void update_a_form(nt_forms_struct **list, const FORM *form, int count) { int n=0; fstring form_name; - unistr2_to_ascii(form_name, &(form->name), sizeof(form_name)-1); + unistr2_to_dos(form_name, &(form->name), sizeof(form_name)-1); DEBUG(106, ("[%s]\n", form_name)); for (n=0; n<count; n++) @@ -976,10 +964,10 @@ static int file_version_is_newer(connection_struct *conn, fstring new_file, DEBUG(6,("file_version_is_newer: Version info not found [%s], use mod time\n", old_file)); use_version = False; - if (fsp->conn->vfs_ops.fstat(fsp, fsp->fd, &st) == -1) goto error_exit; - old_create_time = st.st_mtime; - DEBUGADD(6,("file_version_is_newer: mod time = %ld sec\n", old_create_time)); } + if (fsp->conn->vfs_ops.fstat(fsp, fsp->fd, &st) == -1) goto error_exit; + old_create_time = st.st_mtime; + DEBUGADD(6,("file_version_is_newer: mod time = %ld sec\n", old_create_time)); } close_file(fsp, True); @@ -1005,10 +993,10 @@ static int file_version_is_newer(connection_struct *conn, fstring new_file, DEBUG(6,("file_version_is_newer: Version info not found [%s], use mod time\n", new_file)); use_version = False; - if (fsp->conn->vfs_ops.fstat(fsp, fsp->fd, &st) == -1) goto error_exit; - new_create_time = st.st_mtime; - DEBUGADD(6,("file_version_is_newer: mod time = %ld sec\n", new_create_time)); } + if (fsp->conn->vfs_ops.fstat(fsp, fsp->fd, &st) == -1) goto error_exit; + new_create_time = st.st_mtime; + DEBUGADD(6,("file_version_is_newer: mod time = %ld sec\n", new_create_time)); } close_file(fsp, True); @@ -1052,12 +1040,14 @@ static uint32 get_correct_cversion(fstring architecture, fstring driverpath_in, int cversion; int access_mode; int action; - NTSTATUS nt_status; - pstring driverpath; - DATA_BLOB null_pw; + pstring driverpath; + fstring user_name; + fstring null_pw; files_struct *fsp = NULL; BOOL bad_path; + int ecode; SMB_STRUCT_STAT st; + struct passwd *pass; connection_struct *conn; ZERO_STRUCT(st); @@ -1071,20 +1061,32 @@ static uint32 get_correct_cversion(fstring architecture, fstring driverpath_in, return 0; } + become_root(); + pass = sys_getpwuid(user->uid); + if(pass == NULL) { + DEBUG(0,("get_correct_cversion: Unable to get passwd entry for uid %u\n", + (unsigned int)user->uid )); + unbecome_root(); + *perr = WERR_ACCESS_DENIED; + return -1; + } + /* * Connect to the print$ share under the same account as the user connected * to the rpc pipe. Note we must still be root to do this. */ + fstrcpy(user_name, pass->pw_name ); + DEBUG(10,("get_correct_cversion: uid %d -> user %s\n", (int)user->uid, user_name)); + /* Null password is ok - we are already an authenticated user... */ - null_pw = data_blob(NULL, 0); - become_root(); - conn = make_connection_with_chdir("print$", null_pw, "A:", user->vuid, &nt_status); + *null_pw = '\0'; + conn = make_connection("print$", user_name, null_pw, 0, "A:", user->vuid, &ecode); unbecome_root(); if (conn == NULL) { DEBUG(0,("get_correct_cversion: Unable to connect\n")); - *perr = ntstatus_to_werror(nt_status); + *perr = W_ERROR(ecode); return -1; } @@ -1232,7 +1234,8 @@ 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; @@ -1287,7 +1290,8 @@ 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; @@ -1364,11 +1368,13 @@ BOOL move_driver_to_download_area(NT_PRINTER_DRIVER_INFO_LEVEL driver_abstract, pstring new_dir; pstring old_name; pstring new_name; - DATA_BLOB null_pw; + fstring user_name; + fstring null_pw; connection_struct *conn; - NTSTATUS nt_status; pstring inbuf; pstring outbuf; + struct passwd *pass; + int ecode; int ver = 0; int i; @@ -1388,19 +1394,31 @@ BOOL move_driver_to_download_area(NT_PRINTER_DRIVER_INFO_LEVEL driver_abstract, get_short_archi(architecture, driver->environment); + become_root(); + pass = sys_getpwuid(user->uid); + if(pass == NULL) { + DEBUG(0,("move_driver_to_download_area: Unable to get passwd entry for uid %u\n", + (unsigned int)user->uid )); + unbecome_root(); + return False; + } + /* * Connect to the print$ share under the same account as the user connected to the rpc pipe. * Note we must be root to do this. */ - become_root(); - null_pw = data_blob(NULL, 0); - conn = make_connection_with_chdir("print$", null_pw, "A:", user->vuid, &nt_status); + fstrcpy(user_name, pass->pw_name ); + DEBUG(10,("move_driver_to_download_area: uid %d -> user %s\n", (int)user->uid, user_name)); + + /* Null password is ok - we are already an authenticated user... */ + *null_pw = '\0'; + conn = make_connection("print$", user_name, null_pw, 0, "A:", user->vuid, &ecode); unbecome_root(); if (conn == NULL) { DEBUG(0,("move_driver_to_download_area: Unable to connect\n")); - *perr = ntstatus_to_werror(nt_status); + *perr = W_ERROR(ecode); return False; } @@ -1409,7 +1427,7 @@ BOOL move_driver_to_download_area(NT_PRINTER_DRIVER_INFO_LEVEL driver_abstract, */ if (!become_user(conn, conn->vuid)) { - DEBUG(0,("move_driver_to_download_area: Can't become user!\n")); + DEBUG(0,("move_driver_to_download_area: Can't become user %s\n", user_name )); return False; } @@ -1616,6 +1634,7 @@ static uint32 add_a_printer_driver_3(NT_PRINTER_DRIVER_INFO_LEVEL_3 *driver) } slprintf(key, sizeof(key)-1, "%s%s/%d/%s", DRIVERS_PREFIX, architecture, driver->cversion, driver->name); + dos_to_unix(key); /* Convert key to unix-codepage */ DEBUG(5,("add_a_printer_driver_3: Adding driver with key %s\n", key )); @@ -1696,13 +1715,13 @@ static uint32 add_a_printer_driver_6(NT_PRINTER_DRIVER_INFO_LEVEL_6 *driver) /**************************************************************************** ****************************************************************************/ -static WERROR get_a_printer_driver_3_default(NT_PRINTER_DRIVER_INFO_LEVEL_3 **info_ptr, fstring driver, fstring arch) +static WERROR get_a_printer_driver_3_default(NT_PRINTER_DRIVER_INFO_LEVEL_3 **info_ptr, fstring in_prt, fstring in_arch) { NT_PRINTER_DRIVER_INFO_LEVEL_3 info; ZERO_STRUCT(info); - fstrcpy(info.name, driver); + fstrcpy(info.name, in_prt); fstrcpy(info.defaultdatatype, "RAW"); fstrcpy(info.driverpath, ""); @@ -1723,7 +1742,7 @@ static WERROR get_a_printer_driver_3_default(NT_PRINTER_DRIVER_INFO_LEVEL_3 **in /**************************************************************************** ****************************************************************************/ -static WERROR get_a_printer_driver_3(NT_PRINTER_DRIVER_INFO_LEVEL_3 **info_ptr, fstring drivername, fstring arch, uint32 version) +static WERROR get_a_printer_driver_3(NT_PRINTER_DRIVER_INFO_LEVEL_3 **info_ptr, fstring in_prt, fstring in_arch, uint32 version) { NT_PRINTER_DRIVER_INFO_LEVEL_3 driver; TDB_DATA kbuf, dbuf; @@ -1734,19 +1753,21 @@ static WERROR get_a_printer_driver_3(NT_PRINTER_DRIVER_INFO_LEVEL_3 **info_ptr, ZERO_STRUCT(driver); - get_short_archi(architecture, arch); + get_short_archi(architecture, in_arch); - DEBUG(8,("get_a_printer_driver_3: [%s%s/%d/%s]\n", DRIVERS_PREFIX, architecture, version, drivername)); + DEBUG(8,("get_a_printer_driver_3: [%s%s/%d/%s]\n", DRIVERS_PREFIX, architecture, version, in_prt)); - slprintf(key, sizeof(key)-1, "%s%s/%d/%s", DRIVERS_PREFIX, architecture, version, drivername); + slprintf(key, sizeof(key)-1, "%s%s/%d/%s", DRIVERS_PREFIX, architecture, version, in_prt); kbuf.dptr = key; kbuf.dsize = strlen(key)+1; dbuf = tdb_fetch(tdb_drivers, kbuf); - if (!dbuf.dptr) - return WERR_UNKNOWN_PRINTER_DRIVER; - +#if 0 + if (!dbuf.dptr) return get_a_printer_driver_3_default(info_ptr, in_prt, in_arch); +#else + if (!dbuf.dptr) return WERR_ACCESS_DENIED; +#endif len += tdb_unpack(dbuf.dptr, dbuf.dsize, "dffffffff", &driver.cversion, driver.name, @@ -1759,8 +1780,7 @@ 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, @@ -1775,17 +1795,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); + return get_a_printer_driver_3_default(info_ptr, in_prt, in_arch); } *info_ptr = (NT_PRINTER_DRIVER_INFO_LEVEL_3 *)memdup(&driver, sizeof(driver)); @@ -1864,7 +1882,7 @@ static uint32 dump_a_printer_driver(NT_PRINTER_DRIVER_INFO_LEVEL driver, uint32 NT_PRINTER_DRIVER_INFO_LEVEL_3 *info3; int i; - DEBUG(20,("Dumping printer driver at level [%d]\n", level)); + DEBUG(106,("Dumping printer driver at level [%d]\n", level)); switch (level) { @@ -1875,19 +1893,19 @@ static uint32 dump_a_printer_driver(NT_PRINTER_DRIVER_INFO_LEVEL driver, uint32 else { info3=driver.info_3; - DEBUGADD(20,("version:[%d]\n", info3->cversion)); - DEBUGADD(20,("name:[%s]\n", info3->name)); - DEBUGADD(20,("environment:[%s]\n", info3->environment)); - DEBUGADD(20,("driverpath:[%s]\n", info3->driverpath)); - DEBUGADD(20,("datafile:[%s]\n", info3->datafile)); - DEBUGADD(20,("configfile:[%s]\n", info3->configfile)); - DEBUGADD(20,("helpfile:[%s]\n", info3->helpfile)); - DEBUGADD(20,("monitorname:[%s]\n", info3->monitorname)); - DEBUGADD(20,("defaultdatatype:[%s]\n", info3->defaultdatatype)); + DEBUGADD(106,("version:[%d]\n", info3->cversion)); + DEBUGADD(106,("name:[%s]\n", info3->name)); + DEBUGADD(106,("environment:[%s]\n", info3->environment)); + DEBUGADD(106,("driverpath:[%s]\n", info3->driverpath)); + DEBUGADD(106,("datafile:[%s]\n", info3->datafile)); + DEBUGADD(106,("configfile:[%s]\n", info3->configfile)); + DEBUGADD(106,("helpfile:[%s]\n", info3->helpfile)); + DEBUGADD(106,("monitorname:[%s]\n", info3->monitorname)); + DEBUGADD(106,("defaultdatatype:[%s]\n", info3->defaultdatatype)); for (i=0; info3->dependentfiles && *info3->dependentfiles[i]; i++) { - DEBUGADD(20,("dependentfile:[%s]\n", + DEBUGADD(106,("dependentfile:[%s]\n", info3->dependentfiles[i])); } result=0; @@ -1895,7 +1913,7 @@ static uint32 dump_a_printer_driver(NT_PRINTER_DRIVER_INFO_LEVEL driver, uint32 break; } default: - DEBUGADD(20,("dump_a_printer_driver: Level %u not implemented\n", (unsigned int)level)); + DEBUGADD(106,("dump_a_printer_driver: Level %u not implemented\n", (unsigned int)level)); result=1; break; } @@ -1905,7 +1923,7 @@ static uint32 dump_a_printer_driver(NT_PRINTER_DRIVER_INFO_LEVEL driver, uint32 /**************************************************************************** ****************************************************************************/ -int pack_devicemode(NT_DEVICEMODE *nt_devmode, char *buf, int buflen) +static int pack_devicemode(NT_DEVICEMODE *nt_devmode, char *buf, int buflen) { int len = 0; @@ -1965,52 +1983,22 @@ int pack_devicemode(NT_DEVICEMODE *nt_devmode, char *buf, int buflen) } /**************************************************************************** - Pack all values in all printer keys - ***************************************************************************/ - -static int pack_values(NT_PRINTER_DATA *data, char *buf, int buflen) +****************************************************************************/ +static int pack_specifics(NT_PRINTER_PARAM *param, char *buf, int buflen) { - int len = 0; - int i, j; - REGISTRY_VALUE *val; - REGVAL_CTR *val_ctr; - pstring path; - int num_values; - - if ( !data ) - return 0; + int len = 0; - /* loop over all keys */ - - for ( i=0; i<data->num_keys; i++ ) - { - val_ctr = &data->keys[i].values; - num_values = regval_ctr_numvals( val_ctr ); - - /* loop over all values */ - - for ( j=0; j<num_values; j++ ) - { - /* pathname should be stored as <key>\<value> */ - - 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) ); - } - + while (param != NULL) { + len += tdb_pack(buf+len, buflen-len, "pfdB", + param, + param->value, + param->type, + param->data_len, + param->data); + param=param->next; } - /* terminator */ - - len += tdb_pack(buf+len, buflen-len, "p", NULL); + len += tdb_pack(buf+len, buflen-len, "p", param); return len; } @@ -2027,6 +2015,7 @@ uint32 del_a_printer(char *sharename) TDB_DATA kbuf; slprintf(key, sizeof(key)-1, "%s%s", PRINTERS_PREFIX, sharename); + dos_to_unix(key); /* Convert key to unix-codepage */ kbuf.dptr=key; kbuf.dsize=strlen(key)+1; @@ -2104,7 +2093,7 @@ static WERROR update_a_printer_2(NT_PRINTER_INFO_LEVEL_2 *info) len += pack_devicemode(info->devmode, buf+len, buflen-len); - len += pack_values( &info->data, buf+len, buflen-len ); + len += pack_specifics(info->specific, buf+len, buflen-len); if (buflen != len) { char *tb; @@ -2122,6 +2111,7 @@ static WERROR update_a_printer_2(NT_PRINTER_INFO_LEVEL_2 *info) slprintf(key, sizeof(key)-1, "%s%s", PRINTERS_PREFIX, info->sharename); + dos_to_unix(key); /* Convert key to unix-codepage */ kbuf.dptr = key; kbuf.dsize = strlen(key)+1; @@ -2144,6 +2134,89 @@ 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. ****************************************************************************/ @@ -2244,7 +2317,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); } @@ -2254,35 +2327,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_DATA *data; - int i; + NT_PRINTER_PARAM *param_ptr; - if ( !info ) + if(info == NULL) return; DEBUG(106,("free_nt_printer_info_level_2: deleting info\n")); free_nt_devicemode(&info->devmode); - /* clean up all registry keys */ - - data = &info->data; - for ( i=0; i<data->num_keys; i++ ) - { - SAFE_FREE( data->keys[i].name ); - regval_ctr_destroy( &data->keys[i].values ); + for(param_ptr = info->specific; param_ptr; ) { + NT_PRINTER_PARAM *tofree = param_ptr; + + param_ptr = param_ptr->next; + free_nt_printer_param(&tofree); } - SAFE_FREE( data->keys ); - /* finally the top level structure */ - - SAFE_FREE( *info_ptr ); + SAFE_FREE(*info_ptr); } /**************************************************************************** ****************************************************************************/ -int unpack_devicemode(NT_DEVICEMODE **nt_devmode, char *buf, int buflen) +static int unpack_devicemode(NT_DEVICEMODE **nt_devmode, char *buf, int buflen) { int len = 0; int extra_len = 0; @@ -2356,391 +2423,32 @@ int unpack_devicemode(NT_DEVICEMODE **nt_devmode, char *buf, int buflen) } /**************************************************************************** - allocate and initialize a new slot in - ***************************************************************************/ - -static int add_new_printer_key( NT_PRINTER_DATA *data, char *name ) -{ - 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; -} - -/**************************************************************************** - 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; - - DEBUG(12,("lookup_printerkey: Looking for [%s]\n", name)); - - /* loop over all existing keys */ - - for ( i=0; i<data->num_keys; i++ ) - { - if ( strequal(data->keys[i].name, name) ) { - DEBUG(12,("lookup_printerkey: Found [%s]!\n", name)); - key_index = i; - break; - - } - } - - return key_index; -} - -/**************************************************************************** - ***************************************************************************/ - -uint32 get_printer_subkeys( NT_PRINTER_DATA *data, char* key, fstring **subkeys ) -{ - int i, j; - int key_len; - int num_subkeys = 0; - char *p; - fstring *ptr, *subkeys_ptr = NULL; - fstring subkeyname; - - if ( !data ) - return 0; - - for ( i=0; i<data->num_keys; i++ ) - { - if ( StrnCaseCmp(data->keys[i].name, key, strlen(key)) == 0 ) - { - /* match sure it is a subkey and not the key itself */ - - key_len = strlen( key ); - if ( strlen(data->keys[i].name) == key_len ) - continue; - - /* get subkey path */ - - p = data->keys[i].name + key_len; - if ( *p == '\\' ) - p++; - fstrcpy( subkeyname, p ); - if ( (p = strchr( subkeyname, '\\' )) ) - *p = '\0'; - - /* don't add a key more than once */ - - for ( j=0; j<num_subkeys; j++ ) { - if ( strequal( subkeys_ptr[j], subkeyname ) ) - break; - } - - if ( j != num_subkeys ) - continue; - - /* found a match, so allocate space and copy the name */ - - if ( !(ptr = Realloc( subkeys_ptr, (num_subkeys+2)*sizeof(fstring))) ) { - DEBUG(0,("get_printer_subkeys: Realloc failed for [%d] entries!\n", - num_subkeys+1)); - SAFE_FREE( subkeys ); - return 0; - } - - subkeys_ptr = ptr; - fstrcpy( subkeys_ptr[num_subkeys], subkeyname ); - num_subkeys++; - } - - } - - /* tag of the end */ - - fstrcpy( subkeys_ptr[num_subkeys], "" ); - - *subkeys = subkeys_ptr; - - return num_subkeys; -} - -/**************************************************************************** - ***************************************************************************/ - -WERROR delete_all_printer_data( NT_PRINTER_INFO_LEVEL_2 *p2, char *key ) -{ - NT_PRINTER_DATA *data; - int i; - int removed_keys = 0; - int empty_slot; - - data = &p2->data; - empty_slot = data->num_keys; - - if ( !key ) - return WERR_INVALID_PARAM; - - /* remove all keys */ - - if ( !strlen(key) ) - { - for ( i=0; i<data->num_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 ); - } - - DEBUG(8,("delete_all_printer_data: Removed all Printer Data from printer [%s]\n", - p2->printername )); - - SAFE_FREE( data->keys ); - ZERO_STRUCTP( data ); - - return WERR_OK; - } - - /* remove a specific key (and all subkeys) */ - - for ( i=0; i<data->num_keys; i++ ) - { - if ( StrnCaseCmp( data->keys[i].name, key, strlen(key)) == 0 ) - { - 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 ); - - /* mark the slot as empty */ - - ZERO_STRUCTP( &data->keys[i] ); - } - } - - /* find the first empty slot */ - - for ( i=0; i<data->num_keys; i++ ) { - if ( !data->keys[i].name ) { - empty_slot = i; - removed_keys++; - break; - } - } - - if ( i == data->num_keys ) - /* nothing was removed */ - return WERR_INVALID_PARAM; - - /* move everything down */ - - for ( i=empty_slot+1; i<data->num_keys; i++ ) { - if ( data->keys[i].name ) { - memcpy( &data->keys[empty_slot], &data->keys[i], sizeof(NT_PRINTER_KEY) ); - ZERO_STRUCTP( &data->keys[i] ); - empty_slot++; - removed_keys++; - } - } - - /* update count */ - - data->num_keys -= removed_keys; - - /* sanity check to see if anything is left */ - - if ( !data->num_keys ) - { - DEBUG(8,("delete_all_printer_data: No keys left for printer [%s]\n", p2->printername )); - - SAFE_FREE( data->keys ); - ZERO_STRUCTP( data ); - } - - return WERR_OK; -} - -/**************************************************************************** - ***************************************************************************/ - -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 ) - return WERR_OK; - - 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], type=> [%d], size => [%d]\n", - key, value, type, real_len )); - - return result; -} - -/**************************************************************************** - ***************************************************************************/ - -REGISTRY_VALUE* get_printer_data( NT_PRINTER_INFO_LEVEL_2 *p2, char *key, char *value ) +****************************************************************************/ +static int unpack_specifics(NT_PRINTER_PARAM **list, char *buf, int buflen) { - 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 ); -} + int len = 0; + NT_PRINTER_PARAM param, *p; -/**************************************************************************** - 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 ); + *list = NULL; - /* 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; + while (1) { + len += tdb_unpack(buf+len, buflen-len, "p", &p); + if (!p) break; - /* unpack the next regval */ - len += tdb_unpack(buf+len, buflen-len, "fdB", - string, - &type, - &size, - &data_p); - - /* - * break of the keyname from the value name. - * Should only be one '\' in the string returned. - */ - - str = strrchr( 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 ); + param.value, + ¶m.type, + ¶m.data_len, + ¶m.data); + param.next = *list; + *list = memdup(¶m, sizeof(param)); - DEBUG(8,("specific: [%s:%s], len: %d\n", keyname, valuename, size)); + DEBUG(8,("specific: [%s], len: %d\n", param.value, param.data_len)); } return len; } -/**************************************************************************** - ***************************************************************************/ - static void map_to_os2_driver(fstring drivername) { static BOOL initialised=False; @@ -2767,7 +2475,7 @@ static void map_to_os2_driver(fstring drivername) return; } - lines = file_lines_load(mapfile, &numlines); + lines = file_lines_load(mapfile, &numlines, True); if (numlines == 0) { DEBUG(0,("No entries in OS/2 driver map %s\n",mapfile)); return; @@ -2916,6 +2624,7 @@ static WERROR get_a_printer_2(NT_PRINTER_INFO_LEVEL_2 **info_ptr, fstring sharen ZERO_STRUCT(info); slprintf(key, sizeof(key)-1, "%s%s", PRINTERS_PREFIX, sharename); + dos_to_unix(key); /* Convert key to unix-codepage */ kbuf.dptr = key; kbuf.dsize = strlen(key)+1; @@ -2956,7 +2665,7 @@ static WERROR get_a_printer_2(NT_PRINTER_INFO_LEVEL_2 **info_ptr, fstring sharen slprintf(printername, sizeof(printername)-1, "\\\\%s\\%s", get_called_name(), info.printername); fstrcpy(info.printername, printername); - + len += unpack_devicemode(&info.devmode,dbuf.dptr+len, dbuf.dsize-len); /* @@ -2974,10 +2683,10 @@ static WERROR get_a_printer_2(NT_PRINTER_INFO_LEVEL_2 **info_ptr, fstring sharen info.devmode = construct_nt_devicemode(printername); } - len += unpack_values( &info.data, dbuf.dptr+len, dbuf.dsize-len ); + len += unpack_specifics(&info.specific,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); @@ -3164,25 +2873,29 @@ 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 'values' already set. When called for driver + * Delete any printer data 'specifics' 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). */ - - delete_all_printer_data( info_ptr, "" ); - + while ( (current=info_ptr->specific) != NULL ) { + info_ptr->specific=current->next; + SAFE_FREE(current->data); + SAFE_FREE(current); + } + + ZERO_STRUCT(info); + slprintf(key, sizeof(key)-1, "%s%s", DRIVER_INIT_PREFIX, info_ptr->drivername); + dos_to_unix(key); /* Convert key to unix-codepage */ kbuf.dptr = key; kbuf.dsize = strlen(key)+1; @@ -3196,47 +2909,70 @@ 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. */ - - if ( info.devmode ) { ZERO_STRUCT(info.devmode->devicename); fstrcpy(info.devmode->devicename, info_ptr->printername); - } + /* * NT/2k does not change out the entire DeviceMode of a printer * when changing the driver. Only the driverextra, private, & * driverversion fields. --jerry (Thu Mar 14 08:58:43 CST 2002) * - * Later examination revealed that Windows NT/2k does reset the + * Later e4xamination revealed that Windows NT/2k does reset the * the printer's device mode, bit **only** when you change a * property of the device mode such as the page orientation. * --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 */ - DEBUG(10,("set_driver_init_2: Set printer [%s] init %s DEVMODE for driver [%s]\n", - info_ptr->printername, info_ptr->devmode?"VALID":"NULL", info_ptr->drivername)); + 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 */ - /* Add the printer data 'values' to the new printer */ - - len += unpack_values( &info_ptr->data, dbuf.dptr+len, dbuf.dsize-len ); - + 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); SAFE_FREE(dbuf.dptr); @@ -3254,7 +2990,7 @@ BOOL set_driver_init(NT_PRINTER_INFO_LEVEL *printer, uint32 level) { BOOL result = False; - switch (level) + switch (level) { case 2: result = set_driver_init_2(printer->info_2); @@ -3284,6 +3020,7 @@ BOOL del_driver_init(char *drivername) } slprintf(key, sizeof(key)-1, "%s%s", DRIVER_INIT_PREFIX, drivername); + dos_to_unix(key); /* Convert key to unix-codepage */ kbuf.dptr = key; kbuf.dsize = strlen(key)+1; @@ -3294,7 +3031,7 @@ BOOL del_driver_init(char *drivername) } /**************************************************************************** - Pack up the DEVMODE and values for a printer into a 'driver init' entry + Pack up the DEVMODE and specifics 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 @@ -3315,7 +3052,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_values( &info->data, buf+len, buflen-len ); + len += pack_specifics(info->specific, buf+len, buflen-len); if (buflen != len) { char *tb; @@ -3332,6 +3069,7 @@ static uint32 update_driver_init_2(NT_PRINTER_INFO_LEVEL_2 *info) } slprintf(key, sizeof(key)-1, "%s%s", DRIVER_INIT_PREFIX, info->drivername); + dos_to_unix(key); /* Convert key to unix-codepage */ kbuf.dptr = key; kbuf.dsize = strlen(key)+1; @@ -3346,14 +3084,14 @@ done: SAFE_FREE(buf); - DEBUG(10,("update_driver_init_2: Saved printer [%s] init DEVMODE & values for driver [%s]\n", + DEBUG(10,("update_driver_init_2: Saved printer [%s] init DEVMODE & specifics for driver [%s]\n", info->sharename, info->drivername)); return ret; } /**************************************************************************** - Update (i.e. save) the driver init info (DEVMODE and values) for a printer + Update (i.e. save) the driver init info (DEVMODE and specifics) for a printer ****************************************************************************/ uint32 update_driver_init(NT_PRINTER_INFO_LEVEL printer, uint32 level) @@ -3366,11 +3104,11 @@ uint32 update_driver_init(NT_PRINTER_INFO_LEVEL printer, uint32 level) { case 2: { - result = update_driver_init_2(printer.info_2); + result=update_driver_init_2(printer.info_2); break; } default: - result = 1; + result=1; break; } @@ -3383,7 +3121,7 @@ uint32 update_driver_init(NT_PRINTER_INFO_LEVEL printer, uint32 level) got to keep the endians happy :). ****************************************************************************/ -static BOOL convert_driver_init( TALLOC_CTX *ctx, NT_DEVICEMODE *nt_devmode, uint8 *data, uint32 data_len ) +static BOOL convert_driver_init(NT_PRINTER_PARAM *param, TALLOC_CTX *ctx, NT_DEVICEMODE *nt_devmode) { BOOL result = False; prs_struct ps; @@ -3392,8 +3130,8 @@ static BOOL convert_driver_init( TALLOC_CTX *ctx, NT_DEVICEMODE *nt_devmode, uin ZERO_STRUCT(devmode); prs_init(&ps, 0, ctx, UNMARSHALL); - ps.data_p = (char *)data; - ps.buffer_size = data_len; + 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); @@ -3425,7 +3163,7 @@ static BOOL convert_driver_init( TALLOC_CTX *ctx, NT_DEVICEMODE *nt_devmode, uin about it and you will realize why. JRR 010720 ****************************************************************************/ -static WERROR save_driver_init_2(NT_PRINTER_INFO_LEVEL *printer, uint8 *data, uint32 data_len ) +static WERROR save_driver_init_2(NT_PRINTER_INFO_LEVEL *printer, NT_PRINTER_PARAM *param) { WERROR status = WERR_OK; TALLOC_CTX *ctx = NULL; @@ -3435,10 +3173,8 @@ static WERROR save_driver_init_2(NT_PRINTER_INFO_LEVEL *printer, uint8 *data, ui /* * When the DEVMODE is already set on the printer, don't try to unpack it. */ - DEBUG(8,("save_driver_init_2: Enter...\n")); - - if ( !printer->info_2->devmode && data_len ) - { + + if (!printer->info_2->devmode && param->data_len) { /* * Set devmode on printer info, so entire printer initialization can be * saved to tdb. @@ -3451,14 +3187,14 @@ static WERROR save_driver_init_2(NT_PRINTER_INFO_LEVEL *printer, uint8 *data, ui 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( ctx, nt_devmode, data, data_len )) { + if (!convert_driver_init(param, ctx, nt_devmode)) { DEBUG(10,("save_driver_init_2: error converting DEVMODE\n")); status = WERR_INVALID_PARAM; goto done; @@ -3473,7 +3209,7 @@ static WERROR save_driver_init_2(NT_PRINTER_INFO_LEVEL *printer, uint8 *data, ui * */ - if ( update_driver_init(*printer, 2) != 0 ) { + if (update_driver_init(*printer, 2)!=0) { DEBUG(10,("save_driver_init_2: error updating DEVMODE\n")); status = WERR_NOMEM; goto done; @@ -3490,10 +3226,15 @@ static WERROR save_driver_init_2(NT_PRINTER_INFO_LEVEL *printer, uint8 *data, ui printer->info_2->printername)); } +#if 0 /* JERRY */ + srv_spoolss_sendnotify(p, handle); +#endif + done: talloc_destroy(ctx); - free_nt_devicemode( &nt_devmode ); - + if (nt_devmode) + SAFE_FREE(nt_devmode->private); + SAFE_FREE(nt_devmode); printer->info_2->devmode = tmp_devmode; return status; @@ -3503,7 +3244,7 @@ static WERROR save_driver_init_2(NT_PRINTER_INFO_LEVEL *printer, uint8 *data, ui Update the driver init info (DEVMODE and specifics) for a printer ****************************************************************************/ -WERROR save_driver_init(NT_PRINTER_INFO_LEVEL *printer, uint32 level, uint8 *data, uint32 data_len) +WERROR save_driver_init(NT_PRINTER_INFO_LEVEL *printer, uint32 level, NT_PRINTER_PARAM *param) { WERROR status = WERR_OK; @@ -3511,11 +3252,11 @@ WERROR save_driver_init(NT_PRINTER_INFO_LEVEL *printer, uint32 level, uint8 *dat { case 2: { - status = save_driver_init_2( printer, data, data_len ); + status=save_driver_init_2(printer, param); break; } default: - status = WERR_UNKNOWN_LEVEL; + status=WERR_UNKNOWN_LEVEL; break; } @@ -3632,31 +3373,17 @@ uint32 add_a_printer_driver(NT_PRINTER_DRIVER_INFO_LEVEL driver, uint32 level) /**************************************************************************** ****************************************************************************/ WERROR get_a_printer_driver(NT_PRINTER_DRIVER_INFO_LEVEL *driver, uint32 level, - fstring drivername, fstring architecture, uint32 version) + fstring printername, fstring architecture, uint32 version) { WERROR result; switch (level) { case 3: - /* Sometime we just want any version of the driver */ - - if ( version == DRIVER_ANY_VERSION ) { - /* look for Win2k first and then for NT4 */ - result = get_a_printer_driver_3(&driver->info_3, drivername, - architecture, 3); - - if ( !W_ERROR_IS_OK(result) ) { - result = get_a_printer_driver_3( &driver->info_3, - drivername, architecture, 2 ); - } - } - else { - result = get_a_printer_driver_3(&driver->info_3, drivername, - architecture, version); - } + { + result=get_a_printer_driver_3(&driver->info_3, printername, architecture, version); break; - + } default: result=W_ERROR(1); break; @@ -3664,7 +3391,6 @@ WERROR get_a_printer_driver(NT_PRINTER_DRIVER_INFO_LEVEL *driver, uint32 level, if (W_ERROR_IS_OK(result)) dump_a_printer_driver(*driver, level); - return result; } @@ -3723,336 +3449,78 @@ uint32 free_a_printer_driver(NT_PRINTER_DRIVER_INFO_LEVEL driver, uint32 level) Determine whether or not a particular driver is currently assigned to a printer ****************************************************************************/ - -BOOL printer_driver_in_use ( NT_PRINTER_DRIVER_INFO_LEVEL_3 *info_3 ) +BOOL printer_driver_in_use (char *arch, char *driver) { - int snum; - int n_services = lp_numservices(); - NT_PRINTER_INFO_LEVEL *printer = NULL; + TDB_DATA kbuf, newkey, dbuf; + NT_PRINTER_INFO_LEVEL_2 info; + int ret; - if ( !info_3 ) - return False; + if (!tdb_printers) + if (!nt_printing_init()) + return False; - DEBUG(5,("printer_driver_in_use: Beginning search through ntprinters.tdb...\n")); + DEBUG(5,("printer_driver_in_use: Beginning search through printers.tdb...\n")); /* loop through the printers.tdb and check for the drivername */ - - for (snum=0; snum<n_services; snum++) - { - if ( !(lp_snum_ok(snum) && lp_print_ok(snum) ) ) - continue; - - if ( !W_ERROR_IS_OK(get_a_printer(&printer, 2, lp_servicename(snum))) ) - continue; - - if ( !StrCaseCmp(info_3->name, printer->info_2->drivername) ) { - free_a_printer( &printer, 2 ); - return True; - } - - free_a_printer( &printer, 2 ); - } - - DEBUG(5,("printer_driver_in_use: Completed search through ntprinters.tdb...\n")); - - /* report that the driver is not in use by default */ - - return False; -} - - -/********************************************************************** - Check to see if a ogiven file is in use by *info - *********************************************************************/ - -static BOOL drv_file_in_use( char* file, NT_PRINTER_DRIVER_INFO_LEVEL_3 *info ) -{ - int i = 0; - - if ( !info ) - return False; - - if ( strequal(file, info->driverpath) ) - return True; - - if ( strequal(file, info->datafile) ) - return True; - - if ( strequal(file, info->configfile) ) - return True; - - if ( strequal(file, info->helpfile) ) - return True; - - /* see of there are any dependent files to examine */ - - if ( !info->dependentfiles ) - return False; - - while ( *info->dependentfiles[i] ) + for (kbuf = tdb_firstkey(tdb_printers); kbuf.dptr; + newkey = tdb_nextkey(tdb_printers, kbuf), safe_free(kbuf.dptr), kbuf=newkey) { - if ( strequal(file, info->dependentfiles[i]) ) - return True; - - i++; - } - - return False; - -} -/********************************************************************** - Utility function to remove the dependent file pointed to by the - input parameter from the list - *********************************************************************/ - -static void trim_dependent_file( fstring files[], int idx ) -{ - - /* bump everything down a slot */ + dbuf = tdb_fetch(tdb_printers, kbuf); + if (!dbuf.dptr) + continue; - while( *files[idx+1] ) - { - fstrcpy( files[idx], files[idx+1] ); - idx++; - } - - *files[idx] = '\0'; + if (strncmp(kbuf.dptr, PRINTERS_PREFIX, strlen(PRINTERS_PREFIX)) != 0) + continue; - return; -} + ret = tdb_unpack(dbuf.dptr, dbuf.dsize, "dddddddddddfffffPfffff", + &info.attributes, + &info.priority, + &info.default_priority, + &info.starttime, + &info.untiltime, + &info.status, + &info.cjobs, + &info.averageppm, + &info.changeid, + &info.c_setprinter, + &info.setuptime, + info.servername, + info.printername, + info.sharename, + info.portname, + info.drivername, + info.comment, + info.location, + info.sepfile, + info.printprocessor, + info.datatype, + info.parameters); -/********************************************************************** - Check if any of the files used by src are also used by drv - *********************************************************************/ + SAFE_FREE(dbuf.dptr); -static BOOL trim_overlap_drv_files( NT_PRINTER_DRIVER_INFO_LEVEL_3 *src, - NT_PRINTER_DRIVER_INFO_LEVEL_3 *drv ) -{ - BOOL in_use = False; - int i = 0; - - if ( !src || !drv ) - return False; - - /* check each file. Remove it from the src structure if it overlaps */ - - if ( drv_file_in_use(src->driverpath, drv) ) { - in_use = True; - DEBUG(10,("Removing driverfile [%s] from list\n", src->driverpath)); - fstrcpy( src->driverpath, "" ); - } - - if ( drv_file_in_use(src->datafile, drv) ) { - in_use = True; - DEBUG(10,("Removing datafile [%s] from list\n", src->datafile)); - fstrcpy( src->datafile, "" ); - } - - if ( drv_file_in_use(src->configfile, drv) ) { - in_use = True; - DEBUG(10,("Removing configfile [%s] from list\n", src->configfile)); - fstrcpy( src->configfile, "" ); - } - - if ( drv_file_in_use(src->helpfile, drv) ) { - in_use = True; - DEBUG(10,("Removing helpfile [%s] from list\n", src->helpfile)); - fstrcpy( src->helpfile, "" ); - } - - /* are there any dependentfiles to examine? */ - - if ( !src->dependentfiles ) - return in_use; - - while ( *src->dependentfiles[i] ) - { - if ( drv_file_in_use(src->dependentfiles[i], drv) ) { - in_use = True; - DEBUG(10,("Removing [%s] from dependent file list\n", src->dependentfiles[i])); - trim_dependent_file( src->dependentfiles, i ); + if (ret == -1) { + DEBUG (0,("printer_driver_in_use: tdb_unpack failed for printer %s\n", + info.printername)); + continue; } - else - i++; - } - - return in_use; -} - -/**************************************************************************** - Determine whether or not a particular driver files are currently being - used by any other driver. - - Return value is True if any files were in use by other drivers - and False otherwise. - - Upon return, *info has been modified to only contain the driver files - which are not in use -****************************************************************************/ - -BOOL printer_driver_files_in_use ( NT_PRINTER_DRIVER_INFO_LEVEL_3 *info ) -{ - int i; - int ndrivers; - uint32 version; - fstring *list = NULL; - NT_PRINTER_DRIVER_INFO_LEVEL driver; - - if ( !info ) - return False; - - version = info->cversion; - - /* loop over all driver versions */ - - DEBUG(5,("printer_driver_files_in_use: Beginning search through ntdrivers.tdb...\n")); - - /* get the list of drivers */ - - list = NULL; - ndrivers = get_ntdrivers(&list, info->environment, version); - - DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", - ndrivers, info->environment, version)); - - /* check each driver for overlap in files */ - for (i=0; i<ndrivers; i++) - { - DEBUGADD(5,("\tdriver: [%s]\n", list[i])); - - ZERO_STRUCT(driver); + DEBUG (10,("printer_driver_in_use: Printer - %s (%s)\n", + info.printername, info.drivername)); - if ( !W_ERROR_IS_OK(get_a_printer_driver(&driver, 3, list[i], - info->environment, version)) ) + if (strcmp(info.drivername, driver) == 0) { - SAFE_FREE(list); + DEBUG(5,("printer_driver_in_use: Printer %s using %s\n", + info.printername, driver)); return True; - } - - /* check if d2 uses any files from d1 */ - /* only if this is a different driver than the one being deleted */ - - if ( !strequal(info->name, driver.info_3->name) ) - { - if ( trim_overlap_drv_files(info, driver.info_3) ) { - free_a_printer_driver(driver, 3); - SAFE_FREE( list ); - return True; - } - } - - free_a_printer_driver(driver, 3); - } - - SAFE_FREE(list); - - DEBUG(5,("printer_driver_files_in_use: Completed search through ntdrivers.tdb...\n")); - - driver.info_3 = info; - - if ( DEBUGLEVEL >= 20 ) - dump_a_printer_driver( driver, 3 ); - - return False; -} - -/**************************************************************************** - Actually delete the driver files. Make sure that - printer_driver_files_in_use() return False before calling - this. -****************************************************************************/ - -static BOOL delete_driver_files( NT_PRINTER_DRIVER_INFO_LEVEL_3 *info_3, struct current_user *user ) -{ - int i = 0; - char *s; - connection_struct *conn; - DATA_BLOB null_pw; - NTSTATUS nt_status; - - if ( !info_3 ) - return False; - - DEBUG(6,("delete_driver_files: deleting driver [%s] - version [%d]\n", info_3->name, info_3->cversion)); - - /* - * Connect to the print$ share under the same account as the - * user connected to the rpc pipe. Note we must be root to - * do this. - */ - - become_root(); - null_pw = data_blob( NULL, 0 ); - conn = make_connection_with_chdir( "print$", null_pw, "A:", user->vuid, &nt_status ); - unbecome_root(); - - if ( !conn ) { - DEBUG(0,("delete_driver_files: Unable to connect\n")); - return False; - } - - /* Save who we are - we are temporarily becoming the connection user. */ - - if ( !become_user(conn, conn->vuid) ) { - DEBUG(0,("delete_driver_files: Can't become user!\n")); - return False; - } - - /* now delete the files; must strip the '\print$' string from - fron of path */ - - if ( *info_3->driverpath ) { - if ( (s = strchr( &info_3->driverpath[1], '\\' )) != NULL ) { - DEBUG(10,("deleting driverfile [%s]\n", s)); - unlink_internals(conn, 0, s); - } - } - - if ( *info_3->configfile ) { - if ( (s = strchr( &info_3->configfile[1], '\\' )) != NULL ) { - DEBUG(10,("deleting configfile [%s]\n", s)); - unlink_internals(conn, 0, s); - } + } } + DEBUG(5,("printer_driver_in_use: Completed search through printers.tdb...\n")); - if ( *info_3->datafile ) { - if ( (s = strchr( &info_3->datafile[1], '\\' )) != NULL ) { - DEBUG(10,("deleting datafile [%s]\n", s)); - unlink_internals(conn, 0, s); - } - } - if ( *info_3->helpfile ) { - if ( (s = strchr( &info_3->helpfile[1], '\\' )) != NULL ) { - DEBUG(10,("deleting helpfile [%s]\n", s)); - unlink_internals(conn, 0, s); - } - } - - /* check if we are done removing files */ - - if ( info_3->dependentfiles ) - { - while ( *info_3->dependentfiles[i] ) { - char *file; - - /* bypass the "\print$" portion of the path */ - - if ( (file = strchr( info_3->dependentfiles[i]+1, '\\' )) != NULL ) - { - DEBUG(10,("deleting dependent file [%s]\n", file)); - unlink_internals(conn, 0, file ); - } - - i++; - } - } - - unbecome_user(); - return True; + /* report that the driver is in use by default */ + return False; } /**************************************************************************** @@ -4060,7 +3528,7 @@ static BOOL delete_driver_files( NT_PRINTER_DRIVER_INFO_LEVEL_3 *info_3, struct previously looked up. ***************************************************************************/ -WERROR delete_printer_driver( NT_PRINTER_DRIVER_INFO_LEVEL_3 *info_3, struct current_user *user, +static WERROR delete_printer_driver_internal( NT_PRINTER_DRIVER_INFO_LEVEL_3 *i, struct current_user *user, uint32 version, BOOL delete_files ) { pstring key; @@ -4070,14 +3538,14 @@ WERROR delete_printer_driver( NT_PRINTER_DRIVER_INFO_LEVEL_3 *info_3, struct cur /* delete the tdb data first */ - get_short_archi(arch, info_3->environment); + get_short_archi(arch, i->environment); slprintf(key, sizeof(key)-1, "%s%s/%d/%s", DRIVERS_PREFIX, - arch, version, info_3->name); + arch, version, i->name); DEBUG(5,("delete_printer_driver: key = [%s] delete_files = %s\n", key, delete_files ? "TRUE" : "FALSE" )); - ctr.info_3 = info_3; + ctr.info_3 = i; dump_a_printer_driver( ctr, 3 ); kbuf.dptr=key; @@ -4087,7 +3555,7 @@ WERROR delete_printer_driver( NT_PRINTER_DRIVER_INFO_LEVEL_3 *info_3, struct cur dbuf = tdb_fetch( tdb_drivers, kbuf ); if ( !dbuf.dptr ) { - DEBUG(8,("delete_printer_driver: Driver unknown [%s]\n", key)); + DEBUG(8,("delete_printer_driver_internal: Driver unknown [%s]\n", key)); return WERR_UNKNOWN_PRINTER_DRIVER; } @@ -4096,10 +3564,11 @@ WERROR delete_printer_driver( NT_PRINTER_DRIVER_INFO_LEVEL_3 *info_3, struct cur /* 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; } +#if 0 /* JERRY - no used in Samba 2.2.x */ /* * now delete any associated files if delete_files == True * even if this part failes, we return succes because the @@ -4107,19 +3576,133 @@ WERROR delete_printer_driver( NT_PRINTER_DRIVER_INFO_LEVEL_3 *info_3, struct cur */ if ( delete_files ) - delete_driver_files( info_3, user ); + delete_driver_files( i, user ); + +#endif + + DEBUG(5,("delete_printer_driver_internal: driver delete successful [%s]\n", key)); + + return WERR_OK; +} + +/**************************************************************************** + Remove a printer driver from the TDB. This assumes that the the driver was + previously looked up. + ***************************************************************************/ + +WERROR delete_printer_driver (NT_PRINTER_DRIVER_INFO_LEVEL_3 *i, struct current_user *user, + uint32 version, BOOL delete_files ) + +{ + WERROR err; + + /* + * 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 ) + { + /* Windows NT 4.0 */ + + err = delete_printer_driver_internal(i, user, 2, delete_files ); + if ( !W_ERROR_IS_OK(err) && (W_ERROR_V(err) != ERRunknownprinterdriver ) ) + return err; + /* Windows 2000/XP */ - DEBUG(5,("delete_printer_driver: driver delete successful [%s]\n", key)); + err = delete_printer_driver_internal(i, user, 3, delete_files ); + if ( !W_ERROR_IS_OK(err) && (W_ERROR_V(err) != ERRunknownprinterdriver ) ) + return err; return WERR_OK; } + /* just delete what they asked for */ + + return delete_printer_driver_internal(i, user, version, delete_files ); +} + +/**************************************************************************** +****************************************************************************/ +BOOL get_specific_param_by_index(NT_PRINTER_INFO_LEVEL printer, uint32 level, uint32 param_index, + fstring value, uint8 **data, uint32 *type, uint32 *len) +{ + /* right now that's enough ! */ + NT_PRINTER_PARAM *param; + int i=0; + + param=printer.info_2->specific; + + 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; + } + + 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); +} + /**************************************************************************** Store a security desc for a printer. ****************************************************************************/ -WERROR nt_printing_setsec(const char *printername, SEC_DESC_BUF *secdesc_ctr) +WERROR nt_printing_setsec(char *printername, SEC_DESC_BUF *secdesc_ctr) { SEC_DESC_BUF *new_secdesc_ctr = NULL; SEC_DESC_BUF *old_secdesc_ctr = NULL; @@ -4214,6 +3797,7 @@ WERROR nt_printing_setsec(const char *printername, SEC_DESC_BUF *secdesc_ctr) static SEC_DESC_BUF *construct_default_printer_sdb(TALLOC_CTX *ctx) { + extern DOM_SID global_sam_sid; SEC_ACE ace[3]; SEC_ACCESS sa; SEC_ACL *psa = NULL; @@ -4221,7 +3805,9 @@ static SEC_DESC_BUF *construct_default_printer_sdb(TALLOC_CTX *ctx) SEC_DESC *psd = NULL; DOM_SID owner_sid; size_t sd_size; - + enum SID_NAME_USE name_type; + fstring dos_domain; + /* Create an ACE where Everyone is allowed to print */ init_sec_access(&sa, PRINTER_ACE_PRINT); @@ -4231,16 +3817,25 @@ static SEC_DESC_BUF *construct_default_printer_sdb(TALLOC_CTX *ctx) /* Make the security descriptor owned by the Administrators group on the PDC of the domain. */ - if (secrets_fetch_domain_sid(lp_workgroup(), &owner_sid)) { + /* Note that for hysterical raisins, the argument to + secrets_fetch_domain_sid() must be in dos codepage format. + Aargh! */ + + fstrcpy(dos_domain, lp_workgroup()); + unix_to_dos(dos_domain); + + if (secrets_fetch_domain_sid(dos_domain, &owner_sid)) { sid_append_rid(&owner_sid, DOMAIN_USER_RID_ADMIN); } else { - /* Backup plan - make printer owned by admins. - This should emulate a lanman printer as security - settings can't be changed. */ + /* Backup plan - make printer owned by admins or root. + This should emulate a lanman printer as security + settings can't be changed. */ - sid_copy(&owner_sid, get_global_sam_sid()); - sid_append_rid(&owner_sid, DOMAIN_USER_RID_ADMIN); + if (!lookup_name("root", &owner_sid, &name_type)) { + sid_copy(&owner_sid, &global_sam_sid); + sid_append_rid(&owner_sid, DOMAIN_USER_RID_ADMIN); + } } init_sec_access(&sa, PRINTER_ACE_FULL_CONTROL); @@ -4280,7 +3875,7 @@ static SEC_DESC_BUF *construct_default_printer_sdb(TALLOC_CTX *ctx) Get a security desc for a printer. ****************************************************************************/ -BOOL nt_printing_getsec(TALLOC_CTX *ctx, const char *printername, SEC_DESC_BUF **secdesc_ctr) +BOOL nt_printing_getsec(TALLOC_CTX *ctx, char *printername, SEC_DESC_BUF **secdesc_ctr) { prs_struct ps; fstring key; @@ -4308,7 +3903,7 @@ BOOL nt_printing_getsec(TALLOC_CTX *ctx, const char *printername, SEC_DESC_BUF * prs_init(&ps, (uint32)sec_desc_size((*secdesc_ctr)->sec) + sizeof(SEC_DESC_BUF), ctx, MARSHALL); - if (sec_io_desc_buf("nt_printing_getsec", secdesc_ctr, &ps, 1)) + if (sec_io_desc_buf("nt_printing_setsec", secdesc_ctr, &ps, 1)) tdb_prs_store(tdb_printers, key, &ps); prs_mem_free(&ps); @@ -4322,10 +3917,12 @@ BOOL nt_printing_getsec(TALLOC_CTX *ctx, const char *printername, SEC_DESC_BUF * if (sid_equal((*secdesc_ctr)->sec->owner_sid, &global_sid_World)) { DOM_SID owner_sid; + enum SID_NAME_USE name_type; /* Change sd owner to workgroup administrator */ - if (secrets_fetch_domain_sid(lp_workgroup(), &owner_sid)) { + if (winbind_lookup_name(NULL, lp_workgroup(), &owner_sid, + &name_type)) { SEC_DESC_BUF *new_secdesc_ctr = NULL; SEC_DESC *psd = NULL; size_t size; @@ -4449,7 +4046,7 @@ BOOL print_access_check(struct current_user *user, int snum, int access_type) uint32 access_granted; NTSTATUS status; BOOL result; - const char *pname; + char *pname; TALLOC_CTX *mem_ctx = NULL; extern struct current_user current_user; @@ -4550,3 +4147,76 @@ 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 */ |