diff options
author | Gerald Carter <jerry@samba.org> | 2001-11-22 05:56:09 +0000 |
---|---|---|
committer | Gerald Carter <jerry@samba.org> | 2001-11-22 05:56:09 +0000 |
commit | 116740a5df6294b0a4e244f575108ded87452c18 (patch) | |
tree | 1326b89821403425d0226e6990a266c7d2f338fe | |
parent | 456cdf6aeeb5806083904f109ec05e0fa5a67349 (diff) | |
download | samba-116740a5df6294b0a4e244f575108ded87452c18.tar.gz samba-116740a5df6294b0a4e244f575108ded87452c18.tar.bz2 samba-116740a5df6294b0a4e244f575108ded87452c18.zip |
merge from 2.2
(This used to be commit 96b3a65a73d403a41bf1b3aba79bd743698344ac)
-rw-r--r-- | source3/include/rpc_reg.h | 5 | ||||
-rwxr-xr-x | source3/include/rpc_spoolss.h | 68 | ||||
-rw-r--r-- | source3/printing/nt_printing.c | 42 | ||||
-rw-r--r-- | source3/rpc_parse/parse_spoolss.c | 219 | ||||
-rwxr-xr-x | source3/rpc_server/srv_spoolss.c | 60 | ||||
-rw-r--r-- | source3/rpc_server/srv_spoolss_nt.c | 355 |
6 files changed, 685 insertions, 64 deletions
diff --git a/source3/include/rpc_reg.h b/source3/include/rpc_reg.h index 1906eb1aad..8fe40be6f7 100644 --- a/source3/include/rpc_reg.h +++ b/source3/include/rpc_reg.h @@ -59,6 +59,11 @@ #define HKEY_LOCAL_MACHINE 0x80000002 #define HKEY_USERS 0x80000003 +#define REG_SZ 1 +#define REG_BINARY 3 +#define REG_DWORD 4 +#define REG_MULTI_SZ 7 + /* REG_Q_OPEN_HKCR */ typedef struct q_reg_open_hkcr_info { diff --git a/source3/include/rpc_spoolss.h b/source3/include/rpc_spoolss.h index 0b551c3a1a..72b9d10718 100755 --- a/source3/include/rpc_spoolss.h +++ b/source3/include/rpc_spoolss.h @@ -57,13 +57,6 @@ #define SPOOLSS_SPOOLERINIT 0x3f #define SPOOLSS_RESETPRINTEREX 0x40 #define SPOOLSS_ROUTERREFRESHPRINTERCHANGENOTIFICATION 0x42 -*/ - -/* - * Unimplement Win2k specific RPC's - -#define SPOOLSS_ENUMPRINTERDATAEX 0x4f -#define SPOOLSS_ENUMPRINTERKEY 0x50 #define SPOOLSS_DELETEPRINTERDATAEX 0x51 #define SPOOLSS_DELETEPRINTERDRIVEREX 0x54 #define SPOOLSS_ADDPRINTERDRIVEREX 0x59 @@ -118,8 +111,11 @@ #define SPOOLSS_ADDPRINTEREX 0x46 #define SPOOLSS_ENUMPRINTERDATA 0x48 #define SPOOLSS_DELETEPRINTERDATA 0x49 -#define SPOOLSS_GETPRINTERDATAEX 0x4e #define SPOOLSS_SETPRINTERDATAEX 0x4d +#define SPOOLSS_GETPRINTERDATAEX 0x4e +#define SPOOLSS_ENUMPRINTERDATAEX 0x4f +#define SPOOLSS_ENUMPRINTERKEY 0x50 + #define PRINTER_CONTROL_UNPAUSE 0x00000000 #define PRINTER_CONTROL_PAUSE 0x00000001 @@ -1906,7 +1902,63 @@ typedef struct spool_r_setprinterdataex } SPOOL_R_SETPRINTERDATAEX; + +typedef struct spool_q_enumprinterkey +{ + POLICY_HND handle; + UNISTR2 key; + uint32 size; +} +SPOOL_Q_ENUMPRINTERKEY; + +typedef struct spool_r_enumprinterkey +{ + BUFFER5 keys; + uint32 needed; /* in bytes */ + WERROR status; +} +SPOOL_R_ENUMPRINTERKEY; + +typedef struct printer_enum_values +{ + UNISTR valuename; + uint32 value_len; + uint32 type; + uint8 *data; + uint32 data_len; + +} +PRINTER_ENUM_VALUES; + +typedef struct printer_enum_values_ctr +{ + uint32 size; + uint32 size_of_array; + PRINTER_ENUM_VALUES *values; +} +PRINTER_ENUM_VALUES_CTR; + +typedef struct spool_q_enumprinterdataex +{ + POLICY_HND handle; + UNISTR2 key; + uint32 size; +} +SPOOL_Q_ENUMPRINTERDATAEX; + +typedef struct spool_r_enumprinterdataex +{ + PRINTER_ENUM_VALUES_CTR ctr; + uint32 needed; + uint32 returned; + WERROR status; +} +SPOOL_R_ENUMPRINTERDATAEX; + + + #define PRINTER_DRIVER_VERSION 2 #define PRINTER_DRIVER_ARCHITECTURE "Windows NT x86" #endif /* _RPC_SPOOLSS_H */ + diff --git a/source3/printing/nt_printing.c b/source3/printing/nt_printing.c index e4e33d257f..028f449479 100644 --- a/source3/printing/nt_printing.c +++ b/source3/printing/nt_printing.c @@ -181,7 +181,7 @@ static BOOL upgrade_to_version_2(void) DEBUG(0,("upgrade_to_version_2: upgrading print tdb's to version 2\n")); for (kbuf = tdb_firstkey(tdb_drivers); kbuf.dptr; - newkey = tdb_nextkey(tdb_drivers, kbuf), safe_free(kbuf.dptr), kbuf=newkey) { + newkey = tdb_nextkey(tdb_drivers, kbuf), SAFE_FREE(kbuf.dptr), kbuf=newkey) { dbuf = tdb_fetch(tdb_drivers, kbuf); @@ -323,7 +323,7 @@ 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) { + 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); @@ -510,7 +510,7 @@ int get_ntdrivers(fstring **list, char *architecture, uint32 version) for (kbuf = tdb_firstkey(tdb_drivers); kbuf.dptr; - newkey = tdb_nextkey(tdb_drivers, kbuf), safe_free(kbuf.dptr), kbuf=newkey) { + newkey = tdb_nextkey(tdb_drivers, kbuf), SAFE_FREE(kbuf.dptr), kbuf=newkey) { if (strncmp(kbuf.dptr, key, strlen(key)) != 0) continue; if((fl = Realloc(*list, sizeof(fstring)*(total+1))) == NULL) { @@ -955,6 +955,7 @@ static uint32 get_correct_cversion(fstring architecture, fstring driverpath_in, return -1; } + /* We are temporarily becoming the connection user. */ if (!become_user(conn, conn->vuid)) { DEBUG(0,("get_correct_cversion: Can't become user!\n")); *perr = WERR_ACCESS_DENIED; @@ -2390,16 +2391,13 @@ static WERROR get_a_printer_2_default(NT_PRINTER_INFO_LEVEL_2 **info_ptr, fstrin fstrcpy(info.portname, SAMBA_PRINTER_PORT_NAME); fstrcpy(info.drivername, lp_printerdriver(snum)); -#if 0 /* JERRY */ - if (!*info.drivername) - fstrcpy(info.drivername, "NO DRIVER AVAILABLE FOR THIS PRINTER"); -#else /* by setting the driver name to an empty string, a local NT admin can now run the **local** APW to install a local printer driver for a Samba shared printer in 2.2. Without this, drivers **must** be installed on the Samba server for NT clients --jerry */ +#if 0 /* JERRY --do not uncomment-- */ if (!*info.drivername) - fstrcpy(info.drivername, ""); + fstrcpy(info.drivername, "NO DRIVER AVAILABLE FOR THIS PRINTER"); #endif @@ -2418,9 +2416,15 @@ static WERROR get_a_printer_2_default(NT_PRINTER_INFO_LEVEL_2 **info_ptr, fstrin info.untiltime = 0; /* Minutes since 12:00am GMT */ info.priority = 1; info.default_priority = 1; - info.setuptime = (uint32)time(NULL); + info.setuptime = (uint32)time(NULL) - 86400; /* minus 1 day */ + + /* + * I changed this as I think it is better to have a generic + * DEVMODE than to crash Win2k explorer.exe --jerry + * See the HP Deskjet 990c Win2k drivers for an example. + */ -#if 1 /* JRA - NO NOT CHANGE ! */ +#if 0 /* JRA - NO NOT CHANGE ! */ info.devmode = NULL; #else /* @@ -2460,7 +2464,8 @@ static WERROR get_a_printer_2(NT_PRINTER_INFO_LEVEL_2 **info_ptr, fstring sharen { pstring key; NT_PRINTER_INFO_LEVEL_2 info; - int len = 0; + int len = 0, + devmode_length = 0; TDB_DATA kbuf, dbuf; fstring printername; @@ -2509,6 +2514,19 @@ static WERROR get_a_printer_2(NT_PRINTER_INFO_LEVEL_2 **info_ptr, fstring sharen fstrcpy(info.printername, printername); len += unpack_devicemode(&info.devmode,dbuf.dptr+len, dbuf.dsize-len); +#if 1 + /* + * Some client drivers freak out if there is a NULL devmode + * (probably the driver is not checking before accessing + * the devmode pointer) --jerry + */ + if (!info.devmode) + { + DEBUG(8,("get_a_printer_2: Constructing a default device mode for [%s]\n", + printername)); + info.devmode = construct_nt_devicemode(printername); + } +#endif len += unpack_specifics(&info.specific,dbuf.dptr+len, dbuf.dsize-len); /* This will get the current RPC talloc context, but we should be @@ -3185,7 +3203,7 @@ BOOL printer_driver_in_use (char *arch, char *driver) /* loop through the printers.tdb and check for the drivername */ for (kbuf = tdb_firstkey(tdb_printers); kbuf.dptr; - newkey = tdb_nextkey(tdb_printers, kbuf), safe_free(kbuf.dptr), kbuf=newkey) + newkey = tdb_nextkey(tdb_printers, kbuf), SAFE_FREE(kbuf.dptr), kbuf=newkey) { dbuf = tdb_fetch(tdb_printers, kbuf); diff --git a/source3/rpc_parse/parse_spoolss.c b/source3/rpc_parse/parse_spoolss.c index 6404a83d51..b628fa9913 100644 --- a/source3/rpc_parse/parse_spoolss.c +++ b/source3/rpc_parse/parse_spoolss.c @@ -3212,6 +3212,26 @@ uint32 spoolss_size_printprocdatatype_info_1(PRINTPROCDATATYPE_1 *info) /******************************************************************* return the size required by a struct in the stream ********************************************************************/ +uint32 spoolss_size_printer_enum_values(PRINTER_ENUM_VALUES *p) +{ + uint32 size = 0; + uint32 data_len; + + if (!p) + return 0; + + /* uint32(offset) + uint32(length) + length) */ + size += (size_of_uint32(&p->value_len)*2) + p->value_len; + size += (size_of_uint32(&p->data_len)*2) + p->data_len; + + size += size_of_uint32(&p->type); + + return size; +} + +/******************************************************************* +return the size required by a struct in the stream +********************************************************************/ uint32 spoolss_size_printmonitor_info_1(PRINTMONITOR_1 *info) { @@ -4729,10 +4749,13 @@ static BOOL uniarray_2_dosarray(BUFFER5 *buf5, fstring **ar) n++; } fstrcpy((*ar)[n], ""); - + return True; } + + + /******************************************************************* read a UNICODE array with null terminated strings and null terminated array @@ -6171,7 +6194,6 @@ BOOL spoolss_io_r_getprinterdataex(char *desc, SPOOL_R_GETPRINTERDATAEX *r_u, pr /******************************************************************* * read a structure. - * called from spoolss_q_setprinterdataex (srv_spoolss.c) ********************************************************************/ BOOL spoolss_io_q_setprinterdataex(char *desc, SPOOL_Q_SETPRINTERDATAEX *q_u, prs_struct *ps, int depth) @@ -6207,14 +6229,14 @@ BOOL spoolss_io_q_setprinterdataex(char *desc, SPOOL_Q_SETPRINTERDATAEX *q_u, pr case 0x3: case 0x4: case 0x7: - if (q_u->max_len) { - if (UNMARSHALLING(ps)) - q_u->data=(uint8 *)prs_alloc_mem(ps, q_u->max_len * sizeof(uint8)); - if(q_u->data == NULL) - return False; - if(!prs_uint8s(False,"data", ps, depth, q_u->data, q_u->max_len)) - return False; - } + if (q_u->max_len) { + if (UNMARSHALLING(ps)) + q_u->data=(uint8 *)prs_alloc_mem(ps, q_u->max_len * sizeof(uint8)); + if(q_u->data == NULL) + return False; + if(!prs_uint8s(False,"data", ps, depth, q_u->data, q_u->max_len)) + return False; + } if(!prs_align(ps)) return False; break; @@ -6228,7 +6250,6 @@ BOOL spoolss_io_q_setprinterdataex(char *desc, SPOOL_Q_SETPRINTERDATAEX *q_u, pr /******************************************************************* * write a structure. - * called from spoolss_q_setprinterdataex (srv_spoolss.c) ********************************************************************/ BOOL spoolss_io_r_setprinterdataex(char *desc, SPOOL_R_SETPRINTERDATAEX *r_u, prs_struct *ps, int depth) @@ -6243,3 +6264,179 @@ BOOL spoolss_io_r_setprinterdataex(char *desc, SPOOL_R_SETPRINTERDATAEX *r_u, pr return True; } + + +/******************************************************************* + * read a structure. + ********************************************************************/ + +BOOL spoolss_io_q_enumprinterkey(char *desc, SPOOL_Q_ENUMPRINTERKEY *q_u, prs_struct *ps, int depth) +{ + prs_debug(ps, depth, desc, "spoolss_io_q_enumprinterkey"); + depth++; + + if(!prs_align(ps)) + return False; + if(!smb_io_pol_hnd("printer handle", &q_u->handle, ps, depth)) + return False; + + if(!smb_io_unistr2("", &q_u->key, True, ps, depth)) + return False; + + if(!prs_align(ps)) + return False; + + if(!prs_uint32("size", ps, depth, &q_u->size)) + return False; + + return True; +} + +/******************************************************************* + * write a structure. + ********************************************************************/ + +BOOL spoolss_io_r_enumprinterkey(char *desc, SPOOL_R_ENUMPRINTERKEY *r_u, prs_struct *ps, int depth) +{ + prs_debug(ps, depth, desc, "spoolss_io_r_enumprinterkey"); + depth++; + + if(!prs_align(ps)) + return False; + + if (!smb_io_buffer5("", &r_u->keys, ps, depth)) + return False; + + if(!prs_uint32("needed", ps, depth, &r_u->needed)) + return False; + + if(!prs_werror("status", ps, depth, &r_u->status)) + return False; + + return True; +} + + +/******************************************************************* + * read a structure. + ********************************************************************/ + +BOOL spoolss_io_q_enumprinterdataex(char *desc, SPOOL_Q_ENUMPRINTERDATAEX *q_u, prs_struct *ps, int depth) +{ + prs_debug(ps, depth, desc, "spoolss_io_q_enumprinterdataex"); + depth++; + + if(!prs_align(ps)) + return False; + if(!smb_io_pol_hnd("printer handle", &q_u->handle, ps, depth)) + return False; + + if(!smb_io_unistr2("", &q_u->key, True, ps, depth)) + return False; + + if(!prs_align(ps)) + return False; + + if(!prs_uint32("size", ps, depth, &q_u->size)) + return False; + + return True; +} + +/******************************************************************* +********************************************************************/ +static BOOL spoolss_io_printer_enum_values_ctr(char *desc, prs_struct *ps, + PRINTER_ENUM_VALUES_CTR *ctr, int depth) +{ + int i; + uint32 valuename_offset, + data_offset, + current_offset; + + prs_debug(ps, depth, desc, "spoolss_io_printer_enum_values_ctr"); + depth++; + + if (!prs_uint32("size", ps, depth, &ctr->size)) + return False; + + /* offset data begins at 20 bytes per structure * size_of_array. + Don't forget the uint32 at the beginning */ + + current_offset = 4 + (20*ctr->size_of_array); + + /* first loop to write basic enum_value information */ + + for (i=0; i<ctr->size_of_array; i++) + { + valuename_offset = current_offset; + if (!prs_uint32("valuename_offset", ps, depth, &valuename_offset)) + return False; + + if (!prs_uint32("value_len", ps, depth, &ctr->values[i].value_len)) + return False; + + if (!prs_uint32("type", ps, depth, &ctr->values[i].type)) + return False; + + data_offset = ctr->values[i].value_len + valuename_offset; + if (!prs_uint32("data_offset", ps, depth, &data_offset)) + return False; + + if (!prs_uint32("data_len", ps, depth, &ctr->values[i].data_len)) + return False; + + current_offset = data_offset + ctr->values[i].data_len; + + } + + /* loop #2 for writing the dynamically size objects + while viewing oncversations between Win2k -> Win2k, + 4-byte alignment does not seem to matter here --jerrty */ + + for (i=0; i<ctr->size_of_array; i++) + { + + if (!prs_unistr("valuename", ps, depth, &ctr->values[i].valuename)) + return False; + + if (!prs_uint8s(False, "data", ps, depth, ctr->values[i].data, ctr->values[i].data_len)) + return False; + } + + + + return True; +} + + +/******************************************************************* + * write a structure. + ********************************************************************/ + +BOOL spoolss_io_r_enumprinterdataex(char *desc, SPOOL_R_ENUMPRINTERDATAEX *r_u, prs_struct *ps, int depth) +{ + prs_debug(ps, depth, desc, "spoolss_io_r_enumprinterdataex"); + depth++; + + if(!prs_align(ps)) + return False; + + if (!spoolss_io_printer_enum_values_ctr("", ps, &r_u->ctr, depth )) + return False; + + if(!prs_align(ps)) + return False; + + if(!prs_uint32("needed", ps, depth, &r_u->needed)) + return False; + + if(!prs_uint32("returned", ps, depth, &r_u->returned)) + return False; + + if(!prs_werror("status", ps, depth, &r_u->status)) + return False; + + return True; +} + + diff --git a/source3/rpc_server/srv_spoolss.c b/source3/rpc_server/srv_spoolss.c index 654e3875ce..3a056dcb65 100755 --- a/source3/rpc_server/srv_spoolss.c +++ b/source3/rpc_server/srv_spoolss.c @@ -1259,6 +1259,64 @@ static BOOL api_spoolss_setprinterdataex(pipes_struct *p) return True; } + +/**************************************************************************** +****************************************************************************/ + +static BOOL api_spoolss_enumprinterkey(pipes_struct *p) +{ + SPOOL_Q_ENUMPRINTERKEY q_u; + SPOOL_R_ENUMPRINTERKEY r_u; + prs_struct *data = &p->in_data.data; + prs_struct *rdata = &p->out_data.rdata; + + ZERO_STRUCT(q_u); + ZERO_STRUCT(r_u); + + if(!spoolss_io_q_enumprinterkey("", &q_u, data, 0)) { + DEBUG(0,("spoolss_io_q_setprinterkey: unable to unmarshall SPOOL_Q_ENUMPRINTERKEY.\n")); + return False; + } + + r_u.status = _spoolss_enumprinterkey(p, &q_u, &r_u); + + if(!spoolss_io_r_enumprinterkey("", &r_u, rdata, 0)) { + DEBUG(0,("spoolss_io_r_enumprinterkey: unable to marshall SPOOL_R_ENUMPRINTERKEY.\n")); + return False; + } + + return True; +} + +/**************************************************************************** +****************************************************************************/ + +static BOOL api_spoolss_enumprinterdataex(pipes_struct *p) +{ + SPOOL_Q_ENUMPRINTERDATAEX q_u; + SPOOL_R_ENUMPRINTERDATAEX r_u; + prs_struct *data = &p->in_data.data; + prs_struct *rdata = &p->out_data.rdata; + + ZERO_STRUCT(q_u); + ZERO_STRUCT(r_u); + + if(!spoolss_io_q_enumprinterdataex("", &q_u, data, 0)) { + DEBUG(0,("spoolss_io_q_enumprinterdataex: unable to unmarshall SPOOL_Q_ENUMPRINTERDATAEX.\n")); + return False; + } + + r_u.status = _spoolss_enumprinterdataex(p, &q_u, &r_u); + + if(!spoolss_io_r_enumprinterdataex("", &r_u, rdata, 0)) { + DEBUG(0,("spoolss_io_r_enumprinterdataex: unable to marshall SPOOL_R_ENUMPRINTERDATAEX.\n")); + return False; + } + + return True; +} + + /******************************************************************* \pipe\spoolss commands ********************************************************************/ @@ -1307,6 +1365,8 @@ struct api_struct api_spoolss_cmds[] = {"SPOOLSS_ENUMPRINTPROCDATATYPES", SPOOLSS_ENUMPRINTPROCDATATYPES, api_spoolss_enumprintprocdatatypes }, {"SPOOLSS_GETPRINTERDATAEX", SPOOLSS_GETPRINTERDATAEX, api_spoolss_getprinterdataex }, {"SPOOLSS_SETPRINTERDATAEX", SPOOLSS_SETPRINTERDATAEX, api_spoolss_setprinterdataex }, + {"SPOOLSS_ENUMPRINTERKEY", SPOOLSS_ENUMPRINTERKEY, api_spoolss_enumprinterkey }, + {"SPOOLSS_ENUMPRINTERDATAEX", SPOOLSS_ENUMPRINTERDATAEX, api_spoolss_enumprinterdataex }, { NULL, 0, NULL } }; diff --git a/source3/rpc_server/srv_spoolss_nt.c b/source3/rpc_server/srv_spoolss_nt.c index 968044b6cd..10c022962a 100644 --- a/source3/rpc_server/srv_spoolss_nt.c +++ b/source3/rpc_server/srv_spoolss_nt.c @@ -5,7 +5,8 @@ * Copyright (C) Andrew Tridgell 1992-2000, * Copyright (C) Luke Kenneth Casson Leighton 1996-2000, * Copyright (C) Jean François Micouleau 1998-2000. - * Copyright (C) Jeremy Allison 2001. + * Copyright (C) Jeremy Allison 2001. + * Copyright (C) Gerald Carter 2000-2001. * * 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 @@ -803,6 +804,7 @@ WERROR _spoolss_open_printer_ex( pipes_struct *p, SPOOL_Q_OPEN_PRINTER_EX *q_u, /* map an empty access mask to the minimum access mask */ if (printer_default->access_required == 0x0) printer_default->access_required = PRINTER_ACCESS_USE; + /* * If we are not serving the printer driver for this printer, @@ -1130,6 +1132,7 @@ WERROR _spoolss_deleteprinterdriver(pipes_struct *p, SPOOL_Q_DELETEPRINTERDRIVER /* check that we have a valid driver name first */ if ((version=get_version_id(arch)) == -1) { + /* this is what NT returns */ return WERR_INVALID_ENVIRONMENT; } @@ -1316,7 +1319,7 @@ WERROR _spoolss_getprinterdata(pipes_struct *p, SPOOL_Q_GETPRINTERDATA *q_u, SPO DEBUG(4,("_spoolss_getprinterdata\n")); if (!Printer) { - if((*data=(uint8 *)malloc(4*sizeof(uint8))) == NULL) + if((*data=(uint8 *)talloc_zero(p->mem_ctx, 4*sizeof(uint8))) == NULL) return WERR_NOMEM; DEBUG(0,("_spoolss_getprinterdata: Invalid handle (%s).\n", OUR_HANDLE(handle))); return WERR_BADFID; @@ -1344,9 +1347,8 @@ WERROR _spoolss_getprinterdata(pipes_struct *p, SPOOL_Q_GETPRINTERDATA *q_u, SPO if (*needed > *out_size) return WERR_STATUS_MORE_ENTRIES; - else { + else return WERR_OK; - } } /*************************************************************************** @@ -2235,13 +2237,13 @@ static BOOL construct_notify_printer_info(SPOOL_NOTIFY_INFO *info, int if (!search_notify(type, field, &j) ) continue; - + if((tid=(SPOOL_NOTIFY_INFO_DATA *)Realloc(info->data, (info->count+1)*sizeof(SPOOL_NOTIFY_INFO_DATA))) == NULL) { DEBUG(0,("construct_notify_printer_info: failed to enlarge buffer info->data!\n")); return False; } else info->data = tid; - + current_data=&info->data[info->count]; construct_info_data(current_data, type, field, id); @@ -3180,6 +3182,7 @@ WERROR _spoolss_enumprinters( pipes_struct *p, SPOOL_Q_ENUMPRINTERS *q_u, SPOOL_ uint32 offered = q_u->offered; uint32 *needed = &r_u->needed; uint32 *returned = &r_u->returned; + fstring name; /* that's an [in out] buffer */ @@ -3902,6 +3905,7 @@ WERROR _spoolss_getprinterdriver2(pipes_struct *p, SPOOL_Q_GETPRINTERDRIVER2 *q_ case 6: return getprinterdriver2_level6(servername, architecture, clientmajorversion, snum, buffer, offered, needed); } + return WERR_UNKNOWN_LEVEL; } @@ -4700,9 +4704,9 @@ WERROR _spoolss_addjob(pipes_struct *p, SPOOL_Q_ADDJOB *q_u, SPOOL_R_ADDJOB *r_u r_u->needed = 0; return WERR_INVALID_PARAM; /* this is what a NT server - returns for AddJob. AddJob - must fail on non-local - printers */ + returns for AddJob. AddJob + must fail on non-local + printers */ } /**************************************************************************** @@ -5008,6 +5012,7 @@ static WERROR enumprinterdrivers_level1(fstring servername, fstring architecture int ndrivers; uint32 version; fstring *list = NULL; + NT_PRINTER_DRIVER_INFO_LEVEL driver; DRIVER_INFO_1 *tdi1, *driver_info_1=NULL; @@ -5087,6 +5092,7 @@ static WERROR enumprinterdrivers_level2(fstring servername, fstring architecture int ndrivers; uint32 version; fstring *list = NULL; + NT_PRINTER_DRIVER_INFO_LEVEL driver; DRIVER_INFO_2 *tdi2, *driver_info_2=NULL; @@ -5167,6 +5173,7 @@ static WERROR enumprinterdrivers_level3(fstring servername, fstring architecture int ndrivers; uint32 version; fstring *list = NULL; + NT_PRINTER_DRIVER_INFO_LEVEL driver; DRIVER_INFO_3 *tdi3, *driver_info_3=NULL; @@ -5776,13 +5783,13 @@ static WERROR spoolss_addprinterex_level_2( pipes_struct *p, const UNISTR2 *uni_ return WERR_INVALID_PARAM; } - /* + /* * When a printer is created, the drivername bound to the printer is used - * to lookup previously saved driver initialization info, which is then + * to lookup previously saved driver initialization info, which is then * bound to the new printer, simulating what happens in the Windows arch. */ set_driver_init(printer, 2); - + /* write the ASCII on disk */ err = add_a_printer(*printer, 2); if (!W_ERROR_IS_OK(err)) { @@ -6165,7 +6172,6 @@ WERROR _spoolss_setprinterdata( pipes_struct *p, SPOOL_Q_SETPRINTERDATA *q_u, SP goto done; } - /* Check if we are making any changes or not. Return true if nothing is actually changing. This is not needed anymore but has been left in as an optimization to keep from from @@ -6177,6 +6183,7 @@ WERROR _spoolss_setprinterdata( pipes_struct *p, SPOOL_Q_SETPRINTERDATA *q_u, SP convert_specific_param(¶m, value , type, data, real_len); + if (get_specific_param(*printer, 2, param->value, &old_param.data, &old_param.type, (uint32 *)&old_param.data_len)) { @@ -6192,7 +6199,7 @@ WERROR _spoolss_setprinterdata( pipes_struct *p, SPOOL_Q_SETPRINTERDATA *q_u, SP } unlink_specific_param_if_exist(printer->info_2, param); - + /* * When client side code sets a magic printer data key, detect it and save * the current printer data and the magic key's data (its the DEVMODE) for @@ -6208,7 +6215,7 @@ WERROR _spoolss_setprinterdata( pipes_struct *p, SPOOL_Q_SETPRINTERDATA *q_u, SP add_a_specific_param(printer->info_2, ¶m); status = mod_a_printer(*printer, 2); } - + done: free_a_printer(&printer, 2); if (param) @@ -6326,7 +6333,7 @@ WERROR _spoolss_deleteform( pipes_struct *p, SPOOL_Q_DELETEFORM *q_u, SPOOL_R_DE } count = get_ntforms(&list); - if (!delete_a_form(&list, form_name, &count, &ret)) + if(!delete_a_form(&list, form_name, &count, &ret)) return WERR_INVALID_PARAM; SAFE_FREE(list); @@ -6408,9 +6415,9 @@ WERROR _spoolss_enumprintprocessors(pipes_struct *p, SPOOL_Q_ENUMPRINTPROCESSORS /* UNISTR2 *name = &q_u->name; - notused. */ /* UNISTR2 *environment = &q_u->environment; - notused. */ uint32 level = q_u->level; - NEW_BUFFER *buffer = NULL; + NEW_BUFFER *buffer = NULL; uint32 offered = q_u->offered; - uint32 *needed = &r_u->needed; + uint32 *needed = &r_u->needed; uint32 *returned = &r_u->returned; /* that's an [in out] buffer */ @@ -6570,9 +6577,9 @@ WERROR _spoolss_enumprintmonitors(pipes_struct *p, SPOOL_Q_ENUMPRINTMONITORS *q_ { /* UNISTR2 *name = &q_u->name; - notused. */ uint32 level = q_u->level; - NEW_BUFFER *buffer = NULL; + NEW_BUFFER *buffer = NULL; uint32 offered = q_u->offered; - uint32 *needed = &r_u->needed; + uint32 *needed = &r_u->needed; uint32 *returned = &r_u->returned; /* that's an [in out] buffer */ @@ -6624,8 +6631,8 @@ static WERROR getjob_level_1(print_queue_struct *queue, int count, int snum, uin if (found==False) { SAFE_FREE(queue); SAFE_FREE(info_1); - /* I shoud reply something else ... I can't find the good one */ - return WERR_OK; + /* NT treats not found as bad param... yet another bad choice */ + return WERR_INVALID_PARAM; } fill_job_info_1(info_1, &(queue[i-1]), i, snum); @@ -6677,8 +6684,8 @@ static WERROR getjob_level_2(print_queue_struct *queue, int count, int snum, uin if (found==False) { SAFE_FREE(queue); SAFE_FREE(info_2); - /* I shoud reply something else ... I can't find the good one */ - return WERR_OK; + /* NT treats not found as bad param... yet another bad choice */ + return WERR_INVALID_PARAM; } ret = get_a_printer(&ntprinter, 2, lp_servicename(snum)); @@ -6762,17 +6769,81 @@ WERROR _spoolss_getjob( pipes_struct *p, SPOOL_Q_GETJOB *q_u, SPOOL_R_GETJOB *r_ WERROR _spoolss_getprinterdataex(pipes_struct *p, SPOOL_Q_GETPRINTERDATAEX *q_u, SPOOL_R_GETPRINTERDATAEX *r_u) { - fstring key; + POLICY_HND *handle = &q_u->handle; + uint32 in_size = q_u->size; + uint32 *type = &r_u->type; + uint32 *out_size = &r_u->size; + uint8 **data = &r_u->data; + uint32 *needed = &r_u->needed; - /* From MSDN documentation of GetPrinterDataEx: pass request to - GetPrinterData if key is "PrinterDriverData" */ + fstring key, value; + Printer_entry *Printer = find_printer_index_by_hnd(p, handle); + BOOL found = False; + + DEBUG(4,("_spoolss_getprinterdataex\n")); unistr2_to_ascii(key, &q_u->keyname, sizeof(key) - 1); + unistr2_to_ascii(value, &q_u->valuename, sizeof(value) - 1); - if (strcmp(key, "PrinterDriverData") == 0) - DEBUG(10, ("pass me to getprinterdata\n")); - - return WERR_INVALID_PARAM; + /* in case of problem, return some default values */ + *needed=0; + *type=0; + *out_size=0; + + + if (!Printer) { + if((*data=(uint8 *)talloc_zero(p->mem_ctx, 4*sizeof(uint8))) == NULL) + return WERR_NOMEM; + DEBUG(0,("_spoolss_getprinterdata: Invalid handle (%s).\n", OUR_HANDLE(handle))); + return WERR_BADFID; + } + + + /* Is the handle to a printer or to the server? */ + + if (Printer->printer_type == PRINTER_HANDLE_IS_PRINTSERVER) + { + DEBUG(10,("_spoolss_getprinterdatex: Not implemented for server handles yet\n")); + return WERR_INVALID_PARAM; + } + else + { + /* + * From MSDN documentation of GetPrinterDataEx: pass request + * to GetPrinterData if key is "PrinterDriverData". This is + * the only key we really support. Other keys to implement: + * (a) DsDriver + * (b) DsSpooler + * (c) PnPData + */ + + if (strcmp(key, "PrinterDriverData") != 0) + return WERR_INVALID_PARAM; + + DEBUG(10, ("_spoolss_getprinterdataex: pass me to getprinterdata\n")); + found = getprinterdata_printer(p, p->mem_ctx, handle, value, + type, data, needed, in_size); + + } + + if (!found) { + DEBUG(5, ("value not found, allocating %d\n", *out_size)); + + /* reply this param doesn't exist */ + if (*out_size) { + if((*data=(uint8 *)talloc_zero(p->mem_ctx, *out_size*sizeof(uint8))) == NULL) + return WERR_NOMEM; + } else { + *data = NULL; + } + + return WERR_INVALID_PARAM; + } + + if (*needed > *out_size) + return WERR_MORE_DATA; + else + return WERR_OK; } /******************************************************************** @@ -6781,15 +6852,233 @@ WERROR _spoolss_getprinterdataex(pipes_struct *p, SPOOL_Q_GETPRINTERDATAEX *q_u, WERROR _spoolss_setprinterdataex(pipes_struct *p, SPOOL_Q_SETPRINTERDATAEX *q_u, SPOOL_R_SETPRINTERDATAEX *r_u) { + SPOOL_Q_SETPRINTERDATA q_u_local; + SPOOL_R_SETPRINTERDATA r_u_local; fstring key; + DEBUG(4,("_spoolss_setprinterdataex\n")); + /* From MSDN documentation of SetPrinterDataEx: pass request to SetPrinterData if key is "PrinterDriverData" */ unistr2_to_ascii(key, &q_u->key, sizeof(key) - 1); if (strcmp(key, "PrinterDriverData") == 0) - DEBUG(10, ("pass me to setprinterdata\n")); + return WERR_INVALID_PARAM; + + ZERO_STRUCT(q_u_local); + ZERO_STRUCT(r_u_local); + + /* make a copy to call _spoolss_setprinterdata() */ + + memcpy(&q_u_local.handle, &q_u->handle, sizeof(POLICY_HND)); + copy_unistr2(&q_u_local.value, &q_u->value); + q_u_local.type = q_u->type; + q_u_local.max_len = q_u->max_len; + q_u_local.data = q_u->data; + q_u_local.real_len = q_u->real_len; + q_u_local.numeric_data = q_u->numeric_data; + + return _spoolss_setprinterdata(p, &q_u_local, &r_u_local); +} + +/******************************************************************** + * spoolss_enumprinterkey + ********************************************************************/ + +/* constants for EnumPrinterKey() */ +#define ENUMERATED_KEY_SIZE 19 + +WERROR _spoolss_enumprinterkey(pipes_struct *p, SPOOL_Q_ENUMPRINTERKEY *q_u, SPOOL_R_ENUMPRINTERKEY *r_u) +{ + fstring key; + uint16 enumkeys[ENUMERATED_KEY_SIZE+1]; + char* ptr = NULL; + int i; + char *PrinterKey = "PrinterDriverData"; + + DEBUG(4,("_spoolss_enumprinterkey\n")); - return WERR_INVALID_PARAM; + unistr2_to_ascii(key, &q_u->key, sizeof(key) - 1); + + /* + * we only support enumating all keys (key == "") + * Of course, the only key we support is the "PrinterDriverData" + * key + */ + if (strlen(key) == 0) + { + r_u->needed = ENUMERATED_KEY_SIZE *2; + if (q_u->size < r_u->needed) + return WERR_MORE_DATA; + + ptr = PrinterKey; + for (i=0; i<ENUMERATED_KEY_SIZE-2; i++) + { + enumkeys[i] = (uint16)(*ptr); + ptr++; + } + + if (!make_spoolss_buffer5(p->mem_ctx, &r_u->keys, ENUMERATED_KEY_SIZE, enumkeys)) + return WERR_BADFILE; + + return WERR_OK; + } + + /* The "PrinterDriverData" key should have no subkeys */ + if (strcmp(key, PrinterKey) == 0) + { + r_u-> needed = 2; + if (q_u->size < r_u->needed) + return WERR_MORE_DATA; + enumkeys[0] = 0x0; + if (!make_spoolss_buffer5(p->mem_ctx, &r_u->keys, 1, enumkeys)) + return WERR_BADFILE; + + return WERR_OK; + } + + + /* The return value for an unknown key is documented in MSDN + EnumPrinterKey description */ + return WERR_BADFILE; +} + +/******************************************************************** + * spoolss_enumprinterdataex + ********************************************************************/ + +WERROR _spoolss_enumprinterdataex(pipes_struct *p, SPOOL_Q_ENUMPRINTERDATAEX *q_u, SPOOL_R_ENUMPRINTERDATAEX *r_u) +{ + POLICY_HND *handle = &q_u->handle; + uint32 in_size = q_u->size; + uint32 num_entries, + needed; + NT_PRINTER_INFO_LEVEL *printer = NULL; + PRINTER_ENUM_VALUES *enum_values = NULL; + fstring key, value; + Printer_entry *Printer = find_printer_index_by_hnd(p, handle); + int snum; + uint32 param_index, + data_len, + type; + WERROR result; + uint8 *data=NULL; + uint32 i; + + + DEBUG(4,("_spoolss_enumprinterdataex\n")); + + if (!Printer) { + DEBUG(0,("_spoolss_enumprinterdata: Invalid handle (%s).\n", OUR_HANDLE(handle))); + return WERR_BADFID; + } + + + /* + * The only key we support is "PrinterDriverData". This should return + > an array of all the key/value pairs returned by EnumPrinterDataSee + * _spoolss_getprinterdataex() for details --jerry + */ + + unistr2_to_ascii(key, &q_u->key, sizeof(key) - 1); + if (strcmp(key, "PrinterDriverData") != 0) + { + DEBUG(10,("_spoolss_enumprinterdataex: Unknown keyname [%s]\n", key)); + return WERR_INVALID_PARAM; + } + + + if (!get_printer_snum(p,handle, &snum)) + return WERR_BADFID; + + ZERO_STRUCT(printer); + result = get_a_printer(&printer, 2, lp_servicename(snum)); + if (!W_ERROR_IS_OK(result)) + return result; + + + /* + * loop through all params and build the array to pass + * back to the client + */ + result = WERR_OK; + param_index = 0; + needed = 0; + num_entries = 0; + + while (get_specific_param_by_index(*printer, 2, param_index, value, &data, &type, &data_len)) + { + PRINTER_ENUM_VALUES *ptr; + uint32 add_len = 0; + + DEBUG(10,("retrieved value number [%d] [%s]\n", num_entries, value)); + + if ((ptr=talloc_realloc(p->mem_ctx, enum_values, (num_entries+1) * sizeof(PRINTER_ENUM_VALUES))) == NULL) + { + DEBUG(0,("talloc_realloc failed to allocate more memory!\n")); + result = WERR_NOMEM; + goto done; + } + enum_values = ptr; + + /* copy the data */ + init_unistr(&enum_values[num_entries].valuename, value); + enum_values[num_entries].value_len = (strlen(value)+1) * 2; + enum_values[num_entries].type = type; + + /* + * NULL terminate REG_SZ + * FIXME!!! We should not be correctly problems in the way + * we store PrinterData here. Need to investogate + * SetPrinterData[Ex] --jerry + */ + + if (type == REG_SZ) { + /* fix alignment if the string was stored + in a bizarre fashion */ + if ((data_len % 2) == 0) + add_len = 2; + else + add_len = data_len % 2; + } + + if (!(enum_values[num_entries].data=talloc_zero(p->mem_ctx, data_len+add_len))) { + DEBUG(0,("talloc_realloc failed to allocate more memory for data!\n")); + result = WERR_NOMEM; + goto done; + } + memcpy(enum_values[num_entries].data, data, data_len); + enum_values[num_entries].data_len = data_len + add_len; + + /* keep track of the size of the array in bytes */ + + needed += spoolss_size_printer_enum_values(&enum_values[num_entries]); + + num_entries++; + param_index++; + } + + r_u->needed = needed; + r_u->returned = num_entries; + + if (needed > in_size) { + result = WERR_MORE_DATA; + goto done; + } + + /* copy data into the reply */ + + r_u->ctr.size = r_u->needed; + r_u->ctr.size_of_array = r_u->returned; + r_u->ctr.values = enum_values; + + + +done: + free_a_printer(&printer, 2); + + return result; } + + |