From a44721750944af9beb46f169a49a439b614a8622 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 23 Mar 2001 03:12:58 +0000 Subject: Two OS/2 printer fixes from Jim McDonough @ IBM. First one adds a new info level into the lanman printing and an ioctl to the trans2 code. Andrew - this uses ASCII only. It looks ok to me but please check ! Second one adds a parameter "os2 driver map" that allows OS/2 driver names to be mapped. Jeremy. (This used to be commit da79b519e0b6b4317d7fb5260d74e0e74a7e0b46) --- source3/include/proto.h | 1 + source3/param/loadparm.c | 3 ++ source3/printing/nt_printing.c | 85 ++++++++++++++++++++++++++++++++++++++++++ source3/smbd/lanman.c | 71 +++++++++++++++++++++++++++++------ source3/smbd/trans2.c | 67 ++++++++++++++++++++++++++++++--- 5 files changed, 210 insertions(+), 17 deletions(-) (limited to 'source3') diff --git a/source3/include/proto.h b/source3/include/proto.h index ffa7744326..9d7ec27f95 100644 --- a/source3/include/proto.h +++ b/source3/include/proto.h @@ -1566,6 +1566,7 @@ char *lp_printcapname(void); char *lp_enumports_cmd(void); char *lp_addprinter_cmd(void); char *lp_deleteprinter_cmd(void); +char *lp_os2_driver_map(void); char *lp_lockdir(void); char *lp_utmpdir(void); char *lp_wtmpdir(void); diff --git a/source3/param/loadparm.c b/source3/param/loadparm.c index f930cf2f09..d35ca97292 100644 --- a/source3/param/loadparm.c +++ b/source3/param/loadparm.c @@ -107,6 +107,7 @@ typedef struct char *szEnumPortsCommand; char *szAddPrinterCommand; char *szDeletePrinterCommand; + char *szOs2DriverMap; char *szLockDir; char *szRootdir; char *szDefaultService; @@ -846,6 +847,7 @@ static struct parm_struct parm_table[] = { {"addprinter command", P_STRING, P_GLOBAL, &Globals.szAddPrinterCommand, NULL, NULL, 0}, {"deleteprinter command", P_STRING, P_GLOBAL, &Globals.szDeletePrinterCommand, NULL, NULL, 0}, {"show add printer wizard", P_BOOL, P_GLOBAL, &Globals.bMsAddPrinterWizard, NULL, NULL, 0}, + {"os2 driver map", P_STRING, P_GLOBAL, &Globals.szOs2DriverMap, NULL, NULL, 0}, {"printer name", P_STRING, P_LOCAL, &sDefault.szPrintername, NULL, NULL, FLAG_PRINT|FLAG_DOS_STRING}, {"printer", P_STRING, P_LOCAL, &sDefault.szPrintername, NULL, NULL, FLAG_DOS_STRING}, @@ -1435,6 +1437,7 @@ FN_GLOBAL_STRING(lp_printcapname, &Globals.szPrintcapname) FN_GLOBAL_STRING(lp_enumports_cmd, &Globals.szEnumPortsCommand) FN_GLOBAL_STRING(lp_addprinter_cmd, &Globals.szAddPrinterCommand) FN_GLOBAL_STRING(lp_deleteprinter_cmd, &Globals.szDeletePrinterCommand) +FN_GLOBAL_STRING(lp_os2_driver_map, &Globals.szOs2DriverMap) FN_GLOBAL_STRING(lp_lockdir, &Globals.szLockDir) #ifdef WITH_UTMP FN_GLOBAL_STRING(lp_utmpdir, &Globals.szUtmpDir) diff --git a/source3/printing/nt_printing.c b/source3/printing/nt_printing.c index f5c4a234ee..67ac3819ba 100644 --- a/source3/printing/nt_printing.c +++ b/source3/printing/nt_printing.c @@ -2135,6 +2135,86 @@ static int unpack_specifics(NT_PRINTER_PARAM **list, char *buf, int buflen) return len; } +static void map_to_os2_driver(fstring drivername) +{ + static BOOL initialised=False; + static fstring last_from,last_to; + char *mapfile = lp_os2_driver_map(); + char **lines = NULL; + int numlines = 0; + int i; + + if (!strlen(drivername)) + return; + + if (!*mapfile) + return; + + if (!initialised) { + *last_from = *last_to = 0; + initialised = True; + } + + if (strequal(drivername,last_from)) { + DEBUG(3,("Mapped Windows driver %s to OS/2 driver %s\n",drivername,last_to)); + fstrcpy(drivername,last_to); + return; + } + + lines = file_lines_load(mapfile, &numlines, True); + if (numlines == 0) { + DEBUG(0,("No entries in OS/2 driver map %s\n",mapfile)); + return; + } + + DEBUG(4,("Scanning OS/2 driver map %s\n",mapfile)); + + for( i = 0; i < numlines; i++) { + char *nt_name = lines[i]; + char *os2_name = strchr(nt_name,'='); + + if (!os2_name) + continue; + + *os2_name++ = 0; + + while (isspace(*nt_name)) + nt_name++; + + if (!*nt_name || strchr("#;",*nt_name)) + continue; + + { + int l = strlen(nt_name); + while (l && isspace(nt_name[l-1])) { + nt_name[l-1] = 0; + l--; + } + } + + while (isspace(*os2_name)) + os2_name++; + + { + int l = strlen(os2_name); + while (l && isspace(os2_name[l-1])) { + os2_name[l-1] = 0; + l--; + } + } + + if (strequal(nt_name,drivername)) { + DEBUG(3,("Mapped windows driver %s to os2 driver%s\n",drivername,os2_name)); + fstrcpy(last_from,drivername); + fstrcpy(last_to,os2_name); + fstrcpy(drivername,os2_name); + file_lines_free(lines); + return; + } + } + + file_lines_free(lines); +} /**************************************************************************** get a default printer info 2 struct @@ -2273,6 +2353,11 @@ static uint32 get_a_printer_2(NT_PRINTER_INFO_LEVEL_2 **info_ptr, fstring sharen nt_printing_getsec(get_talloc_ctx(), sharename, &info.secdesc_buf); + /* Fix for OS/2 drivers. */ + + if (get_remote_arch() == RA_OS2) + map_to_os2_driver(info.drivername); + safe_free(dbuf.dptr); *info_ptr=memdup(&info, sizeof(info)); diff --git a/source3/smbd/lanman.c b/source3/smbd/lanman.c index 45ce286634..e9df2ed41e 100644 --- a/source3/smbd/lanman.c +++ b/source3/smbd/lanman.c @@ -474,7 +474,7 @@ static void fill_printjob_info(connection_struct *conn, int snum, int uLevel, PACKI(desc,"D",queue->size); /* ulSize */ PACKS(desc,"z",queue->file); /* pszComment */ } - if (uLevel == 2 || uLevel == 3) { + if (uLevel == 2 || uLevel == 3 || uLevel == 4) { PACKI(desc,"W",queue->priority); /* uPriority */ PACKS(desc,"z",queue->user); /* pszUserName */ PACKI(desc,"W",n+1); /* uPosition */ @@ -494,6 +494,17 @@ static void fill_printjob_info(connection_struct *conn, int snum, int uLevel, PACKS(desc,"z","NULL"); /* pszDriverName */ PackDriverData(desc); /* pDriverData */ PACKS(desc,"z",""); /* pszPrinterName */ + } else if (uLevel == 4) { /* OS2 */ + PACKS(desc,"z",""); /* pszSpoolFileName */ + PACKS(desc,"z",""); /* pszPortName */ + PACKS(desc,"z",""); /* pszStatus */ + PACKI(desc,"D",0); /* ulPagesSpooled */ + PACKI(desc,"D",0); /* ulPagesSent */ + PACKI(desc,"D",0); /* ulPagesPrinted */ + PACKI(desc,"D",0); /* ulTimePrinted */ + PACKI(desc,"D",0); /* ulExtendJobStatus */ + PACKI(desc,"D",0); /* ulStartPage */ + PACKI(desc,"D",0); /* ulEndPage */ } } } @@ -859,7 +870,8 @@ static BOOL api_DosPrintQGetInfo(connection_struct *conn, struct pack_desc desc; print_queue_struct *queue=NULL; print_status_struct status; - + char* tmpdata=NULL; + memset((char *)&status,'\0',sizeof(status)); memset((char *)&desc,'\0',sizeof(desc)); @@ -907,9 +919,19 @@ static BOOL api_DosPrintQGetInfo(connection_struct *conn, count = print_queue_status(snum, &queue,&status); } - if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt); - desc.base = *rdata; - desc.buflen = mdrcnt; + if (mdrcnt > 0) { + *rdata = REALLOC(*rdata,mdrcnt); + desc.base = *rdata; + desc.buflen = mdrcnt; + } else { + /* + * Don't return data but need to get correct length + * init_package will return wrong size if buflen=0 + */ + desc.buflen = getlen(desc.format); + desc.base = tmpdata = (char *) malloc (desc.buflen); + } + if (init_package(&desc,1,count)) { desc.subcount = count; fill_printq_info(conn,snum,uLevel,&desc,count,queue,&status); @@ -948,7 +970,8 @@ static BOOL api_DosPrintQGetInfo(connection_struct *conn, DEBUG(4,("printqgetinfo: errorcode %d\n",desc.errcode)); if (queue) free(queue); - + if (tmpdata) free (tmpdata); + return(True); } @@ -2000,6 +2023,7 @@ static int check_printjob_info(struct pack_desc* desc, case 1: desc->format = "WB21BB16B10zWWzDDz"; break; case 2: desc->format = "WWzWWDDzz"; break; case 3: desc->format = "WWzWWDDzzzzzzzzzzlz"; break; + case 4: desc->format = "WWzWWDDzzzzzDDDDDDD"; break; default: return False; } if (strcmp(desc->format,id) != 0) return False; @@ -2755,6 +2779,7 @@ static BOOL api_WPrintJobGetInfo(connection_struct *conn,uint16 vuid, char *para struct pack_desc desc; print_queue_struct *queue=NULL; print_status_struct status; + char *tmpdata=NULL; uLevel = SVAL(p,2); @@ -2776,9 +2801,19 @@ static BOOL api_WPrintJobGetInfo(connection_struct *conn,uint16 vuid, char *para for (i = 0; i < count; i++) { if (queue[i].job == job) break; } - if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt); - desc.base = *rdata; - desc.buflen = mdrcnt; + + if (mdrcnt > 0) { + *rdata = REALLOC(*rdata,mdrcnt); + desc.base = *rdata; + desc.buflen = mdrcnt; + } else { + /* + * Don't return data but need to get correct length + * init_package will return wrong size if buflen=0 + */ + desc.buflen = getlen(desc.format); + desc.base = tmpdata = (char *)malloc ( desc.buflen ); + } if (init_package(&desc,1,0)) { if (i < count) { @@ -2798,6 +2833,7 @@ static BOOL api_WPrintJobGetInfo(connection_struct *conn,uint16 vuid, char *para SSVAL(*rparam,4,desc.neededlen); if (queue) free(queue); + if (tmpdata) free(tmpdata); DEBUG(4,("WPrintJobGetInfo: errorcode %d\n",desc.errcode)); return(True); @@ -2932,6 +2968,7 @@ static BOOL api_WPrintDestGetInfo(connection_struct *conn,uint16 vuid, char *par int uLevel; struct pack_desc desc; int snum; + char *tmpdata=NULL; memset((char *)&desc,'\0',sizeof(desc)); @@ -2959,9 +2996,18 @@ static BOOL api_WPrintDestGetInfo(connection_struct *conn,uint16 vuid, char *par desc.neededlen = 0; } else { - if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt); - desc.base = *rdata; - desc.buflen = mdrcnt; + if (mdrcnt > 0) { + *rdata = REALLOC(*rdata,mdrcnt); + desc.base = *rdata; + desc.buflen = mdrcnt; + } else { + /* + * Don't return data but need to get correct length + * init_package will return wrong size if buflen=0 + */ + desc.buflen = getlen(desc.format); + desc.base = tmpdata = (char *)malloc ( desc.buflen ); + } if (init_package(&desc,1,0)) { fill_printdest_info(conn,snum,uLevel,&desc); } @@ -2975,6 +3021,7 @@ static BOOL api_WPrintDestGetInfo(connection_struct *conn,uint16 vuid, char *par SSVAL(*rparam,4,desc.neededlen); DEBUG(4,("WPrintDestGetInfo: errorcode %d\n",desc.errcode)); + if (tmpdata) free (tmpdata); return(True); } diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index 0489e23040..b9c8ab086c 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -30,6 +30,7 @@ extern int smb_read_error; extern fstring local_machine; extern int global_oplock_break; extern uint32 global_client_caps; +extern pstring global_myname; /**************************************************************************** Send the required number of replies back. @@ -2193,6 +2194,41 @@ static int call_trans2getdfsreferral(connection_struct *conn, char* inbuf, return(-1); } +#define LMCAT_SPL 0x53 +#define LMFUNC_GETJOBID 0x60 + +/**************************************************************************** + reply to a TRANS2_IOCTL - used for OS/2 printing. +****************************************************************************/ + +static int call_trans2ioctl(connection_struct *conn, char* inbuf, + char* outbuf, int length, int bufsize, + char** pparams, char** ppdata) +{ + char *pdata = *ppdata; + files_struct *fsp = file_fsp(inbuf,smb_vwv15); + + if ((SVAL(inbuf,(smb_setup+4)) == LMCAT_SPL) && + (SVAL(inbuf,(smb_setup+6)) == LMFUNC_GETJOBID)) { + pdata = Realloc(*ppdata, 32); + if(pdata == NULL) { + return(ERROR(ERRDOS,ERRnomem)); + } + *ppdata = pdata; + + /* NOTE - THIS IS ASCII ONLY AT THE MOMENT - NOT SURE IF OS/2 + CAN ACCEPT THIS IN UNICODE. JRA. */ + + SSVAL(pdata,0,fsp->print_jobid); /* Job number */ + StrnCpy(pdata+2, global_myname, 15); /* Our NetBIOS name */ + StrnCpy(pdata+18, lp_servicename(SNUM(conn)), 13); /* Service name */ + send_trans2_replies(outbuf,bufsize,*pparams,0,*ppdata,32); + return(-1); + } else { + DEBUG(2,("Unknown TRANS2_IOCTL\n")); + return(ERROR(ERRSRV,ERRerror)); + } +} /**************************************************************************** reply to a SMBfindclose (stop trans2 directory search) @@ -2301,9 +2337,24 @@ int reply_trans2(connection_struct *conn, /* All trans2 messages we handle have smb_sucnt == 1 - ensure this is so as a sanity check */ if (suwcnt != 1) { - DEBUG(2,("Invalid smb_sucnt in trans2 call\n")); - END_PROFILE(SMBtrans2); - return(ERROR(ERRSRV,ERRerror)); + /* + * Need to have rc=0 for ioctl to get job id for OS/2. + * Network printing will fail if function is not successful. + * Similar function in reply.c will be used if protocol + * is LANMAN1.0 instead of LM1.2X002. + * Until DosPrintSetJobInfo with PRJINFO3 is supported, + * outbuf doesn't have to be set(only job id is used). + */ + if ( (suwcnt == 4) && (tran_call == TRANSACT2_IOCTL) && + (SVAL(inbuf,(smb_setup+4)) == LMCAT_SPL) && + (SVAL(inbuf,(smb_setup+6)) == LMFUNC_GETJOBID)) { + DEBUG(2,("Got Trans2 DevIOctl jobid\n")); + } else { + DEBUG(2,("Invalid smb_sucnt in trans2 call(%d)\n",suwcnt)); + DEBUG(2,("Transaction is %d\n",tran_call)); + END_PROFILE(SMBtrans2); + return(ERROR(ERRSRV,ERRerror)); + } } /* Allocate the space for the maximum needed parameters and data */ @@ -2466,10 +2517,16 @@ int reply_trans2(connection_struct *conn, case TRANSACT2_GET_DFS_REFERRAL: START_PROFILE_NESTED(Trans2_get_dfs_referral); - outsize = call_trans2getdfsreferral(conn,inbuf,outbuf,length, - bufsize, ¶ms, &data); + outsize = call_trans2getdfsreferral(conn,inbuf,outbuf,length, + bufsize, ¶ms, &data); END_PROFILE_NESTED(Trans2_get_dfs_referral); break; + case TRANSACT2_IOCTL: + START_PROFILE_NESTED(Trans2_ioctl); + outsize = call_trans2ioctl(conn,inbuf,outbuf,length, + bufsize,¶ms,&data); + END_PROFILE_NESTED(Trans2_ioctl); + break; default: /* Error in request */ DEBUG(2,("Unknown request %d in trans2 call\n", tran_call)); -- cgit