use some symbolic names for print queue status
[tprouty/samba.git] / source / smbd / ipc.c
index eb0abc37c0270c19997ae9f4397cbb4e7126bc3e..4f87d632d2e8f7ee49d4be0d0bfabbbfd474ec72 100644 (file)
@@ -48,7 +48,6 @@ extern fstring global_myworkgroup;
 #define NERR_BufTooSmall (NERR_BASE+23)
 #define NERR_JobNotFound (NERR_BASE+51)
 #define NERR_DestNotFound (NERR_BASE+52)
-#define ERROR_INVALID_LEVEL 124
 
 #define ACCESS_READ 0x01
 #define ACCESS_WRITE 0x02
@@ -59,8 +58,6 @@ extern fstring global_myworkgroup;
 #define SNLEN 15               /* service name length */
 #define QNLEN 12               /* queue name maximum length */
 
-extern int Client;
-extern int oplock_sock;
 extern int smb_read_error;
 
 static BOOL api_Unsupported(connection_struct *conn,uint16 vuid, char *param,char *data,
@@ -82,7 +79,7 @@ static int CopyExpanded(connection_struct *conn,
        if (!src || !dst || !n || !(*dst)) return(0);
 
        StrnCpy(buf,src,sizeof(buf)/2);
-       string_sub(buf,"%S",lp_servicename(snum));
+       pstring_sub(buf,"%S",lp_servicename(snum));
        standard_sub(conn,buf);
        StrnCpy(*dst,buf,*n);
        l = strlen(*dst) + 1;
@@ -95,7 +92,7 @@ static int CopyAndAdvance(char** dst, char* src, int* n)
 {
   int l;
   if (!src || !dst || !n || !(*dst)) return(0);
-  StrnCpy(*dst,src,*n);
+  StrnCpy(*dst,src,*n-1);
   l = strlen(*dst) + 1;
   (*dst) += l;
   (*n) -= l;
@@ -107,7 +104,7 @@ static int StrlenExpanded(connection_struct *conn, int snum, char* s)
        pstring buf;
        if (!s) return(0);
        StrnCpy(buf,s,sizeof(buf)/2);
-       string_sub(buf,"%S",lp_servicename(snum));
+       pstring_sub(buf,"%S",lp_servicename(snum));
        standard_sub(conn,buf);
        return strlen(buf) + 1;
 }
@@ -117,7 +114,7 @@ static char* Expand(connection_struct *conn, int snum, char* s)
        static pstring buf;
        if (!s) return(NULL);
        StrnCpy(buf,s,sizeof(buf)/2);
-       string_sub(buf,"%S",lp_servicename(snum));
+       pstring_sub(buf,"%S",lp_servicename(snum));
        standard_sub(conn,buf);
        return &buf[0];
 }
@@ -139,57 +136,58 @@ static BOOL prefix_ok(char *str,char *prefix)
  cause of some of the ipc problems being experienced.  lkcl26dec97
 
  ******************************************************************/
+
 static void copy_trans_params_and_data(char *outbuf, int align,
-                               struct mem_buf *rparam, struct mem_buf *rdata,
-                               int param_offset, int data_offset,
-                               int param_len, int data_len)
+                               char *rparam, int param_offset, int param_len,
+                               char *rdata, int data_offset, int data_len)
 {
-       char *copy_into = smb_buf(outbuf);
+       char *copy_into = smb_buf(outbuf)+1;
+
+       if(param_len < 0)
+               param_len = 0;
+
+       if(data_len < 0)
+               data_len = 0;
 
        DEBUG(5,("copy_trans_params_and_data: params[%d..%d] data[%d..%d]\n",
                        param_offset, param_offset + param_len,
                        data_offset , data_offset  + data_len));
 
-       if (param_len) mem_buf_copy(copy_into, rparam, param_offset, param_len);
+       if (param_len)
+               memcpy(copy_into, &rparam[param_offset], param_len);
+
        copy_into += param_len + align;
-       if (data_len ) mem_buf_copy(copy_into, rdata , data_offset , data_len);
+
+       if (data_len )
+               memcpy(copy_into, &rdata[data_offset], data_len);
 }
 
 /****************************************************************************
-  send a trans reply
-  ****************************************************************************/
+ Send a trans reply.
+ ****************************************************************************/
+
 static void send_trans_reply(char *outbuf,
-                               struct mem_buf *rdata,
-                               struct mem_buf *rparam,
-                               uint16 *setup, int lsetup, int max_data_ret)
+                               char *rparam, int rparam_len,
+                               char *rdata, int rdata_len,
+                               BOOL buffer_too_large)
 {
-       int i;
        int this_ldata,this_lparam;
-       int tot_data=0,tot_param=0;
+       int tot_data_sent = 0;
+       int tot_param_sent = 0;
        int align;
 
-       int ldata  = rdata  ? mem_buf_len(rdata ) : 0;
-       int lparam = rparam ? mem_buf_len(rparam) : 0;
-
-       BOOL buffer_too_large = max_data_ret ? ldata > max_data_ret : False;
+       int ldata  = rdata  ? rdata_len : 0;
+       int lparam = rparam ? rparam_len : 0;
 
        if (buffer_too_large)
-       {
-               DEBUG(5,("send_trans_reply: buffer %d too large %d\n", ldata, max_data_ret));
-               ldata = max_data_ret;
-       }
+               DEBUG(5,("send_trans_reply: buffer %d too large\n", ldata ));
 
-       this_lparam = MIN(lparam,max_send - (500+lsetup*SIZEOFWORD)); /* hack */
-       this_ldata  = MIN(ldata,max_send - (500+lsetup*SIZEOFWORD+this_lparam));
+       this_lparam = MIN(lparam,max_send - 500); /* hack */
+       this_ldata  = MIN(ldata,max_send - (500+this_lparam));
 
-#ifdef CONFUSE_NETMONITOR_MSRPC_DECODING
-       /* if you don't want Net Monitor to decode your packets, do this!!! */
-       align = ((this_lparam+1)%4);
-#else
-       align = (this_lparam%4);
-#endif
+       align = ((this_lparam)%4);
 
-       set_message(outbuf,10+lsetup,align+this_ldata+this_lparam,True);
+       set_message(outbuf,10,1+align+this_ldata+this_lparam,True);
 
        if (buffer_too_large)
        {
@@ -199,58 +197,57 @@ static void send_trans_reply(char *outbuf,
        }
 
        copy_trans_params_and_data(outbuf, align,
-                                  rparam     , rdata,
-                                  tot_param  , tot_data,
-                                  this_lparam, this_ldata);
+                                                               rparam, tot_param_sent, this_lparam,
+                                                               rdata, tot_data_sent, this_ldata);
 
        SSVAL(outbuf,smb_vwv0,lparam);
        SSVAL(outbuf,smb_vwv1,ldata);
        SSVAL(outbuf,smb_vwv3,this_lparam);
-       SSVAL(outbuf,smb_vwv4,smb_offset(smb_buf(outbuf),outbuf));
+       SSVAL(outbuf,smb_vwv4,smb_offset(smb_buf(outbuf)+1,outbuf));
        SSVAL(outbuf,smb_vwv5,0);
        SSVAL(outbuf,smb_vwv6,this_ldata);
-       SSVAL(outbuf,smb_vwv7,smb_offset(smb_buf(outbuf)+this_lparam+align,outbuf));
+       SSVAL(outbuf,smb_vwv7,smb_offset(smb_buf(outbuf)+1+this_lparam+align,outbuf));
        SSVAL(outbuf,smb_vwv8,0);
-       SSVAL(outbuf,smb_vwv9,lsetup);
-
-       for (i=0;i<lsetup;i++)
-       {
-               SSVAL(outbuf,smb_vwv10+i*SIZEOFWORD,setup[i]);
-       }
+       SSVAL(outbuf,smb_vwv9,0);
 
        show_msg(outbuf);
-       send_smb(Client,outbuf);
+       send_smb(smbd_server_fd(),outbuf);
 
-       tot_data = this_ldata;
-       tot_param = this_lparam;
+       tot_data_sent = this_ldata;
+       tot_param_sent = this_lparam;
 
-       while (tot_data < ldata || tot_param < lparam)
+       while (tot_data_sent < ldata || tot_param_sent < lparam)
        {
-               this_lparam = MIN(lparam-tot_param, max_send - 500); /* hack */
-               this_ldata  = MIN(ldata -tot_data , max_send - (500+this_lparam));
+               this_lparam = MIN(lparam-tot_param_sent, max_send - 500); /* hack */
+               this_ldata  = MIN(ldata -tot_data_sent, max_send - (500+this_lparam));
+
+               if(this_lparam < 0)
+                       this_lparam = 0;
+
+               if(this_ldata < 0)
+                       this_ldata = 0;
 
                align = (this_lparam%4);
 
-               set_message(outbuf,10,this_ldata+this_lparam+align,False);
+               set_message(outbuf,10,1+this_ldata+this_lparam+align,False);
 
                copy_trans_params_and_data(outbuf, align,
-                                          rparam     , rdata,
-                                          tot_param  , tot_data,
-                                          this_lparam, this_ldata);
+                                                                       rparam, tot_param_sent, this_lparam,
+                                                                       rdata, tot_data_sent, this_ldata);
 
                SSVAL(outbuf,smb_vwv3,this_lparam);
-               SSVAL(outbuf,smb_vwv4,smb_offset(smb_buf(outbuf),outbuf));
-               SSVAL(outbuf,smb_vwv5,tot_param);
+               SSVAL(outbuf,smb_vwv4,smb_offset(smb_buf(outbuf)+1,outbuf));
+               SSVAL(outbuf,smb_vwv5,tot_param_sent);
                SSVAL(outbuf,smb_vwv6,this_ldata);
-               SSVAL(outbuf,smb_vwv7,smb_offset(smb_buf(outbuf)+this_lparam+align,outbuf));
-               SSVAL(outbuf,smb_vwv8,tot_data);
+               SSVAL(outbuf,smb_vwv7,smb_offset(smb_buf(outbuf)+1+this_lparam+align,outbuf));
+               SSVAL(outbuf,smb_vwv8,tot_data_sent);
                SSVAL(outbuf,smb_vwv9,0);
 
                show_msg(outbuf);
-               send_smb(Client,outbuf);
+               send_smb(smbd_server_fd(),outbuf);
 
-               tot_data  += this_ldata;
-               tot_param += this_lparam;
+               tot_data_sent  += this_ldata;
+               tot_param_sent += this_lparam;
        }
 }
 
@@ -293,6 +290,9 @@ static int getlen(char* p)
     case 'W':                  /* word (2 byte) */
       n += 2;
       break;
+    case 'K':                  /* status word? (2 byte) */
+      n += 2;
+      break;
     case 'N':                  /* count of substructures (word) at end */
       n += 2;
       break;
@@ -373,17 +373,14 @@ va_dcl
   }
 #if CHECK_TYPES
   str = va_arg(args,char*);
-  if (strncmp(str,p->curpos,strlen(str)) != 0) {
-    DEBUG(2,("type error in package: %s instead of %*s\n",str,
-            strlen(str),p->curpos));
-    va_end(args);
-    smb_panic("invalid types in ipc");
-    return 0;
-  }
+  SMB_ASSERT(strncmp(str,p->curpos,strlen(str)) == 0);
 #endif
   stringneeded = -1;
 
