Two OS/2 printer fixes from Jim McDonough @ IBM.
authorJeremy Allison <jra@samba.org>
Fri, 23 Mar 2001 03:12:58 +0000 (03:12 +0000)
committerJeremy Allison <jra@samba.org>
Fri, 23 Mar 2001 03:12:58 +0000 (03:12 +0000)
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
source3/param/loadparm.c
source3/printing/nt_printing.c
source3/smbd/lanman.c
source3/smbd/trans2.c

index ffa77443264a88f3319990a50cb4bbb260f594c1..9d7ec27f95a00b5b15b68866c64dbc363932592a 100644 (file)
@@ -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);
index f930cf2f0997805641add64f765bfb52a2fb3bb1..d35ca97292b2174b8fda66ab2b12fe9ff003ae2a 100644 (file)
@@ -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)
index f5c4a234ee21d3daf18650e87cf8457dfefae634..67ac3819ba255819b412ea4159ec33b62c4d3521 100644 (file)
@@ -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));
 
index 45ce286634f7dadf44c3b9aeb2d3f284cae7dac1..e9df2ed41e5405054e0d4e1022338e867e924f1e 100644 (file)
@@ -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);
 }
 
index 0489e2304007c070d12ec18156de7bc16816ac95..b9c8ab086cb55f96514eb33e228c025fb00412aa 100644 (file)
@@ -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, &params, &data);
+        outsize = call_trans2getdfsreferral(conn,inbuf,outbuf,length,
+                                           bufsize, &params, &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,&params,&data);
+               END_PROFILE_NESTED(Trans2_ioctl);
+               break;
        default:
                /* Error in request */
                DEBUG(2,("Unknown request %d in trans2 call\n", tran_call));