Fixed two debug prints.
[kai/samba.git] / source / smbd / ipc.c
index 65f85719ae4ba57c8d7122fab4725755125eb79c..eed5a71401750d638129fe10b9f865807956617a 100644 (file)
@@ -2,10 +2,10 @@
    Unix SMB/Netbios implementation.
    Version 1.9.
    Inter-process communication and named pipe handling
-   Copyright (C) Andrew Tridgell 1992-1997
+   Copyright (C) Andrew Tridgell 1992-1998
 
    SMB Version handling
-   Copyright (C) John H Terpstra 1995-1997
+   Copyright (C) John H Terpstra 1995-1998
    
    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
@@ -27,6 +27,7 @@
    */
 
 #include "includes.h"
+#include "nterr.h"
 
 #ifdef CHECK_TYPES
 #undef CHECK_TYPES
 
 extern int DEBUGLEVEL;
 extern int max_send;
-extern files_struct Files[];
-extern connection_struct Connections[];
 
 extern fstring local_machine;
-extern fstring myworkgroup;
+extern fstring global_myworkgroup;
 
 #define NERR_Success 0
 #define NERR_badpass 86
@@ -50,7 +49,6 @@ extern fstring myworkgroup;
 #define NERR_JobNotFound (NERR_BASE+51)
 #define NERR_DestNotFound (NERR_BASE+52)
 #define ERROR_INVALID_LEVEL 124
-#define ERROR_MORE_DATA 234
 
 #define ACCESS_READ 0x01
 #define ACCESS_WRITE 0x02
@@ -62,32 +60,34 @@ extern fstring myworkgroup;
 #define QNLEN 12               /* queue name maximum length */
 
 extern int Client;
+extern int smb_read_error;
 
-static BOOL api_Unsupported(int cnum,uint16 vuid, char *param,char *data,
+static BOOL api_Unsupported(connection_struct *conn,uint16 vuid, char *param,char *data,
                            int mdrcnt,int mprcnt,
                            char **rdata,char **rparam,
                            int *rdata_len,int *rparam_len);
-static BOOL api_TooSmall(int cnum,uint16 vuid, char *param,char *data,
+static BOOL api_TooSmall(connection_struct *conn,uint16 vuid, char *param,char *data,
                         int mdrcnt,int mprcnt,
                         char **rdata,char **rparam,
                         int *rdata_len,int *rparam_len);
 
 
-static int CopyExpanded(int cnum, int snum, char** dst, char* src, int* n)
+static int CopyExpanded(connection_struct *conn, 
+                       int snum, char** dst, char* src, int* n)
 {
-  pstring buf;
-  int l;
-
-  if (!src || !dst || !n || !(*dst)) return(0);
-
-  StrnCpy(buf,src,sizeof(buf)/2);
-  string_sub(buf,"%S",lp_servicename(snum));
-  standard_sub(cnum,buf);
-  StrnCpy(*dst,buf,*n);
-  l = strlen(*dst) + 1;
-  (*dst) += l;
-  (*n) -= l;
-  return l;
+       pstring buf;
+       int l;
+
+       if (!src || !dst || !n || !(*dst)) return(0);
+
+       StrnCpy(buf,src,sizeof(buf)/2);
+       string_sub(buf,"%S",lp_servicename(snum));
+       standard_sub(conn,buf);
+       StrnCpy(*dst,buf,*n);
+       l = strlen(*dst) + 1;
+       (*dst) += l;
+       (*n) -= l;
+       return l;
 }
 
 static int CopyAndAdvance(char** dst, char* src, int* n)
@@ -101,24 +101,24 @@ static int CopyAndAdvance(char** dst, char* src, int* n)
   return l;
 }
 
-static int StrlenExpanded(int cnum, int snum, char* s)
+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));
-  standard_sub(cnum,buf);
-  return strlen(buf) + 1;
+       pstring buf;
+       if (!s) return(0);
+       StrnCpy(buf,s,sizeof(buf)/2);
+       string_sub(buf,"%S",lp_servicename(snum));
+       standard_sub(conn,buf);
+       return strlen(buf) + 1;
 }
 
-static char* Expand(int cnum, int snum, char* s)
+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));
-  standard_sub(cnum,buf);
-  return &buf[0];
+       static pstring buf;
+       if (!s) return(NULL);
+       StrnCpy(buf,s,sizeof(buf)/2);
+       string_sub(buf,"%S",lp_servicename(snum));
+       standard_sub(conn,buf);
+       return &buf[0];
 }
 
 /*******************************************************************
@@ -129,74 +129,123 @@ static BOOL prefix_ok(char *str,char *prefix)
   return(strncmp(str,prefix,strlen(prefix)) == 0);
 }
 
+/*******************************************************************
+ copies parameters and data, as needed, into the smb buffer
+
+ *both* the data and params sections should be aligned.  this
+ is fudged in the rpc pipes by 
+ at present, only the data section is.  this may be a possible
+ 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 *copy_into = smb_buf(outbuf)+1;
+
+       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);
+       copy_into += param_len + align;
+       if (data_len ) mem_buf_copy(copy_into, rdata , data_offset , data_len);
+}
 
 /****************************************************************************
   send a trans reply
   ****************************************************************************/
-static void send_trans_reply(char *outbuf,char *data,char *param,uint16 *setup,
-                            int ldata,int lparam,int lsetup)
+static void send_trans_reply(char *outbuf,
+                               struct mem_buf *rdata,
+                               struct mem_buf *rparam,
+                               uint16 *setup, int lsetup, int max_data_ret)
 {
-  int i;
-  int this_ldata,this_lparam;
-  int tot_data=0,tot_param=0;
-  int align;
-
-  this_lparam = MIN(lparam,max_send - (500+lsetup*SIZEOFWORD)); /* hack */
-  this_ldata = MIN(ldata,max_send - (500+lsetup*SIZEOFWORD+this_lparam));
-
-  align = (this_lparam%4);
-
-  set_message(outbuf,10+lsetup,align+this_ldata+this_lparam,True);
-  if (this_lparam)
-    memcpy(smb_buf(outbuf),param,this_lparam);
-  if (this_ldata)
-    memcpy(smb_buf(outbuf)+this_lparam+align,data,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_vwv5,0);
-  SSVAL(outbuf,smb_vwv6,this_ldata);
-  SSVAL(outbuf,smb_vwv7,smb_offset(smb_buf(outbuf)+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]);
-
-  show_msg(outbuf);
-  send_smb(Client,outbuf);
-
-  tot_data = this_ldata;
-  tot_param = this_lparam;
-
-  while (tot_data < ldata || tot_param < lparam)
-    {
-      this_lparam = MIN(lparam-tot_param,max_send - 500); /* hack */
-      this_ldata = MIN(ldata-tot_data,max_send - (500+this_lparam));
-
-      align = (this_lparam%4);
-
-      set_message(outbuf,10,this_ldata+this_lparam+align,False);
-      if (this_lparam)
-       memcpy(smb_buf(outbuf),param+tot_param,this_lparam);
-      if (this_ldata)
-       memcpy(smb_buf(outbuf)+this_lparam+align,data+tot_data,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_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_vwv9,0);
-
-      show_msg(outbuf);
-      send_smb(Client,outbuf);
-
-      tot_data += this_ldata;
-      tot_param += this_lparam;
-    }
+       int i;
+       int this_ldata,this_lparam;
+       int tot_data=0,tot_param=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;
+
+       if (buffer_too_large)
+       {
+               DEBUG(5,("send_trans_reply: buffer %d too large %d\n", ldata, max_data_ret));
+               ldata = max_data_ret;
+       }
+
+       this_lparam = MIN(lparam,max_send - (500+lsetup*SIZEOFWORD)); /* hack */
+       this_ldata  = MIN(ldata,max_send - (500+lsetup*SIZEOFWORD+this_lparam));
+
+       align = ((this_lparam)%4);
+
+       set_message(outbuf,10+lsetup,1+align+this_ldata+this_lparam,True);
+
+       if (buffer_too_large)
+       {
+               /* issue a buffer size warning.  on a DCE/RPC pipe, expect an SMBreadX... */
+               SIVAL(outbuf, smb_flg2, FLAGS2_32_BIT_ERROR_CODES);
+               SIVAL(outbuf, smb_rcls, 0x80000000 | NT_STATUS_ACCESS_VIOLATION);
+       }
+
+       copy_trans_params_and_data(outbuf, align,
+                                  rparam     , rdata,
+                                  tot_param  , tot_data,
+                                  this_lparam, 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)+1,outbuf));
+       SSVAL(outbuf,smb_vwv5,0);
+       SSVAL(outbuf,smb_vwv6,this_ldata);
+       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]);
+       }
+
+       show_msg(outbuf);
+       send_smb(Client,outbuf);
+
+       tot_data = this_ldata;
+       tot_param = this_lparam;
+
+       while (tot_data < ldata || tot_param < lparam)
+       {
+               this_lparam = MIN(lparam-tot_param, max_send - 500); /* hack */
+               this_ldata  = MIN(ldata -tot_data , max_send - (500+this_lparam));
+
+               align = (this_lparam%4);
+
+               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);
+
+               SSVAL(outbuf,smb_vwv3,this_lparam);
+               SSVAL(outbuf,smb_vwv4,smb_offset(smb_buf(outbuf)+1,outbuf));
+               SSVAL(outbuf,smb_vwv5,tot_param);
+               SSVAL(outbuf,smb_vwv6,this_ldata);
+               SSVAL(outbuf,smb_vwv7,smb_offset(smb_buf(outbuf)+1+this_lparam+align,outbuf));
+               SSVAL(outbuf,smb_vwv8,tot_data);
+               SSVAL(outbuf,smb_vwv9,0);
+
+               show_msg(outbuf);
+               send_smb(Client,outbuf);
+
+               tot_data  += this_ldata;
+               tot_param += this_lparam;
+       }
 }
 
 struct pack_desc {
@@ -218,7 +267,7 @@ static int get_counter(char** p)
 {
   int i, n;
   if (!p || !(*p)) return(1);
-  if (!isdigit(**p)) return 1;
+  if (!isdigit((int)**p)) return 1;
   for (n = 0;;) {
     i = **p;
     if (isdigit(i))
@@ -273,11 +322,12 @@ static BOOL init_package(struct pack_desc* p, int count, int subcount)
   p->subcount = 0;
   p->curpos = p->format;
   if (i > n) {
+    p->neededlen = i;
     i = n = 0;
-    p->errcode = NERR_BufTooSmall;
+    p->errcode = ERRmoredata;
   }
-
-  p->errcode = NERR_Success;
+  else
+    p->errcode = NERR_Success;
   p->buflen = i;
   n -= i;
   p->stringbuf = p->base + i;
@@ -285,7 +335,7 @@ static BOOL init_package(struct pack_desc* p, int count, int subcount)
   return(p->errcode == NERR_Success);
 }
 
-#ifdef __STDC__
+#ifdef HAVE_STDARG_H
 static int package(struct pack_desc* p, ...)
 {
 #else
@@ -300,7 +350,7 @@ va_dcl
   int is_string=0, stringused;
   int32 temp;
 
-#ifdef __STDC__
+#ifdef HAVE_STDARG_H
   va_start(args,p);
 #else
   va_start(args);
@@ -317,15 +367,7 @@ 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);
-#if AJT
-    ajt_panic();
-#endif  
-    return 0;
-  }
+  SMB_ASSERT(strncmp(str,p->curpos,strlen(str)) == 0);
 #endif
   stringneeded = -1;
 
@@ -377,7 +419,7 @@ va_dcl
       stringused = stringneeded;
       if (stringused > p->stringlen) {
        stringused = (is_string ? p->stringlen : 0);
-       if (p->errcode == NERR_Success) p->errcode = ERROR_MORE_DATA;
+       if (p->errcode == NERR_Success) p->errcode = ERRmoredata;
       }
       if (!stringused)
        SIVAL(p->structbuf,0,0);
@@ -399,7 +441,7 @@ va_dcl
     p->usedlen += needed;
   }
   else {
-    if (p->errcode == NERR_Success) p->errcode = NERR_BufTooSmall;
+    if (p->errcode == NERR_Success) p->errcode = ERRmoredata;
   }
   return 1;
 }
