diff options
author | Jean-François Micouleau <jfm@samba.org> | 1999-07-27 10:46:44 +0000 |
---|---|---|
committer | Jean-François Micouleau <jfm@samba.org> | 1999-07-27 10:46:44 +0000 |
commit | 4bff2675746518af740e475e4e996247ac21d817 (patch) | |
tree | 86cf0e3697c4091909be7dd9466bf213acc2964b | |
parent | f2e0bbffb5e40df4850b6bd0eae73a8fb0edc6d7 (diff) | |
download | samba-4bff2675746518af740e475e4e996247ac21d817.tar.gz samba-4bff2675746518af740e475e4e996247ac21d817.tar.bz2 samba-4bff2675746518af740e475e4e996247ac21d817.zip |
- enumprintprocessors and enumprintmonitors added.
- getjob (level 1 and 2) done.
- better handling of getprinterdriver (level 2).
- added workaround to print PCL files.
Now the spoolss code should be compliant with all kind of printers :-)
Jean Francois
(This used to be commit bf9b639bf9162d61eb152af506dc2c1a7e8a4c85)
-rw-r--r-- | source3/include/proto.h | 4 | ||||
-rwxr-xr-x | source3/include/rpc_spoolss.h | 50 | ||||
-rw-r--r-- | source3/rpc_parse/parse_spoolss.c | 407 | ||||
-rwxr-xr-x | source3/rpc_server/srv_spoolss.c | 334 |
4 files changed, 699 insertions, 96 deletions
diff --git a/source3/include/proto.h b/source3/include/proto.h index 04b002ae57..2c7b386ac2 100644 --- a/source3/include/proto.h +++ b/source3/include/proto.h @@ -2868,6 +2868,8 @@ void spoolss_io_r_getprinterdriverdir(char *desc, SPOOL_R_GETPRINTERDRIVERDIR *r void spoolss_io_q_getprinterdriverdir(char *desc, SPOOL_Q_GETPRINTERDRIVERDIR *q_u, prs_struct *ps, int depth); void spoolss_io_r_enumprintprocessors(char *desc, SPOOL_R_ENUMPRINTPROCESSORS *r_u, prs_struct *ps, int depth); void spoolss_io_q_enumprintprocessors(char *desc, SPOOL_Q_ENUMPRINTPROCESSORS *q_u, prs_struct *ps, int depth); +void spoolss_io_r_enumprintmonitors(char *desc, SPOOL_R_ENUMPRINTMONITORS *r_u, prs_struct *ps, int depth); +void spoolss_io_q_enumprintmonitors(char *desc, SPOOL_Q_ENUMPRINTMONITORS *q_u, prs_struct *ps, int depth); void spoolss_io_r_enumprinterdata(char *desc, SPOOL_R_ENUMPRINTERDATA *r_u, prs_struct *ps, int depth); void spoolss_io_q_enumprinterdata(char *desc, SPOOL_Q_ENUMPRINTERDATA *q_u, prs_struct *ps, int depth); void spoolss_io_q_setprinterdata(char *desc, SPOOL_Q_SETPRINTERDATA *q_u, prs_struct *ps, int depth); @@ -2877,6 +2879,8 @@ void spoolss_io_q_addform(char *desc, SPOOL_Q_ADDFORM *q_u, prs_struct *ps, int void spoolss_io_r_addform(char *desc, SPOOL_R_ADDFORM *r_u, prs_struct *ps, int depth); void spoolss_io_q_setform(char *desc, SPOOL_Q_SETFORM *q_u, prs_struct *ps, int depth); void spoolss_io_r_setform(char *desc, SPOOL_R_SETFORM *r_u, prs_struct *ps, int depth); +void spoolss_io_r_getjob(char *desc, SPOOL_R_GETJOB *r_u, prs_struct *ps, int depth); +void spoolss_io_q_getjob(char *desc, SPOOL_Q_GETJOB *q_u, prs_struct *ps, int depth); /*The following definitions come from rpc_parse/parse_srv.c */ diff --git a/source3/include/rpc_spoolss.h b/source3/include/rpc_spoolss.h index 8476ad7691..a8f934fc47 100755 --- a/source3/include/rpc_spoolss.h +++ b/source3/include/rpc_spoolss.h @@ -29,7 +29,6 @@ /* spoolss pipe: this are the calls which are not implemented ... #define SPOOLSS_OPENPRINTER 0x01 -#define SPOOLSS_GETJOB 0x03 #define SPOOLSS_DELETEPRINTER 0x06 #define SPOOLSS_GETPRINTERDRIVER 0x0b #define SPOOLSS_DELETEPRINTERDRIVER 0x0d @@ -40,7 +39,6 @@ #define SPOOLSS_WAITFORPRINTERCHANGE 0x1c #define SPOOLSS_DELETEFORM 0x1f #define SPOOLSS_GETFORM 0x20 -#define SPOOLSS_ENUMMONITORS 0x24 #define SPOOLSS_ADDPORT 0x25 #define SPOOLSS_CONFIGUREPORT 0x26 #define SPOOLSS_DELETEPORT 0x27 @@ -73,6 +71,7 @@ #define SPOOLSS_ENUMPRINTERS 0x00 #define SPOOLSS_SETJOB 0x02 +#define SPOOLSS_GETJOB 0x03 #define SPOOLSS_ENUMJOBS 0x04 #define SPOOLSS_ADDPRINTER 0x05 #define SPOOLSS_SETPRINTER 0x07 @@ -95,6 +94,7 @@ #define SPOOLSS_SETFORM 0x21 #define SPOOLSS_ENUMFORMS 0x22 #define SPOOLSS_ENUMPORTS 0x23 +#define SPOOLSS_ENUMMONITORS 0x24 #define SPOOLSS_ENUMPRINTPROCESSORDATATYPES 0x33 #define SPOOLSS_GETPRINTERDRIVER2 0x35 /* find close printer notification */ @@ -891,7 +891,7 @@ typedef struct driver_info_3 UNISTR datafile; UNISTR configfile; UNISTR helpfile; - UNISTR dependentfiles; + UNISTR **dependentfiles; UNISTR monitorname; UNISTR defaultdatatype; } DRIVER_INFO_3; @@ -977,7 +977,7 @@ typedef struct s_job_info_2 UNISTR printprocessor; UNISTR parameters; UNISTR drivername; - DEVICEMODE devmode; + DEVICEMODE *devmode; UNISTR text_status; /* SEC_DESC sec_desc;*/ uint32 status; @@ -1369,6 +1369,28 @@ typedef struct spool_r_enumprintprocessordatatypes uint32 status; } SPOOL_R_ENUMPRINTPROCESSORDATATYPES; +typedef struct spool_q_enumprintmonitors +{ + UNISTR2 name; + uint32 level; + BUFFER buffer; + uint32 buf_size; +} SPOOL_Q_ENUMPRINTMONITORS; + +typedef struct printmonitor_1 +{ + UNISTR name; +} PRINTMONITOR_1; + +typedef struct spool_r_enumprintmonitors +{ + uint32 level; + PRINTMONITOR_1 *info_1; + uint32 offered; + uint32 numofprintmonitors; + uint32 status; +} SPOOL_R_ENUMPRINTMONITORS; + typedef struct spool_q_enumprinterdata { PRINTER_HND handle; @@ -1445,6 +1467,26 @@ typedef struct spool_r_setform uint32 status; } SPOOL_R_SETFORM; +typedef struct spool_q_getjob +{ + PRINTER_HND handle; + uint32 jobid; + uint32 level; + BUFFER buffer; + uint32 buf_size; +} SPOOL_Q_GETJOB; + +typedef struct spool_r_getjob +{ + uint32 level; + union { + JOB_INFO_1 *job_info_1; + JOB_INFO_2 *job_info_2; + } job; + uint32 offered; + uint32 status; +} SPOOL_R_GETJOB; + #define PRINTER_DRIVER_VERSION 2 #define PRINTER_DRIVER_ARCHITECTURE "Windows NT x86" diff --git a/source3/rpc_parse/parse_spoolss.c b/source3/rpc_parse/parse_spoolss.c index 08ea5f73a2..a1ee058e06 100644 --- a/source3/rpc_parse/parse_spoolss.c +++ b/source3/rpc_parse/parse_spoolss.c @@ -98,16 +98,13 @@ static void smb_io_doc_info_1(char *desc, DOC_INFO_1 *info_1, prs_struct *ps, in prs_align(ps); - prs_uint32("p_docname", ps, depth, &(info_1->p_docname)); + prs_uint32("p_docname", ps, depth, &(info_1->p_docname)); prs_uint32("p_outputfile", ps, depth, &(info_1->p_outputfile)); - prs_uint32("p_datatype", ps, depth, &(info_1->p_datatype)); + prs_uint32("p_datatype", ps, depth, &(info_1->p_datatype)); - if (info_1->p_docname) - smb_io_unistr2("", &(info_1->docname),True,ps,depth); - if (info_1->p_outputfile) - smb_io_unistr2("", &(info_1->outputfile),True,ps,depth); - if (info_1->p_datatype) - smb_io_unistr2("", &(info_1->datatype),True,ps,depth); + smb_io_unistr2("", &(info_1->docname), info_1->p_docname, ps, depth); + smb_io_unistr2("", &(info_1->outputfile), info_1->p_outputfile, ps, depth); + smb_io_unistr2("", &(info_1->datatype), info_1->p_datatype, ps, depth); } /******************************************************************* @@ -818,6 +815,35 @@ static void smb_io_relstr(char *desc, prs_struct *ps, int depth, UNISTR *buffer, prs_uint32("offset", ps, depth, &(relative_offset)); } + +/******************************************************************* + * write a array UNICODE strings and its relative pointer. + * used by 2 RPC structs + ********************************************************************/ +static void smb_io_relarraystr(char *desc, prs_struct *ps, int depth, UNISTR ***buffer, + uint32 *start_offset, uint32 *end_offset) +{ + int i=0; + uint32 struct_offset; + uint32 relative_offset; + struct_offset=ps->offset; + + + while ( (*buffer)[i]!=0x0000 ) + { + *end_offset-= 2*(str_len_uni((*buffer)[i])+1); + ps->offset=*end_offset; + spoolss_smb_io_unistr(desc, (*buffer)[i], ps, depth); + + i++; + } + + ps->offset=struct_offset; + relative_offset=*end_offset-*start_offset; + + prs_uint32("offset", ps, depth, &(relative_offset)); +} + /******************************************************************* * write a DEVICEMODE struct. * on reading allocate memory for the private member @@ -1053,7 +1079,9 @@ static void smb_io_printer_driver_info_3(char *desc, DRIVER_INFO_3 *info,prs_str smb_io_relstr("datafile", ps, depth, &(info->datafile), start_offset, end_offset); smb_io_relstr("configfile", ps, depth, &(info->configfile), start_offset, end_offset); smb_io_relstr("helpfile", ps, depth, &(info->helpfile), start_offset, end_offset); - smb_io_relstr("dependentfiles", ps, depth, &(info->dependentfiles), start_offset, end_offset); + + smb_io_relarraystr("dependentfiles", ps, depth, &(info->dependentfiles), start_offset, end_offset); + smb_io_relstr("monitorname", ps, depth, &(info->monitorname), start_offset, end_offset); smb_io_relstr("defaultdatatype", ps, depth, &(info->defaultdatatype), start_offset, end_offset); } @@ -1061,64 +1089,64 @@ static void smb_io_printer_driver_info_3(char *desc, DRIVER_INFO_3 *info,prs_str /******************************************************************* ********************************************************************/ static void smb_io_job_info_1(char *desc, JOB_INFO_1 *info, prs_struct *ps, int depth, - uint32 *start_offset, uint32 *end_offset) + uint32 *start_offset, uint32 *end_offset) { prs_debug(ps, depth, desc, "smb_io_job_info_1"); depth++; *start_offset=ps->offset; - prs_uint32("jobid", ps, depth, &(info->jobid)); - smb_io_relstr("printername",ps, depth, &(info->printername), start_offset, end_offset); - smb_io_relstr("machinename",ps, depth, &(info->machinename), start_offset, end_offset); - smb_io_relstr("username",ps, depth, &(info->username), start_offset, end_offset); - smb_io_relstr("document",ps, depth, &(info->document), start_offset, end_offset); - smb_io_relstr("datatype",ps, depth, &(info->datatype), start_offset, end_offset); - smb_io_relstr("text_status",ps, depth, &(info->text_status), start_offset, end_offset); - prs_uint32("status", ps, depth, &(info->status)); - prs_uint32("priority", ps, depth, &(info->priority)); - prs_uint32("position", ps, depth, &(info->position)); - prs_uint32("totalpages", ps, depth, &(info->totalpages)); - prs_uint32("pagesprinted", ps, depth, &(info->pagesprinted)); + prs_uint32("jobid", ps, depth, &(info->jobid)); + smb_io_relstr("printername", ps, depth, &(info->printername), start_offset, end_offset); + smb_io_relstr("machinename", ps, depth, &(info->machinename), start_offset, end_offset); + smb_io_relstr("username", ps, depth, &(info->username), start_offset, end_offset); + smb_io_relstr("document", ps, depth, &(info->document), start_offset, end_offset); + smb_io_relstr("datatype", ps, depth, &(info->datatype), start_offset, end_offset); + smb_io_relstr("text_status", ps, depth, &(info->text_status), start_offset, end_offset); + prs_uint32("status", ps, depth, &(info->status)); + prs_uint32("priority", ps, depth, &(info->priority)); + prs_uint32("position", ps, depth, &(info->position)); + prs_uint32("totalpages", ps, depth, &(info->totalpages)); + prs_uint32("pagesprinted", ps, depth, &(info->pagesprinted)); spoolss_io_system_time("submitted", ps, depth, &(info->submitted) ); } /******************************************************************* ********************************************************************/ static void smb_io_job_info_2(char *desc, JOB_INFO_2 *info, prs_struct *ps, int depth, - uint32 *start_offset, uint32 *end_offset) + uint32 *start_offset, uint32 *end_offset) { int pipo=0; prs_debug(ps, depth, desc, "smb_io_job_info_2"); depth++; *start_offset=ps->offset; - prs_uint32("jobid", ps, depth, &(info->jobid)); - smb_io_relstr("printername",ps, depth, &(info->printername), start_offset, end_offset); - smb_io_relstr("machinename",ps, depth, &(info->machinename), start_offset, end_offset); - smb_io_relstr("username",ps, depth, &(info->username), start_offset, end_offset); - smb_io_relstr("document",ps, depth, &(info->document), start_offset, end_offset); - smb_io_relstr("notifyname",ps, depth, &(info->notifyname), start_offset, end_offset); - smb_io_relstr("datatype",ps, depth, &(info->datatype), start_offset, end_offset); + prs_uint32("jobid", ps, depth, &(info->jobid)); + smb_io_relstr("printername", ps, depth, &(info->printername), start_offset, end_offset); + smb_io_relstr("machinename", ps, depth, &(info->machinename), start_offset, end_offset); + smb_io_relstr("username", ps, depth, &(info->username), start_offset, end_offset); + smb_io_relstr("document", ps, depth, &(info->document), start_offset, end_offset); + smb_io_relstr("notifyname", ps, depth, &(info->notifyname), start_offset, end_offset); + smb_io_relstr("datatype", ps, depth, &(info->datatype), start_offset, end_offset); - smb_io_relstr("printprocessor",ps, depth, &(info->printprocessor), start_offset, end_offset); - smb_io_relstr("parameters",ps, depth, &(info->parameters), start_offset, end_offset); - smb_io_relstr("drivername",ps, depth, &(info->drivername), start_offset, end_offset); - smb_io_reldevmode("devmode", ps, depth, &(info->devmode), start_offset, end_offset); - smb_io_relstr("text_status",ps, depth, &(info->text_status), start_offset, end_offset); + smb_io_relstr("printprocessor", ps, depth, &(info->printprocessor), start_offset, end_offset); + smb_io_relstr("parameters", ps, depth, &(info->parameters), start_offset, end_offset); + smb_io_relstr("drivername", ps, depth, &(info->drivername), start_offset, end_offset); + smb_io_reldevmode("devmode", ps, depth, info->devmode, start_offset, end_offset); + smb_io_relstr("text_status", ps, depth, &(info->text_status), start_offset, end_offset); /* SEC_DESC sec_desc;*/ prs_uint32("Hack! sec desc", ps, depth, &pipo); - prs_uint32("status", ps, depth, &(info->status)); - prs_uint32("priority", ps, depth, &(info->priority)); - prs_uint32("position", ps, depth, &(info->position)); - prs_uint32("starttime", ps, depth, &(info->starttime)); - prs_uint32("untiltime", ps, depth, &(info->untiltime)); - prs_uint32("totalpages", ps, depth, &(info->totalpages)); - prs_uint32("size", ps, depth, &(info->size)); + prs_uint32("status", ps, depth, &(info->status)); + prs_uint32("priority", ps, depth, &(info->priority)); + prs_uint32("position", ps, depth, &(info->position)); + prs_uint32("starttime", ps, depth, &(info->starttime)); + prs_uint32("untiltime", ps, depth, &(info->untiltime)); + prs_uint32("totalpages", ps, depth, &(info->totalpages)); + prs_uint32("size", ps, depth, &(info->size)); spoolss_io_system_time("submitted", ps, depth, &(info->submitted) ); - prs_uint32("timeelapsed", ps, depth, &(info->timeelapsed)); - prs_uint32("pagesprinted", ps, depth, &(info->pagesprinted)); + prs_uint32("timeelapsed", ps, depth, &(info->timeelapsed)); + prs_uint32("pagesprinted", ps, depth, &(info->pagesprinted)); } /******************************************************************* @@ -1157,6 +1185,30 @@ static void smb_io_port_2(char *desc, PORT_INFO_2 *info, prs_struct *ps, int dep } /******************************************************************* +********************************************************************/ +static void smb_io_processor_info_1(char *desc, PRINTPROCESSOR_1 *info, prs_struct *ps, int depth, + uint32 *start_offset, uint32 *end_offset) +{ + prs_debug(ps, depth, desc, "smb_io_processor_info_1"); + depth++; + *start_offset=ps->offset; + + smb_io_relstr("name",ps, depth, &(info->name), start_offset, end_offset); +} + +/******************************************************************* +********************************************************************/ +static void smb_io_monitor_info_1(char *desc, PRINTMONITOR_1 *info, prs_struct *ps, int depth, + uint32 *start_offset, uint32 *end_offset) +{ + prs_debug(ps, depth, desc, "smb_io_monitor_info_1"); + depth++; + *start_offset=ps->offset; + + smb_io_relstr("name",ps, depth, &(info->name), start_offset, end_offset); +} + +/******************************************************************* return the size required by a struct in the stream ********************************************************************/ static uint32 spoolss_size_printer_info_0(PRINTER_INFO_0 *info) @@ -1255,6 +1307,9 @@ return the size required by a struct in the stream static uint32 spoolss_size_printer_driver_info_3(DRIVER_INFO_3 *info) { int size=0; + UNISTR **string; + int i=0; + DEBUG(9,("Sizing driver info_3\n")); size+=size_of_uint32( &(info->version) ); size+=size_of_relative_string( &(info->name) ); @@ -1263,9 +1318,17 @@ static uint32 spoolss_size_printer_driver_info_3(DRIVER_INFO_3 *info) size+=size_of_relative_string( &(info->datafile) ); size+=size_of_relative_string( &(info->configfile) ); size+=size_of_relative_string( &(info->helpfile) ); - size+=size_of_relative_string( &(info->dependentfiles) ); size+=size_of_relative_string( &(info->monitorname) ); size+=size_of_relative_string( &(info->defaultdatatype) ); + + string=info->dependentfiles; + + while ( (string)[i]!=0x0000 ) + { + size+=2*(1+ str_len_uni( string[i] ) ); + i++; + } + size+=4; DEBUGADD(9,("size: [%d]\n", size)); return (size); @@ -1312,7 +1375,7 @@ static uint32 spoolss_size_job_info_2(JOB_INFO_2 *info) size+=size_of_relative_string( &(info->printprocessor) ); size+=size_of_relative_string( &(info->parameters) ); size+=size_of_relative_string( &(info->drivername) ); - size+=size_of_device_mode( &(info->devmode) ); + size+=size_of_device_mode( info->devmode ); size+=size_of_relative_string( &(info->text_status) ); /* SEC_DESC sec_desc;*/ size+=size_of_uint32( &(info->status) ); @@ -1365,6 +1428,28 @@ static uint32 spoolss_size_port_info_2(PORT_INFO_2 *info) } /******************************************************************* +return the size required by a struct in the stream +********************************************************************/ +static uint32 spoolss_size_processor_info_1(PRINTPROCESSOR_1 *info) +{ + int size=0; + size+=size_of_relative_string( &(info->name) ); + + return (size); +} + +/******************************************************************* +return the size required by a struct in the stream +********************************************************************/ +static uint32 spoolss_size_monitor_info_1(PRINTMONITOR_1 *info) +{ + int size=0; + size+=size_of_relative_string( &(info->name) ); + + return (size); +} + +/******************************************************************* * read a uint8 buffer of size *size. * allocate memory for it * return a pointer to the allocated memory and the size @@ -3216,6 +3301,7 @@ void spoolss_io_r_enumprintprocessors(char *desc, SPOOL_R_ENUMPRINTPROCESSORS *r uint32 useless_ptr=0xADDE0FF0; uint32 start_offset, end_offset, beginning; uint32 bufsize_required=0; + int i; prs_debug(ps, depth, desc, "spoolss_io_r_enumprintprocessors"); depth++; @@ -3228,12 +3314,12 @@ void spoolss_io_r_enumprintprocessors(char *desc, SPOOL_R_ENUMPRINTPROCESSORS *r { PRINTPROCESSOR_1 *info_1; info_1=r_u->info_1; -/* + for (i=0; i<r_u->numofprintprocessors; i++) { - bufsize_required += spoolss_size_port_info_2(&(info_1[i])); + bufsize_required += spoolss_size_processor_info_1(&(info_1[i])); } -*/ break; + break; } } @@ -3265,14 +3351,14 @@ void spoolss_io_r_enumprintprocessors(char *desc, SPOOL_R_ENUMPRINTPROCESSORS *r switch (r_u->level) { - case 2: + case 1: { -/* PORT_INFO_2 *info; - for (i=0; i<r_u->numofports; i++) + PRINTPROCESSOR_1 *info_1; + for (i=0; i<r_u->numofprintprocessors; i++) { - info = &(r_u->port.port_info_2[i]); - smb_io_port_2(desc, info, ps, depth, &start_offset, &end_offset); - }*/ + info_1 = &(r_u->info_1[i]); + smb_io_processor_info_1(desc, info_1, ps, depth, &start_offset, &end_offset); + } break; } } @@ -3313,6 +3399,106 @@ void spoolss_io_q_enumprintprocessors(char *desc, SPOOL_Q_ENUMPRINTPROCESSORS *q /******************************************************************* ********************************************************************/ +void spoolss_io_r_enumprintmonitors(char *desc, SPOOL_R_ENUMPRINTMONITORS *r_u, prs_struct *ps, int depth) +{ + uint32 useless_ptr=0xADDE0FF0; + uint32 start_offset, end_offset, beginning; + uint32 bufsize_required=0; + int i; + + prs_debug(ps, depth, desc, "spoolss_io_r_enumprintmonitors"); + depth++; + + prs_align(ps); + prs_uint32("pointer", ps, depth, &useless_ptr); + switch (r_u->level) + { + case 1: + { + PRINTMONITOR_1 *info_1; + info_1=r_u->info_1; + + for (i=0; i<r_u->numofprintmonitors; i++) + { + bufsize_required += spoolss_size_monitor_info_1(&(info_1[i])); + } + break; + } + } + + DEBUG(4,("size needed: %d\n",bufsize_required)); + DEBUG(4,("size offered: %d\n",r_u->offered)); + + /* check if the buffer is big enough for the datas */ + if (r_u->offered<bufsize_required) + { + + /* it's too small */ + r_u->status=ERROR_INSUFFICIENT_BUFFER; /* say so */ + r_u->offered=0; /* don't send back the buffer */ + + DEBUG(4,("buffer too small\n")); + + prs_uint32("size of buffer", ps, depth, &(r_u->offered)); + } + else + { + mem_grow_data(&(ps->data), ps->io, r_u->offered, 0); + + DEBUG(4,("buffer large enough\n")); + + prs_uint32("size of buffer", ps, depth, &(r_u->offered)); + beginning=ps->offset; + start_offset=ps->offset; + end_offset=start_offset+r_u->offered; + + switch (r_u->level) + { + case 1: + { + PRINTMONITOR_1 *info_1; + for (i=0; i<r_u->numofprintmonitors; i++) + { + info_1 = &(r_u->info_1[i]); + smb_io_monitor_info_1(desc, info_1, ps, depth, &start_offset, &end_offset); + } + break; + } + } + ps->offset=beginning+r_u->offered; + prs_align(ps); + } + + /* + * if the buffer was too small, send the minimum required size + * if it was too large, send the real needed size + */ + + prs_uint32("size of buffer needed", ps, depth, &(bufsize_required)); + prs_uint32("numofprintmonitors", ps, depth, &(r_u->numofprintmonitors)); + prs_uint32("status", ps, depth, &(r_u->status)); +} + +/******************************************************************* +********************************************************************/ +void spoolss_io_q_enumprintmonitors(char *desc, SPOOL_Q_ENUMPRINTMONITORS *q_u, prs_struct *ps, int depth) +{ + uint32 useless; + prs_debug(ps, depth, desc, "spoolss_io_q_enumprintmonitors"); + depth++; + + prs_align(ps); + prs_uint32("useless", ps, depth, &useless); + smb_io_unistr2("", &(q_u->name),True,ps,depth); + prs_align(ps); + prs_uint32("level", ps, depth, &(q_u->level)); + spoolss_io_read_buffer("", ps, depth, &(q_u->buffer)); + prs_align(ps); + prs_uint32("buf_size", ps, depth, &(q_u->buf_size)); +} + +/******************************************************************* +********************************************************************/ void spoolss_io_r_enumprinterdata(char *desc, SPOOL_R_ENUMPRINTERDATA *r_u, prs_struct *ps, int depth) { prs_debug(ps, depth, desc, "spoolss_io_r_enumprinterdata"); @@ -3504,3 +3690,114 @@ void spoolss_io_r_setform(char *desc, SPOOL_R_SETFORM *r_u, prs_struct *ps, int prs_uint32("status", ps, depth, &(r_u->status)); } +/******************************************************************* +********************************************************************/ +void spoolss_io_r_getjob(char *desc, SPOOL_R_GETJOB *r_u, prs_struct *ps, int depth) +{ + uint32 useless_ptr=0xADDE0FF0; + uint32 start_offset, end_offset, beginning; + uint32 bufsize_required=0; + + prs_debug(ps, depth, desc, "spoolss_io_r_getjob"); + depth++; + + prs_align(ps); + + prs_uint32("pointer", ps, depth, &useless_ptr); + + switch (r_u->level) + { + case 1: + { + JOB_INFO_1 *info; + info=r_u->job.job_info_1; + + bufsize_required += spoolss_size_job_info_1(info); + break; + } + case 2: + { + JOB_INFO_2 *info; + info=r_u->job.job_info_2; + + bufsize_required += spoolss_size_job_info_2(info); + break; + } + } + + DEBUG(4,("spoolss_io_r_getjob, size needed: %d\n",bufsize_required)); + DEBUG(4,("spoolss_io_r_getjob, size offered: %d\n",r_u->offered)); + + /* check if the buffer is big enough for the datas */ + if (r_u->offered<bufsize_required) + { + /* it's too small */ + r_u->status=ERROR_INSUFFICIENT_BUFFER; /* say so */ + r_u->offered=0; /* don't send back the buffer */ + + DEBUG(4,("spoolss_io_r_getjob, buffer too small\n")); + + prs_uint32("size of buffer", ps, depth, &(r_u->offered)); + } + else + { + mem_grow_data(&(ps->data), ps->io, r_u->offered, 0); + + DEBUG(4,("spoolss_io_r_enumjobs, buffer large enough\n")); + + prs_uint32("size of buffer", ps, depth, &(r_u->offered)); + beginning=ps->offset; + start_offset=ps->offset; + end_offset=start_offset+r_u->offered; + + switch (r_u->level) + { + case 1: + { + JOB_INFO_1 *info; + info = r_u->job.job_info_1; + smb_io_job_info_1(desc, info, ps, depth, &start_offset, &end_offset); + break; + } + case 2: + { + JOB_INFO_2 *info; + info = r_u->job.job_info_2; + smb_io_job_info_2(desc, info, ps, depth, &start_offset, &end_offset); + break; + } + + } + ps->offset=beginning+r_u->offered; + prs_align(ps); + } + + /* + * if the buffer was too small, send the minimum required size + * if it was too large, send the real needed size + */ + + prs_uint32("size of buffer needed", ps, depth, &(bufsize_required)); + prs_uint32("status", ps, depth, &(r_u->status)); +} + +/******************************************************************* +********************************************************************/ +void spoolss_io_q_getjob(char *desc, SPOOL_Q_GETJOB *q_u, prs_struct *ps, int depth) +{ + + prs_debug(ps, depth, desc, ""); + depth++; + + prs_align(ps); + + smb_io_prt_hnd("printer handle",&(q_u->handle),ps,depth); + prs_uint32("jobid", ps, depth, &(q_u->jobid)); + prs_uint32("level", ps, depth, &(q_u->level)); + + spoolss_io_read_buffer("", ps, depth, &(q_u->buffer)); + + prs_align(ps); + + prs_uint32("buf_size", ps, depth, &(q_u->buf_size)); +} diff --git a/source3/rpc_server/srv_spoolss.c b/source3/rpc_server/srv_spoolss.c index 2cb5543f26..067fdd3ff7 100755 --- a/source3/rpc_server/srv_spoolss.c +++ b/source3/rpc_server/srv_spoolss.c @@ -1424,18 +1424,25 @@ static void api_spoolss_rfnpcnex(pipes_struct *p, prs_struct *data, * construct_printer_info_0 * fill a printer_info_1 struct ********************************************************************/ -static void construct_printer_info_0(PRINTER_INFO_0 *printer,int snum, pstring servername, connection_struct *conn) +static BOOL construct_printer_info_0(PRINTER_INFO_0 *printer,int snum, pstring servername, connection_struct *conn) { pstring chaine; int count; + NT_PRINTER_INFO_LEVEL ntprinter; print_queue_struct *queue=NULL; print_status_struct status; bzero(&status,sizeof(status)); + + if (get_a_printer(&ntprinter, 2, lp_servicename(snum)) != 0) + { + return (False); + } + count=get_printqueue(snum, conn ,&queue,&status); /* the description and the name are of the form \\server\share */ - slprintf(chaine,sizeof(chaine)-1,"\\\\%s\\%s",servername, lp_servicename(snum)); + slprintf(chaine,sizeof(chaine)-1,"\\\\%s\\%s",servername, ntprinter.info_2->printername); make_unistr(&(printer->printername), chaine); @@ -1472,8 +1479,11 @@ static void construct_printer_info_0(PRINTER_INFO_0 *printer,int snum, pstring s printer->unknown21 = 0x0648; printer->unknown22 = 0x0; printer->unknown23 = 0x5; + if (queue) free(queue); - + + free_a_printer(ntprinter, 2); + return (True); } /******************************************************************** @@ -1729,12 +1739,19 @@ static void enum_all_printers_info_2(PRINTER_INFO_2 ***printers, uint32 *number, /**************************************************************************** ****************************************************************************/ +static void free_devmode(DEVICEMODE *devmode) +{ + if (devmode->private!=NULL) + free(devmode->private); + if (devmode!=NULL) + free(devmode); +} + +/**************************************************************************** +****************************************************************************/ static void free_printer_info_2(PRINTER_INFO_2 *printer) { - if (printer->devmode->private!=NULL) - free(printer->devmode->private); - if (printer->devmode!=NULL) - free(printer->devmode); + free_devmode(printer->devmode); if (printer!=NULL) free(printer); } @@ -2024,6 +2041,40 @@ static void construct_printer_driver_info_2(DRIVER_INFO_2 *info, int snum, } /******************************************************************** + * copy a strings array and convert to UNICODE + ********************************************************************/ +static void make_unistr_array(UNISTR ***uni_array, char **char_array) +{ + int i=0; + char *v; + + DEBUG(6,("make_unistr_array\n")); + + for (v=char_array[i]; *v!='\0'; v=char_array[i]) + { + DEBUGADD(6,("i:%d:", i)); + DEBUGADD(6,("%s:%d:", v, strlen(v))); + + *uni_array=(UNISTR **)Realloc(*uni_array, sizeof(UNISTR *)*(i+1)); + DEBUGADD(7,("realloc:[%p],", *uni_array)); + + (*uni_array)[i]=(UNISTR *)malloc( sizeof(UNISTR) ); + DEBUGADD(7,("alloc:[%p],", (*uni_array)[i])); + + make_unistr( (*uni_array)[i], v ); + DEBUGADD(7,("copy\n")); + + i++; + } + DEBUGADD(7,("last one\n")); + + *uni_array=(UNISTR **)Realloc(*uni_array, sizeof(UNISTR *)*(i+1)); + (*uni_array)[i]=(UNISTR *)malloc( sizeof(UNISTR)); + (*uni_array)[i]=0x0000; + DEBUGADD(6,("last one:done\n")); +} + +/******************************************************************** * construct_printer_info_3 * fill a printer_info_3 struct ********************************************************************/ @@ -2062,7 +2113,8 @@ static void fill_printer_driver_info_3(DRIVER_INFO_3 *info, make_unistr( &(info->monitorname), driver.info_3->monitorname ); make_unistr( &(info->defaultdatatype), driver.info_3->defaultdatatype ); - make_unistr( &(info->dependentfiles), "" ); + info->dependentfiles=NULL; + make_unistr_array(&(info->dependentfiles), driver.info_3->dependentfiles); } /******************************************************************** @@ -2227,26 +2279,6 @@ static void api_spoolss_endpageprinter(pipes_struct *p, prs_struct *data, spoolss_reply_endpageprinter(&q_u, rdata); } -/**************************************************************************** -****************************************************************************/ -static void spoolss_reply_startdocprinter(SPOOL_Q_STARTDOCPRINTER *q_u, prs_struct *rdata) -{ - SPOOL_R_STARTDOCPRINTER r_u; - int pnum = find_printer_index_by_hnd(&(q_u->handle)); - - if (OPEN_HANDLE(pnum)) - { - r_u.jobid=Printer[pnum].current_jobid; - r_u.status=0x0; - - spoolss_io_r_startdocprinter("",&r_u,rdata,0); - } - else - { - DEBUG(3,("Error in startdocprinter printer handle (pnum=%x)\n",pnum)); - } -} - /******************************************************************** * api_spoolss_getprinter * called from the spoolss dispatcher @@ -2256,8 +2288,12 @@ static void api_spoolss_startdocprinter(pipes_struct *p, prs_struct *data, prs_struct *rdata) { SPOOL_Q_STARTDOCPRINTER q_u; + SPOOL_R_STARTDOCPRINTER r_u; + DOC_INFO_1 *info_1; + pstring fname; pstring tempname; + pstring datatype; int fd = -1; int snum; int pnum; @@ -2265,9 +2301,29 @@ static void api_spoolss_startdocprinter(pipes_struct *p, prs_struct *data, /* decode the stream and fill the struct */ spoolss_io_q_startdocprinter("", &q_u, data, 0); + info_1=&(q_u.doc_info_container.docinfo.doc_info_1); + r_u.status=0x0; pnum = find_printer_index_by_hnd(&(q_u.handle)); - if (OPEN_HANDLE(pnum)) + /* + * a nice thing with NT is it doesn't listen to what you tell it. + * when asked to send _only_ RAW datas, it tries to send datas + * in EMF format. + * + * So I add checks like in NT Server ... + */ + + if (info_1->p_datatype != 0) + { + unistr2_to_ascii(datatype, &(info_1->docname), sizeof(datatype)); + if (strcmp(datatype, "RAW") != 0) + { + r_u.jobid=0; + r_u.status=1804; + } + } + + if (r_u.status==0 && OPEN_HANDLE(pnum)) { /* get the share number of the printer */ get_printer_snum(&(q_u.handle),&snum); @@ -2291,8 +2347,12 @@ static void api_spoolss_startdocprinter(pipes_struct *p, prs_struct *data, Printer[pnum].document_fd=fd; Printer[pnum].document_started=True; - } - spoolss_reply_startdocprinter(&q_u, rdata); + r_u.jobid=Printer[pnum].current_jobid; + r_u.status=0x0; + + } + + spoolss_io_r_startdocprinter("",&r_u,rdata,0); } /**************************************************************************** @@ -2665,19 +2725,30 @@ static void fill_job_info_1(JOB_INFO_1 *job_info, print_queue_struct *queue, /**************************************************************************** ****************************************************************************/ -static void fill_job_info_2(JOB_INFO_2 *job_info, print_queue_struct *queue, +static BOOL fill_job_info_2(JOB_INFO_2 *job_info, print_queue_struct *queue, int position, int snum) { pstring temp_name; + DEVICEMODE *devmode; + NT_PRINTER_INFO_LEVEL ntprinter; + pstring chaine; struct tm *t; time_t unixdate = time(NULL); + + if (get_a_printer(&ntprinter, 2, lp_servicename(snum)) !=0 ) + { + return (False); + } t=gmtime(&unixdate); snprintf(temp_name, sizeof(temp_name), "\\\\%s", global_myname); job_info->jobid=queue->job; - make_unistr(&(job_info->printername), lp_servicename(snum)); + + snprintf(chaine, sizeof(chaine)-1, "\\\\%s\\%s", global_myname, ntprinter.info_2->printername); + make_unistr(&(job_info->printername), chaine); + make_unistr(&(job_info->machinename), temp_name); make_unistr(&(job_info->username), queue->user); make_unistr(&(job_info->document), queue->file); @@ -2685,9 +2756,6 @@ static void fill_job_info_2(JOB_INFO_2 *job_info, print_queue_struct *queue, make_unistr(&(job_info->datatype), "RAW"); make_unistr(&(job_info->printprocessor), "winprint"); make_unistr(&(job_info->parameters), ""); - -/* here the devicemode should be filled up */ - make_unistr(&(job_info->text_status), ""); /* and here the security descriptor */ @@ -2702,6 +2770,14 @@ static void fill_job_info_2(JOB_INFO_2 *job_info, print_queue_struct *queue, make_systemtime(&(job_info->submitted), t); job_info->timeelapsed=0; job_info->pagesprinted=0; + + devmode=(DEVICEMODE *)malloc(sizeof(DEVICEMODE)); + ZERO_STRUCTP(devmode); + construct_dev_mode(devmode, snum, global_myname); + job_info->devmode=devmode; + + free_a_printer(ntprinter, 2); + return (True); } /**************************************************************************** @@ -2772,6 +2848,7 @@ static void spoolss_reply_enumjobs(SPOOL_Q_ENUMJOBS *q_u, prs_struct *rdata, con } case 2: { + free_devmode(job_info_2->devmode); free(job_info_2); break; } @@ -3470,7 +3547,6 @@ static void api_spoolss_addform(pipes_struct *p, prs_struct *data, spoolss_reply_addform(&q_u, rdata); } - /**************************************************************************** ****************************************************************************/ static void spoolss_reply_setform(SPOOL_Q_SETFORM *q_u, prs_struct *rdata) @@ -3510,6 +3586,187 @@ static void api_spoolss_setform(pipes_struct *p, prs_struct *data, spoolss_reply_setform(&q_u, rdata); } +/**************************************************************************** +****************************************************************************/ +static void spoolss_reply_enumprintprocessors(SPOOL_Q_ENUMPRINTPROCESSORS *q_u, prs_struct *rdata) +{ + SPOOL_R_ENUMPRINTPROCESSORS r_u; + PRINTPROCESSOR_1 *info_1; + + DEBUG(5,("spoolss_reply_enumprintprocessors\n")); + + /* + * Enumerate the print processors ... + * + * Just reply with "winprint", to keep NT happy + * and I can use my nice printer checker. + */ + + r_u.status = 0x0; + r_u.offered = q_u->buf_size; + r_u.level = q_u->level; + + r_u.numofprintprocessors = 0x1; + + info_1 = (PRINTPROCESSOR_1 *)malloc(sizeof(PRINTPROCESSOR_1)); + + make_unistr(&(info_1->name), "winprint"); + + r_u.info_1=info_1; + + spoolss_io_r_enumprintprocessors("", &r_u, rdata, 0); +} + +/**************************************************************************** +****************************************************************************/ +static void api_spoolss_enumprintprocessors(pipes_struct *p, prs_struct *data, + prs_struct *rdata) +{ + SPOOL_Q_ENUMPRINTPROCESSORS q_u; + + spoolss_io_q_enumprintprocessors("", &q_u, data, 0); + + spoolss_reply_enumprintprocessors(&q_u, rdata); +} + +/**************************************************************************** +****************************************************************************/ +static void spoolss_reply_enumprintmonitors(SPOOL_Q_ENUMPRINTMONITORS *q_u, prs_struct *rdata) +{ + SPOOL_R_ENUMPRINTMONITORS r_u; + PRINTMONITOR_1 *info_1; + + DEBUG(5,("spoolss_reply_enumprintmonitors\n")); + + /* + * Enumerate the print monitors ... + * + * Just reply with "Local Port", to keep NT happy + * and I can use my nice printer checker. + */ + + r_u.status = 0x0; + r_u.offered = q_u->buf_size; + r_u.level = q_u->level; + + r_u.numofprintmonitors = 0x1; + + info_1 = (PRINTMONITOR_1 *)malloc(sizeof(PRINTMONITOR_1)); + + make_unistr(&(info_1->name), "Local Port"); + + r_u.info_1=info_1; + + spoolss_io_r_enumprintmonitors("", &r_u, rdata, 0); +} + +/**************************************************************************** +****************************************************************************/ +static void api_spoolss_enumprintmonitors(pipes_struct *p, prs_struct *data, + prs_struct *rdata) +{ + SPOOL_Q_ENUMPRINTMONITORS q_u; + + spoolss_io_q_enumprintmonitors("", &q_u, data, 0); + + spoolss_reply_enumprintmonitors(&q_u, rdata); +} + +/**************************************************************************** +****************************************************************************/ +static void spoolss_reply_getjob(SPOOL_Q_GETJOB *q_u, prs_struct *rdata, connection_struct *conn) +{ + SPOOL_R_GETJOB r_u; + int snum; + int count; + int i; + print_queue_struct *queue=NULL; + print_status_struct status; + JOB_INFO_1 *job_info_1=NULL; + JOB_INFO_2 *job_info_2=NULL; + + DEBUG(4,("spoolss_reply_getjob\n")); + + bzero(&status,sizeof(status)); + + r_u.offered=q_u->buf_size; + + if (get_printer_snum(&(q_u->handle), &snum)) + { + count=get_printqueue(snum, conn, &queue, &status); + + r_u.level=q_u->level; + + DEBUGADD(4,("count:[%d], status:[%d], [%s]\n", count, status.status, status.message)); + + switch (r_u.level) + { + case 1: + { + job_info_1=(JOB_INFO_1 *)malloc(sizeof(JOB_INFO_1)); + + for (i=0; i<count; i++) + { + if (queue[i].job==(int)q_u->jobid) + { + fill_job_info_1(job_info_1, &(queue[i]), i, snum); + } + } + r_u.job.job_info_1=job_info_1; + break; + } + case 2: + { + job_info_2=(JOB_INFO_2 *)malloc(sizeof(JOB_INFO_2)); + + for (i=0; i<count; i++) + { + if (queue[i].job==(int)q_u->jobid) + { + fill_job_info_2(job_info_2, &(queue[i]), i, snum); + } + } + r_u.job.job_info_2=job_info_2; + break; + } + } + } + + r_u.status=0x0; + + spoolss_io_r_getjob("",&r_u,rdata,0); + switch (r_u.level) + { + case 1: + { + free(job_info_1); + break; + } + case 2: + { + free_devmode(job_info_2->devmode); + free(job_info_2); + break; + } + } + if (queue) free(queue); + +} + +/**************************************************************************** +****************************************************************************/ +static void api_spoolss_getjob(pipes_struct *p, prs_struct *data, + prs_struct *rdata) +{ + SPOOL_Q_GETJOB q_u; + + spoolss_io_q_getjob("", &q_u, data, 0); + + spoolss_reply_getjob(&q_u, rdata, p->conn); + + spoolss_io_free_buffer(&(q_u.buffer)); +} + /******************************************************************* \pipe\spoolss commands ********************************************************************/ @@ -3544,6 +3801,9 @@ struct api_struct api_spoolss_cmds[] = {"SPOOLSS_SETPRINTERDATA", SPOOLSS_SETPRINTERDATA, api_spoolss_setprinterdata }, {"SPOOLSS_ADDFORM", SPOOLSS_ADDFORM, api_spoolss_addform }, {"SPOOLSS_SETFORM", SPOOLSS_SETFORM, api_spoolss_setform }, + {"SPOOLSS_ENUMPRINTPROCESSORS", SPOOLSS_ENUMPRINTPROCESSORS, api_spoolss_enumprintprocessors }, + {"SPOOLSS_ENUMMONITORS", SPOOLSS_ENUMMONITORS, api_spoolss_enumprintmonitors }, + {"SPOOLSS_GETJOB", SPOOLSS_GETJOB, api_spoolss_getjob }, { NULL, 0, NULL } }; |