-  if (!p->curpos) return(0);
+  if (!p->curpos) {
+    va_end(args);
+    return(0);
+  }
 
   switch( *p->curpos++ ) {
   case 'W':                    /* word (2 byte) */
@@ -391,6 +388,11 @@ va_dcl
     temp = va_arg(args,int);
     if (p->buflen >= needed) SSVAL(p->structbuf,0,temp);
     break;
+  case 'K':                    /* status word? (2 byte) */
+    needed = 2;
+    temp = va_arg(args,int);
+    if (p->buflen >= needed) SSVAL(p->structbuf,0,temp);
+    break;
   case 'N':                    /* count of substructures (word) at end */
     needed = 2;
     p->subcount = va_arg(args,int);
@@ -405,7 +407,7 @@ va_dcl
     needed = get_counter(&p->curpos);
     {
       char *s = va_arg(args,char*);
-      if (p->buflen >= needed) StrnCpy(p->structbuf,s?s:"",needed);
+      if (p->buflen >= needed) StrnCpy(p->structbuf,s?s:"",needed-1);
     }
     break;
   case 'z':                    /* offset to zero terminated string (4 byte) */
@@ -480,7 +482,6 @@ static void PACKS(struct pack_desc* desc,char *t,char *v)
 /****************************************************************************
   get a print queue
   ****************************************************************************/
-
 static void PackDriverData(struct pack_desc* desc)
 {
   char drivdata[4+4+32];
@@ -516,6 +517,9 @@ static int check_printq_info(struct pack_desc* desc,
   case 5:
     desc->format = "z";
     break;
+  case 51:
+    desc->format = "K";
+    break;
   case 52:
     desc->format = "WzzzzzzzzN";
     desc->subformat = "z";
@@ -527,6 +531,48 @@ static int check_printq_info(struct pack_desc* desc,
   return True;
 }
 
+
+#define JOB_STATUS_QUEUED 0
+#define JOB_STATUS_PAUSED 1
+#define JOB_STATUS_SPOOLING 2
+#define JOB_STATUS_PRINTING 3
+#define JOB_STATUS_PRINTED 4
+
+#define QUEUE_STATUS_PAUSED 1
+#define QUEUE_STATUS_ERROR 2
+
+/* turn a print job status into a on the wire status 
+   right now these are complete guesses - need to fill them in (tridge)
+*/
+static int printj_status(int v)
+{
+       switch (v) {
+       case LPQ_QUEUED:
+               return JOB_STATUS_QUEUED;
+       case LPQ_PAUSED:
+               return JOB_STATUS_PAUSED;
+       case LPQ_SPOOLING:
+               return JOB_STATUS_SPOOLING;
+       case LPQ_PRINTING:
+               return JOB_STATUS_PRINTING;
+       }
+       return 0;
+}
+
+/* turn a print queue status into a on the wire status 
+   right now these are complete guesses - need to fill them in (tridge)
+*/
+static int printq_status(int v)
+{
+       switch (v) {
+       case LPQ_QUEUED:
+               return 0;
+       case LPQ_PAUSED:
+               return QUEUE_STATUS_PAUSED;
+       }
+       return QUEUE_STATUS_ERROR;
+}
+
 static void fill_printjob_info(connection_struct *conn, int snum, int uLevel,
                               struct pack_desc* desc,
                               print_queue_struct* queue, int n)
@@ -536,7 +582,7 @@ static void fill_printjob_info(connection_struct *conn, int snum, int uLevel,
   /* the client expects localtime */
   t -= TimeDiff(t);
 
-  PACKI(desc,"W",printjob_encode(snum, queue->job)); /* uJobId */
+  PACKI(desc,"W",queue->job); /* uJobId */
   if (uLevel == 1) {
     PACKS(desc,"B21",queue->user); /* szUserName */
     PACKS(desc,"B","");                /* pad */
@@ -544,7 +590,7 @@ static void fill_printjob_info(connection_struct *conn, int snum, int uLevel,
     PACKS(desc,"B10","PM_Q_RAW"); /* szDataType */
     PACKS(desc,"z","");                /* pszParms */
     PACKI(desc,"W",n+1);               /* uPosition */
-    PACKI(desc,"W",queue->status); /* fsStatus */
+    PACKI(desc,"W",printj_status(queue->status)); /* fsStatus */
     PACKS(desc,"z","");                /* pszStatus */
     PACKI(desc,"D",t); /* ulSubmitted */
     PACKI(desc,"D",queue->size); /* ulSize */
@@ -554,7 +600,7 @@ static void fill_printjob_info(connection_struct *conn, int snum, int uLevel,
     PACKI(desc,"W",queue->priority);           /* uPriority */
     PACKS(desc,"z",queue->user); /* pszUserName */
     PACKI(desc,"W",n+1);               /* uPosition */
-    PACKI(desc,"W",queue->status); /* fsStatus */
+    PACKI(desc,"W",printj_status(queue->status)); /* fsStatus */
     PACKI(desc,"D",t); /* ulSubmitted */
     PACKI(desc,"D",queue->size); /* ulSize */
     PACKS(desc,"z","Samba");   /* pszComment */
@@ -574,169 +620,191 @@ static void fill_printjob_info(connection_struct *conn, int snum, int uLevel,
   }
 }
 
+
+static void fill_printq_info_52(connection_struct *conn, int snum, int uLevel,
+                               struct pack_desc* desc,
+                               int count, print_queue_struct* queue,
+                               print_status_struct* status)
+{
+       int i,ok=0;
+       pstring tok,driver,datafile,langmon,helpfile,datatype;
+       char *p,*q;
+       FILE *f;
+       pstring fname;
+       
+       pstrcpy(fname,lp_driverfile());
+       f=sys_fopen(fname,"r");
+       if (!f) {
+               DEBUG(3,("fill_printq_info: Can't open %s - %s\n",fname,strerror(errno)));
+               desc->errcode=NERR_notsupported;
+               return;
+       }
+       
+       if((p=(char *)malloc(8192*sizeof(char))) == NULL) {
+               DEBUG(0,("fill_printq_info: malloc fail !\n"));
+               desc->errcode=NERR_notsupported;
+               fclose(f);
+               return;
+       }
+
+       memset(p, '\0',8192*sizeof(char));
+       q=p;
+       
+       /* lookup the long printer driver name in the file
+          description */
+       while (f && !feof(f) && !ok) {
+               p = q;                  /* reset string pointer */
+               fgets(p,8191,f);
+               p[strlen(p)-1]='\0';
+               if (next_token(&p,tok,":",sizeof(tok)) &&
+                   (strlen(lp_printerdriver(snum)) == strlen(tok)) &&
+                   (!strncmp(tok,lp_printerdriver(snum),strlen(lp_printerdriver(snum)))))
+                       ok=1;
+       }
+       fclose(f);
+       
+       /* driver file name */
+       if (ok && !next_token(&p,driver,":",sizeof(driver))) ok = 0;
+       /* data file name */
+       if (ok && !next_token(&p,datafile,":",sizeof(datafile))) ok = 0;
+       /*
+        * for the next tokens - which may be empty - I have
+        * to check for empty tokens first because the
+        * next_token function will skip all empty token
+        * fields */
+       if (ok) {
+               /* help file */
+               if (*p == ':') {
+                       *helpfile = '\0';
+                       p++;
+               } else if (!next_token(&p,helpfile,":",sizeof(helpfile))) ok = 0;
+       }
+       
+       if (ok) {
+               /* language monitor */
+               if (*p == ':') {
+                       *langmon = '\0';
+                       p++;
+               } else if (!next_token(&p,langmon,":",sizeof(langmon)))
+                       ok = 0;
+       }
+       
+       /* default data type */
+       if (ok && !next_token(&p,datatype,":",sizeof(datatype))) 
+               ok = 0;
+       
+       if (ok) {
+               PACKI(desc,"W",0x0400);               /* don't know */
+               PACKS(desc,"z",lp_printerdriver(snum));    /* long printer name */
+               PACKS(desc,"z",driver);                    /* Driverfile Name */
+               PACKS(desc,"z",datafile);                  /* Datafile name */
+               PACKS(desc,"z",langmon);                         /* language monitor */
+               PACKS(desc,"z",lp_driverlocation(snum));   /* share to retrieve files */
+               PACKS(desc,"z",datatype);                        /* default data type */
+               PACKS(desc,"z",helpfile);                  /* helpfile name */
+               PACKS(desc,"z",driver);                    /* driver name */
+               DEBUG(3,("Driver:%s:\n",driver));
+               DEBUG(3,("Data File:%s:\n",datafile));
+               DEBUG(3,("Language Monitor:%s:\n",langmon));
+               DEBUG(3,("Data Type:%s:\n",datatype));
+               DEBUG(3,("Help File:%s:\n",helpfile));
+               PACKI(desc,"N",count);                     /* number of files to copy */
+               for (i=0;i<count;i++) {
+                               /* no need to check return value here
+                                * - it was already tested in
+                                * get_printerdrivernumber */
+                       next_token(&p,tok,",",sizeof(tok));
+                       PACKS(desc,"z",tok);         /* driver files to copy */
+                       DEBUG(3,("file:%s:\n",tok));
+               }
+               
+               DEBUG(3,("fill_printq_info on <%s> gave %d entries\n",
+                        SERVICE(snum),count));
+       } else {
+               DEBUG(3,("fill_printq_info: Can't supply driver files\n"));
+               desc->errcode=NERR_notsupported;
+       }
+       free(q);
+}
+
+
 static void fill_printq_info(connection_struct *conn, int snum, int uLevel,
                             struct pack_desc* desc,
                             int count, print_queue_struct* queue,
                             print_status_struct* status)
 {
-  switch (uLevel) {
-    case 1:
-    case 2:
-      PACKS(desc,"B13",SERVICE(snum));
-      break;
-    case 3:
-    case 4:
-    case 5:
-      PACKS(desc,"z",Expand(conn,snum,SERVICE(snum)));
-      break;
-  }
-
-  if (uLevel == 1 || uLevel == 2) {
-    PACKS(desc,"B","");                /* alignment */
-    PACKI(desc,"W",5);         /* priority */
-    PACKI(desc,"W",0);         /* start time */
-    PACKI(desc,"W",0);         /* until time */
-    PACKS(desc,"z","");                /* pSepFile */
-    PACKS(desc,"z","lpd");     /* pPrProc */
-    PACKS(desc,"z",SERVICE(snum)); /* pDestinations */
-    PACKS(desc,"z","");                /* pParms */
-    if (snum < 0) {
-      PACKS(desc,"z","UNKNOWN PRINTER");
-      PACKI(desc,"W",LPSTAT_ERROR);
-    }
-    else if (!status || !status->message[0]) {
-      PACKS(desc,"z",Expand(conn,snum,lp_comment(snum)));
-      PACKI(desc,"W",LPSTAT_OK); /* status */
-    } else {
-      PACKS(desc,"z",status->message);
-      PACKI(desc,"W",status->status); /* status */
-    }
-    PACKI(desc,(uLevel == 1 ? "W" : "N"),count);
-  }
-  if (uLevel == 3 || uLevel == 4) {
-    PACKI(desc,"W",5);         /* uPriority */
-    PACKI(desc,"W",0);         /* uStarttime */
-    PACKI(desc,"W",0);         /* uUntiltime */
-    PACKI(desc,"W",5);         /* pad1 */
-    PACKS(desc,"z","");                /* pszSepFile */
-    PACKS(desc,"z","WinPrint");        /* pszPrProc */
-    PACKS(desc,"z","");                /* pszParms */
-    if (!status || !status->message[0]) {
-      PACKS(desc,"z",Expand(conn,snum,lp_comment(snum))); /* pszComment */
-      PACKI(desc,"W",LPSTAT_OK); /* fsStatus */
-    } else {
-      PACKS(desc,"z",status->message); /* pszComment */
-      PACKI(desc,"W",status->status); /* fsStatus */
-    }
-    PACKI(desc,(uLevel == 3 ? "W" : "N"),count);       /* cJobs */
-    PACKS(desc,"z",SERVICE(snum)); /* pszPrinters */
-    PACKS(desc,"z",lp_printerdriver(snum));            /* pszDriverName */
-    PackDriverData(desc);      /* pDriverData */
-  }
-  if (uLevel == 2 || uLevel == 4) {
-    int i;
-    for (i=0;i<count;i++)
-      fill_printjob_info(conn,snum,uLevel == 2 ? 1 : 2,desc,&queue[i],i);
-  }
-
-  if (uLevel==52) {
-    int i,ok=0;
-    pstring tok,driver,datafile,langmon,helpfile,datatype;
-    char *p,*q;
-    FILE *f;
-    pstring fname;
-
-    pstrcpy(fname,lp_driverfile());
-    f=fopen(fname,"r");
-    if (!f) {
-      DEBUG(3,("fill_printq_info: Can't open %s - %s\n",fname,strerror(errno)));
-      desc->errcode=NERR_notsupported;
-      return;
-    }
-
-    p=(char *)malloc(8192*sizeof(char));
-    bzero(p, 8192*sizeof(char));
-    q=p;
-
-    /* lookup the long printer driver name in the file description */
-    while (f && !feof(f) && !ok)
-    {
-      p = q;                   /* reset string pointer */
-      fgets(p,8191,f);
-      p[strlen(p)-1]='\0';
-      if (next_token(&p,tok,":") &&
-        (strlen(lp_printerdriver(snum)) == strlen(tok)) &&
-        (!strncmp(tok,lp_printerdriver(snum),strlen(lp_printerdriver(snum)))))
-       ok=1;
-    }
-    fclose(f);
+       switch (uLevel) {
+       case 1:
+       case 2:
+               PACKS(desc,"B13",SERVICE(snum));
+               break;
+       case 3:
+       case 4:
+       case 5:
+               PACKS(desc,"z",Expand(conn,snum,SERVICE(snum)));
+               break;
+       case 51:
+               PACKI(desc,"K",printq_status(status->status));
+               break;
+       }
 
-    /* driver file name */
-    if (ok && !next_token(&p,driver,":")) ok = 0;
-    /* data file name */
-    if (ok && !next_token(&p,datafile,":")) ok = 0;
-      /*
-       * for the next tokens - which may be empty - I have to check for empty
-       * tokens first because the next_token function will skip all empty
-       * token fields 
-       */
-    if (ok) {
-      /* help file */
-      if (*p == ':') {
-         *helpfile = '\0';
-         p++;
-      } else if (!next_token(&p,helpfile,":")) ok = 0;
-    }
+       if (uLevel == 1 || uLevel == 2) {
+               PACKS(desc,"B","");             /* alignment */
+               PACKI(desc,"W",5);              /* priority */
+               PACKI(desc,"W",0);              /* start time */
+               PACKI(desc,"W",0);              /* until time */
+               PACKS(desc,"z","");             /* pSepFile */
+               PACKS(desc,"z","lpd");  /* pPrProc */
+               PACKS(desc,"z",SERVICE(snum)); /* pDestinations */
+               PACKS(desc,"z","");             /* pParms */
+               if (snum < 0) {
+                       PACKS(desc,"z","UNKNOWN PRINTER");
+                       PACKI(desc,"W",LPSTAT_ERROR);
+               }
+               else if (!status || !status->message[0]) {
+                       PACKS(desc,"z",Expand(conn,snum,lp_comment(snum)));
+                       PACKI(desc,"W",LPSTAT_OK); /* status */
+               } else {
+                       PACKS(desc,"z",status->message);
+                       PACKI(desc,"W",printq_status(status->status)); /* status */
+               }
+               PACKI(desc,(uLevel == 1 ? "W" : "N"),count);
+       }
 
-    if (ok) {
-      /* language monitor */
-      if (*p == ':') {
-         *langmon = '\0';
-         p++;
-      } else if (!next_token(&p,langmon,":")) ok = 0;
-    }
+       if (uLevel == 3 || uLevel == 4) {
+               PACKI(desc,"W",5);              /* uPriority */
+               PACKI(desc,"W",0);              /* uStarttime */
+               PACKI(desc,"W",0);              /* uUntiltime */
+               PACKI(desc,"W",5);              /* pad1 */
+               PACKS(desc,"z","");             /* pszSepFile */
+               PACKS(desc,"z","WinPrint");     /* pszPrProc */
+               PACKS(desc,"z","");             /* pszParms */
+               if (!status || !status->message[0]) {
+                       PACKS(desc,"z",Expand(conn,snum,lp_comment(snum))); /* pszComment */
+                       PACKI(desc,"W",LPSTAT_OK); /* fsStatus */
+               } else {
+                       PACKS(desc,"z",status->message); /* pszComment */
+                       PACKI(desc,"W",printq_status(status->status)); /* fsStatus */
+               }
+               PACKI(desc,(uLevel == 3 ? "W" : "N"),count);    /* cJobs */
+               PACKS(desc,"z",SERVICE(snum)); /* pszPrinters */
+               PACKS(desc,"z",lp_printerdriver(snum));         /* pszDriverName */
+               PackDriverData(desc);   /* pDriverData */
+       }
 
-    /* default data type */
-    if (ok && !next_token(&p,datatype,":")) ok = 0;
-
-    if (ok) {
-      PACKI(desc,"W",0x0400);                    /* don't know */
-      PACKS(desc,"z",lp_printerdriver(snum));    /* long printer name */
-      PACKS(desc,"z",driver);                    /* Driverfile Name */
-      PACKS(desc,"z",datafile);                  /* Datafile name */
-      PACKS(desc,"z",langmon);                  /* language monitor */
-      PACKS(desc,"z",lp_driverlocation(snum));   /* share to retrieve files */
-      PACKS(desc,"z",datatype);                         /* default data type */
-      PACKS(desc,"z",helpfile);                  /* helpfile name */
-      PACKS(desc,"z",driver);                    /* driver name */
-      DEBUG(3,("Driver:%s:\n",driver));
-      DEBUG(3,("Data File:%s:\n",datafile));
-      DEBUG(3,("Language Monitor:%s:\n",langmon));
-      DEBUG(3,("Data Type:%s:\n",datatype));
-      DEBUG(3,("Help File:%s:\n",helpfile));
-      PACKI(desc,"N",count);                     /* number of files to copy */
-      for (i=0;i<count;i++)
-      {
-       /* no need to check return value here - it was already tested in
-        * get_printerdrivernumber
-        */
-        next_token(&p,tok,",");
-        PACKS(desc,"z",tok);                        /* driver files to copy */
-        DEBUG(3,("file:%s:\n",tok));
-      }
+       if (uLevel == 2 || uLevel == 4) {
+               int i;
+               for (i=0;i<count;i++)
+                       fill_printjob_info(conn,snum,uLevel == 2 ? 1 : 2,desc,&queue[i],i);
+       }
 
-      DEBUG(3,("fill_printq_info on <%s> gave %d entries\n",
-           SERVICE(snum),count));
-    } else {
-      DEBUG(3,("fill_printq_info: Can't supply driver files\n"));
-      desc->errcode=NERR_notsupported;
-    }
-    free(q);
-  }
+       if (uLevel==52) {
+               fill_printq_info_52(conn, snum, uLevel, desc, count, queue, status);
+       }
 }
 
 /* This function returns the number of files for a given driver */
-int get_printerdrivernumber(int snum)
+static int get_printerdrivernumber(int snum)
 {
   int i=0,ok=0;
   pstring tok;
@@ -747,13 +815,18 @@ int get_printerdrivernumber(int snum)
   pstrcpy(fname,lp_driverfile());
 
   DEBUG(4,("In get_printerdrivernumber: %s\n",fname));
-  f=fopen(fname,"r");
+  f=sys_fopen(fname,"r");
   if (!f) {
     DEBUG(3,("get_printerdrivernumber: Can't open %s - %s\n",fname,strerror(errno)));
     return(0);
   }
 
-  p=(char *)malloc(8192*sizeof(char));
+  if((p=(char *)malloc(8192*sizeof(char))) == NULL) {
+    DEBUG(3,("get_printerdrivernumber: malloc fail !\n"));
+    fclose(f);
+    return 0;
+  }
+
   q=p; /* need it to free memory because p change ! */
 
   /* lookup the long printer driver name in the file description */
@@ -761,7 +834,7 @@ int get_printerdrivernumber(int snum)
   {
     p = q;                     /* reset string pointer */
     fgets(p,8191,f);
-    if (next_token(&p,tok,":") &&
+    if (next_token(&p,tok,":",sizeof(tok)) &&
       (!strncmp(tok,lp_printerdriver(snum),strlen(lp_printerdriver(snum))))) 
        ok=1;
   }
@@ -777,7 +850,7 @@ int get_printerdrivernumber(int snum)
       return(0);
 
     /* count the number of files */
-    while (next_token(&p,tok,","))
+    while (next_token(&p,tok,",",sizeof(tok)))
        i++;
   }
   free(q);
@@ -795,7 +868,7 @@ static BOOL api_DosPrintQGetInfo(connection_struct *conn,
   char *str2 = skip_string(str1,1);
   char *p = skip_string(str2,1);
   char *QueueName = p;
-  int uLevel,cbBuf;
+  int uLevel;
   int count=0;
   int snum;
   char* str3;
@@ -803,12 +876,11 @@ static BOOL api_DosPrintQGetInfo(connection_struct *conn,
   print_queue_struct *queue=NULL;
   print_status_struct status;
   
-  bzero(&status,sizeof(status));
-  bzero(&desc,sizeof(desc));
+  memset((char *)&status,'\0',sizeof(status));
+  memset((char *)&desc,'\0',sizeof(desc));
  
   p = skip_string(p,1);
   uLevel = SVAL(p,0);
-  cbBuf = SVAL(p,2);
   str3 = p + 4;
  
   /* remove any trailing username */
@@ -818,7 +890,20 @@ static BOOL api_DosPrintQGetInfo(connection_struct *conn,
  
   /* check it's a supported varient */
   if (!prefix_ok(str1,"zWrLh")) return False;
-  if (!check_printq_info(&desc,uLevel,str2,str3)) return False;
+  if (!check_printq_info(&desc,uLevel,str2,str3)) {
+    /*
+     * Patch from Scott Moomaw <scott@bridgewater.edu>
+     * to return the 'invalid info level' error if an
+     * unknown level was requested.
+     */
+    *rdata_len = 0;
+    *rparam_len = 6;
+    *rparam = REALLOC(*rparam,*rparam_len);
+    SSVALS(*rparam,0,ERROR_INVALID_LEVEL);
+    SSVAL(*rparam,2,0);
+    SSVAL(*rparam,4,0);
+    return(True);
+  }
  
   snum = lp_servicenumber(QueueName);
   if (snum < 0 && pcap_printername_ok(QueueName,NULL)) {
@@ -835,7 +920,7 @@ static BOOL api_DosPrintQGetInfo(connection_struct *conn,
          count = get_printerdrivernumber(snum);
          DEBUG(3,("api_DosPrintQGetInfo: Driver files count: %d\n",count));
   } else {
-         count = get_printqueue(snum, conn,&queue,&status);
+         count = print_queue_status(snum, &queue,&status);
   }
 
   if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
@@ -844,6 +929,26 @@ static BOOL api_DosPrintQGetInfo(connection_struct *conn,
   if (init_package(&desc,1,count)) {
          desc.subcount = count;
          fill_printq_info(conn,snum,uLevel,&desc,count,queue,&status);
+  } else if(uLevel == 0) {
+       /*
+        * This is a *disgusting* hack.
+        * This is *so* bad that even I'm embarrassed (and I
+        * have no shame). Here's the deal :
+        * Until we get the correct SPOOLSS code into smbd
+        * then when we're running with NT SMB support then
+        * NT makes this call with a level of zero, and then
+        * immediately follows it with an open request to
+        * the \\SRVSVC pipe. If we allow that open to
+        * succeed then NT barfs when it cannot open the
+        * \\SPOOLSS pipe immediately after and continually
+        * whines saying "Printer name is invalid" forever
+        * after. If we cause *JUST THIS NEXT OPEN* of \\SRVSVC
+        * to fail, then NT downgrades to using the downlevel code
+        * and everything works as well as before. I hate
+        * myself for adding this code.... JRA.
+        */
+
+       fail_next_srvsvc_open();
   }
 
   *rdata_len = desc.usedlen;
@@ -883,28 +988,50 @@ static BOOL api_DosPrintQEnum(connection_struct *conn, uint16 vuid, char* param,
   int* subcntarr = NULL;
   int queuecnt, subcnt=0, succnt=0;
  
-  bzero(&desc,sizeof(desc));
+  memset((char *)&desc,'\0',sizeof(desc));
 
   DEBUG(3,("DosPrintQEnum uLevel=%d\n",uLevel));
  
   if (!prefix_ok(param_format,"WrLeh")) return False;
-  if (!check_printq_info(&desc,uLevel,output_format1,output_format2))
-    return False;
+  if (!check_printq_info(&desc,uLevel,output_format1,output_format2)) {
+    /*
+     * Patch from Scott Moomaw <scott@bridgewater.edu>
+     * to return the 'invalid info level' error if an
+     * unknown level was requested.
+     */
+    *rdata_len = 0;
+    *rparam_len = 6;
+    *rparam = REALLOC(*rparam,*rparam_len);
+    SSVALS(*rparam,0,ERROR_INVALID_LEVEL);
+    SSVAL(*rparam,2,0);
+    SSVAL(*rparam,4,0);
+    return(True);
+  }
+
   queuecnt = 0;
   for (i = 0; i < services; i++)
     if (lp_snum_ok(i) && lp_print_ok(i) && lp_browseable(i))
       queuecnt++;
   if (uLevel > 0) {
-    queue = (print_queue_struct**)malloc(queuecnt*sizeof(print_queue_struct*));
+    if((queue = (print_queue_struct**)malloc(queuecnt*sizeof(print_queue_struct*))) == NULL) {
+      DEBUG(0,("api_DosPrintQEnum: malloc fail !\n"));
+      return False;
+    }
     memset(queue,0,queuecnt*sizeof(print_queue_struct*));
-    status = (print_status_struct*)malloc(queuecnt*sizeof(print_status_struct));
+    if((status = (print_status_struct*)malloc(queuecnt*sizeof(print_status_struct))) == NULL) {
+      DEBUG(0,("api_DosPrintQEnum: malloc fail !\n"));
+      return False;
+    }
     memset(status,0,queuecnt*sizeof(print_status_struct));
-    subcntarr = (int*)malloc(queuecnt*sizeof(int));
+    if((subcntarr = (int*)malloc(queuecnt*sizeof(int))) == NULL) {
+      DEBUG(0,("api_DosPrintQEnum: malloc fail !\n"));
+      return False;
+    }
     subcnt = 0;
     n = 0;
     for (i = 0; i < services; i++)
       if (lp_snum_ok(i) && lp_print_ok(i) && lp_browseable(i)) {
-       subcntarr[n] = get_printqueue(i, conn,&queue[n],&status[n]);
+       subcntarr[n] = print_queue_status(i, &queue[n],&status[n]);
        subcnt += subcntarr[n];
        n++;
       }
@@ -992,7 +1119,7 @@ static int get_server_info(uint32 servertype,
   pstrcat(fname,"/");
   pstrcat(fname,SERVER_LIST);
 
-  f = fopen(fname,"r");
+  f = sys_fopen(fname,"r");
 
   if (!f) {
     DEBUG(4,("Can't open %s - %s\n",fname,strerror(errno)));
@@ -1023,14 +1150,14 @@ static int get_server_info(uint32 servertype,
       (*servers) = (struct srv_info_struct *)
        Realloc(*servers,sizeof(**servers)*alloced);
       if (!(*servers)) return(0);
-      bzero((char *)((*servers)+count),sizeof(**servers)*(alloced-count));
+      memset((char *)((*servers)+count),'\0',sizeof(**servers)*(alloced-count));
     }
     s = &(*servers)[count];
     
-    if (!next_token(&ptr,s->name   , NULL)) continue;
-    if (!next_token(&ptr,stype     , NULL)) continue;
-    if (!next_token(&ptr,s->comment, NULL)) continue;
-    if (!next_token(&ptr,s->domain , NULL)) {
+    if (!next_token(&ptr,s->name   , NULL, sizeof(s->name))) continue;
+    if (!next_token(&ptr,stype     , NULL, sizeof(stype))) continue;
+    if (!next_token(&ptr,s->comment, NULL, sizeof(s->comment))) continue;
+    if (!next_token(&ptr,s->domain , NULL, sizeof(s->domain))) {
       /* this allows us to cope with an old nmbd */
       pstrcpy(s->domain,global_myworkgroup); 
     }
@@ -1263,7 +1390,7 @@ static BOOL api_RNetServerEnum(connection_struct *conn, uint16 vuid, char *param
 
   *rdata_len = fixed_len + string_len;
   *rdata = REALLOC(*rdata,*rdata_len);
-  bzero(*rdata,*rdata_len);
+  memset(*rdata,'\0',*rdata_len);
   
   p2 = (*rdata) + fixed_len;   /* auxilliary data (strings) will go here */
   p = *rdata;
@@ -1321,7 +1448,6 @@ static BOOL api_RNetGroupGetUsers(connection_struct *conn, uint16 vuid, char *pa
   if (!prefix_ok(str1,"zWrLeh")) return False;
   
   *rdata_len = 0;
-  *rdata = NULL;
   
   *rparam_len = 8;
   *rparam = REALLOC(*rparam,*rparam_len);
@@ -1601,8 +1727,9 @@ static BOOL api_NetRemoteTOD(connection_struct *conn,uint16 vuid, char *param,ch
 }
 
 /****************************************************************************
-  set the user password
-  ****************************************************************************/
+ Set the user password.
+*****************************************************************************/
+
 static BOOL api_SetUserPassword(connection_struct *conn,uint16 vuid, char *param,char *data,
                                int mdrcnt,int mprcnt,
                                char **rdata,char **rparam,
@@ -1616,6 +1743,8 @@ static BOOL api_SetUserPassword(connection_struct *conn,uint16 vuid, char *param
 
   p = skip_string(p,1);
 
+  memset(pass1,'\0',sizeof(pass1));
+  memset(pass2,'\0',sizeof(pass2));
   memcpy(pass1,p,16);
   memcpy(pass2,p+16,16);
 
@@ -1642,20 +1771,59 @@ static BOOL api_SetUserPassword(connection_struct *conn,uint16 vuid, char *param
   (void)Get_Pwnam( user, True);
 
   /*
-   * Attempt the plaintext password change first.
-   * Older versions of Windows seem to do this.
+   * Attempt to verify the old password against smbpasswd entries
+   * Win98 clients send old and new password in plaintext for this call.
    */
 
-  if (password_ok(user,pass1,strlen(pass1),NULL) &&
-      chgpasswd(user,pass1,pass2,False))
   {
-    SSVAL(*rparam,0,NERR_Success);
+    fstring saved_pass2;
+    struct smb_passwd *smbpw = NULL;
+
+    /*
+     * Save the new password as change_oem_password overwrites it
+     * with zeros.
+     */
+
+    fstrcpy(saved_pass2, pass2);
+
+    if (check_plaintext_password(user,pass1,strlen(pass1),&smbpw) &&
+        change_oem_password(smbpw,pass2,False))
+    {
+      SSVAL(*rparam,0,NERR_Success);
+
+      /*
+       * If unix password sync was requested, attempt to change
+       * the /etc/passwd database also. Return failure if this cannot
+       * be done.
+       */
+
+      if(lp_unix_password_sync() && !chgpasswd(user,pass1,saved_pass2,False))
+        SSVAL(*rparam,0,NERR_badpass);
+    }
+  }
+
+  /*
+   * If the above failed, attempt the plaintext password change.
+   * This tests against the /etc/passwd database only.
+   */
+
+  if(SVAL(*rparam,0) != NERR_Success)
+  {
+    if (password_ok(user, pass1,strlen(pass1),NULL) &&
+        chgpasswd(user,pass1,pass2,False))
+    {
+      SSVAL(*rparam,0,NERR_Success);
+    }
   }
 
   /*
    * If the plaintext change failed, attempt
-   * the encrypted. NT will generate this
-   * after trying the samr method.
+   * the old encrypted method. NT will generate this
+   * after trying the samr method. Note that this
+   * method is done as a last resort as this
+   * password change method loses the NT password hash
+   * and cannot change the UNIX password as no plaintext
+   * is received.
    */
 
   if(SVAL(*rparam,0) != NERR_Success)
@@ -1669,8 +1837,8 @@ static BOOL api_SetUserPassword(connection_struct *conn,uint16 vuid, char *param
     }
   }
 
-  bzero(pass1,sizeof(fstring));
-  bzero(pass2,sizeof(fstring));         
+  memset((char *)pass1,'\0',sizeof(fstring));
+  memset((char *)pass2,'\0',sizeof(fstring));   
         
   return(True);
 }
@@ -1685,11 +1853,7 @@ static BOOL api_SamOEMChangePassword(connection_struct *conn,uint16 vuid, char *
                                int *rdata_len,int *rparam_len)
 {
   fstring user;
-  fstring new_passwd;
-  struct smb_passwd *sampw = NULL;
   char *p = param + 2;
-  int ret = True;
-
   *rparam_len = 2;
   *rparam = REALLOC(*rparam,*rparam_len);
 
@@ -1701,13 +1865,13 @@ static BOOL api_SamOEMChangePassword(connection_struct *conn,uint16 vuid, char *
    * Check the parameter definition is correct.
    */
   if(!strequal(param + 2, "zsT")) {
-    DEBUG(0,("api_SamOEMChangePassword: Invalid parameter string %sn\n", param + 2));
+    DEBUG(0,("api_SamOEMChangePassword: Invalid parameter string %s\n", param + 2));
     return False;
   }
   p = skip_string(p, 1);
 
   if(!strequal(p, "B516B16")) {
-    DEBUG(0,("api_SamOEMChangePassword: Invalid data parameter string %sn\n", p));
+    DEBUG(0,("api_SamOEMChangePassword: Invalid data parameter string %s\n", p));
     return False;
   }
   p = skip_string(p,1);
@@ -1729,24 +1893,8 @@ static BOOL api_SamOEMChangePassword(connection_struct *conn,uint16 vuid, char *
    */
   (void)Get_Pwnam( user, True);
 
-  if(check_oem_password( user, (unsigned char *)data, &sampw, 
-                         new_passwd, (int)sizeof(new_passwd)) == False) {
-    return True;
-  }
-
-  /* 
-   * At this point we have the new case-sensitive plaintext
-   * password in the fstring new_passwd. If we wanted to synchronise
-   * with UNIX passwords we would call a UNIX password changing 
-   * function here. However it would have to be done as root
-   * as the plaintext of the old users password is not 
-   * available. JRA.
-   */
-
-  if(lp_unix_password_sync())
-    ret = chgpasswd(user,"", new_passwd, True);
-  if(ret && change_oem_password( sampw, new_passwd, False)) {
+  if (pass_oem_change(user, (uchar*) data, (uchar *)&data[516], NULL, NULL))
+  {
     SSVAL(*rparam,0,NERR_Success);
   }
 
@@ -1762,60 +1910,46 @@ static BOOL api_RDosPrintJobDel(connection_struct *conn,uint16 vuid, char *param
                                char **rdata,char **rparam,
                                int *rdata_len,int *rparam_len)
 {
-  int function = SVAL(param,0);
-  char *str1 = param+2;
-  char *str2 = skip_string(str1,1);
-  char *p = skip_string(str2,1);
-  int jobid, snum;
-  int i, count;
-
-  printjob_decode(SVAL(p,0), &snum, &jobid);
-
-  /* check it's a supported varient */
-  if (!(strcsequal(str1,"W") && strcsequal(str2,"")))
-    return(False);
-
-  *rparam_len = 4;
-  *rparam = REALLOC(*rparam,*rparam_len);
+       int function = SVAL(param,0);
+       char *str1 = param+2;
+       char *str2 = skip_string(str1,1);
+       char *p = skip_string(str2,1);
+       int jobid, errcode;
 
-  *rdata_len = 0;
+       jobid = SVAL(p,0);
 
-  SSVAL(*rparam,0,NERR_Success);
+       /* check it's a supported varient */
+       if (!(strcsequal(str1,"W") && strcsequal(str2,"")))
+               return(False);
 
-  if (snum >= 0 && VALID_SNUM(snum))
-    {
-      print_queue_struct *queue=NULL;
-      lpq_reset(snum);
-      count = get_printqueue(snum,conn,&queue,NULL);
-  
-      for (i=0;i<count;i++)
-       if ((queue[i].job&0xFF) == jobid)
-         {
-           switch (function) {
-           case 81:            /* delete */ 
-             DEBUG(3,("Deleting queue entry %d\n",queue[i].job));
-             del_printqueue(conn,snum,queue[i].job);
-             break;
-           case 82:            /* pause */
-           case 83:            /* resume */
-             DEBUG(3,("%s queue entry %d\n",
-                      (function==82?"pausing":"resuming"),queue[i].job));
-             status_printjob(conn,snum,queue[i].job,
-                             (function==82?LPQ_PAUSED:LPQ_QUEUED));
-             break;
-           }
-           break;
-         }
-  
-      if (i==count)
-       SSVAL(*rparam,0,NERR_JobNotFound);
+       *rparam_len = 4;
+       *rparam = REALLOC(*rparam,*rparam_len); 
+       *rdata_len = 0;
 
-      if (queue) free(queue);
-    }
+       if (!print_job_exists(jobid)) {
+               errcode = NERR_JobNotFound;
+               goto out;
+       }
 
-  SSVAL(*rparam,2,0);          /* converter word */
+       errcode = NERR_notsupported;
+       
+       switch (function) {
+       case 81:                /* delete */ 
+               if (print_job_delete(jobid)) errcode = NERR_Success;
+               break;
+       case 82:                /* pause */
+               if (print_job_pause(jobid)) errcode = NERR_Success;
+               break;
+       case 83:                /* resume */
+               if (print_job_resume(jobid)) errcode = NERR_Success;
+               break;
+       }
+       
+ out:
+       SSVAL(*rparam,0,errcode);       
+       SSVAL(*rparam,2,0);             /* converter word */
 
-  return(True);
+       return(True);
 }
 
 /****************************************************************************
@@ -1826,59 +1960,45 @@ static BOOL api_WPrintQueuePurge(connection_struct *conn,uint16 vuid, char *para
                                 char **rdata,char **rparam,
                                 int *rdata_len,int *rparam_len)
 {
-  int function = SVAL(param,0);
-  char *str1 = param+2;
-  char *str2 = skip_string(str1,1);
-  char *QueueName = skip_string(str2,1);
-  int snum;
+       int function = SVAL(param,0);
+       char *str1 = param+2;
+       char *str2 = skip_string(str1,1);
+       char *QueueName = skip_string(str2,1);
+       int errcode = NERR_notsupported;
+       int snum;
 
-  /* check it's a supported varient */
-  if (!(strcsequal(str1,"z") && strcsequal(str2,"")))
-    return(False);
+       /* check it's a supported varient */
+       if (!(strcsequal(str1,"z") && strcsequal(str2,"")))
+               return(False);
 
-  *rparam_len = 4;
-  *rparam = REALLOC(*rparam,*rparam_len);
+       *rparam_len = 4;
+       *rparam = REALLOC(*rparam,*rparam_len);
+       *rdata_len = 0;
 
-  *rdata_len = 0;
+       snum = print_queue_snum(QueueName);
 
-  SSVAL(*rparam,0,NERR_Success);
-  SSVAL(*rparam,2,0);          /* converter word */
+       if (snum == -1) {
+               errcode = NERR_JobNotFound;
+               goto out;
+       }
 
-  snum = lp_servicenumber(QueueName);
-  if (snum < 0 && pcap_printername_ok(QueueName,NULL)) {
-    int pnum = lp_servicenumber(PRINTERS_NAME);
-    if (pnum >= 0) {
-      lp_add_printer(QueueName,pnum);
-      snum = lp_servicenumber(QueueName);
-    }
-  }
+       switch (function) {
+       case 74: /* Pause queue */
+               if (print_queue_pause(snum)) errcode = NERR_Success;
+               break;
+       case 75: /* Resume queue */
+               if (print_queue_resume(snum)) errcode = NERR_Success;
+               break;
+       case 103: /* Purge */
+               if (print_queue_purge(snum)) errcode = NERR_Success;
+               break;
+       }
 
-  if (snum >= 0 && VALID_SNUM(snum)) {
-    lpq_reset(snum);
-    
-    switch (function) {
-    case 74: /* Pause queue */
-    case 75: /* Resume queue */
-      status_printqueue(conn,snum,(function==74?LPSTAT_STOPPED:LPSTAT_OK));
-      DEBUG(3,("Print queue %s, queue=%s\n",
-            (function==74?"pause":"resume"),QueueName));
-      break;
-    case 103: /* Purge */
-      {
-        print_queue_struct *queue=NULL;
-        int i, count;
-        count = get_printqueue(snum,conn,&queue,NULL);
-        for (i = 0; i < count; i++)
-          del_printqueue(conn,snum,queue[i].job);
-        if (queue) free(queue);
-        DEBUG(3,("Print queue purge, queue=%s\n",QueueName));
-        break;
-      }
-    }
-  }
+ out:
+       SSVAL(*rparam,0,errcode);
+       SSVAL(*rparam,2,0);             /* converter word */
 
-  return(True);
+       return(True);
 }
 
 
@@ -1892,16 +2012,16 @@ static BOOL api_WPrintQueuePurge(connection_struct *conn,uint16 vuid, char *para
 static int check_printjob_info(struct pack_desc* desc,
                               int uLevel, char* id)
 {
-  desc->subformat = NULL;
-  switch( uLevel ) {
-  case 0: desc->format = "W"; break;
-  case 1: desc->format = "WB21BB16B10zWWzDDz"; break;
-  case 2: desc->format = "WWzWWDDzz"; break;
-  case 3: desc->format = "WWzWWDDzzzzzzzzzzlz"; break;
-  default: return False;
-  }
-  if (strcmp(desc->format,id) != 0) return False;
-  return True;
+       desc->subformat = NULL;
+       switch( uLevel ) {
+       case 0: desc->format = "W"; break;
+       case 1: desc->format = "WB21BB16B10zWWzDDz"; break;
+       case 2: desc->format = "WWzWWDDzz"; break;
+       case 3: desc->format = "WWzWWDDzzzzzzzzzzlz"; break;
+       default: return False;
+       }
+       if (strcmp(desc->format,id) != 0) return False;
+       return True;
 }
 
 static BOOL api_PrintJobInfo(connection_struct *conn,uint16 vuid,char *param,char *data,
@@ -1913,15 +2033,12 @@ static BOOL api_PrintJobInfo(connection_struct *conn,uint16 vuid,char *param,cha
        char *str1 = param+2;
        char *str2 = skip_string(str1,1);
        char *p = skip_string(str2,1);
-       int jobid, snum;
+       int jobid;
        int uLevel = SVAL(p,2);
-       int function = SVAL(p,4);       /* what is this ?? */
-       int i;
-       char *s = data;
-       files_struct *fsp;
+       int function = SVAL(p,4);
+       int place, errcode;
 
-       printjob_decode(SVAL(p,0), &snum, &jobid);
-   
+       jobid = SVAL(p,0);
        *rparam_len = 4;
        *rparam = REALLOC(*rparam,*rparam_len);
   
@@ -1931,80 +2048,37 @@ static BOOL api_PrintJobInfo(connection_struct *conn,uint16 vuid,char *param,cha
        if ((strcmp(str1,"WWsTP")) || 
            (!check_printjob_info(&desc,uLevel,str2)))
                return(False);
-   
+
+       if (!print_job_exists(jobid)) {
+               errcode=NERR_JobNotFound;
+               goto out;
+       }
+
+       errcode = NERR_notsupported;
+
        switch (function) {
-       case 0x6:       /* change job place in the queue, 
-                          data gives the new place */
-               if (snum >= 0 && VALID_SNUM(snum)) {
-                       print_queue_struct *queue=NULL;
-                       int count;
-  
-                       lpq_reset(snum);
-                       count = get_printqueue(snum,conn,&queue,NULL);
-                       for (i=0;i<count;i++)   /* find job */
-                               if ((queue[i].job&0xFF) == jobid) break;
-           
-                       if (i==count) {
-                               desc.errcode=NERR_JobNotFound;
-                               if (queue) free(queue);
-                       } else {
-                               desc.errcode=NERR_Success;
-                               i++;
-#if 0  
-                               {
-                                       int place= SVAL(data,0);
-                                       /* we currently have no way of
-                                          doing this. Can any unix do it? */
-                                       if (i < place)  /* move down */;
-                                       else if (i > place )    /* move up */;
-                               }
-#endif
-                               desc.errcode=NERR_notsupported; /* not yet 
-                                                                  supported */
-                               if (queue) free(queue);
-                       }
-               } else {
-                       desc.errcode=NERR_JobNotFound;
+       case 0x6:
+               /* change job place in the queue, 
+                  data gives the new place */
+               place = SVAL(data,0);
+               if (print_job_set_place(jobid, place)) {
+                       errcode=NERR_Success;
                }
                break;
 
-       case 0xb:   /* change print job name, data gives the name */
-               /* jobid, snum should be zero */
-               if (isalpha((int)*s)) {
-                       pstring name;
-                       int l = 0;
-                       while (l<64 && *s) {
-                               if (issafe(*s)) name[l++] = *s;
-                               s++;
-                       }      
-                       name[l] = 0;
-       
-                       DEBUG(3,("Setting print name to %s\n",name));
-       
-                       fsp = file_find_print();        
-
-                       if (fsp) {
-                               connection_struct *fconn = fsp->conn;
-                               unbecome_user();
-             
-                               if (!become_user(fconn,vuid) || 
-                                   !become_service(fconn,True))
-                                       break;
-             
-                               if (sys_rename(fsp->fsp_name,name) == 0) {
-                                       string_set(&fsp->fsp_name,name);
-                               }
-                               break;
-                       }
+       case 0xb:   
+               /* change print job name, data gives the name */
+               if (print_job_set_name(jobid, data)) {
+                       errcode=NERR_Success;
                }
-               desc.errcode=NERR_Success;
                break;
 
-       default:                        /* not implemented */
+       default:
                return False;
        }
-       SSVALS(*rparam,0,desc.errcode);
+
+ out:
+       SSVALS(*rparam,0,errcode);
        SSVAL(*rparam,2,0);             /* converter word */
        
        return(True);
@@ -2077,7 +2151,7 @@ static BOOL api_RNetServerGetInfo(connection_struct *conn,uint16 vuid, char *par
       pstring comment;
       uint32 servertype= lp_default_server_announce();
 
-      pstrcpy(comment,lp_serverstring());
+      pstrcpy(comment,string_truncate(lp_serverstring(), MAX_SERVER_STRING_LENGTH));
 
       if ((count=get_server_info(SV_TYPE_ALL,&servers,global_myworkgroup))>0) {
        for (i=0;i<count;i++)
@@ -2376,7 +2450,7 @@ static BOOL api_RNetUserGetInfo(connection_struct *conn,uint16 vuid, char *param
        Don't depend on vuser being non-null !!. JRA */
     user_struct *vuser = get_valid_user_struct(vuid);
     if(vuser != NULL)
-      DEBUG(3,("  Username of UID %d is %s\n", vuser->uid, vuser->name));
+      DEBUG(3,("  Username of UID %d is %s\n", (int)vuser->uid, vuser->name));
 
     *rparam_len = 6;
     *rparam = REALLOC(*rparam,*rparam_len);
@@ -2436,7 +2510,7 @@ static BOOL api_RNetUserGetInfo(connection_struct *conn,uint16 vuid, char *param
                SIVAL(p,usri11_auth_flags,AF_OP_PRINT);         /* auth flags */
                SIVALS(p,usri11_password_age,-1);               /* password age */
                SIVAL(p,usri11_homedir,PTR_DIFF(p2,p)); /* home dir */
-               pstrcpy(p2, lp_logon_path());
+               pstrcpy(p2, lp_logon_home());
                p2 = skip_string(p2,1);
                SIVAL(p,usri11_parms,PTR_DIFF(p2,p)); /* parms */
                pstrcpy(p2,"");
@@ -2472,12 +2546,15 @@ static BOOL api_RNetUserGetInfo(connection_struct *conn,uint16 vuid, char *param
                SSVAL(p,42,
                conn->admin_user?USER_PRIV_ADMIN:USER_PRIV_USER);
                SIVAL(p,44,PTR_DIFF(p2,*rdata)); /* home dir */
-               pstrcpy(p2,lp_logon_path());
+               pstrcpy(p2,lp_logon_home());
                p2 = skip_string(p2,1);
                SIVAL(p,48,PTR_DIFF(p2,*rdata)); /* comment */
                *p2++ = 0;
                SSVAL(p,52,0);          /* flags */
-               SIVAL(p,54,0);          /* script_path */
+               SIVAL(p,54,PTR_DIFF(p2,*rdata));                /* script_path */
+               pstrcpy(p2,lp_logon_script());
+               standard_sub( conn, p2 );             
+               p2 = skip_string(p2,1);
                if (uLevel == 2)
                {
                        SIVAL(p,60,0);          /* auth_flags */
@@ -2576,12 +2653,11 @@ static BOOL api_WWkstaUserLogon(connection_struct *conn,uint16 vuid, char *param
   int uLevel;
   struct pack_desc desc;
   char* name;
-  char* logon_script;
 
   uLevel = SVAL(p,0);
   name = p + 2;
 
-  bzero(&desc,sizeof(desc));
+  memset((char *)&desc,'\0',sizeof(desc));
 
   DEBUG(3,("WWkstaUserLogon uLevel=%d name=%s\n",uLevel,name));
 
@@ -2622,9 +2698,12 @@ static BOOL api_WWkstaUserLogon(connection_struct *conn,uint16 vuid, char *param
 
 /* JHT - By calling lp_logon_script() and standard_sub() we have */
 /* made sure all macros are fully substituted and available */
-    logon_script = lp_logon_script();
-    standard_sub( conn, logon_script );
-    PACKS(&desc,"z", logon_script);            /* script path */
+    {
+      pstring logon_script;
+      pstrcpy(logon_script,lp_logon_script());
+      standard_sub( conn, logon_script );
+      PACKS(&desc,"z", logon_script);          /* script path */
+    }
 /* End of JHT mods */
 
     PACKI(&desc,"D",0x00000000);               /* reserved */
@@ -2681,7 +2760,7 @@ static BOOL api_WPrintJobGetInfo(connection_struct *conn,uint16 vuid, char *para
   char *str1 = param+2;
   char *str2 = skip_string(str1,1);
   char *p = skip_string(str2,1);
-  int uLevel,cbBuf;
+  int uLevel;
   int count;
   int i;
   int snum;
@@ -2691,10 +2770,9 @@ static BOOL api_WPrintJobGetInfo(connection_struct *conn,uint16 vuid, char *para
   print_status_struct status;
 
   uLevel = SVAL(p,2);
-  cbBuf = SVAL(p,4);
 
-  bzero(&desc,sizeof(desc));
-  bzero(&status,sizeof(status));
+  memset((char *)&desc,'\0',sizeof(desc));
+  memset((char *)&status,'\0',sizeof(status));
 
   DEBUG(3,("WPrintJobGetInfo uLevel=%d uJobId=0x%X\n",uLevel,SVAL(p,0)));
 
@@ -2702,13 +2780,13 @@ static BOOL api_WPrintJobGetInfo(connection_struct *conn,uint16 vuid, char *para
   if (strcmp(str1,"WWrLh") != 0) return False;
   if (!check_printjob_info(&desc,uLevel,str2)) return False;
 
-  printjob_decode(SVAL(p,0), &snum, &job);
+  job = SVAL(p,0);
 
   if (snum < 0 || !VALID_SNUM(snum)) return(False);
 
-  count = get_printqueue(snum,conn,&queue,&status);
+  count = print_queue_status(snum,&queue,&status);
   for (i = 0; i < count; i++) {
-    if ((queue[i].job & 0xFF) == job) break;
+    if (queue[i].job == job) break;
   }
   if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
   desc.base = *rdata;
@@ -2746,7 +2824,7 @@ static BOOL api_WPrintJobEnumerate(connection_struct *conn,uint16 vuid, char *pa
   char *str2 = skip_string(str1,1);
   char *p = skip_string(str2,1);
   char* name = p;
-  int uLevel,cbBuf;
+  int uLevel;
   int count;
   int i, succnt=0;
   int snum;
@@ -2754,12 +2832,11 @@ static BOOL api_WPrintJobEnumerate(connection_struct *conn,uint16 vuid, char *pa
   print_queue_struct *queue=NULL;
   print_status_struct status;
 
-  bzero(&desc,sizeof(desc));
-  bzero(&status,sizeof(status));
+  memset((char *)&desc,'\0',sizeof(desc));
+  memset((char *)&status,'\0',sizeof(status));
 
   p = skip_string(p,1);
   uLevel = SVAL(p,0);
-  cbBuf = SVAL(p,2);
 
   DEBUG(3,("WPrintJobEnumerate uLevel=%d name=%s\n",uLevel,name));
 
@@ -2779,7 +2856,7 @@ static BOOL api_WPrintJobEnumerate(connection_struct *conn,uint16 vuid, char *pa
 
   if (snum < 0 || !VALID_SNUM(snum)) return(False);
 
-  count = get_printqueue(snum,conn,&queue,&status);
+  count = print_queue_status(snum,&queue,&status);
   if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
   desc.base = *rdata;
   desc.buflen = mdrcnt;
@@ -2864,15 +2941,14 @@ static BOOL api_WPrintDestGetInfo(connection_struct *conn,uint16 vuid, char *par
   char *str2 = skip_string(str1,1);
   char *p = skip_string(str2,1);
   char* PrinterName = p;
-  int uLevel,cbBuf;
+  int uLevel;
   struct pack_desc desc;
   int snum;
 
-  bzero(&desc,sizeof(desc));
+  memset((char *)&desc,'\0',sizeof(desc));
 
   p = skip_string(p,1);
   uLevel = SVAL(p,0);
-  cbBuf = SVAL(p,2);
 
   DEBUG(3,("WPrintDestGetInfo uLevel=%d PrinterName=%s\n",uLevel,PrinterName));
 
@@ -2922,16 +2998,15 @@ static BOOL api_WPrintDestEnum(connection_struct *conn,uint16 vuid, char *param,
   char *str1 = param+2;
   char *str2 = skip_string(str1,1);
   char *p = skip_string(str2,1);
-  int uLevel,cbBuf;
+  int uLevel;
   int queuecnt;
   int i, n, succnt=0;
   struct pack_desc desc;
   int services = lp_numservices();
 
-  bzero(&desc,sizeof(desc));
+  memset((char *)&desc,'\0',sizeof(desc));
 
   uLevel = SVAL(p,0);
-  cbBuf = SVAL(p,2);
 
   DEBUG(3,("WPrintDestEnum uLevel=%d\n",uLevel));
 
@@ -2980,14 +3055,13 @@ static BOOL api_WPrintDriverEnum(connection_struct *conn,uint16 vuid, char *para
   char *str1 = param+2;
   char *str2 = skip_string(str1,1);
   char *p = skip_string(str2,1);
-  int uLevel,cbBuf;
+  int uLevel;
   int succnt;
   struct pack_desc desc;
 
-  bzero(&desc,sizeof(desc));
+  memset((char *)&desc,'\0',sizeof(desc));
 
   uLevel = SVAL(p,0);
-  cbBuf = SVAL(p,2);
 
   DEBUG(3,("WPrintDriverEnum uLevel=%d\n",uLevel));
 
@@ -3025,14 +3099,13 @@ static BOOL api_WPrintQProcEnum(connection_struct *conn,uint16 vuid, char *param
   char *str1 = param+2;
   char *str2 = skip_string(str1,1);
   char *p = skip_string(str2,1);
-  int uLevel,cbBuf;
+  int uLevel;
   int succnt;
   struct pack_desc desc;
 
-  bzero(&desc,sizeof(desc));
+  memset((char *)&desc,'\0',sizeof(desc));
 
   uLevel = SVAL(p,0);
-  cbBuf = SVAL(p,2);
 
   DEBUG(3,("WPrintQProcEnum uLevel=%d\n",uLevel));
 
@@ -3071,14 +3144,13 @@ static BOOL api_WPrintPortEnum(connection_struct *conn,uint16 vuid, char *param,
   char *str1 = param+2;
   char *str2 = skip_string(str1,1);
   char *p = skip_string(str2,1);
-  int uLevel,cbBuf;
+  int uLevel;
   int succnt;
   struct pack_desc desc;
 
-  bzero(&desc,sizeof(desc));
+  memset((char *)&desc,'\0',sizeof(desc));
 
   uLevel = SVAL(p,0);
-  cbBuf = SVAL(p,2);
 
   DEBUG(3,("WPrintPortEnum uLevel=%d\n",uLevel));
 
@@ -3087,7 +3159,7 @@ static BOOL api_WPrintPortEnum(connection_struct *conn,uint16 vuid, char *param,
   if (uLevel != 0 || strcmp(str2,"B9") != 0) return False;
 
   if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
-  bzero(&desc,sizeof(desc));
+  memset((char *)&desc,'\0',sizeof(desc));
   desc.base = *rdata;
   desc.buflen = mdrcnt;
   desc.format = str2;
@@ -3110,221 +3182,71 @@ static BOOL api_WPrintPortEnum(connection_struct *conn,uint16 vuid, char *param,
   return(True);
 }
 
-struct api_cmd
-{
-  char * pipe_clnt_name;
-  char * pipe_srv_name;
-  BOOL (*fn) (pipes_struct *, prs_struct *);
-};
-
-static struct api_cmd api_fd_commands[] =
-{
-    { "lsarpc",   "lsass",   api_ntlsa_rpc },
-    { "samr",     "lsass",   api_samr_rpc },
-    { "srvsvc",   "ntsvcs",  api_srvsvc_rpc },
-    { "wkssvc",   "ntsvcs",  api_wkssvc_rpc },
-    { "NETLOGON", "lsass",   api_netlog_rpc },
-    { "winreg",   "winreg",  api_reg_rpc },
-    { NULL,       NULL,      NULL }
-};
+/****************************************************************************
+ Start the first part of an RPC reply which began with an SMBtrans request.
+****************************************************************************/
 
-static BOOL api_pipe_bind_req(pipes_struct *p, prs_struct *pd)
+static BOOL api_rpc_trans_reply(char *outbuf, pipes_struct *p)
 {
-       BOOL ntlmssp_auth = False;
-       fstring ack_pipe_name;
-       int i = 0;
-
-       DEBUG(5,("api_pipe_bind_req: decode request. %d\n", __LINE__));
-
-       for (i = 0; api_fd_commands[i].pipe_clnt_name; i++)
-       {
-               if (strequal(api_fd_commands[i].pipe_clnt_name, p->name) &&
-                   api_fd_commands[i].fn != NULL)
-               {
-                       DEBUG(3,("api_pipe_bind_req: \\PIPE\\%s -> \\PIPE\\%s\n",
-                                  api_fd_commands[i].pipe_clnt_name,
-                                  api_fd_commands[i].pipe_srv_name));
-                       fstrcpy(p->pipe_srv_name, api_fd_commands[i].pipe_srv_name);
-                       break;
-               }
-       }
-
-       if (api_fd_commands[i].fn == NULL) return False;
-
-       /* decode the bind request */
-       smb_io_rpc_hdr_rb("", &p->hdr_rb, pd, 0);
-
-       if (pd->offset == 0) return False;
-
-       if (p->hdr.auth_len != 0)
-       {
-               /* decode the authentication verifier */
-               smb_io_rpc_auth_ntlmssp_req("", &p->ntlmssp_req, pd, 0);
+       char *rdata = malloc(p->max_trans_reply);
+       int data_len;
 
-               if (pd->offset == 0) return False;
-
-               /* ignore the version number for now */
-               ntlmssp_auth = strequal(p->ntlmssp_req.ntlmssp_str, "NTLMSSP");
+       if(rdata == NULL) {
+               DEBUG(0,("api_rpc_trans_reply: malloc fail.\n"));
+               return False;
        }
 
-       /* name has to be \PIPE\xxxxx */
-       fstrcpy(ack_pipe_name, "\\PIPE\\");
-       fstrcat(ack_pipe_name, p->pipe_srv_name);
-
-       DEBUG(5,("api_pipe_bind_req: make response. %d\n", __LINE__));
-
-       prs_init(&(p->rdata), 1024, 4, 0, False);
-       prs_init(&(p->rhdr ), 0x10, 4, 0, False);
-       prs_init(&(p->rauth), 1024, 4, 0, False);
-
-    /***/
-       /*** do the bind ack first ***/
-    /***/
-
-       make_rpc_hdr_ba(&p->hdr_ba,
-                                       p->hdr_rb.bba.max_tsize,
-                       p->hdr_rb.bba.max_rsize,
-                       p->hdr_rb.bba.assoc_gid,
-                                       ack_pipe_name,
-                                       0x1, 0x0, 0x0,
-                                       &(p->hdr_rb.transfer));
-
-       smb_io_rpc_hdr_ba("", &p->hdr_ba, &p->rdata, 0);
-       mem_realloc_data(p->rdata.data, p->rdata.offset);
-
-    /***/
-       /*** now the authentication ***/
-    /***/
-
-       if (ntlmssp_auth)
-       {
-               uint8 data[16];
-               bzero(data, sizeof(data)); /* first 8 bytes are non-zero */
-
-               make_rpc_auth_ntlmssp_resp(&p->ntlmssp_resp,
-                                          0x0a, 0x06, 0,
-                                          "NTLMSSP", 2,
-                                          0x00000000, 0x0000b2b3, 0x000082b1,
-                                          data);
-               smb_io_rpc_auth_ntlmssp_resp("", &p->ntlmssp_resp, &p->rauth, 0);
-               mem_realloc_data(p->rauth.data, p->rauth.offset);
+       if((data_len = read_from_pipe( p, rdata, p->max_trans_reply)) < 0) {
+               free(rdata);
+               return False;
        }
 
-    /***/
-       /*** then do the header, now we know the length ***/
-    /***/
-
-       make_rpc_hdr(&p->hdr, RPC_BINDACK, RPC_FLG_FIRST | RPC_FLG_LAST,
-                                p->hdr.call_id,
-                    p->rdata.offset + p->rauth.offset,
-                    p->rauth.offset);
-
-       smb_io_rpc_hdr("", &p->hdr, &p->rhdr, 0);
-       mem_realloc_data(p->rhdr.data, p->rdata.offset);
-
-    /***/
-       /*** link rpc header, bind acknowledgment and authentication responses ***/
-    /***/
-
-       p->rhdr.data->offset.start = 0;
-       p->rhdr.data->offset.end   = p->rhdr.offset;
-       p->rhdr.data->next         = p->rdata.data;
-
-       if (ntlmssp_auth)
-       {
-               p->rdata.data->offset.start = p->rhdr.offset;
-               p->rdata.data->offset.end   = p->rhdr.offset + p->rdata.offset;
-               p->rdata.data->next         = p->rauth.data;
-
-               p->rauth.data->offset.start = p->rhdr.offset + p->rdata.offset;
-               p->rauth.data->offset.end   = p->rhdr.offset + p->rauth.offset + p->rdata.offset;
-               p->rauth.data->next         = NULL;
-       }
-       else
-       {
-               p->rdata.data->offset.start = p->rhdr.offset;
-               p->rdata.data->offset.end   = p->rhdr.offset + p->rdata.offset;
-               p->rdata.data->next         = NULL;
-       }
+       send_trans_reply(outbuf, NULL, 0, rdata, data_len, p->out_data.current_pdu_len > data_len);
 
+       free(rdata);
        return True;
 }
 
-static BOOL api_pipe_request(pipes_struct *p, prs_struct *pd)
-{
-       int i = 0;
-
-       for (i = 0; api_fd_commands[i].pipe_clnt_name; i++)
-       {
-               if (strequal(api_fd_commands[i].pipe_clnt_name, p->name) &&
-                   api_fd_commands[i].fn != NULL)
-               {
-                       DEBUG(3,("Doing \\PIPE\\%s\n", api_fd_commands[i].pipe_clnt_name));
-                       return api_fd_commands[i].fn(p, pd);
-               }
-       }
-       return False;
-}
+/****************************************************************************
+ WaitNamedPipeHandleState 
+****************************************************************************/
 
-static BOOL api_dce_rpc_command(char *outbuf,
-                               pipes_struct *p,
-                               prs_struct *pd)
+static BOOL api_WNPHS(char *outbuf, pipes_struct *p, char *param, int param_len)
 {
-       BOOL reply = False;
-       if (pd->data == NULL) return False;
-
-       /* process the rpc header */
-       smb_io_rpc_hdr("", &p->hdr, pd, 0);
+       uint16 priority;
 
-       if (pd->offset == 0) return False;
+       if (!param || param_len < 2)
+               return False;
 
-       switch (p->hdr.pkt_type)
-       {
-               case RPC_BIND   :
-               {
-                       reply = api_pipe_bind_req(p, pd);
-                       break;
-               }
-               case RPC_REQUEST:
-               {
-                       reply = api_pipe_request (p, pd);
-                       break;
-               }
-       }
+       priority = SVAL(param,0);
+       DEBUG(4,("WaitNamedPipeHandleState priority %x\n", priority));
 
-       if (reply)
-       {
+       if (wait_rpc_pipe_hnd_state(p, priority)) {
                /* now send the reply */
-               send_trans_reply(outbuf, p->rhdr.data, NULL, NULL, 0, p->file_offset);
-
-               if (mem_buf_len(p->rhdr.data) <= p->file_offset)
-               {
-                       /* all of data was sent: no need to wait for SMBreadX calls */
-                       mem_free_data(p->rhdr .data);
-                       mem_free_data(p->rdata.data);
-               }
+               send_trans_reply(outbuf, NULL, 0, NULL, 0, False);
+               return True;
        }
-
-       return reply;
+       return False;
 }
 
+
 /****************************************************************************
  SetNamedPipeHandleState 
 ****************************************************************************/
-static BOOL api_SNPHS(char *outbuf, pipes_struct *p, char *param)
+
+static BOOL api_SNPHS(char *outbuf, pipes_struct *p, char *param, int param_len)
 {
        uint16 id;
 
-       if (!param) return False;
+       if (!param || param_len < 2)
+               return False;
 
-       id = param[0] + (param[1] << 8);
-       DEBUG(4,("lsarpc SetNamedPipeHandleState to code %x\n", id));
+       id = SVAL(param,0);
+       DEBUG(4,("SetNamedPipeHandleState to code %x\n", id));
 
-       if (set_rpc_pipe_hnd_state(p, id))
-       {
+       if (set_rpc_pipe_hnd_state(p, id)) {
                /* now send the reply */
-               send_trans_reply(outbuf, NULL, NULL, NULL, 0, p->file_offset);
-
+               send_trans_reply(outbuf, NULL, 0, NULL, 0, False);
                return True;
        }
        return False;
@@ -3332,114 +3254,93 @@ static BOOL api_SNPHS(char *outbuf, pipes_struct *p, char *param)
 
 
 /****************************************************************************
when no reply is generated, indicate unsupported.
When no reply is generated, indicate unsupported.
  ****************************************************************************/
+
 static BOOL api_no_reply(char *outbuf, int max_rdata_len)
 {
-       struct mem_buf rparam;
-
-       mem_init(&rparam, 0);
-       mem_alloc_data(&rparam, 4);
-
-       rparam.offset.start = 0;
-       rparam.offset.end   = 4;
+       char rparam[4];
 
        /* unsupported */
-       SSVAL(rparam.data,0,NERR_notsupported);
-       SSVAL(rparam.data,2,0); /* converter word */
+       SSVAL(rparam,0,NERR_notsupported);
+       SSVAL(rparam,2,0); /* converter word */
 
        DEBUG(3,("Unsupported API fd command\n"));
 
        /* now send the reply */
-       send_trans_reply(outbuf, NULL, &rparam, NULL, 0, max_rdata_len);
-
-       mem_free_data(&rparam);
+       send_trans_reply(outbuf, rparam, 4, NULL, 0, False);
 
-       return(-1);
+       return -1;
 }
 
 /****************************************************************************
-  handle remote api calls delivered to a named pipe already opened.
-  ****************************************************************************/
+ Handle remote api calls delivered to a named pipe already opened.
+ ****************************************************************************/
+
 static int api_fd_reply(connection_struct *conn,uint16 vuid,char *outbuf,
                        uint16 *setup,char *data,char *params,
                        int suwcnt,int tdscnt,int tpscnt,int mdrcnt,int mprcnt)
 {
-       BOOL reply    = False;
-
+       BOOL reply = False;
+       pipes_struct *p = NULL;
        int pnum;
        int subcommand;
-       pipes_struct *p = NULL;
-       prs_struct pd;
-       struct mem_buf data_buf;
 
        DEBUG(5,("api_fd_reply\n"));
 
-       /* fake up a data buffer from the api_fd_reply data parameters */
-       mem_create(&data_buf, data, tdscnt, 0, False);
-       data_buf.offset.start = 0;
-       data_buf.offset.end   = tdscnt;
-
-       /* fake up a parsing structure */
-       pd.data = &data_buf;
-       pd.align = 4;
-       pd.io = True;
-       pd.offset = 0;
-
        /* First find out the name of this file. */
-       if (suwcnt != 2)
-       {
+       if (suwcnt != 2) {
                DEBUG(0,("Unexpected named pipe transaction.\n"));
                return(-1);
        }
 
        /* Get the file handle and hence the file name. */
-       pnum = setup[1];
-       subcommand = setup[0];
-       p = get_rpc_pipe(pnum);
+       /* 
+        * NB. The setup array has already been transformed
+        * via SVAL and so is in gost byte order.
+        */
+       pnum = ((int)setup[1]) & 0xFFFF;
+       subcommand = ((int)setup[0]) & 0xFFFF;
 
-       if (p != NULL)
-       {
-               DEBUG(3,("Got API command 0x%x on pipe \"%s\" (pnum %x)",
-                                 subcommand, p->name, pnum));
+       if(!(p = get_rpc_pipe(pnum))) {
+               DEBUG(1,("api_fd_reply: INVALID PIPE HANDLE: %x\n", pnum));
+               return api_no_reply(outbuf, mdrcnt);
+       }
 
-               /* record maximum data length that can be transmitted in an SMBtrans */
-               p->file_offset = mdrcnt;
+       DEBUG(3,("Got API command 0x%x on pipe \"%s\" (pnum %x)", subcommand, p->name, pnum));
 
-                DEBUG(10,("api_fd_reply: p:%p file_offset: %d\n",
-                           p, p->file_offset));
+       /* record maximum data length that can be transmitted in an SMBtrans */
+       p->max_trans_reply = mdrcnt;
 
-               switch (subcommand)
-               {
-                       case 0x26:
-                       {
-                               /* dce/rpc command */
-                               reply = api_dce_rpc_command(outbuf, p, &pd);
-                               break;
-                       }
-                       case 0x01:
-                       {
-                               /* Set Named Pipe Handle state */
-                               reply = api_SNPHS(outbuf, p, params);
-                               break;
-                       }
-               }
-       }
-       else
-       {
-               DEBUG(1,("api_fd_reply: INVALID PIPE HANDLE: %x\n", pnum));
+       DEBUG(10,("api_fd_reply: p:%p max_trans_reply: %d\n", p, p->max_trans_reply));
+
+       switch (subcommand) {
+       case 0x26:
+               /* dce/rpc command */
+               reply = write_to_pipe(p, data, tdscnt);
+               if (reply)
+                       reply = api_rpc_trans_reply(outbuf, p);
+               break;
+       case 0x53:
+               /* Wait Named Pipe Handle state */
+               reply = api_WNPHS(outbuf, p, params, tpscnt);
+               break;
+       case 0x01:
+               /* Set Named Pipe Handle state */
+               reply = api_SNPHS(outbuf, p, params, tpscnt);
+               break;
        }
 
        if (!reply)
-       {
                return api_no_reply(outbuf, mdrcnt);
-       }
+
        return -1;
 }
 
 /****************************************************************************
-  the buffer was too small
-  ****************************************************************************/
+ The buffer was too small
+ ****************************************************************************/
+
 static BOOL api_TooSmall(connection_struct *conn,uint16 vuid, char *param,char *data,
                         int mdrcnt,int mprcnt,
                         char **rdata,char **rparam,
@@ -3459,8 +3360,9 @@ static BOOL api_TooSmall(connection_struct *conn,uint16 vuid, char *param,char *
 
 
 /****************************************************************************
-  the request is not supported
-  ****************************************************************************/
+ The request is not supported
+ ****************************************************************************/
+
 static BOOL api_Unsupported(connection_struct *conn,uint16 vuid, char *param,char *data,
                            int mdrcnt,int mprcnt,
                            char **rdata,char **rparam,
@@ -3523,14 +3425,13 @@ struct
 
 
 /****************************************************************************
-  handle remote api calls
-  ****************************************************************************/
+ Handle remote api calls
+ ****************************************************************************/
+
 static int api_reply(connection_struct *conn,uint16 vuid,char *outbuf,char *data,char *params,
                     int tdscnt,int tpscnt,int mdrcnt,int mprcnt)
 {
-  int api_command = SVAL(params,0);
-  struct mem_buf rdata_buf;
-  struct mem_buf rparam_buf;
+  int api_command;
   char *rdata = NULL;
   char *rparam = NULL;
   int rdata_len = 0;
@@ -3538,54 +3439,62 @@ static int api_reply(connection_struct *conn,uint16 vuid,char *outbuf,char *data
   BOOL reply=False;
   int i;
 
+  if (!params) {
+         DEBUG(0,("ERROR: NULL params in api_reply()\n"));
+         return 0;
+  }
+
+  api_command = SVAL(params,0);
+
   DEBUG(3,("Got API command %d of form <%s> <%s> (tdscnt=%d,tpscnt=%d,mdrcnt=%d,mprcnt=%d)\n",
-          api_command,params+2,skip_string(params+2,1),
+          api_command,
+          params+2,
+          skip_string(params+2,1),
           tdscnt,tpscnt,mdrcnt,mprcnt));
 
-  for (i=0;api_commands[i].name;i++)
-    if (api_commands[i].id == api_command && api_commands[i].fn)
-      {
-       DEBUG(3,("Doing %s\n",api_commands[i].name));
-       break;
-      }
+  for (i=0;api_commands[i].name;i++) {
+    if (api_commands[i].id == api_command && api_commands[i].fn) {
+        DEBUG(3,("Doing %s\n",api_commands[i].name));
+        break;
+    }
+  }
+
+  rdata = (char *)malloc(1024);
+  if (rdata)
+    memset(rdata,'\0',1024);
 
-  rdata = (char *)malloc(1024); if (rdata) bzero(rdata,1024);
-  rparam = (char *)malloc(1024); if (rparam) bzero(rparam,1024);
+  rparam = (char *)malloc(1024);
+  if (rparam)
+    memset(rparam,'\0',1024);
+
+  if(!rdata || !rparam) {
+    DEBUG(0,("api_reply: malloc fail !\n"));
+    return -1;
+  }
 
   reply = api_commands[i].fn(conn,vuid,params,data,mdrcnt,mprcnt,
                             &rdata,&rparam,&rdata_len,&rparam_len);
 
 
   if (rdata_len > mdrcnt ||
-      rparam_len > mprcnt)
-    {
+      rparam_len > mprcnt) {
       reply = api_TooSmall(conn,vuid,params,data,mdrcnt,mprcnt,
                           &rdata,&rparam,&rdata_len,&rparam_len);
-    }
-           
+  }
 
   /* if we get False back then it's actually unsupported */
   if (!reply)
     api_Unsupported(conn,vuid,params,data,mdrcnt,mprcnt,
                    &rdata,&rparam,&rdata_len,&rparam_len);
 
-      
-  mem_create(&rdata_buf , rdata , rdata_len , 0, False);
-  mem_create(&rparam_buf, rparam, rparam_len, 0, False);
-
-  rdata_buf.offset.start = 0;
-  rdata_buf.offset.end   = rdata_len;
+  send_trans_reply(outbuf, rparam, rparam_len, rdata, rdata_len, False);
 
-  rparam_buf.offset.start = 0;
-  rparam_buf.offset.end   = rparam_len;
-
-  /* now send the reply */
-  send_trans_reply(outbuf, &rdata_buf, &rparam_buf, NULL, 0, 0);
-
-  if (rdata ) free(rdata);
-  if (rparam) free(rparam);
+  if (rdata )
+    free(rdata);
+  if (rparam)
+    free(rparam);
   
-  return(-1);
+  return -1;
 }
 
 /****************************************************************************
@@ -3599,31 +3508,36 @@ static int named_pipe(connection_struct *conn,uint16 vuid, char *outbuf,char *na
        DEBUG(3,("named pipe command on <%s> name\n", name));
 
        if (strequal(name,"LANMAN"))
-       {
                return api_reply(conn,vuid,outbuf,data,params,tdscnt,tpscnt,mdrcnt,mprcnt);
-       }
 
-       if (strlen(name) < 1)
+       if (strequal(name,"WKSSVC") ||
+           strequal(name,"SRVSVC") ||
+           strequal(name,"WINREG") ||
+           strequal(name,"SAMR") ||
+           strequal(name,"LSARPC"))
        {
+               DEBUG(4,("named pipe command from Win95 (wow!)\n"));
                return api_fd_reply(conn,vuid,outbuf,setup,data,params,suwcnt,tdscnt,tpscnt,mdrcnt,mprcnt);
        }
 
+       if (strlen(name) < 1)
+               return api_fd_reply(conn,vuid,outbuf,setup,data,params,suwcnt,tdscnt,tpscnt,mdrcnt,mprcnt);
+
        if (setup)
-       {
                DEBUG(3,("unknown named pipe: setup 0x%X setup1=%d\n", (int)setup[0],(int)setup[1]));
-       }
 
        return 0;
 }
 
 
 /****************************************************************************
-  reply to a SMBtrans
-  ****************************************************************************/
+ Reply to a SMBtrans.
+ ****************************************************************************/
+
 int reply_trans(connection_struct *conn, char *inbuf,char *outbuf, int size, int bufsize)
 {
        fstring name;
-
+       int name_offset = 0;
        char *data=NULL,*params=NULL;
        uint16 *setup=NULL;
        int outsize = 0;
@@ -3641,7 +3555,7 @@ int reply_trans(connection_struct *conn, char *inbuf,char *outbuf, int size, int
        int dsoff = SVAL(inbuf,smb_vwv12);
        int suwcnt = CVAL(inbuf,smb_vwv13);
 
-       bzero(name, sizeof(name));
+       memset(name, '\0',sizeof(name));
        fstrcpy(name,smb_buf(inbuf));
 
        if (dscnt > tdscnt || pscnt > tpscnt) {
@@ -3649,18 +3563,27 @@ int reply_trans(connection_struct *conn, char *inbuf,char *outbuf, int size, int
        }
   
        if (tdscnt)  {
-               data = (char *)malloc(tdscnt);
+               if((data = (char *)malloc(tdscnt)) == NULL) {
+                       DEBUG(0,("reply_trans: data malloc fail for %d bytes !\n", tdscnt));
+                       return(ERROR(ERRDOS,ERRnomem));
+               } 
                memcpy(data,smb_base(inbuf)+dsoff,dscnt);
        }
 
        if (tpscnt) {
-               params = (char *)malloc(tpscnt);
+               if((params = (char *)malloc(tpscnt)) == NULL) {
+                       DEBUG(0,("reply_trans: param malloc fail for %d bytes !\n", tpscnt));
+                       return(ERROR(ERRDOS,ERRnomem));
+               } 
                memcpy(params,smb_base(inbuf)+psoff,pscnt);
        }
 
        if (suwcnt) {
                int i;
-               setup = (uint16 *)malloc(suwcnt*sizeof(setup[0]));
+               if((setup = (uint16 *)malloc(suwcnt*sizeof(uint16))) == NULL) {
+          DEBUG(0,("reply_trans: setup malloc fail for %d bytes !\n", (int)(suwcnt * sizeof(uint16))));
+                 return(ERROR(ERRDOS,ERRnomem));
+        } 
                for (i=0;i<suwcnt;i++)
                        setup[i] = SVAL(inbuf,smb_vwv14+i*SIZEOFWORD);
        }
@@ -3671,7 +3594,7 @@ int reply_trans(connection_struct *conn, char *inbuf,char *outbuf, int size, int
                   of the parameter/data bytes */
                outsize = set_message(outbuf,0,0,True);
                show_msg(outbuf);
-               send_smb(Client,outbuf);
+               send_smb(smbd_server_fd(),outbuf);
        }
 
        /* receive the rest of the trans packet */
@@ -3679,18 +3602,21 @@ int reply_trans(connection_struct *conn, char *inbuf,char *outbuf, int size, int
                BOOL ret;
                int pcnt,poff,dcnt,doff,pdisp,ddisp;
       
-               ret = receive_next_smb(Client,oplock_sock,inbuf,bufsize,SMB_SECONDARY_WAIT);
+               ret = receive_next_smb(inbuf,bufsize,SMB_SECONDARY_WAIT);
 
-               if ((ret && (CVAL(inbuf, smb_com) != SMBtrans)) || !ret) {
+               if ((ret && (CVAL(inbuf, smb_com) != SMBtranss)) || !ret) {
                        if(ret) {
                                DEBUG(0,("reply_trans: Invalid secondary trans packet\n"));
                        } else {
                                DEBUG(0,("reply_trans: %s in getting secondary trans response.\n",
                                         (smb_read_error == READ_ERROR) ? "error" : "timeout" ));
                        }
-                       if (params) free(params);
-                       if (data) free(data);
-                       if (setup) free(setup);
+                       if (params)
+                               free(params);
+                       if (data)
+                               free(data);
+                       if (setup)
+                               free(setup);
                        return(ERROR(ERRSRV,ERRerror));
                }
 
@@ -3724,9 +3650,18 @@ int reply_trans(connection_struct *conn, char *inbuf,char *outbuf, int size, int
        DEBUG(3,("trans <%s> data=%d params=%d setup=%d\n",
                 name,tdscnt,tpscnt,suwcnt));
        
-       if (strncmp(name,"\\PIPE\\",strlen("\\PIPE\\")) == 0) {
+       /*
+        * WinCE wierdness....
+        */
+
+       if (name[0] == '\\' && (StrnCaseCmp(&name[1],local_machine, strlen(local_machine)) == 0) &&
+                       (name[strlen(local_machine)+1] == '\\'))
+               name_offset = strlen(local_machine)+1;
+
+       if (strncmp(&name[name_offset],"\\PIPE\\",strlen("\\PIPE\\")) == 0) {
                DEBUG(5,("calling named_pipe\n"));
-               outsize = named_pipe(conn,vuid,outbuf,name+strlen("\\PIPE\\"),setup,data,params,
+               outsize = named_pipe(conn,vuid,outbuf,
+                                    name+name_offset+strlen("\\PIPE\\"),setup,data,params,
                                     suwcnt,tdscnt,tpscnt,msrcnt,mdrcnt,mprcnt);
        } else {
                DEBUG(3,("invalid pipe name\n"));
@@ -3734,9 +3669,12 @@ int reply_trans(connection_struct *conn, char *inbuf,char *outbuf, int size, int
        }
 
        
-       if (data) free(data);
-       if (params) free(params);
-       if (setup) free(setup);
+       if (data)
+               free(data);
+       if (params)
+               free(params);
+       if (setup)
+               free(setup);
        
        if (close_on_completion)
                close_cnum(conn,vuid);