diff options
Diffstat (limited to 'source3/rpc_server')
-rw-r--r-- | source3/rpc_server/srv_spoolss_nt.c | 314 |
1 files changed, 193 insertions, 121 deletions
diff --git a/source3/rpc_server/srv_spoolss_nt.c b/source3/rpc_server/srv_spoolss_nt.c index 41f37c3f74..9170b8afdd 100644 --- a/source3/rpc_server/srv_spoolss_nt.c +++ b/source3/rpc_server/srv_spoolss_nt.c @@ -72,7 +72,17 @@ typedef struct _Printer{ } client; } Printer_entry; +typedef struct _counter_printer_0 { + ubi_dlNode Next; + ubi_dlNode Prev; + + int snum; + uint32 counter; +} counter_printer_0; + static ubi_dlList Printer_list; +static ubi_dlList counter_list; + #define OPEN_HANDLE(pnum) ((pnum!=NULL) && (pnum->open!=False)) @@ -82,6 +92,7 @@ static ubi_dlList Printer_list; void init_printer_hnd(void) { ubi_dlInitList(&Printer_list); + ubi_dlInitList(&counter_list); } /**************************************************************************** @@ -1485,22 +1496,50 @@ uint32 _spoolss_rfnpcnex( const POLICY_HND *handle, uint32 change, * construct_printer_info_0 * fill a printer_info_1 struct ********************************************************************/ -static BOOL construct_printer_info_0(PRINTER_INFO_0 *printer,int snum, pstring servername) +static BOOL construct_printer_info_0(PRINTER_INFO_0 *printer, int snum, pstring servername) { pstring chaine; int count; NT_PRINTER_INFO_LEVEL ntprinter; - + counter_printer_0 *session_counter; + uint32 global_counter; + struct tm *t; + print_queue_struct *queue=NULL; print_status_struct status; + memset(&status, 0, sizeof(status)); if (get_a_printer(&ntprinter, 2, lp_servicename(snum)) != 0) - { - return (False); - } + return False; count=get_printqueue(snum, NULL, &queue, &status); + + /* check if we already have a counter for this printer */ + session_counter = (counter_printer_0 *)ubi_dlFirst(&counter_list); + + for(; session_counter; session_counter = (counter_printer_0 *)ubi_dlNext(session_counter)) { + if (session_counter->snum == snum) + break; + } + + /* it's the first time, add it to the list */ + if (session_counter==NULL) { + session_counter=(counter_printer_0 *)malloc(sizeof(counter_printer_0)); + ZERO_STRUCTP(session_counter); + session_counter->snum=snum; + session_counter->counter=0; + ubi_dlAddHead( &counter_list, (ubi_dlNode *)session_counter); + } + + /* increment it */ + session_counter->counter++; + + /* JFM: + * the global_counter should be stored in a TDB as it's common to all the clients + * and should be zeroed on samba startup + */ + global_counter=session_counter->counter; /* the description and the name are of the form \\server\share */ slprintf(chaine,sizeof(chaine)-1,"\\\\%s\\%s",servername, ntprinter.info_2->printername); @@ -1511,36 +1550,48 @@ static BOOL construct_printer_info_0(PRINTER_INFO_0 *printer,int snum, pstring s init_unistr(&(printer->servername), chaine); printer->cjobs = count; - printer->attributes = PRINTER_ATTRIBUTE_SHARED \ - | PRINTER_ATTRIBUTE_NETWORK \ - | PRINTER_ATTRIBUTE_RAW_ONLY ; - printer->unknown0 = 0x1; /* pointer */ - printer->unknown1 = 0x000A07CE; /* don't known */ - printer->unknown2 = 0x00020005; - printer->unknown3 = 0x0006000D; - printer->unknown4 = 0x02180026; - printer->unknown5 = 0x09; - printer->unknown6 = 0x36; - printer->majorversion = 0x0004; /* NT 4 */ - printer->buildversion = 0x0565; /* build 1381 */ - printer->unknown7 = 0x1; - printer->unknown8 = 0x0; - printer->unknown9 = 0x2; - printer->unknown10 = 0x3; - printer->unknown11 = 0x0; - printer->unknown12 = 0x0; - printer->unknown13 = 0x0; - printer->unknown14 = 0x1; - printer->unknown15 = 0x024a; /*586 Pentium ? */ - printer->unknown16 = 0x0; - printer->unknown17 = 0x423ed444; /* CacheChangeID */ - printer->unknown18 = 0x0; - printer->status = status.status; - printer->unknown20 = 0x0; - printer->unknown21 = 0x0648; - printer->unknown22 = 0x0; - printer->unknown23 = 0x5; - + printer->total_jobs = 0; + printer->total_bytes = 0; + + t=gmtime(&ntprinter.info_2->setuptime); + + printer->year = t->tm_year+1900; + printer->month = t->tm_mon+1; + printer->dayofweek = t->tm_wday; + printer->day = t->tm_mday; + printer->hour = t->tm_hour; + printer->minute = t->tm_min; + printer->second = t->tm_sec; + printer->milliseconds = 0; + + printer->global_counter = global_counter; + printer->total_pages = 0; + printer->major_version = 0x0004; /* NT 4 */ + printer->build_version = 0x0565; /* build 1381 */ + printer->unknown7 = 0x1; + printer->unknown8 = 0x0; + printer->unknown9 = 0x2; + printer->session_counter = session_counter->counter; + printer->unknown11 = 0x0; + printer->printer_errors = 0x0; /* number of print failure */ + printer->unknown13 = 0x0; + printer->unknown14 = 0x1; + printer->unknown15 = 0x024a; /* 586 Pentium ? */ + printer->unknown16 = 0x0; + printer->change_id = ntprinter.info_2->changeid; /* ChangeID in milliseconds*/ + printer->unknown18 = 0x0; + printer->status = status.status; + printer->unknown20 = 0x0; + printer->c_setprinter = ntprinter.info_2->c_setprinter; /* how many times setprinter has been called */ + printer->unknown22 = 0x0; + printer->unknown23 = 0x6; /* 6 ???*/ + printer->unknown24 = 0; /* unknown 24 to 26 are always 0 */ + printer->unknown25 = 0; + printer->unknown26 = 0; + printer->unknown27 = 0; + printer->unknown28 = 0; + printer->unknown29 = 0; + safe_free(queue); free_a_printer(ntprinter, 2); @@ -1640,52 +1691,57 @@ static void construct_dev_mode(DEVICEMODE *devmode, int snum, char *servername) * construct_printer_info_2 * fill a printer_info_2 struct ********************************************************************/ -static BOOL construct_printer_info_2(PRINTER_INFO_2 *printer, int snum, pstring servername) +static BOOL construct_printer_info_2(pstring servername, PRINTER_INFO_2 *printer, int snum) { pstring chaine; + pstring chaine2; + pstring sl; int count; DEVICEMODE *devmode; NT_PRINTER_INFO_LEVEL ntprinter; - + print_queue_struct *queue=NULL; print_status_struct status; memset(&status, 0, sizeof(status)); - count=get_printqueue(snum, NULL, &queue, &status); if (get_a_printer(&ntprinter, 2, lp_servicename(snum)) !=0 ) - { - return (False); - } - - snprintf(chaine, sizeof(chaine)-1, "\\\\%s", servername); - init_unistr(&(printer->servername), chaine); /* servername*/ - - snprintf(chaine, sizeof(chaine)-1, "\\\\%s\\%s", servername, ntprinter.info_2->printername); - init_unistr(&(printer->printername), chaine); /* printername*/ + return False; + + memset(&status, 0, sizeof(status)); + count=get_printqueue(snum, NULL, &queue, &status); - init_unistr(&(printer->sharename), lp_servicename(snum)); /* sharename */ + snprintf(chaine, sizeof(chaine)-1, "%s", servername); - init_unistr(&(printer->portname), lp_servicename(snum)); /* port */ - init_unistr(&(printer->drivername), ntprinter.info_2->drivername); /* drivername */ - - init_unistr(&(printer->comment), ntprinter.info_2->comment); /* comment */ - init_unistr(&(printer->location), ntprinter.info_2->location); /* location */ - init_unistr(&(printer->sepfile), ntprinter.info_2->sepfile); /* separator file */ - init_unistr(&(printer->printprocessor), ntprinter.info_2->printprocessor);/* print processor */ - init_unistr(&(printer->datatype), ntprinter.info_2->datatype); /* datatype */ - init_unistr(&(printer->parameters), ntprinter.info_2->parameters); /* parameters (of print processor) */ + if (strlen(servername)!=0) + fstrcpy(sl, "\\"); + else + fstrcpy(sl, '\0'); + + snprintf(chaine2, sizeof(chaine)-1, "%s%s%s", servername, sl, ntprinter.info_2->printername); + + init_unistr(&printer->servername, chaine); /* servername*/ + init_unistr(&printer->printername, chaine2); /* printername*/ + init_unistr(&printer->sharename, lp_servicename(snum)); /* sharename */ + init_unistr(&printer->portname, lp_servicename(snum)); /* port */ + init_unistr(&printer->drivername, ntprinter.info_2->drivername); /* drivername */ + init_unistr(&printer->comment, lp_comment(snum)); /* comment */ + init_unistr(&printer->location, ntprinter.info_2->location); /* location */ + init_unistr(&printer->sepfile, ntprinter.info_2->sepfile); /* separator file */ + init_unistr(&printer->printprocessor, ntprinter.info_2->printprocessor);/* print processor */ + init_unistr(&printer->datatype, ntprinter.info_2->datatype); /* datatype */ + init_unistr(&printer->parameters, ntprinter.info_2->parameters); /* parameters (of print processor) */ printer->attributes = PRINTER_ATTRIBUTE_SHARED \ - | PRINTER_ATTRIBUTE_NETWORK \ - | PRINTER_ATTRIBUTE_RAW_ONLY ; /* attributes */ - - printer->priority = ntprinter.info_2->priority; /* priority */ - printer->defaultpriority = ntprinter.info_2->default_priority; /* default priority */ - printer->starttime = ntprinter.info_2->starttime; /* starttime */ - printer->untiltime = ntprinter.info_2->untiltime; /* untiltime */ - printer->status = status.status; /* status */ - printer->cjobs = count; /* jobs */ - printer->averageppm = ntprinter.info_2->averageppm; /* average pages per minute */ + | PRINTER_ATTRIBUTE_LOCAL \ + | PRINTER_ATTRIBUTE_RAW_ONLY ; /* attributes */ + + printer->priority = ntprinter.info_2->priority; /* priority */ + printer->defaultpriority = ntprinter.info_2->default_priority; /* default priority */ + printer->starttime = ntprinter.info_2->starttime; /* starttime */ + printer->untiltime = ntprinter.info_2->untiltime; /* untiltime */ + printer->status = status.status; /* status */ + printer->cjobs = count; /* jobs */ + printer->averageppm = ntprinter.info_2->averageppm; /* average pages per minute */ devmode=(DEVICEMODE *)malloc(sizeof(DEVICEMODE)); ZERO_STRUCTP(devmode); @@ -1694,29 +1750,7 @@ static BOOL construct_printer_info_2(PRINTER_INFO_2 *printer, int snum, pstring safe_free(queue); free_a_printer(ntprinter, 2); - return (True); -} - -/******************************************************************** - * enum_printer_info_2 - * glue between spoolss_enumprinters and construct_printer_info_2 - ********************************************************************/ -static BOOL get_printer_info_2(PRINTER_INFO_2 **printer, int snum, int number) -{ - pstring servername; - - *printer=(PRINTER_INFO_2 *)malloc(sizeof(PRINTER_INFO_2)); - DEBUG(4,("Allocated memory for ONE PRINTER_INFO_2 at [%p]\n", *printer)); - pstrcpy(servername, global_myname); - if (!construct_printer_info_2(*printer, snum, servername)) - { - free(*printer); - return (False); - } - else - { - return (True); - } + return True; } /******************************************************************** @@ -1736,8 +1770,7 @@ static BOOL enum_all_printers_info_1(fstring server, uint32 flags, NEW_BUFFER *b if (lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) ) { DEBUG(4,("Found a printer in smb.conf: %s[%x]\n", lp_servicename(snum), snum)); - if (construct_printer_info_1(server, flags, ¤t_prt, snum)) - { + if (construct_printer_info_1(server, flags, ¤t_prt, snum)) { printers=Realloc(printers, (*returned +1)*sizeof(PRINTER_INFO_1)); DEBUG(4,("ReAlloced memory for [%d] PRINTER_INFO_1\n", *returned)); memcpy(&(printers[*returned]), ¤t_prt, sizeof(PRINTER_INFO_1)); @@ -1781,10 +1814,10 @@ static BOOL enum_all_printers_info_1_local(fstring name, NEW_BUFFER *buffer, uin if (!strcmp(name, temp)) { fstrcat(temp, "\\"); - enum_all_printers_info_1(temp, PRINTER_ENUM_ICON8, buffer, offered, needed, returned); + return enum_all_printers_info_1(temp, PRINTER_ENUM_ICON8, buffer, offered, needed, returned); } else - enum_all_printers_info_1("", PRINTER_ENUM_ICON8, buffer, offered, needed, returned); + return enum_all_printers_info_1("", PRINTER_ENUM_ICON8, buffer, offered, needed, returned); } /******************************************************************** @@ -1800,7 +1833,7 @@ static BOOL enum_all_printers_info_1_name(fstring name, NEW_BUFFER *buffer, uint if (!strcmp(name, temp)) { fstrcat(temp, "\\"); - enum_all_printers_info_1(temp, PRINTER_ENUM_ICON8, buffer, offered, needed, returned); + return enum_all_printers_info_1(temp, PRINTER_ENUM_ICON8, buffer, offered, needed, returned); } else return ERROR_INVALID_NAME; @@ -1840,8 +1873,10 @@ static BOOL enum_all_printers_info_1_remote(fstring name, NEW_BUFFER *buffer, ui /* check the required size. */ *needed += spoolss_size_printer_info_1(printer); - if (!alloc_buffer_size(buffer, *needed)) + if (!alloc_buffer_size(buffer, *needed)) { + safe_free(printer); return ERROR_INSUFFICIENT_BUFFER; + } /* fill the buffer with the structures */ new_smb_io_printer_info_1("", buffer, printer, 0); @@ -1868,7 +1903,7 @@ static BOOL enum_all_printers_info_1_network(fstring name, NEW_BUFFER *buffer, u fstrcpy(temp, "\\\\"); fstrcat(temp, global_myname); fstrcat(temp, "\\"); - enum_all_printers_info_1(temp, PRINTER_ENUM_UNKNOWN_8, buffer, offered, needed, returned); + return enum_all_printers_info_1(temp, PRINTER_ENUM_UNKNOWN_8, buffer, offered, needed, returned); } /******************************************************************** @@ -1876,38 +1911,40 @@ static BOOL enum_all_printers_info_1_network(fstring name, NEW_BUFFER *buffer, u * * called from api_spoolss_enumprinters (see this to understand) ********************************************************************/ -static BOOL enum_all_printers_info_2(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned) +static BOOL enum_all_printers_info_2(fstring servername, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned) { int snum; int i; int n_services=lp_numservices(); - PRINTER_INFO_2 **printers=NULL; + PRINTER_INFO_2 *printers=NULL; + PRINTER_INFO_2 current_prt; for (snum=0; snum<n_services; snum++) { if (lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) ) { - DEBUG(4,("Found a printer in smb.conf: %s[%x]\n", lp_servicename(snum), snum)); - printers=Realloc(printers, ((*returned)+1)*sizeof(PRINTER_INFO_2 *)); - DEBUG(4,("ReAlloced memory for [%d] PRINTER_INFO_2 pointers\n", (*returned)+1)); - if (get_printer_info_2( &(printers[*returned]), snum, *returned) ) + + if (construct_printer_info_2(servername, ¤t_prt, snum)) { + printers=Realloc(printers, (*returned +1)*sizeof(PRINTER_INFO_2)); + DEBUG(4,("ReAlloced memory for [%d] PRINTER_INFO_2\n", *returned)); + memcpy(&(printers[*returned]), ¤t_prt, sizeof(PRINTER_INFO_2)); (*returned)++; + } } } /* check the required size. */ for (i=0; i<*returned; i++) - (*needed) += spoolss_size_printer_info_2(printers[i]); - - DEBUG(4,("we need [%d] bytes\n", *needed)); + (*needed) += spoolss_size_printer_info_2(&(printers[i])); if (!alloc_buffer_size(buffer, *needed)) return ERROR_INSUFFICIENT_BUFFER; /* fill the buffer with the structures */ for (i=0; i<*returned; i++) - new_smb_io_printer_info_2("", buffer, printers[i], 0); + new_smb_io_printer_info_2("", buffer, &(printers[i]), 0); /* clear memory */ + safe_free(printers); if (*needed > offered) { *returned=0; @@ -1948,7 +1985,33 @@ static uint32 enumprinters_level2( uint32 flags, fstring servername, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned) { - return enum_all_printers_info_2(buffer, offered, needed, returned); + fstring temp; + + fstrcpy(temp, "\\\\"); + fstrcat(temp, global_myname); + + if (flags & PRINTER_ENUM_LOCAL) { + if (!strcmp(servername, temp)) { + fstrcat(temp, "\\"); + return enum_all_printers_info_2(temp, buffer, offered, needed, returned); + } + else + return enum_all_printers_info_2("", buffer, offered, needed, returned); + } + + if (flags & PRINTER_ENUM_NAME) { + if (!strcmp(servername, temp)) { + fstrcat(temp, "\\"); + return enum_all_printers_info_2(temp, buffer, offered, needed, returned); + } + else + return ERROR_INVALID_NAME; + } + + if (flags & PRINTER_ENUM_REMOTE) + return ERROR_INVALID_LEVEL; + + return NT_STATUS_NO_PROBLEMO; } /******************************************************************** @@ -2018,13 +2081,16 @@ static uint32 getprinter_level_0(pstring servername, int snum, NEW_BUFFER *buffe PRINTER_INFO_0 *printer=NULL; printer=(PRINTER_INFO_0*)malloc(sizeof(PRINTER_INFO_0)); + construct_printer_info_0(printer, snum, servername); /* check the required size. */ *needed += spoolss_size_printer_info_0(printer); - if (!alloc_buffer_size(buffer, *needed)) + if (!alloc_buffer_size(buffer, *needed)) { + safe_free(printer); return ERROR_INSUFFICIENT_BUFFER; + } /* fill the buffer with the structures */ new_smb_io_printer_info_0("", buffer, printer, 0); @@ -2051,8 +2117,10 @@ static uint32 getprinter_level_1(pstring servername, int snum, NEW_BUFFER *buffe /* check the required size. */ *needed += spoolss_size_printer_info_1(printer); - if (!alloc_buffer_size(buffer, *needed)) + if (!alloc_buffer_size(buffer, *needed)) { + safe_free(printer); return ERROR_INSUFFICIENT_BUFFER; + } /* fill the buffer with the structures */ new_smb_io_printer_info_1("", buffer, printer, 0); @@ -2072,15 +2140,21 @@ static uint32 getprinter_level_1(pstring servername, int snum, NEW_BUFFER *buffe static uint32 getprinter_level_2(pstring servername, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed) { PRINTER_INFO_2 *printer=NULL; + fstring temp; - printer=(PRINTER_INFO_2*)malloc(sizeof(PRINTER_INFO_2)); - construct_printer_info_2(printer, snum, servername); + printer=(PRINTER_INFO_2*)malloc(sizeof(PRINTER_INFO_2)); + + fstrcpy(temp, "\\\\"); + fstrcat(temp, servername); + construct_printer_info_2(temp, printer, snum); /* check the required size. */ *needed += spoolss_size_printer_info_2(printer); - if (!alloc_buffer_size(buffer, *needed)) + if (!alloc_buffer_size(buffer, *needed)) { + safe_free(printer); return ERROR_INSUFFICIENT_BUFFER; + } /* fill the buffer with the structures */ new_smb_io_printer_info_2("", buffer, printer, 0); @@ -2108,9 +2182,7 @@ uint32 _spoolss_getprinter(POLICY_HND *handle, uint32 level, pstrcpy(servername, global_myname); if (!get_printer_snum(handle, &snum)) - { return NT_STATUS_INVALID_HANDLE; - } switch (level) { case 0: @@ -2123,7 +2195,7 @@ uint32 _spoolss_getprinter(POLICY_HND *handle, uint32 level, return getprinter_level_2(servername,snum, buffer, offered, needed); break; default: - return NT_STATUS_INVALID_LEVEL; + return ERROR_INVALID_LEVEL; break; } } @@ -3617,11 +3689,11 @@ uint32 _spoolss_getprinterdriverdirectory(UNISTR2 *name, UNISTR2 *uni_environmen /**************************************************************************** ****************************************************************************/ -uint32 _spoolss_enumprinterdata(const POLICY_HND *handle, uint32 index, +uint32 _spoolss_enumprinterdata(const POLICY_HND *handle, uint32 idx, uint32 in_value_len, uint32 in_data_len, uint32 *out_max_value_len, uint16 **out_value, uint32 *out_value_len, uint32 *out_type, - uint32 *out_max_data_len, uint8 **out_data, uint32 *out_data_len) + uint32 *out_max_data_len, uint8 **data_out, uint32 *out_data_len) { NT_PRINTER_INFO_LEVEL printer; @@ -3645,7 +3717,7 @@ uint32 _spoolss_enumprinterdata(const POLICY_HND *handle, uint32 index, *out_type=0; *out_max_data_len=0; - *out_data=NULL; + *data_out=NULL; *out_data_len=0; DEBUG(5,("spoolss_enumprinterdata\n")); @@ -3696,7 +3768,7 @@ uint32 _spoolss_enumprinterdata(const POLICY_HND *handle, uint32 index, * that's the number of bytes not the number of unicode chars */ - if (!get_specific_param_by_index(printer, 2, index, value, &data, &type, &data_len)) { + if (!get_specific_param_by_index(printer, 2, idx, value, &data, &type, &data_len)) { free_a_printer(printer, 2); return ERROR_NO_MORE_ITEMS; } @@ -3719,7 +3791,7 @@ uint32 _spoolss_enumprinterdata(const POLICY_HND *handle, uint32 index, /* the data is counted in bytes */ *out_max_data_len=in_data_len; - *out_data=(uint8 *)malloc(in_data_len*sizeof(uint8)); + *data_out=(uint8 *)malloc(in_data_len*sizeof(uint8)); memcpy(*out_data, data, data_len); *out_data_len=data_len; |