@@ -433,7 +475,7 @@ static void PackDriverData(struct pack_desc* desc)
   SIVAL(drivdata,0,sizeof drivdata); /* cb */
   SIVAL(drivdata,4,1000);      /* lVersion */
   memset(drivdata+8,0,32);     /* szDeviceName */
-  strcpy(drivdata+8,"NULL");
+  pstrcpy(drivdata+8,"NULL");
   PACKl(desc,"l",drivdata,sizeof drivdata); /* pDriverData */
 }
 
@@ -473,7 +515,7 @@ static int check_printq_info(struct pack_desc* desc,
   return True;
 }
 
-static void fill_printjob_info(int cnum, int snum, int uLevel,
+static void fill_printjob_info(connection_struct *conn, int snum, int uLevel,
                               struct pack_desc* desc,
                               print_queue_struct* queue, int n)
 {
@@ -520,7 +562,7 @@ static void fill_printjob_info(int cnum, int snum, int uLevel,
   }
 }
 
-static void fill_printq_info(int cnum, int snum, int uLevel,
+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)
@@ -533,7 +575,7 @@ static void fill_printq_info(int cnum, int snum, int uLevel,
     case 3:
     case 4:
     case 5:
-      PACKS(desc,"z",Expand(cnum,snum,SERVICE(snum)));
+      PACKS(desc,"z",Expand(conn,snum,SERVICE(snum)));
       break;
   }
 
@@ -551,7 +593,7 @@ static void fill_printq_info(int cnum, int snum, int uLevel,
       PACKI(desc,"W",LPSTAT_ERROR);
     }
     else if (!status || !status->message[0]) {
-      PACKS(desc,"z",Expand(cnum,snum,lp_comment(snum)));
+      PACKS(desc,"z",Expand(conn,snum,lp_comment(snum)));
       PACKI(desc,"W",LPSTAT_OK); /* status */
     } else {
       PACKS(desc,"z",status->message);
@@ -568,7 +610,7 @@ static void fill_printq_info(int cnum, int snum, int uLevel,
     PACKS(desc,"z","WinPrint");        /* pszPrProc */
     PACKS(desc,"z","");                /* pszParms */
     if (!status || !status->message[0]) {
-      PACKS(desc,"z",Expand(cnum,snum,lp_comment(snum))); /* pszComment */
+      PACKS(desc,"z",Expand(conn,snum,lp_comment(snum))); /* pszComment */
       PACKI(desc,"W",LPSTAT_OK); /* fsStatus */
     } else {
       PACKS(desc,"z",status->message); /* pszComment */
@@ -582,80 +624,113 @@ static void fill_printq_info(int cnum, int snum, int uLevel,
   if (uLevel == 2 || uLevel == 4) {
     int i;
     for (i=0;i<count;i++)
-      fill_printjob_info(cnum,snum,uLevel == 2 ? 1 : 2,desc,&queue[i],i);
+      fill_printjob_info(conn,snum,uLevel == 2 ? 1 : 2,desc,&queue[i],i);
   }
 
   if (uLevel==52) {
     int i,ok=0;
-    pstring tok,driver,short_name;
+    pstring tok,driver,datafile,langmon,helpfile,datatype;
     char *p,*q;
     FILE *f;
     pstring fname;
 
-    strcpy(fname,lp_driverfile());
-
+    pstrcpy(fname,lp_driverfile());
     f=fopen(fname,"r");
     if (!f) {
-      DEBUG(0,("fill_printq_info: Can't open %s - %s\n",fname,strerror(errno)));
+      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;
     }
 
-    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';
-      next_token(&p,tok,":");
-      if(!strncmp(tok,lp_printerdriver(snum),strlen(lp_printerdriver(snum)))) ok=1;
+      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);
 
-    next_token(&p,short_name,":");
-    next_token(&p,driver,":");
+    /* 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;
+    }
 
-    PACKI(desc,"W",0x0400);                      /* don't know */
-    PACKS(desc,"z",lp_printerdriver(snum));        /* long printer name */
+    if (ok) {
+      /* language monitor */
+      if (*p == ':') {
+         *langmon = '\0';
+         p++;
+      } else if (!next_token(&p,langmon,":",sizeof(langmon))) ok = 0;
+    }
 
-    if (ok)
-    {
-      PACKS(desc,"z",driver);                    /* Driver Name */
-      PACKS(desc,"z",short_name);                /* short printer name */
+    /* 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,("short name:%s:\n",short_name));
-    }
-    else 
-    {
-      PACKS(desc,"z","");
-      PACKS(desc,"z","");
-    }
+      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));
+      }
 
-    PACKS(desc,"z","");
-    PACKS(desc,"z",lp_driverlocation(snum));       /* share to retrieve files */
-    PACKS(desc,"z","EMF");
-    PACKS(desc,"z","");
-    if (ok)
-      PACKS(desc,"z",driver);                      /* driver name */
-    else
-      PACKS(desc,"z","");
-    PACKI(desc,"N",count);                         /* number of files to copy */
-    for (i=0;i<count;i++)
-    {
-      next_token(&p,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);
   }
-
-  DEBUG(3,("fill_printq_info on <%s> gave %d entries\n",SERVICE(snum),count));
 }
 
-/* This function returns the number of file for a given driver */
-int get_printerdrivernumber(int snum)
+/* This function returns the number of files for a given driver */
+static int get_printerdrivernumber(int snum)
 {
   int i=0,ok=0;
   pstring tok;
@@ -663,41 +738,54 @@ int get_printerdrivernumber(int snum)
   FILE *f;
   pstring fname;
 
-  strcpy(fname,lp_driverfile());
+  pstrcpy(fname,lp_driverfile());
 
   DEBUG(4,("In get_printerdrivernumber: %s\n",fname));
   f=fopen(fname,"r");
   if (!f) {
-    DEBUG(0,("get_printerdrivernumber: Can't open %s - %s\n",fname,strerror(errno)));
+    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 */
   while (!feof(f) && !ok)
   {
+    p = q;                     /* reset string pointer */
     fgets(p,8191,f);
-    next_token(&p,tok,":");
-    if(!strncmp(tok,lp_printerdriver(snum),strlen(lp_printerdriver(snum)))) ok=1;
+    if (next_token(&p,tok,":",sizeof(tok)) &&
+      (!strncmp(tok,lp_printerdriver(snum),strlen(lp_printerdriver(snum))))) 
+       ok=1;
   }
+  fclose(f);
 
   if (ok) {
-    /* skip 2 fields */
-    next_token(&p,tok,":");  /* short name */
-    next_token(&p,tok,":");  /* driver name */
+    /* skip 5 fields */
+    i = 5;
+    while (*p && i) {
+      if (*p++ == ':') i--;
+    }
+    if (!*p || i)
+      return(0);
+
     /* count the number of files */
-    while (next_token(&p,tok,","))
+    while (next_token(&p,tok,",",sizeof(tok)))
        i++;
   }
-  fclose(f);
   free(q);
 
   return(i);
 }
 
-static BOOL api_DosPrintQGetInfo(int cnum,uint16 vuid, char *param,char *data,
+static BOOL api_DosPrintQGetInfo(connection_struct *conn,
+                                uint16 vuid, char *param,char *data,
                                 int mdrcnt,int mprcnt,
                                 char **rdata,char **rparam,
                                 int *rdata_len,int *rparam_len)
@@ -706,7 +794,7 @@ static BOOL api_DosPrintQGetInfo(int cnum,uint16 vuid, char *param,char *data,
   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;
@@ -719,7 +807,6 @@ static BOOL api_DosPrintQGetInfo(int cnum,uint16 vuid, char *param,char *data,
  
   p = skip_string(p,1);
   uLevel = SVAL(p,0);
-  cbBuf = SVAL(p,2);
   str3 = p + 4;
  
   /* remove any trailing username */
@@ -742,20 +829,19 @@ static BOOL api_DosPrintQGetInfo(int cnum,uint16 vuid, char *param,char *data,
   
   if (snum < 0 || !VALID_SNUM(snum)) return(False);
 
-  if (uLevel==52)
-  {
-    count = get_printerdrivernumber(snum);
-    DEBUG(3,("api_DosPrintQGetInfo: Driver files count: %d\n",count));
+  if (uLevel==52) {
+         count = get_printerdrivernumber(snum);
+         DEBUG(3,("api_DosPrintQGetInfo: Driver files count: %d\n",count));
+  } else {
+         count = get_printqueue(snum, conn,&queue,&status);
   }
-  else
-    count = get_printqueue(snum,cnum,&queue,&status);
 
   if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
   desc.base = *rdata;
   desc.buflen = mdrcnt;
   if (init_package(&desc,1,count)) {
-    desc.subcount = count;
-    fill_printq_info(cnum,snum,uLevel,&desc,count,queue,&status);
+         desc.subcount = count;
+         fill_printq_info(conn,snum,uLevel,&desc,count,queue,&status);
   }
 
   *rdata_len = desc.usedlen;
@@ -777,7 +863,7 @@ static BOOL api_DosPrintQGetInfo(int cnum,uint16 vuid, char *param,char *data,
 /****************************************************************************
   view list of all print jobs on all queues
   ****************************************************************************/
-static BOOL api_DosPrintQEnum(int cnum, uint16 vuid, char* param, char* data,
+static BOOL api_DosPrintQEnum(connection_struct *conn, uint16 vuid, char* param, char* data,
                              int mdrcnt, int mprcnt,
                              char **rdata, char** rparam,
                              int *rdata_len, int *rparam_len)
@@ -807,16 +893,25 @@ static BOOL api_DosPrintQEnum(int cnum, uint16 vuid, char* param, char* data,
     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,cnum,&queue[n],&status[n]);
+       subcntarr[n] = get_printqueue(i, conn,&queue[n],&status[n]);
        subcnt += subcntarr[n];
        n++;
       }
@@ -830,7 +925,7 @@ static BOOL api_DosPrintQEnum(int cnum, uint16 vuid, char* param, char* data,
     succnt = 0;
     for (i = 0; i < services; i++)
       if (lp_snum_ok(i) && lp_print_ok(i) && lp_browseable(i)) {
-       fill_printq_info(cnum,i,uLevel,&desc,subcntarr[n],queue[n],&status[n]);
+       fill_printq_info(conn,i,uLevel,&desc,subcntarr[n],queue[n],&status[n]);
        n++;
        if (desc.errcode == NERR_Success) succnt = n;
       }
@@ -901,8 +996,8 @@ static int get_server_info(uint32 servertype,
 
   pstrcpy(fname,lp_lockdir());
   trim_string(fname,NULL,"/");
-  strcat(fname,"/");
-  strcat(fname,SERVER_LIST);
+  pstrcat(fname,"/");
+  pstrcat(fname,SERVER_LIST);
 
   f = fopen(fname,"r");
 
@@ -939,12 +1034,12 @@ static int get_server_info(uint32 servertype,
     }
     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 */
-      strcpy(s->domain,myworkgroup); 
+      pstrcpy(s->domain,global_myworkgroup); 
     }
     
     if (sscanf(stype,"%X",&s->type) != 1) { 
@@ -1089,7 +1184,7 @@ static BOOL srv_comp(struct srv_info_struct *s1,struct srv_info_struct *s2)
   view list of servers available (or possibly domains). The info is
   extracted from lists saved by nmbd on the local host
   ****************************************************************************/
-static BOOL api_RNetServerEnum(int cnum, uint16 vuid, char *param, char *data,
+static BOOL api_RNetServerEnum(connection_struct *conn, uint16 vuid, char *param, char *data,
                               int mdrcnt, int mprcnt, char **rdata, 
                               char **rparam, int *rdata_len, int *rparam_len)
 {
@@ -1101,7 +1196,7 @@ static BOOL api_RNetServerEnum(int cnum, uint16 vuid, char *param, char *data,
   uint32 servertype = IVAL(p,4);
   char *p2;
   int data_len, fixed_len, string_len;
-  int f_len, s_len;
+  int f_len = 0, s_len = 0;
   struct srv_info_struct *servers=NULL;
   int counted=0,total=0;
   int i,missed;
@@ -1140,7 +1235,7 @@ static BOOL api_RNetServerEnum(int cnum, uint16 vuid, char *param, char *data,
   if (strcmp(str1, "WrLehDz") == 0) {
     StrnCpy(domain, p, sizeof(fstring)-1);
   } else {
-    StrnCpy(domain, myworkgroup, sizeof(fstring)-1);    
+    StrnCpy(domain, global_myworkgroup, sizeof(fstring)-1);    
   }
 
   if (lp_browse_list())
@@ -1199,7 +1294,7 @@ static BOOL api_RNetServerEnum(int cnum, uint16 vuid, char *param, char *data,
   
   *rparam_len = 8;
   *rparam = REALLOC(*rparam,*rparam_len);
-  SSVAL(*rparam,0,(missed == 0 ? NERR_Success : ERROR_MORE_DATA));
+  SSVAL(*rparam,0,(missed == 0 ? NERR_Success : ERRmoredata));
   SSVAL(*rparam,2,0);
   SSVAL(*rparam,4,counted);
   SSVAL(*rparam,6,counted+missed);
@@ -1212,6 +1307,39 @@ static BOOL api_RNetServerEnum(int cnum, uint16 vuid, char *param, char *data,
   return(True);
 }
 
+/****************************************************************************
+  command 0x34 - suspected of being a "Lookup Names" stub api
+  ****************************************************************************/
+static BOOL api_RNetGroupGetUsers(connection_struct *conn, uint16 vuid, char *param, char *data,
+                              int mdrcnt, int mprcnt, char **rdata, 
+                              char **rparam, int *rdata_len, int *rparam_len)
+{
+  char *str1 = param+2;
+  char *str2 = skip_string(str1,1);
+  char *p = skip_string(str2,1);
+  int uLevel = SVAL(p,0);
+  int buf_len = SVAL(p,2);
+  int counted=0;
+  int missed=0;
+
+       DEBUG(5,("RNetGroupGetUsers: %s %s %s %d %d\n",
+               str1, str2, p, uLevel, buf_len));
+
+  if (!prefix_ok(str1,"zWrLeh")) return False;
+  
+  *rdata_len = 0;
+  *rdata = NULL;
+  
+  *rparam_len = 8;
+  *rparam = REALLOC(*rparam,*rparam_len);
+
+  SSVAL(*rparam,0,0x08AC); /* informational warning message */
+  SSVAL(*rparam,2,0);
+  SSVAL(*rparam,4,counted);
+  SSVAL(*rparam,6,counted+missed);
+
+  return(True);
+}
 
 /****************************************************************************
   get info about a share
@@ -1236,7 +1364,7 @@ static BOOL check_share_info(int uLevel, char* id)
   return True;
 }
 
-static int fill_share_info(int cnum, int snum, int uLevel,
+static int fill_share_info(connection_struct *conn, int snum, int uLevel,
                           char** buf, int* buflen,
                           char** stringbuf, int* stringspace, char* baseaddr)
 {
@@ -1258,7 +1386,7 @@ static int fill_share_info(int cnum, int snum, int uLevel,
   if (!buf)
     {
       len = 0;
-      if (uLevel > 0) len += StrlenExpanded(cnum,snum,lp_comment(snum));
+      if (uLevel > 0) len += StrlenExpanded(conn,snum,lp_comment(snum));
       if (uLevel > 1) len += strlen(lp_pathname(snum)) + 1;
       if (buflen) *buflen = struct_len;
       if (stringspace) *stringspace = len;
@@ -1291,7 +1419,7 @@ static int fill_share_info(int cnum, int snum, int uLevel,
       if (strequal("IPC$",lp_servicename(snum))) type = STYPE_IPC;
       SSVAL(p,14,type);                /* device type */
       SIVAL(p,16,PTR_DIFF(p2,baseaddr));
-      len += CopyExpanded(cnum,snum,&p2,lp_comment(snum),&l2);
+      len += CopyExpanded(conn,snum,&p2,lp_comment(snum),&l2);
     }
   
   if (uLevel > 1)
@@ -1331,7 +1459,7 @@ static int fill_share_info(int cnum, int snum, int uLevel,
   return len;
 }
 
-static BOOL api_RNetShareGetInfo(int cnum,uint16 vuid, char *param,char *data,
+static BOOL api_RNetShareGetInfo(connection_struct *conn,uint16 vuid, char *param,char *data,
                                 int mdrcnt,int mprcnt,
                                 char **rdata,char **rparam,
                                 int *rdata_len,int *rparam_len)
@@ -1351,7 +1479,7 @@ static BOOL api_RNetShareGetInfo(int cnum,uint16 vuid, char *param,char *data,
  
   *rdata = REALLOC(*rdata,mdrcnt);
   p = *rdata;
-  *rdata_len = fill_share_info(cnum,snum,uLevel,&p,&mdrcnt,0,0,0);
+  *rdata_len = fill_share_info(conn,snum,uLevel,&p,&mdrcnt,0,0,0);
   if (*rdata_len < 0) return False;
  
   *rparam_len = 6;
@@ -1366,7 +1494,7 @@ static BOOL api_RNetShareGetInfo(int cnum,uint16 vuid, char *param,char *data,
 /****************************************************************************
   view list of shares available
   ****************************************************************************/
-static BOOL api_RNetShareEnum(int cnum,uint16 vuid, char *param,char *data,
+static BOOL api_RNetShareEnum(connection_struct *conn,uint16 vuid, char *param,char *data,
                              int mdrcnt,int mprcnt,
                              char **rdata,char **rparam,
                              int *rdata_len,int *rparam_len)
@@ -1379,9 +1507,10 @@ static BOOL api_RNetShareEnum(int cnum,uint16 vuid, char *param,char *data,
   char *p2;
   int count=lp_numservices();
   int total=0,counted=0;
+  BOOL missed = False;
   int i;
   int data_len, fixed_len, string_len;
-  int f_len, s_len;
+  int f_len = 0, s_len = 0;
  
   if (!prefix_ok(str1,"WrLeh")) return False;
   if (!check_share_info(uLevel,str2)) return False;
@@ -1389,16 +1518,18 @@ static BOOL api_RNetShareEnum(int cnum,uint16 vuid, char *param,char *data,
   data_len = fixed_len = string_len = 0;
   for (i=0;i<count;i++)
     if (lp_browseable(i) && lp_snum_ok(i))
+    {
+      total++;
+      data_len += fill_share_info(conn,i,uLevel,0,&f_len,0,&s_len,0);
+      if (data_len <= buf_len)
       {
-       total++;
-       data_len += fill_share_info(cnum,i,uLevel,0,&f_len,0,&s_len,0);
-       if (data_len <= buf_len)
-         {
-           counted++;
-           fixed_len += f_len;
-           string_len += s_len;
-         }
+        counted++;
+        fixed_len += f_len;
+        string_len += s_len;
       }
+      else
+        missed = True;
+    }
   *rdata_len = fixed_len + string_len;
   *rdata = REALLOC(*rdata,*rdata_len);
   memset(*rdata,0,*rdata_len);
@@ -1409,12 +1540,12 @@ static BOOL api_RNetShareEnum(int cnum,uint16 vuid, char *param,char *data,
   s_len = string_len;
   for (i = 0; i < count;i++)
     if (lp_browseable(i) && lp_snum_ok(i))
-      if (fill_share_info(cnum,i,uLevel,&p,&f_len,&p2,&s_len,*rdata) < 0)
+      if (fill_share_info(conn,i,uLevel,&p,&f_len,&p2,&s_len,*rdata) < 0)
        break;
   
   *rparam_len = 8;
   *rparam = REALLOC(*rparam,*rparam_len);
-  SSVAL(*rparam,0,NERR_Success);
+  SSVAL(*rparam,0,missed ? ERRmoredata : NERR_Success);
   SSVAL(*rparam,2,0);
   SSVAL(*rparam,4,counted);
   SSVAL(*rparam,6,total);
@@ -1430,7 +1561,7 @@ static BOOL api_RNetShareEnum(int cnum,uint16 vuid, char *param,char *data,
 /****************************************************************************
   get the time of day info
   ****************************************************************************/
-static BOOL api_NetRemoteTOD(int cnum,uint16 vuid, char *param,char *data,
+static BOOL api_NetRemoteTOD(connection_struct *conn,uint16 vuid, char *param,char *data,
                             int mdrcnt,int mprcnt,
                             char **rdata,char **rparam,
                             int *rdata_len,int *rparam_len)
@@ -1479,7 +1610,7 @@ static BOOL api_NetRemoteTOD(int cnum,uint16 vuid, char *param,char *data,
 /****************************************************************************
   set the user password
   ****************************************************************************/
-static BOOL api_SetUserPassword(int cnum,uint16 vuid, char *param,char *data,
+static BOOL api_SetUserPassword(connection_struct *conn,uint16 vuid, char *param,char *data,
                                int mdrcnt,int mprcnt,
                                char **rdata,char **rparam,
                                int *rdata_len,int *rparam_len)
@@ -1492,8 +1623,8 @@ static BOOL api_SetUserPassword(int cnum,uint16 vuid, char *param,char *data,
 
   p = skip_string(p,1);
 
-  StrnCpy(pass1,p,16);
-  StrnCpy(pass2,p+16,16);
+  memcpy(pass1,p,16);
+  memcpy(pass2,p+16,16);
 
   *rparam_len = 4;
   *rparam = REALLOC(*rparam,*rparam_len);
@@ -1505,23 +1636,115 @@ static BOOL api_SetUserPassword(int cnum,uint16 vuid, char *param,char *data,
 
   DEBUG(3,("Set password for <%s>\n",user));
 
-  if (password_ok(user,pass1,strlen(pass1),NULL) &&
-      chgpasswd(user,pass1,pass2))
+  /*
+   * Pass the user through the NT -> unix user mapping
+   * function.
+   */
+
+  (void)map_username(user);
+
+  /*
+   * Do any UNIX username case mangling.
+   */
+  (void)Get_Pwnam( user, True);
+
+  /*
+   * Attempt the plaintext password change first.
+   * Older versions of Windows seem to do this.
+   */
+
+  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.
+   */
+
+  if(SVAL(*rparam,0) != NERR_Success)
+  {
+    struct smb_passwd *sampw = NULL;
+
+    if(check_lanman_password(user,(unsigned char *)pass1,(unsigned char *)pass2, &sampw) && 
+       change_lanman_password(sampw,(unsigned char *)pass1,(unsigned char *)pass2))
+    {
+      SSVAL(*rparam,0,NERR_Success);
+    }
+  }
+
   bzero(pass1,sizeof(fstring));
   bzero(pass2,sizeof(fstring));         
         
   return(True);
 }
 
+/****************************************************************************
+  Set the user password (SamOEM version - gets plaintext).
+****************************************************************************/
+
+static BOOL api_SamOEMChangePassword(connection_struct *conn,uint16 vuid, char *param,char *data,
+                               int mdrcnt,int mprcnt,
+                               char **rdata,char **rparam,
+                               int *rdata_len,int *rparam_len)
+{
+  fstring user;
+  char *p = param + 2;
+  *rparam_len = 2;
+  *rparam = REALLOC(*rparam,*rparam_len);
+
+  *rdata_len = 0;
+
+  SSVAL(*rparam,0,NERR_badpass);
+
+  /*
+   * Check the parameter definition is correct.
+   */
+  if(!strequal(param + 2, "zsT")) {
+    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 %s\n", p));
+    return False;
+  }
+  p = skip_string(p,1);
+
+  fstrcpy(user,p);
+  p = skip_string(p,1);
+
+  DEBUG(3,("api_SamOEMChangePassword: Change password for <%s>\n",user));
+
+  /*
+   * Pass the user through the NT -> unix user mapping
+   * function.
+   */
+
+  (void)map_username(user);
+
+  /*
+   * Do any UNIX username case mangling.
+   */
+  (void)Get_Pwnam( user, True);
+
+  if (pass_oem_change(user, (uchar*) data, (uchar *)&data[516], NULL, NULL))
+  {
+    SSVAL(*rparam,0,NERR_Success);
+  }
+
+  return(True);
+}
+
 /****************************************************************************
   delete a print job
   Form: <W> <> 
   ****************************************************************************/
-static BOOL api_RDosPrintJobDel(int cnum,uint16 vuid, char *param,char *data,
+static BOOL api_RDosPrintJobDel(connection_struct *conn,uint16 vuid, char *param,char *data,
                                int mdrcnt,int mprcnt,
                                char **rdata,char **rparam,
                                int *rdata_len,int *rparam_len)
@@ -1550,7 +1773,7 @@ static BOOL api_RDosPrintJobDel(int cnum,uint16 vuid, char *param,char *data,
     {
       print_queue_struct *queue=NULL;
       lpq_reset(snum);
-      count = get_printqueue(snum,cnum,&queue,NULL);
+      count = get_printqueue(snum,conn,&queue,NULL);
   
       for (i=0;i<count;i++)
        if ((queue[i].job&0xFF) == jobid)
@@ -1558,13 +1781,13 @@ static BOOL api_RDosPrintJobDel(int cnum,uint16 vuid, char *param,char *data,
            switch (function) {
            case 81:            /* delete */ 
              DEBUG(3,("Deleting queue entry %d\n",queue[i].job));
-             del_printqueue(cnum,snum,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(cnum,snum,queue[i].job,
+             status_printjob(conn,snum,queue[i].job,
                              (function==82?LPQ_PAUSED:LPQ_QUEUED));
              break;
            }
@@ -1582,11 +1805,15 @@ static BOOL api_RDosPrintJobDel(int cnum,uint16 vuid, char *param,char *data,
   return(True);
 }
 
-static BOOL api_WPrintQueuePurge(int cnum,uint16 vuid, char *param,char *data,
+/****************************************************************************
+  Purge a print queue - or pause or resume it.
+  ****************************************************************************/
+static BOOL api_WPrintQueuePurge(connection_struct *conn,uint16 vuid, char *param,char *data,
                                 int mdrcnt,int mprcnt,
                                 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);
@@ -1614,19 +1841,30 @@ static BOOL api_WPrintQueuePurge(int cnum,uint16 vuid, char *param,char *data,
   }
 
   if (snum >= 0 && VALID_SNUM(snum)) {
-    print_queue_struct *queue=NULL;
-    int i, count;
     lpq_reset(snum);
     
-    count = get_printqueue(snum,cnum,&queue,NULL);
-    for (i = 0; i < count; i++)
-      del_printqueue(cnum,snum,queue[i].job);
-    
-    if (queue) free(queue);
+    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;
+      }
+    }
   }
 
-  DEBUG(3,("Print queue purge, queue=%s\n",QueueName));
-
   return(True);
 }
 
@@ -1653,119 +1891,117 @@ static int check_printjob_info(struct pack_desc* desc,
   return True;
 }
 
-static BOOL api_PrintJobInfo(int cnum,uint16 vuid,char *param,char *data,
+static BOOL api_PrintJobInfo(connection_struct *conn,uint16 vuid,char *param,char *data,
                             int mdrcnt,int mprcnt,
                             char **rdata,char **rparam,
                             int *rdata_len,int *rparam_len)
 {
-  struct pack_desc desc;
-  char *str1 = param+2;
-  char *str2 = skip_string(str1,1);
-  char *p = skip_string(str2,1);
-  int jobid, snum;
-  int uLevel = SVAL(p,2);
-  int function = SVAL(p,4);    /* what is this ?? */
-  int i;
-  char *s = data;
-
-  printjob_decode(SVAL(p,0), &snum, &jobid);
+       struct pack_desc desc;
+       char *str1 = param+2;
+       char *str2 = skip_string(str1,1);
+       char *p = skip_string(str2,1);
+       int jobid, snum;
+       int uLevel = SVAL(p,2);
+       int function = SVAL(p,4);       /* what is this ?? */
+       int i;
+       char *s = data;
+       files_struct *fsp;
+
+       printjob_decode(SVAL(p,0), &snum, &jobid);
    
-  *rparam_len = 4;
-  *rparam = REALLOC(*rparam,*rparam_len);
+       *rparam_len = 4;
+       *rparam = REALLOC(*rparam,*rparam_len);
   
-  *rdata_len = 0;
-  
-  /* check it's a supported varient */
-  if ((strcmp(str1,"WWsTP")) || (!check_printjob_info(&desc,uLevel,str2)))
-    return(False);
+       *rdata_len = 0;
+       
+       /* check it's a supported varient */
+       if ((strcmp(str1,"WWsTP")) || 
+           (!check_printjob_info(&desc,uLevel,str2)))
+               return(False);
    
-  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;
+       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,cnum,&queue,NULL);
-       for (i=0;i<count;i++)   /* find job */
-         if ((queue[i].job&0xFF) == jobid) break;
+                       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 (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 */;
-         }
+                               {
+                                       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;
-    break;
-  case 0xb:   /* change print job name, data gives the name */
-    /* jobid, snum should be zero */
-    if (isalpha(*s))
-      {
-       pstring name;
-       int l = 0;
-       while (l<64 && *s)
-         {
-           if (issafe(*s)) name[l++] = *s;
-           s++;
-         }      
-       name[l] = 0;
+                               desc.errcode=NERR_notsupported; /* not yet 
+                                                                  supported */
+                               if (queue) free(queue);
+                       }
+               } else {
+                       desc.errcode=NERR_JobNotFound;
+               }
+               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));
+                       DEBUG(3,("Setting print name to %s\n",name));
        
-        become_root(True);
-
-       for (i=0;i<MAX_OPEN_FILES;i++)
-         if (Files[i].open && Files[i].print_file)
-           {
-             pstring wd;
-          int fcnum = Files[i].cnum;
-             GetWd(wd);
-             unbecome_user();
+                       fsp = file_find_print();        
+
+                       if (fsp) {
+                               connection_struct *fconn = fsp->conn;
+                               unbecome_user();
              
-             if (!become_user(&Connections[fcnum], fcnum,vuid) || 
-                 !become_service(fcnum,True))
-               break;
+                               if (!become_user(fconn,vuid) || 
+                                   !become_service(fconn,True))
+                                       break;
              
-             if (sys_rename(Files[i].name,name) == 0)
-               string_set(&Files[i].name,name);
-             break;
-           }
+                               if (dos_rename(fsp->fsp_name,name) == 0) {
+                                       string_set(&fsp->fsp_name,name);
+                               }
+                               break;
+                       }
+               }
+               desc.errcode=NERR_Success;
+               break;
 
-         unbecome_root(True);
-      }
-    desc.errcode=NERR_Success;
-  
-    break;
-  default:                     /* not implemented */
-    return False;
-  }
+       default:                        /* not implemented */
+               return False;
+       }
  
-  SSVALS(*rparam,0,desc.errcode);
-  SSVAL(*rparam,2,0);          /* converter word */
-  
-  return(True);
+       SSVALS(*rparam,0,desc.errcode);
+       SSVAL(*rparam,2,0);             /* converter word */
+       
+       return(True);
 }
 
 
 /****************************************************************************
   get info about the server
   ****************************************************************************/
-static BOOL api_RNetServerGetInfo(int cnum,uint16 vuid, char *param,char *data,
+static BOOL api_RNetServerGetInfo(connection_struct *conn,uint16 vuid, char *param,char *data,
                                  int mdrcnt,int mprcnt,
                                  char **rdata,char **rparam,
                                  int *rdata_len,int *rparam_len)
@@ -1830,7 +2066,7 @@ static BOOL api_RNetServerGetInfo(int cnum,uint16 vuid, char *param,char *data,
 
       pstrcpy(comment,lp_serverstring());
 
-      if ((count=get_server_info(SV_TYPE_ALL,&servers,myworkgroup))>0) {
+      if ((count=get_server_info(SV_TYPE_ALL,&servers,global_myworkgroup))>0) {
        for (i=0;i<count;i++)
          if (strequal(servers[i].name,local_machine))
       {
@@ -1848,7 +2084,7 @@ static BOOL api_RNetServerGetInfo(int cnum,uint16 vuid, char *param,char *data,
        SIVAL(p,6,0);
       } else {
        SIVAL(p,6,PTR_DIFF(p2,*rdata));
-       standard_sub(cnum,comment);
+       standard_sub(conn,comment);
        StrnCpy(p2,comment,MAX(mdrcnt - struct_len,0));
        p2 = skip_string(p2,1);
       }
@@ -1873,7 +2109,7 @@ static BOOL api_RNetServerGetInfo(int cnum,uint16 vuid, char *param,char *data,
 /****************************************************************************
   get info about the server
   ****************************************************************************/
-static BOOL api_NetWkstaGetInfo(int cnum,uint16 vuid, char *param,char *data,
+static BOOL api_NetWkstaGetInfo(connection_struct *conn,uint16 vuid, char *param,char *data,
                                int mdrcnt,int mprcnt,
                                char **rdata,char **rparam,
                                int *rdata_len,int *rparam_len)
@@ -1905,18 +2141,18 @@ static BOOL api_NetWkstaGetInfo(int cnum,uint16 vuid, char *param,char *data,
 
 
   SIVAL(p,0,PTR_DIFF(p2,*rdata)); /* host name */
-  strcpy(p2,local_machine);
+  pstrcpy(p2,local_machine);
   strupper(p2);
   p2 = skip_string(p2,1);
   p += 4;
 
   SIVAL(p,0,PTR_DIFF(p2,*rdata));
-  strcpy(p2,sesssetup_user);
+  pstrcpy(p2,sesssetup_user);
   p2 = skip_string(p2,1);
   p += 4;
 
   SIVAL(p,0,PTR_DIFF(p2,*rdata)); /* login domain */
-  strcpy(p2,myworkgroup);
+  pstrcpy(p2,global_myworkgroup);
   strupper(p2);
   p2 = skip_string(p2,1);
   p += 4;
@@ -1926,12 +2162,12 @@ static BOOL api_NetWkstaGetInfo(int cnum,uint16 vuid, char *param,char *data,
   p += 2;
 
   SIVAL(p,0,PTR_DIFF(p2,*rdata));
-  strcpy(p2,myworkgroup);      /* don't know.  login domain?? */
+  pstrcpy(p2,global_myworkgroup);      /* don't know.  login domain?? */
   p2 = skip_string(p2,1);
   p += 4;
 
   SIVAL(p,0,PTR_DIFF(p2,*rdata)); /* don't know */
-  strcpy(p2,"");
+  pstrcpy(p2,"");
   p2 = skip_string(p2,1);
   p += 4;
 
@@ -2110,7 +2346,7 @@ There is no auxiliary data in the response.
 #define AF_OP_ACCOUNTS  3
 
 
-static BOOL api_RNetUserGetInfo(int cnum,uint16 vuid, char *param,char *data,
+static BOOL api_RNetUserGetInfo(connection_struct *conn,uint16 vuid, char *param,char *data,
                                int mdrcnt,int mprcnt,
                                char **rdata,char **rparam,
                                int *rdata_len,int *rparam_len)
@@ -2123,8 +2359,11 @@ static BOOL api_RNetUserGetInfo(int cnum,uint16 vuid, char *param,char *data,
        char *p2;
 
     /* get NIS home of a previously validated user - simeon */
+    /* With share level security vuid will always be zero.
+       Don't depend on vuser being non-null !!. JRA */
     user_struct *vuser = get_valid_user_struct(vuid);
-    DEBUG(3,("  Username of UID %d is %s\n", vuser->uid, vuser->name));
+    if(vuser != NULL)
+      DEBUG(3,("  Username of UID %d is %s\n", (int)vuser->uid, vuser->name));
 
     *rparam_len = 6;
     *rparam = REALLOC(*rparam,*rparam_len);
@@ -2165,44 +2404,44 @@ static BOOL api_RNetUserGetInfo(int cnum,uint16 vuid, char *param,char *data,
        if (uLevel >= 10)
        {
                SIVAL(p,usri11_comment,PTR_DIFF(p2,p)); /* comment */
-               strcpy(p2,"Comment");
+               pstrcpy(p2,"Comment");
                p2 = skip_string(p2,1);
 
                SIVAL(p,usri11_usr_comment,PTR_DIFF(p2,p)); /* user_comment */
-               strcpy(p2,"UserComment");
+               pstrcpy(p2,"UserComment");
                p2 = skip_string(p2,1);
 
                /* EEK! the cifsrap.txt doesn't have this in!!!! */
                SIVAL(p,usri11_full_name,PTR_DIFF(p2,p)); /* full name */
-               strcpy(p2,vuser->real_name);    /* simeon */
+               pstrcpy(p2,((vuser != NULL) ? vuser->real_name : UserName));
                p2 = skip_string(p2,1);
        }
 
        if (uLevel == 11) /* modelled after NTAS 3.51 reply */
        {         
-               SSVAL(p,usri11_priv,Connections[cnum].admin_user?USER_PRIV_ADMIN:USER_PRIV_USER); 
+               SSVAL(p,usri11_priv,conn->admin_user?USER_PRIV_ADMIN:USER_PRIV_USER); 
                SIVAL(p,usri11_auth_flags,AF_OP_PRINT);         /* auth flags */
-               SIVALS(p,usri11_password_age,0xffffffff);               /* password age */
+               SIVALS(p,usri11_password_age,-1);               /* password age */
                SIVAL(p,usri11_homedir,PTR_DIFF(p2,p)); /* home dir */
-               strcpy(p2, lp_logon_path());
+               pstrcpy(p2, lp_logon_path());
                p2 = skip_string(p2,1);
                SIVAL(p,usri11_parms,PTR_DIFF(p2,p)); /* parms */
-               strcpy(p2,"");
+               pstrcpy(p2,"");
                p2 = skip_string(p2,1);
                SIVAL(p,usri11_last_logon,0);           /* last logon */
                SIVAL(p,usri11_last_logoff,0);          /* last logoff */
-               SSVALS(p,usri11_bad_pw_count,0xffffffff);               /* bad pw counts */
-               SSVALS(p,usri11_num_logons,0xffffffff);         /* num logons */
+               SSVALS(p,usri11_bad_pw_count,-1);       /* bad pw counts */
+               SSVALS(p,usri11_num_logons,-1);         /* num logons */
                SIVAL(p,usri11_logon_server,PTR_DIFF(p2,p)); /* logon server */
-               strcpy(p2,"\\\\*");
+               pstrcpy(p2,"\\\\*");
                p2 = skip_string(p2,1);
                SSVAL(p,usri11_country_code,0);         /* country code */
 
                SIVAL(p,usri11_workstations,PTR_DIFF(p2,p)); /* workstations */
-               strcpy(p2,"");
+               pstrcpy(p2,"");
                p2 = skip_string(p2,1);
 
-               SIVALS(p,usri11_max_storage,0xffffffff);                /* max storage */
+               SIVALS(p,usri11_max_storage,-1);                /* max storage */
                SSVAL(p,usri11_units_per_week,168);             /* units per week */
                SIVAL(p,usri11_logon_hours,PTR_DIFF(p2,p)); /* logon hours */
 
@@ -2218,9 +2457,9 @@ static BOOL api_RNetUserGetInfo(int cnum,uint16 vuid, char *param,char *data,
                memset(p+22,' ',16);    /* password */
                SIVALS(p,38,-1);                /* password age */
                SSVAL(p,42,
-               Connections[cnum].admin_user?USER_PRIV_ADMIN:USER_PRIV_USER);
+               conn->admin_user?USER_PRIV_ADMIN:USER_PRIV_USER);
                SIVAL(p,44,PTR_DIFF(p2,*rdata)); /* home dir */
-               strcpy(p2,lp_logon_path());
+               pstrcpy(p2,lp_logon_path());
                p2 = skip_string(p2,1);
                SIVAL(p,48,PTR_DIFF(p2,*rdata)); /* comment */
                *p2++ = 0;
@@ -2230,11 +2469,11 @@ static BOOL api_RNetUserGetInfo(int cnum,uint16 vuid, char *param,char *data,
                {
                        SIVAL(p,60,0);          /* auth_flags */
                        SIVAL(p,64,PTR_DIFF(p2,*rdata)); /* full_name */
-                       strcpy(p2,vuser->real_name);    /* simeon */
+                       pstrcpy(p2,((vuser != NULL) ? vuser->real_name : UserName));
                        p2 = skip_string(p2,1);
                        SIVAL(p,68,0);          /* urs_comment */
                        SIVAL(p,72,PTR_DIFF(p2,*rdata)); /* parms */
-                       strcpy(p2,"");
+                       pstrcpy(p2,"");
                        p2 = skip_string(p2,1);
                        SIVAL(p,76,0);          /* workstations */
                        SIVAL(p,80,0);          /* last_logon */
@@ -2248,7 +2487,7 @@ static BOOL api_RNetUserGetInfo(int cnum,uint16 vuid, char *param,char *data,
                        SSVALS(p,102,-1);       /* bad_pw_count */
                        SSVALS(p,104,-1);       /* num_logons */
                        SIVAL(p,106,PTR_DIFF(p2,*rdata)); /* logon_server */
-                       strcpy(p2,"\\\\%L");
+                       pstrcpy(p2,"\\\\%L");
                        standard_sub_basic(p2);
                        p2 = skip_string(p2,1);
                        SSVAL(p,110,49);        /* country_code */
@@ -2266,7 +2505,7 @@ static BOOL api_RNetUserGetInfo(int cnum,uint16 vuid, char *param,char *data,
 /*******************************************************************
   get groups that a user is a member of
   ******************************************************************/
-static BOOL api_NetUserGetGroups(int cnum,uint16 vuid, char *param,char *data,
+static BOOL api_NetUserGetGroups(connection_struct *conn,uint16 vuid, char *param,char *data,
                                 int mdrcnt,int mprcnt,
                                 char **rdata,char **rparam,
                                 int *rdata_len,int *rparam_len)
@@ -2299,10 +2538,10 @@ static BOOL api_NetUserGetGroups(int cnum,uint16 vuid, char *param,char *data,
   p = *rdata;
 
   /* XXXX we need a real SAM database some day */
-  strcpy(p,"Users"); p += 21; count++;
-  strcpy(p,"Domain Users"); p += 21; count++;
-  strcpy(p,"Guests"); p += 21; count++;
-  strcpy(p,"Domain Guests"); p += 21; count++;
+  pstrcpy(p,"Users"); p += 21; count++;
+  pstrcpy(p,"Domain Users"); p += 21; count++;
+  pstrcpy(p,"Guests"); p += 21; count++;
+  pstrcpy(p,"Domain Guests"); p += 21; count++;
 
   *rdata_len = PTR_DIFF(p,*rdata);
 
@@ -2313,7 +2552,7 @@ static BOOL api_NetUserGetGroups(int cnum,uint16 vuid, char *param,char *data,
 }
 
 
-static BOOL api_WWkstaUserLogon(int cnum,uint16 vuid, char *param,char *data,
+static BOOL api_WWkstaUserLogon(connection_struct *conn,uint16 vuid, char *param,char *data,
                                int mdrcnt,int mprcnt,
                                char **rdata,char **rparam,
                                int *rdata_len,int *rparam_len)
@@ -2348,7 +2587,7 @@ static BOOL api_WWkstaUserLogon(int cnum,uint16 vuid, char *param,char *data,
     PACKS(&desc,"B21",name);   /* eff. name */
     PACKS(&desc,"B","");               /* pad */
     PACKI(&desc,"W",
-         Connections[cnum].admin_user?USER_PRIV_ADMIN:USER_PRIV_USER);
+         conn->admin_user?USER_PRIV_ADMIN:USER_PRIV_USER);
     PACKI(&desc,"D",0);                /* auth flags XXX */
     PACKI(&desc,"W",0);                /* num logons */
     PACKI(&desc,"W",0);                /* bad pw count */
@@ -2361,17 +2600,17 @@ static BOOL api_WWkstaUserLogon(int cnum,uint16 vuid, char *param,char *data,
     PACKI(&desc,"D",-1);               /* password must change */
     {
       fstring mypath;
-      strcpy(mypath,"\\\\");
-      strcat(mypath,local_machine);
+      fstrcpy(mypath,"\\\\");
+      fstrcat(mypath,local_machine);
       strupper(mypath);
       PACKS(&desc,"z",mypath); /* computer */
     }
-    PACKS(&desc,"z",myworkgroup);/* domain */
+    PACKS(&desc,"z",global_myworkgroup);/* domain */
 
 /* 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( cnum, logon_script );
+    standard_sub( conn, logon_script );
     PACKS(&desc,"z", logon_script);            /* script path */
 /* End of JHT mods */
 
@@ -2393,7 +2632,7 @@ static BOOL api_WWkstaUserLogon(int cnum,uint16 vuid, char *param,char *data,
 /****************************************************************************
   api_WAccessGetUserPerms
   ****************************************************************************/
-static BOOL api_WAccessGetUserPerms(int cnum,uint16 vuid, char *param,char *data,
+static BOOL api_WAccessGetUserPerms(connection_struct *conn,uint16 vuid, char *param,char *data,
                                    int mdrcnt,int mprcnt,
                                    char **rdata,char **rparam,
                                    int *rdata_len,int *rparam_len)
@@ -2421,7 +2660,7 @@ static BOOL api_WAccessGetUserPerms(int cnum,uint16 vuid, char *param,char *data
 /****************************************************************************
   api_WPrintJobEnumerate
   ****************************************************************************/
-static BOOL api_WPrintJobGetInfo(int cnum,uint16 vuid, char *param,char *data,
+static BOOL api_WPrintJobGetInfo(connection_struct *conn,uint16 vuid, char *param,char *data,
                                 int mdrcnt,int mprcnt,
                                 char **rdata,char **rparam,
                                 int *rdata_len,int *rparam_len)
@@ -2429,7 +2668,7 @@ static BOOL api_WPrintJobGetInfo(int cnum,uint16 vuid, char *param,char *data,
   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;
@@ -2439,7 +2678,6 @@ static BOOL api_WPrintJobGetInfo(int cnum,uint16 vuid, char *param,char *data,
   print_status_struct status;
 
   uLevel = SVAL(p,2);
-  cbBuf = SVAL(p,4);
 
   bzero(&desc,sizeof(desc));
   bzero(&status,sizeof(status));
@@ -2454,7 +2692,7 @@ static BOOL api_WPrintJobGetInfo(int cnum,uint16 vuid, char *param,char *data,
 
   if (snum < 0 || !VALID_SNUM(snum)) return(False);
 
-  count = get_printqueue(snum,cnum,&queue,&status);
+  count = get_printqueue(snum,conn,&queue,&status);
   for (i = 0; i < count; i++) {
     if ((queue[i].job & 0xFF) == job) break;
   }
@@ -2464,7 +2702,7 @@ static BOOL api_WPrintJobGetInfo(int cnum,uint16 vuid, char *param,char *data,
 
   if (init_package(&desc,1,0)) {
     if (i < count) {
-      fill_printjob_info(cnum,snum,uLevel,&desc,&queue[i],i);
+      fill_printjob_info(conn,snum,uLevel,&desc,&queue[i],i);
       *rdata_len = desc.usedlen;
     }
     else {
@@ -2485,7 +2723,7 @@ static BOOL api_WPrintJobGetInfo(int cnum,uint16 vuid, char *param,char *data,
   return(True);
 }
 
-static BOOL api_WPrintJobEnumerate(int cnum,uint16 vuid, char *param,char *data,
+static BOOL api_WPrintJobEnumerate(connection_struct *conn,uint16 vuid, char *param,char *data,
                                   int mdrcnt,int mprcnt,
                                   char **rdata,char **rparam,
                                   int *rdata_len,int *rparam_len)
@@ -2494,7 +2732,7 @@ static BOOL api_WPrintJobEnumerate(int cnum,uint16 vuid, char *param,char *data,
   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;
@@ -2507,7 +2745,6 @@ static BOOL api_WPrintJobEnumerate(int cnum,uint16 vuid, char *param,char *data,
 
   p = skip_string(p,1);
   uLevel = SVAL(p,0);
-  cbBuf = SVAL(p,2);
 
   DEBUG(3,("WPrintJobEnumerate uLevel=%d name=%s\n",uLevel,name));
 
@@ -2527,7 +2764,7 @@ static BOOL api_WPrintJobEnumerate(int cnum,uint16 vuid, char *param,char *data,
 
   if (snum < 0 || !VALID_SNUM(snum)) return(False);
 
-  count = get_printqueue(snum,cnum,&queue,&status);
+  count = get_printqueue(snum,conn,&queue,&status);
   if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
   desc.base = *rdata;
   desc.buflen = mdrcnt;
@@ -2535,7 +2772,7 @@ static BOOL api_WPrintJobEnumerate(int cnum,uint16 vuid, char *param,char *data,
   if (init_package(&desc,count,0)) {
     succnt = 0;
     for (i = 0; i < count; i++) {
-      fill_printjob_info(cnum,snum,uLevel,&desc,&queue[i],i);
+      fill_printjob_info(conn,snum,uLevel,&desc,&queue[i],i);
       if (desc.errcode == NERR_Success) succnt = i+1;
     }
   }
@@ -2570,7 +2807,7 @@ static int check_printdest_info(struct pack_desc* desc,
   return True;
 }
 
-static void fill_printdest_info(int cnum, int snum, int uLevel,
+static void fill_printdest_info(connection_struct *conn, int snum, int uLevel,
                                struct pack_desc* desc)
 {
   char buf[100];
@@ -2603,7 +2840,7 @@ static void fill_printdest_info(int cnum, int snum, int uLevel,
   }
 }
 
-static BOOL api_WPrintDestGetInfo(int cnum,uint16 vuid, char *param,char *data,
+static BOOL api_WPrintDestGetInfo(connection_struct *conn,uint16 vuid, char *param,char *data,
                                  int mdrcnt,int mprcnt,
                                  char **rdata,char **rparam,
                                  int *rdata_len,int *rparam_len)
@@ -2612,7 +2849,7 @@ static BOOL api_WPrintDestGetInfo(int cnum,uint16 vuid, char *param,char *data,
   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;
 
@@ -2620,7 +2857,6 @@ static BOOL api_WPrintDestGetInfo(int cnum,uint16 vuid, char *param,char *data,
 
   p = skip_string(p,1);
   uLevel = SVAL(p,0);
-  cbBuf = SVAL(p,2);
 
   DEBUG(3,("WPrintDestGetInfo uLevel=%d PrinterName=%s\n",uLevel,PrinterName));
 
@@ -2647,7 +2883,7 @@ static BOOL api_WPrintDestGetInfo(int cnum,uint16 vuid, char *param,char *data,
     desc.base = *rdata;
     desc.buflen = mdrcnt;
     if (init_package(&desc,1,0)) {
-      fill_printdest_info(cnum,snum,uLevel,&desc);
+      fill_printdest_info(conn,snum,uLevel,&desc);
     }
     *rdata_len = desc.usedlen;
   }
@@ -2662,7 +2898,7 @@ static BOOL api_WPrintDestGetInfo(int cnum,uint16 vuid, char *param,char *data,
   return(True);
 }
 
-static BOOL api_WPrintDestEnum(int cnum,uint16 vuid, char *param,char *data,
+static BOOL api_WPrintDestEnum(connection_struct *conn,uint16 vuid, char *param,char *data,
                               int mdrcnt,int mprcnt,
                               char **rdata,char **rparam,
                               int *rdata_len,int *rparam_len)
@@ -2670,7 +2906,7 @@ static BOOL api_WPrintDestEnum(int cnum,uint16 vuid, char *param,char *data,
   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;
@@ -2679,7 +2915,6 @@ static BOOL api_WPrintDestEnum(int cnum,uint16 vuid, char *param,char *data,
   bzero(&desc,sizeof(desc));
 
   uLevel = SVAL(p,0);
-  cbBuf = SVAL(p,2);
 
   DEBUG(3,("WPrintDestEnum uLevel=%d\n",uLevel));
 
@@ -2700,7 +2935,7 @@ static BOOL api_WPrintDestEnum(int cnum,uint16 vuid, char *param,char *data,
     n = 0;
     for (i = 0; i < services; i++) {
       if (lp_snum_ok(i) && lp_print_ok(i) && lp_browseable(i)) {
-       fill_printdest_info(cnum,i,uLevel,&desc);
+       fill_printdest_info(conn,i,uLevel,&desc);
        n++;
        if (desc.errcode == NERR_Success) succnt = n;
       }
@@ -2720,7 +2955,7 @@ static BOOL api_WPrintDestEnum(int cnum,uint16 vuid, char *param,char *data,
   return(True);
 }
 
-static BOOL api_WPrintDriverEnum(int cnum,uint16 vuid, char *param,char *data,
+static BOOL api_WPrintDriverEnum(connection_struct *conn,uint16 vuid, char *param,char *data,
                                 int mdrcnt,int mprcnt,
                                 char **rdata,char **rparam,
                                 int *rdata_len,int *rparam_len)
@@ -2728,14 +2963,13 @@ static BOOL api_WPrintDriverEnum(int cnum,uint16 vuid, char *param,char *data,
   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));
 
   uLevel = SVAL(p,0);
-  cbBuf = SVAL(p,2);
 
   DEBUG(3,("WPrintDriverEnum uLevel=%d\n",uLevel));
 
@@ -2765,7 +2999,7 @@ static BOOL api_WPrintDriverEnum(int cnum,uint16 vuid, char *param,char *data,
   return(True);
 }
 
-static BOOL api_WPrintQProcEnum(int cnum,uint16 vuid, char *param,char *data,
+static BOOL api_WPrintQProcEnum(connection_struct *conn,uint16 vuid, char *param,char *data,
                                int mdrcnt,int mprcnt,
                                char **rdata,char **rparam,
                                int *rdata_len,int *rparam_len)
@@ -2773,14 +3007,13 @@ static BOOL api_WPrintQProcEnum(int cnum,uint16 vuid, char *param,char *data,
   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));
 
   uLevel = SVAL(p,0);
-  cbBuf = SVAL(p,2);
 
   DEBUG(3,("WPrintQProcEnum uLevel=%d\n",uLevel));
 
@@ -2811,7 +3044,7 @@ static BOOL api_WPrintQProcEnum(int cnum,uint16 vuid, char *param,char *data,
   return(True);
 }
 
-static BOOL api_WPrintPortEnum(int cnum,uint16 vuid, char *param,char *data,
+static BOOL api_WPrintPortEnum(connection_struct *conn,uint16 vuid, char *param,char *data,
                               int mdrcnt,int mprcnt,
                               char **rdata,char **rparam,
                               int *rdata_len,int *rparam_len)
@@ -2819,14 +3052,13 @@ static BOOL api_WPrintPortEnum(int cnum,uint16 vuid, char *param,char *data,
   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));
 
   uLevel = SVAL(p,0);
-  cbBuf = SVAL(p,2);
 
   DEBUG(3,("WPrintPortEnum uLevel=%d\n",uLevel));
 
@@ -2858,124 +3090,181 @@ static BOOL api_WPrintPortEnum(int cnum,uint16 vuid, char *param,char *data,
   return(True);
 }
 
+static void api_rpc_trans_reply(char *outbuf,
+                               pipes_struct *p,
+                               prs_struct *pd)
+{
+       send_trans_reply(outbuf, p->rhdr.data, NULL, NULL, 0, p->file_offset);
 
-struct
+       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);
+               mem_free_data(p->rdata_i.data);
+       }
+}
+
+/****************************************************************************
+ WaitNamedPipeHandleState 
+****************************************************************************/
+static BOOL api_WNPHS(char *outbuf, pipes_struct *p, char *param)
 {
-  char * name;
-  char * pipename;
-  int subcommand;
-  BOOL (*fn) ();
-} api_fd_commands [] =
-  {
-#ifdef NTDOMAIN
-    { "SetNmdPpHndState",      "lsarpc",       1,      api_LsarpcSNPHS },
-    { "SetNmdPpHndState",      "srvsvc",       1,      api_LsarpcSNPHS },
-    { "SetNmdPpHndState",      "NETLOGON",     1,      api_LsarpcSNPHS },
-    { "TransactNmPipe",        "lsarpc",       0x26,   api_ntLsarpcTNP },
-    { "TransactNmPipe",        "srvsvc",       0x26,   api_srvsvcTNP },
-    { "TransactNmPipe",        "NETLOGON",     0x26,   api_netlogrpcTNP },
-#else
-    { "SetNmdPpHndState",      "lsarpc",       1,      api_LsarpcSNPHS },
-    { "TransactNmPipe"  ,      "lsarpc",       0x26,   api_LsarpcTNP },
-#endif
-    { NULL,            NULL,           -1,     (BOOL (*)())api_Unsupported }
-  };
+       uint16 priority;
+
+       if (!param) return False;
+
+       priority = param[0] + (param[1] << 8);
+       DEBUG(4,("WaitNamedPipeHandleState priority %x\n", priority));
+
+       if (wait_rpc_pipe_hnd_state(p, priority))
+       {
+               /* now send the reply */
+               send_trans_reply(outbuf, NULL, NULL, NULL, 0, p->file_offset);
+
+               return True;
+       }
+       return False;
+}
+
+
+/****************************************************************************
+ SetNamedPipeHandleState 
+****************************************************************************/
+static BOOL api_SNPHS(char *outbuf, pipes_struct *p, char *param)
+{
+       uint16 id;
+
+       if (!param) return False;
+
+       id = param[0] + (param[1] << 8);
+       DEBUG(4,("SetNamedPipeHandleState to code %x\n", id));
+
+       if (set_rpc_pipe_hnd_state(p, id))
+       {
+               /* now send the reply */
+               send_trans_reply(outbuf, NULL, NULL, NULL, 0, p->file_offset);
+
+               return True;
+       }
+       return False;
+}
+
+
+/****************************************************************************
+ 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;
+
+       /* unsupported */
+       SSVAL(rparam.data,0,NERR_notsupported);
+       SSVAL(rparam.data,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);
+
+       return(-1);
+}
 
 /****************************************************************************
   handle remote api calls delivered to a named pipe already opened.
   ****************************************************************************/
-static int api_fd_reply(int cnum,uint16 vuid,char *outbuf,
+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)
 {
-  char *rdata = NULL;
-  char *rparam = NULL;
-  int rdata_len = 0;
-  int rparam_len = 0;
+       BOOL reply    = False;
 
-  BOOL reply = False;
+       int pnum;
+       int subcommand;
+       pipes_struct *p = NULL;
+       prs_struct pd;
 
-  int i;
-  int fd;
-  int subcommand;
-  pstring pipe_name;
-  
-  DEBUG(5,("api_fd_reply\n"));
-  /* First find out the name of this file. */
-  if (suwcnt != 2)
-    {
-      DEBUG(0,("Unexpected named pipe transaction.\n"));
-      return(-1);
-    }
-  
-  /* Get the file handle and hence the file name. */
-  fd = setup[1];
-  subcommand = setup[0];
-  if (fd >= 0 && fd < MAX_OPEN_FILES)
-  {
-    pstrcpy(pipe_name, Files[fd].name);
-  }
-  else
-  {
-    pipe_name[0] = 0;
-    DEBUG(1,("api_fd_reply: INVALID FILE HANDLE: %x\n", fd));
-  }
+       DEBUG(5,("api_fd_reply\n"));
 
-  DEBUG(3,("Got API command %d on pipe %s (fd %x)",
-            subcommand, pipe_name, fd));
-  DEBUG(3,("(tdscnt=%d,tpscnt=%d,mdrcnt=%d,mprcnt=%d,cnum=%d,vuid=%d)\n",
-          tdscnt,tpscnt,mdrcnt,mprcnt,cnum,vuid));
-  
-  for (i = 0; api_fd_commands[i].name; i++)
-  {
-    if (strequal(api_fd_commands[i].pipename, pipe_name) &&
-           api_fd_commands[i].subcommand == subcommand &&
-           api_fd_commands[i].fn)
-    {
-         DEBUG(3,("Doing %s\n", api_fd_commands[i].name));
-         break;
-    }
-  }
-  
-  rdata  = (char *)malloc(1024); if (rdata ) bzero(rdata ,1024);
-  rparam = (char *)malloc(1024); if (rparam) bzero(rparam,1024);
-  
-  DEBUG(10,("calling api_fd_command\n"));
+       /* make a static data parsing structure from the api_fd_reply data */
+       prs_init(&pd, 0, 4, 0, True);
+       mem_create(pd.data, data, 0, tdscnt, 0, False);
 
-  reply = api_fd_commands[i].fn(cnum,vuid,params,data,mdrcnt,mprcnt,
-                               &rdata,&rparam,&rdata_len,&rparam_len);
-  
-  DEBUG(10,("called api_fd_command\n"));
+       /* First find out the name of this file. */
+       if (suwcnt != 2)
+       {
+               DEBUG(0,("Unexpected named pipe transaction.\n"));
+               return(-1);
+       }
 
-  if (rdata_len > mdrcnt || rparam_len > mprcnt)
-  {
-    reply = api_TooSmall(cnum,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(cnum,vuid,params,data,mdrcnt,mprcnt,
-                   &rdata,&rparam,&rdata_len,&rparam_len);
-  
-  /* now send the reply */
-  send_trans_reply(outbuf,rdata,rparam,NULL,rdata_len,rparam_len,0);
-  
-  if (rdata)
-    free(rdata);
-  if (rparam)
-    free(rparam);
-  
-  return(-1);
-}
+       /* Get the file handle and hence the file name. */
+       pnum = setup[1];
+       subcommand = setup[0];
+       p = get_rpc_pipe(pnum);
+
+       if (p != NULL)
+       {
+               DEBUG(3,("Got API command 0x%x on pipe \"%s\" (pnum %x)",
+                                 subcommand, p->name, pnum));
+
+               /* record maximum data length that can be transmitted in an SMBtrans */
+               p->file_offset = mdrcnt;
 
+                DEBUG(10,("api_fd_reply: p:%p file_offset: %d\n",
+                           p, p->file_offset));
+
+               switch (subcommand)
+               {
+                       case 0x26:
+                       {
+                               /* dce/rpc command */
+                               reply = rpc_command(p, &pd);
+                               if (reply)
+                               {
+                                       api_rpc_trans_reply(outbuf, p, &pd);
+                               }
+                               break;
+                       }
+                       case 0x53:
+                       {
+                               /* Wait Named Pipe Handle state */
+                               reply = api_WNPHS(outbuf, p, params);
+                               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));
+       }
 
+       mem_free_data(pd.data);
+
+       if (!reply)
+       {
+               return api_no_reply(outbuf, mdrcnt);
+       }
+       return -1;
+}
 
 /****************************************************************************
   the buffer was too small
   ****************************************************************************/
-static BOOL api_TooSmall(int cnum,uint16 vuid, char *param,char *data,
+static BOOL api_TooSmall(connection_struct *conn,uint16 vuid, char *param,char *data,
                         int mdrcnt,int mprcnt,
                         char **rdata,char **rparam,
                         int *rdata_len,int *rparam_len)
@@ -2996,7 +3285,7 @@ static BOOL api_TooSmall(int cnum,uint16 vuid, char *param,char *data,
 /****************************************************************************
   the request is not supported
   ****************************************************************************/
-static BOOL api_Unsupported(int cnum,uint16 vuid, char *param,char *data,
+static BOOL api_Unsupported(connection_struct *conn,uint16 vuid, char *param,char *data,
                            int mdrcnt,int mprcnt,
                            char **rdata,char **rparam,
                            int *rdata_len,int *rparam_len)
@@ -3021,44 +3310,51 @@ struct
 {
   char *name;
   int id;
-  BOOL (*fn)();
+  BOOL (*fn)(connection_struct *,uint16,char *,char *,
+            int,int,char **,char **,int *,int *);
   int flags;
 } api_commands[] = {
-  {"RNetShareEnum",    0,      (BOOL (*)())api_RNetShareEnum,0},
-  {"RNetShareGetInfo", 1,      (BOOL (*)())api_RNetShareGetInfo,0},
-  {"RNetServerGetInfo",        13,     (BOOL (*)())api_RNetServerGetInfo,0},
-  {"RNetUserGetInfo",  56,     (BOOL (*)())api_RNetUserGetInfo,0},
-  {"NetUserGetGroups", 59,     (BOOL (*)())api_NetUserGetGroups,0},
-  {"NetWkstaGetInfo",  63,     (BOOL (*)())api_NetWkstaGetInfo,0},
-  {"DosPrintQEnum",    69,     (BOOL (*)())api_DosPrintQEnum,0},
-  {"DosPrintQGetInfo", 70,     (BOOL (*)())api_DosPrintQGetInfo,0},
-  {"WPrintJobEnumerate",76,    (BOOL (*)())api_WPrintJobEnumerate,0},
-  {"WPrintJobGetInfo", 77,     (BOOL (*)())api_WPrintJobGetInfo,0},
-  {"RDosPrintJobDel",  81,     (BOOL (*)())api_RDosPrintJobDel,0},
-  {"RDosPrintJobPause",        82,     (BOOL (*)())api_RDosPrintJobDel,0},
-  {"RDosPrintJobResume",83,    (BOOL (*)())api_RDosPrintJobDel,0},
-  {"WPrintDestEnum",   84,     (BOOL (*)())api_WPrintDestEnum,0},
-  {"WPrintDestGetInfo",        85,     (BOOL (*)())api_WPrintDestGetInfo,0},
-  {"NetRemoteTOD",     91,     (BOOL (*)())api_NetRemoteTOD,0},
-  {"WPrintQueuePurge", 103,    (BOOL (*)())api_WPrintQueuePurge,0},
-  {"NetServerEnum",    104,    (BOOL (*)())api_RNetServerEnum,0},
-  {"WAccessGetUserPerms",105,  (BOOL (*)())api_WAccessGetUserPerms,0},
-  {"SetUserPassword",  115,    (BOOL (*)())api_SetUserPassword,0},
-  {"WWkstaUserLogon",  132,    (BOOL (*)())api_WWkstaUserLogon,0},
-  {"PrintJobInfo",     147,    (BOOL (*)())api_PrintJobInfo,0},
-  {"WPrintDriverEnum", 205,    (BOOL (*)())api_WPrintDriverEnum,0},
-  {"WPrintQProcEnum",  206,    (BOOL (*)())api_WPrintQProcEnum,0},
-  {"WPrintPortEnum",   207,    (BOOL (*)())api_WPrintPortEnum,0},
-  {NULL,               -1,     (BOOL (*)())api_Unsupported,0}};
+  {"RNetShareEnum",    0,      api_RNetShareEnum,0},
+  {"RNetShareGetInfo", 1,      api_RNetShareGetInfo,0},
+  {"RNetServerGetInfo",        13,     api_RNetServerGetInfo,0},
+  {"RNetGroupGetUsers", 52,    api_RNetGroupGetUsers,0},
+  {"RNetUserGetInfo",  56,     api_RNetUserGetInfo,0},
+  {"NetUserGetGroups", 59,     api_NetUserGetGroups,0},
+  {"NetWkstaGetInfo",  63,     api_NetWkstaGetInfo,0},
+  {"DosPrintQEnum",    69,     api_DosPrintQEnum,0},
+  {"DosPrintQGetInfo", 70,     api_DosPrintQGetInfo,0},
+  {"WPrintQueuePause",  74, api_WPrintQueuePurge,0},
+  {"WPrintQueueResume", 75, api_WPrintQueuePurge,0},
+  {"WPrintJobEnumerate",76,    api_WPrintJobEnumerate,0},
+  {"WPrintJobGetInfo", 77,     api_WPrintJobGetInfo,0},
+  {"RDosPrintJobDel",  81,     api_RDosPrintJobDel,0},
+  {"RDosPrintJobPause",        82,     api_RDosPrintJobDel,0},
+  {"RDosPrintJobResume",83,    api_RDosPrintJobDel,0},
+  {"WPrintDestEnum",   84,     api_WPrintDestEnum,0},
+  {"WPrintDestGetInfo",        85,     api_WPrintDestGetInfo,0},
+  {"NetRemoteTOD",     91,     api_NetRemoteTOD,0},
+  {"WPrintQueuePurge", 103,    api_WPrintQueuePurge,0},
+  {"NetServerEnum",    104,    api_RNetServerEnum,0},
+  {"WAccessGetUserPerms",105,  api_WAccessGetUserPerms,0},
+  {"SetUserPassword",  115,    api_SetUserPassword,0},
+  {"WWkstaUserLogon",  132,    api_WWkstaUserLogon,0},
+  {"PrintJobInfo",     147,    api_PrintJobInfo,0},
+  {"WPrintDriverEnum", 205,    api_WPrintDriverEnum,0},
+  {"WPrintQProcEnum",  206,    api_WPrintQProcEnum,0},
+  {"WPrintPortEnum",   207,    api_WPrintPortEnum,0},
+  {"SamOEMChangePassword", 214, api_SamOEMChangePassword,0},
+  {NULL,               -1,     api_Unsupported,0}};
 
 
 /****************************************************************************
   handle remote api calls
   ****************************************************************************/
-static int api_reply(int cnum,uint16 vuid,char *outbuf,char *data,char *params,
+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);
+  int api_command;
+  struct mem_buf rdata_buf;
+  struct mem_buf rparam_buf;
   char *rdata = NULL;
   char *rparam = NULL;
   int rdata_len = 0;
@@ -3066,46 +3362,57 @@ static int api_reply(int cnum,uint16 vuid,char *outbuf,char *data,char *params,
   BOOL reply=False;
   int i;
 
+  SMB_ASSERT(params != 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;
+        DEBUG(3,("Doing %s\n",api_commands[i].name));
+        break;
       }
 
   rdata = (char *)malloc(1024); if (rdata) bzero(rdata,1024);
   rparam = (char *)malloc(1024); if (rparam) bzero(rparam,1024);
 
-  reply = api_commands[i].fn(cnum,vuid,params,data,mdrcnt,mprcnt,
+  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)
     {
-      reply = api_TooSmall(cnum,vuid,params,data,mdrcnt,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(cnum,vuid,params,data,mdrcnt,mprcnt,
+    api_Unsupported(conn,vuid,params,data,mdrcnt,mprcnt,
                    &rdata,&rparam,&rdata_len,&rparam_len);
 
       
+  mem_create(&rdata_buf , rdata , 0, rdata_len , 0, False);
+  mem_create(&rparam_buf, rparam, 0, rparam_len, 0, False);
 
   /* now send the reply */
-  send_trans_reply(outbuf,rdata,rparam,NULL,rdata_len,rparam_len,0);
+  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);
 }
@@ -3113,7 +3420,7 @@ static int api_reply(int cnum,uint16 vuid,char *outbuf,char *data,char *params,
 /****************************************************************************
   handle named pipe commands
   ****************************************************************************/
-static int named_pipe(int cnum,uint16 vuid, char *outbuf,char *name,
+static int named_pipe(connection_struct *conn,uint16 vuid, char *outbuf,char *name,
                      uint16 *setup,char *data,char *params,
                      int suwcnt,int tdscnt,int tpscnt,
                      int msrcnt,int mdrcnt,int mprcnt)
@@ -3122,12 +3429,22 @@ static int named_pipe(int cnum,uint16 vuid, char *outbuf,char *name,
 
        if (strequal(name,"LANMAN"))
        {
-               return api_reply(cnum,vuid,outbuf,data,params,tdscnt,tpscnt,mdrcnt,mprcnt);
+               return api_reply(conn,vuid,outbuf,data,params,tdscnt,tpscnt,mdrcnt,mprcnt);
+       }
+
+       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(cnum,vuid,outbuf,setup,data,params,suwcnt,tdscnt,tpscnt,mdrcnt,mprcnt);
+               return api_fd_reply(conn,vuid,outbuf,setup,data,params,suwcnt,tdscnt,tpscnt,mdrcnt,mprcnt);
        }
 
        if (setup)
@@ -3142,135 +3459,151 @@ static int named_pipe(int cnum,uint16 vuid, char *outbuf,char *name,
 /****************************************************************************
   reply to a SMBtrans
   ****************************************************************************/
-int reply_trans(char *inbuf,char *outbuf)
+int reply_trans(connection_struct *conn, char *inbuf,char *outbuf, int size, int bufsize)
 {
-  fstring name;
-
-  char *data=NULL,*params=NULL;
-  uint16 *setup=NULL;
-
-  int outsize = 0;
-  int cnum = SVAL(inbuf,smb_tid);
-  uint16 vuid = SVAL(inbuf,smb_uid);
-
-  int tpscnt = SVAL(inbuf,smb_vwv0);
-  int tdscnt = SVAL(inbuf,smb_vwv1);
-  int mprcnt = SVAL(inbuf,smb_vwv2);
-  int mdrcnt = SVAL(inbuf,smb_vwv3);
-  int msrcnt = CVAL(inbuf,smb_vwv4);
-  BOOL close_on_completion = BITSETW(inbuf+smb_vwv5,0);
-  BOOL one_way = BITSETW(inbuf+smb_vwv5,1);
-  int pscnt = SVAL(inbuf,smb_vwv9);
-  int psoff = SVAL(inbuf,smb_vwv10);
-  int dscnt = SVAL(inbuf,smb_vwv11);
-  int dsoff = SVAL(inbuf,smb_vwv12);
-  int suwcnt = CVAL(inbuf,smb_vwv13);
-
-  bzero(name, sizeof(name));
-  fstrcpy(name,smb_buf(inbuf));
-
-  if (dscnt > tdscnt || pscnt > tpscnt) {
-         exit_server("invalid trans parameters\n");
-  }
+       fstring name;
+        int name_offset = 0;
+       char *data=NULL,*params=NULL;
+       uint16 *setup=NULL;
+       int outsize = 0;
+       uint16 vuid = SVAL(inbuf,smb_uid);
+       int tpscnt = SVAL(inbuf,smb_vwv0);
+       int tdscnt = SVAL(inbuf,smb_vwv1);
+       int mprcnt = SVAL(inbuf,smb_vwv2);
+       int mdrcnt = SVAL(inbuf,smb_vwv3);
+       int msrcnt = CVAL(inbuf,smb_vwv4);
+       BOOL close_on_completion = BITSETW(inbuf+smb_vwv5,0);
+       BOOL one_way = BITSETW(inbuf+smb_vwv5,1);
+       int pscnt = SVAL(inbuf,smb_vwv9);
+       int psoff = SVAL(inbuf,smb_vwv10);
+       int dscnt = SVAL(inbuf,smb_vwv11);
+       int dsoff = SVAL(inbuf,smb_vwv12);
+       int suwcnt = CVAL(inbuf,smb_vwv13);
+
+       bzero(name, sizeof(name));
+       fstrcpy(name,smb_buf(inbuf));
+
+       if (dscnt > tdscnt || pscnt > tpscnt) {
+               exit_server("invalid trans parameters\n");
+       }
   
-  if (tdscnt)
-    {
-      data = (char *)malloc(tdscnt);
-      memcpy(data,smb_base(inbuf)+dsoff,dscnt);
-    }
-  if (tpscnt)
-    {
-      params = (char *)malloc(tpscnt);
-      memcpy(params,smb_base(inbuf)+psoff,pscnt);
-    }
+       if (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 (suwcnt)
-    {
-      int i;
-      setup = (uint16 *)malloc(suwcnt*sizeof(setup[0]));
-      for (i=0;i<suwcnt;i++)
-       setup[i] = SVAL(inbuf,smb_vwv14+i*SIZEOFWORD);
-    }
+       if (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;
+               if((setup = (uint16 *)malloc(suwcnt*sizeof(uint16))) == NULL) {
+          DEBUG(0,("reply_trans: setup malloc fail for %d bytes !\n", suwcnt * sizeof(uint16)));
+                 return(ERROR(ERRDOS,ERRnomem));
+        } 
+               for (i=0;i<suwcnt;i++)
+                       setup[i] = SVAL(inbuf,smb_vwv14+i*SIZEOFWORD);
+       }
 
-  if (pscnt < tpscnt || dscnt < tdscnt)
-    {
-      /* We need to send an interim response then receive the rest
-        of the parameter/data bytes */
-      outsize = set_message(outbuf,0,0,True);
-      show_msg(outbuf);
-      send_smb(Client,outbuf);
-    }
 
-  /* receive the rest of the trans packet */
-  while (pscnt < tpscnt || dscnt < tdscnt)
-    {
-      int pcnt,poff,dcnt,doff,pdisp,ddisp;
-      
-      if (!receive_smb(Client,inbuf, SMB_SECONDARY_WAIT) ||
-         CVAL(inbuf, smb_com) != SMBtrans)
-       {
-         DEBUG(2,("Invalid secondary trans2 packet\n"));
-         if (params) free(params);
-         if (data) free(data);
-         if (setup) free(setup);
-         return(ERROR(ERRSRV,ERRerror));
+       if (pscnt < tpscnt || dscnt < tdscnt) {
+               /* We need to send an interim response then receive the rest
+                  of the parameter/data bytes */
+               outsize = set_message(outbuf,0,0,True);
+               show_msg(outbuf);
+               send_smb(Client,outbuf);
        }
 
-      show_msg(inbuf);
+       /* receive the rest of the trans packet */
+       while (pscnt < tpscnt || dscnt < tdscnt) {
+               BOOL ret;
+               int pcnt,poff,dcnt,doff,pdisp,ddisp;
       
-      tpscnt = SVAL(inbuf,smb_vwv0);
-      tdscnt = SVAL(inbuf,smb_vwv1);
+               ret = receive_next_smb(inbuf,bufsize,SMB_SECONDARY_WAIT);
+
+               if ((ret && (CVAL(inbuf, smb_com) != SMBtrans)) || !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);
+                       return(ERROR(ERRSRV,ERRerror));
+               }
 
-      pcnt = SVAL(inbuf,smb_vwv2);
-      poff = SVAL(inbuf,smb_vwv3);
-      pdisp = SVAL(inbuf,smb_vwv4);
-      
-      dcnt = SVAL(inbuf,smb_vwv5);
-      doff = SVAL(inbuf,smb_vwv6);
-      ddisp = SVAL(inbuf,smb_vwv7);
+               show_msg(inbuf);
       
-      pscnt += pcnt;
-      dscnt += dcnt;
-
-      if (dscnt > tdscnt || pscnt > tpscnt) {
-             exit_server("invalid trans parameters\n");
-      }
-
-      if (pcnt)
-       memcpy(params+pdisp,smb_base(inbuf)+poff,pcnt);
-      if (dcnt)
-       memcpy(data+ddisp,smb_base(inbuf)+doff,dcnt);      
-    }
-
-
-  DEBUG(3,("trans <%s> data=%d params=%d setup=%d\n",name,tdscnt,tpscnt,suwcnt));
-
-  if (strncmp(name,"\\PIPE\\",strlen("\\PIPE\\")) == 0)
-  {
-    DEBUG(5,("calling named_pipe\n"));
-    outsize = named_pipe(cnum,vuid,outbuf,name+strlen("\\PIPE\\"),setup,data,params,
-                        suwcnt,tdscnt,tpscnt,msrcnt,mdrcnt,mprcnt);
-  }
-  else
-  {
-    DEBUG(3,("invalid pipe name\n"));
-    outsize = 0;
-  }
-
-
-  if (data) free(data);
-  if (params) free(params);
-  if (setup) free(setup);
-
-  if (close_on_completion)
-    close_cnum(cnum,vuid);
+               tpscnt = SVAL(inbuf,smb_vwv0);
+               tdscnt = SVAL(inbuf,smb_vwv1);
+
+               pcnt = SVAL(inbuf,smb_vwv2);
+               poff = SVAL(inbuf,smb_vwv3);
+               pdisp = SVAL(inbuf,smb_vwv4);
+               
+               dcnt = SVAL(inbuf,smb_vwv5);
+               doff = SVAL(inbuf,smb_vwv6);
+               ddisp = SVAL(inbuf,smb_vwv7);
+               
+               pscnt += pcnt;
+               dscnt += dcnt;
+               
+               if (dscnt > tdscnt || pscnt > tpscnt) {
+                       exit_server("invalid trans parameters\n");
+               }
+               
+               if (pcnt)
+                       memcpy(params+pdisp,smb_base(inbuf)+poff,pcnt);
+               if (dcnt)
+                       memcpy(data+ddisp,smb_base(inbuf)+doff,dcnt);      
+       }
+       
+       
+       DEBUG(3,("trans <%s> data=%d params=%d setup=%d\n",
+                name,tdscnt,tpscnt,suwcnt));
+       
+        /*
+         * WinCE wierdness....
+         */
+
+        if (name[0] == '\\' && (StrnCaseCmp(&name[1],local_machine,
+                                strlen(local_machine)) == 0)) {
+          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+name_offset+strlen("\\PIPE\\"),setup,data,params,
+                                    suwcnt,tdscnt,tpscnt,msrcnt,mdrcnt,mprcnt);
+       } else {
+               DEBUG(3,("invalid pipe name\n"));
+               outsize = 0;
+       }
 
-  if (one_way)
-    return(-1);
-  
-  if (outsize == 0)
-    return(ERROR(ERRSRV,ERRnosupport));
+       
+       if (data) free(data);
+       if (params) free(params);
+       if (setup) free(setup);
+       
+       if (close_on_completion)
+               close_cnum(conn,vuid);
 
-  return(outsize);
+       if (one_way)
+               return(-1);
+       
+       if (outsize == 0)
+               return(ERROR(ERRSRV,ERRnosupport));
+       
+       return(outsize);
 }