ipc.c: Changed reply_trans to use receive_next_smb() to cope
[tprouty/samba.git] / source / smbd / ipc.c
index 0a54936cd022d867ab161534988c1fcc3171ec90..c862ff3b3895e842d0c039280961f04cf703ed9d 100644 (file)
@@ -2,7 +2,10 @@
    Unix SMB/Netbios implementation.
    Version 1.9.
    Inter-process communication and named pipe handling
-   Copyright (C) Andrew Tridgell 1992-1995
+   Copyright (C) Andrew Tridgell 1992-1997
+
+   SMB Version handling
+   Copyright (C) John H Terpstra 1995-1997
    
    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
 #define CHECK_TYPES 0
 
 extern int DEBUGLEVEL;
-extern int maxxmit;
+extern int max_send;
 extern files_struct Files[];
 extern connection_struct Connections[];
 
 extern fstring local_machine;
+extern fstring myworkgroup;
 
 #define NERR_Success 0
 #define NERR_badpass 86
@@ -48,8 +52,6 @@ extern fstring local_machine;
 #define ERROR_INVALID_LEVEL 124
 #define ERROR_MORE_DATA 234
 
-#define REALLOC(ptr,size) Realloc(ptr,MAX((size),4*1024))
-
 #define ACCESS_READ 0x01
 #define ACCESS_WRITE 0x02
 #define ACCESS_CREATE 0x04
@@ -59,10 +61,19 @@ extern fstring local_machine;
 #define SNLEN 15               /* service name length */
 #define QNLEN 12               /* queue name maximum length */
 
-#define MAJOR_VERSION 2
-#define MINOR_VERSION 0
-
 extern int Client;
+extern int oplock_sock;
+extern int smb_read_error;
+
+static BOOL api_Unsupported(int cnum,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,
+                        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)
 {
@@ -132,10 +143,15 @@ static void send_trans_reply(char *outbuf,char *data,char *param,uint16 *setup,
   int tot_data=0,tot_param=0;
   int align;
 
-  this_lparam = MIN(lparam,maxxmit - (500+lsetup*SIZEOFWORD)); /* hack */
-  this_ldata = MIN(ldata,maxxmit - (500+lsetup*SIZEOFWORD+this_lparam));
+  this_lparam = MIN(lparam,max_send - (500+lsetup*SIZEOFWORD)); /* hack */
+  this_ldata = MIN(ldata,max_send - (500+lsetup*SIZEOFWORD+this_lparam));
 
+#ifdef CONFUSE_NETMONITOR_MSRPC_DECODING
+  /* if you don't want Net Monitor to decode your packets, do this!!! */
+  align = ((this_lparam+1)%4);
+#else
   align = (this_lparam%4);
+#endif
 
   set_message(outbuf,10+lsetup,align+this_ldata+this_lparam,True);
   if (this_lparam)
@@ -163,8 +179,8 @@ static void send_trans_reply(char *outbuf,char *data,char *param,uint16 *setup,
 
   while (tot_data < ldata || tot_param < lparam)
     {
-      this_lparam = MIN(lparam-tot_param,maxxmit - 500); /* hack */
-      this_ldata = MIN(ldata-tot_data,maxxmit - (500+this_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);
 
@@ -429,7 +445,7 @@ static void PackDriverData(struct pack_desc* desc)
 }
 
 static int check_printq_info(struct pack_desc* desc,
-                            int uLevel, const char* id1, const char* id2)
+                            int uLevel, char *id1, char *id2)
 {
   desc->subformat = NULL;
   switch( uLevel ) {
@@ -453,6 +469,10 @@ static int check_printq_info(struct pack_desc* desc,
   case 5:
     desc->format = "z";
     break;
+  case 52:
+    desc->format = "WzzzzzzzzN";
+    desc->subformat = "z";
+    break;
   default: return False;
   }
   if (strcmp(desc->format,id1) != 0) return False;
@@ -469,7 +489,7 @@ static void fill_printjob_info(int cnum, int snum, int uLevel,
   /* the client expects localtime */
   t -= TimeDiff(t);
 
-  PACKI(desc,"W",((snum%0xFF)<<8) | (queue->job%0xFF)); /* uJobId */
+  PACKI(desc,"W",printjob_encode(snum, queue->job)); /* uJobId */
   if (uLevel == 1) {
     PACKS(desc,"B21",queue->user); /* szUserName */
     PACKS(desc,"B","");                /* pad */
@@ -512,11 +532,18 @@ static void fill_printq_info(int cnum, int snum, int uLevel,
                             int count, print_queue_struct* queue,
                             print_status_struct* status)
 {
-  if (uLevel < 3) {
-    PACKS(desc,"B13",SERVICE(snum));
-  } else {
-    PACKS(desc,"z",Expand(cnum,snum,SERVICE(snum)));
+  switch (uLevel) {
+    case 1:
+    case 2:
+      PACKS(desc,"B13",SERVICE(snum));
+      break;
+    case 3:
+    case 4:
+    case 5:
+      PACKS(desc,"z",Expand(cnum,snum,SERVICE(snum)));
+      break;
   }
+
   if (uLevel == 1 || uLevel == 2) {
     PACKS(desc,"B","");                /* alignment */
     PACKI(desc,"W",5);         /* priority */
@@ -564,11 +591,120 @@ static void fill_printq_info(int cnum, int snum, int uLevel,
     for (i=0;i<count;i++)
       fill_printjob_info(cnum,snum,uLevel == 2 ? 1 : 2,desc,&queue[i],i);
   }
+
+  if (uLevel==52) {
+    int i,ok=0;
+    pstring tok,driver,short_name;
+    char *p,*q;
+    FILE *f;
+    pstring fname;
+
+    strcpy(fname,lp_driverfile());
+
+    f=fopen(fname,"r");
+    if (!f) {
+      DEBUG(0,("fill_printq_info: Can't open %s - %s\n",fname,strerror(errno)));
+    }
+
+    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)
+    {
+      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;
+    }
+
+    fclose(f);
+
+    next_token(&p,short_name,":");
+    next_token(&p,driver,":");
+
+    PACKI(desc,"W",0x0400);                      /* don't know */
+    PACKS(desc,"z",lp_printerdriver(snum));        /* long printer name */
+
+    if (ok)
+    {
+      PACKS(desc,"z",driver);                    /* Driver Name */
+      PACKS(desc,"z",short_name);                /* short printer name */
+      DEBUG(3,("Driver:%s:\n",driver));
+      DEBUG(3,("short name:%s:\n",short_name));
+    }
+    else 
+    {
+      PACKS(desc,"z","");
+      PACKS(desc,"z","");
+    }
+
+    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));
+    }
+    free(q);
+  }
+
   DEBUG(3,("fill_printq_info on <%s> gave %d entries\n",SERVICE(snum),count));
 }
 
-static BOOL api_DosPrintQGetInfo(int cnum,int uid, char *param,char *data,
+/* This function returns the number of file for a given driver */
+int get_printerdrivernumber(int snum)
+{
+  int i=0,ok=0;
+  pstring tok;
+  char *p,*q;
+  FILE *f;
+  pstring fname;
+
+  strcpy(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)));
+    return(0);
+  }
+
+  p=(char *)malloc(8192*sizeof(char));
+  q=p; /* need it to free memory because p change ! */
+
+  /* lookup the long printer driver name in the file description */
+  while (!feof(f) && !ok)
+  {
+    fgets(p,8191,f);
+    next_token(&p,tok,":");
+    if(!strncmp(tok,lp_printerdriver(snum),strlen(lp_printerdriver(snum)))) ok=1;
+  }
+
+  if (ok) {
+    /* skip 2 fields */
+    next_token(&p,tok,":");  /* short name */
+    next_token(&p,tok,":");  /* driver name */
+    /* count the number of files */
+    while (next_token(&p,tok,","))
+       i++;
+  }
+  fclose(f);
+  free(q);
+
+  return(i);
+}
+
+static BOOL api_DosPrintQGetInfo(int cnum,uint16 vuid, char *param,char *data,
                                 int mdrcnt,int mprcnt,
                                 char **rdata,char **rparam,
                                 int *rdata_len,int *rparam_len)
@@ -613,7 +749,14 @@ static BOOL api_DosPrintQGetInfo(int cnum,int uid, char *param,char *data,
   
   if (snum < 0 || !VALID_SNUM(snum)) return(False);
 
-  count = get_printqueue(snum,cnum,&queue,&status);
+  if (uLevel==52)
+  {
+    count = get_printerdrivernumber(snum);
+    DEBUG(3,("api_DosPrintQGetInfo: Driver files count: %d\n",count));
+  }
+  else
+    count = get_printqueue(snum,cnum,&queue,&status);
+
   if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
   desc.base = *rdata;
   desc.buflen = mdrcnt;
@@ -641,7 +784,7 @@ static BOOL api_DosPrintQGetInfo(int cnum,int uid, char *param,char *data,
 /****************************************************************************
   view list of all print jobs on all queues
   ****************************************************************************/
-static BOOL api_DosPrintQEnum(int cnum, int uid, char* param, char* data,
+static BOOL api_DosPrintQEnum(int cnum, uint16 vuid, char* param, char* data,
                              int mdrcnt, int mprcnt,
                              char **rdata, char** rparam,
                              int *rdata_len, int *rparam_len)
@@ -663,7 +806,7 @@ static BOOL api_DosPrintQEnum(int cnum, int uid, char* param, char* data,
 
   DEBUG(3,("DosPrintQEnum uLevel=%d\n",uLevel));
  
-  if (prefix_ok(param_format,"WrLeh")) return False;
+  if (!prefix_ok(param_format,"WrLeh")) return False;
   if (!check_printq_info(&desc,uLevel,output_format1,output_format2))
     return False;
   queuecnt = 0;
@@ -738,78 +881,22 @@ static BOOL check_server_info(int uLevel, char* id)
   return True;
 }
 
-/* used for server information: client, nameserv and ipc */
 struct srv_info_struct
 {
   fstring name;
   uint32 type;
   fstring comment;
-  fstring domain; /* used ONLY in ipc.c NOT namework.c */
-  BOOL server_added; /* used ONLY in ipc.c NOT namework.c */
+  fstring domain;
+  BOOL server_added;
 };
 
-/*******************************************************************
-  filter out unwanted server info 
-  ******************************************************************/
-static BOOL filter_server_info(struct srv_info_struct *server, 
-                              BOOL domains,
-                              char *domain, uint32 request)
-{
-  if (*domain == 0)
-    {
-      if (strequal(lp_workgroup(), server->domain)) {
-       return True;
-      }
-      else if (domains)
-       {
-         DEBUG(4,("primary domain:reject %8x %s %s\n",request,server->name,server->domain));
-         return False;
-       }
-      else if ((request & SV_TYPE_DOMAIN_ENUM) &&
-              (server->type & SV_TYPE_DOMAIN_ENUM))
-       {
-         DEBUG(4,("rej:DOM %8x: %s %s\n",server->type,server->name,server->domain));
-         return False;
-       }
-      
-      return True;
-    }
-  else
-    {
-      if (strequal(domain, server->domain))
-       {
-         /*
-           if (request     == SV_TYPE_LOCAL_LIST_ONLY &&
-           !(server->type & SV_TYPE_LOCAL_LIST_ONLY))
-           {
-           DEBUG(4,("rej:LOC %8x: ok %s %s\n",request,server->name,server->domain));
-           return False;
-           }
-           */
-         if ((request == (SV_TYPE_LOCAL_LIST_ONLY|SV_TYPE_DOMAIN_ENUM)) &&
-                               !(server->type&SV_TYPE_DOMAIN_ENUM))
-           {
-             DEBUG(4,("rej:LOCDOM %8x: ok %s %s\n",request,server->name,server->domain));
-             return False;
-           }
-         
-         return True;
-       }
-      else if (!domains)
-       {
-         DEBUG(4,("domain:%s %s %s\n",domain,server->name,server->domain));
-         return False;
-       }
-      return True;
-    }
-}
 
 /*******************************************************************
   get server info lists from the files saved by nmbd. Return the
   number of entries
   ******************************************************************/
 static int get_server_info(uint32 servertype, 
-                          struct srv_info_struct **servers, BOOL domains, 
+                          struct srv_info_struct **servers,
                           char *domain)
 {
   FILE *f;
@@ -817,8 +904,9 @@ static int get_server_info(uint32 servertype,
   int count=0;
   int alloced=0;
   pstring line;
+  BOOL local_list_only;
 
-  strcpy(fname,lp_lockdir());
+  pstrcpy(fname,lp_lockdir());
   trim_string(fname,NULL,"/");
   strcat(fname,"/");
   strcat(fname,SERVER_LIST);
@@ -831,9 +919,12 @@ static int get_server_info(uint32 servertype,
   }
 
   /* request for everything is code for request all servers */
-  if (servertype == SV_TYPE_ALL) servertype &= ~SV_TYPE_DOMAIN_ENUM;
+  if (servertype == SV_TYPE_ALL) 
+       servertype &= ~(SV_TYPE_DOMAIN_ENUM|SV_TYPE_LOCAL_LIST_ONLY);
 
-  DEBUG(4,("Servertype search: %8x domains:%s\n",servertype,BOOLSTR(domains)));
+  local_list_only = (servertype & SV_TYPE_LOCAL_LIST_ONLY);
+
+  DEBUG(4,("Servertype search: %8x\n",servertype));
 
   while (!feof(f))
   {
@@ -860,7 +951,7 @@ static int get_server_info(uint32 servertype,
     if (!next_token(&ptr,s->comment, NULL)) continue;
     if (!next_token(&ptr,s->domain , NULL)) {
       /* this allows us to cope with an old nmbd */
-      strcpy(s->domain,my_workgroup()); 
+      strcpy(s->domain,myworkgroup); 
     }
     
     if (sscanf(stype,"%X",&s->type) != 1) { 
@@ -868,34 +959,40 @@ static int get_server_info(uint32 servertype,
       ok = False; 
     }
     
+       /* Filter the servers/domains we return based on what was asked for. */
+
+       /* Check to see if we are being asked for a local list only. */
+       if(local_list_only && ((s->type & SV_TYPE_LOCAL_LIST_ONLY) == 0)) {
+         DEBUG(4,("r: local list only"));
+         ok = False;
+       }
+
     /* doesn't match up: don't want it */
     if (!(servertype & s->type)) { 
       DEBUG(4,("r:serv type ")); 
       ok = False; 
     }
     
-    if ((servertype == ~SV_TYPE_DOMAIN_ENUM) &&
+    if ((servertype & SV_TYPE_DOMAIN_ENUM) != 
        (s->type & SV_TYPE_DOMAIN_ENUM))
       {
-       DEBUG(4,("s:all x dom  "));
+       DEBUG(4,("s: dom mismatch "));
        ok = False;
       }
     
-    if (domains && !(domain && *domain && strequal(domain, s->domain)))
+    if (!strequal(domain, s->domain) && !(servertype & SV_TYPE_DOMAIN_ENUM))
       {
-       if (!(s->type & SV_TYPE_DOMAIN_ENUM))
-         {
-           DEBUG(4,("r:dom enum  "));
-           ok = False;
-         }
+       ok = False;
       }
     
+       /* We should never return a server type with a SV_TYPE_LOCAL_LIST_ONLY set. */
+       s->type &= ~SV_TYPE_LOCAL_LIST_ONLY;
+
     if (ok)
       {
        DEBUG(4,("**SV** %20s %8x %25s %15s\n",
                 s->name, s->type, s->comment, s->domain));
        
-       s->type |= SV_TYPE_LOCAL_LIST_ONLY;
        s->server_added = True;
        count++;
       }
@@ -999,7 +1096,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, int uid, char *param, char *data,
+static BOOL api_RNetServerEnum(int cnum, uint16 vuid, char *param, char *data,
                               int mdrcnt, int mprcnt, char **rdata, 
                               char **rparam, int *rdata_len, int *rparam_len)
 {
@@ -1014,18 +1111,30 @@ static BOOL api_RNetServerEnum(int cnum, int uid, char *param, char *data,
   int f_len, s_len;
   struct srv_info_struct *servers=NULL;
   int counted=0,total=0;
-  int i;
+  int i,missed;
   fstring domain;
-  BOOL domains;
   BOOL domain_request;
-  BOOL local_request = servertype & SV_TYPE_LOCAL_LIST_ONLY;
+  BOOL local_request;
+
+  /* If someone sets all the bits they don't really mean to set
+     DOMAIN_ENUM and LOCAL_LIST_ONLY, they just want all the
+     known servers. */
+
+  if (servertype == SV_TYPE_ALL) 
+    servertype &= ~(SV_TYPE_DOMAIN_ENUM|SV_TYPE_LOCAL_LIST_ONLY);
+
+  /* If someone sets SV_TYPE_LOCAL_LIST_ONLY but hasn't set
+     any other bit (they may just set this bit on it's own) they 
+     want all the locally seen servers. However this bit can be 
+     set on its own so set the requested servers to be 
+     ALL - DOMAIN_ENUM. */
 
-  /*if (servertype == SV_TYPE_ALL) servertype &= ~(SV_TYPE_DOMAIN_ENUM|SV_TYPE_LOCAL_LIST_ONLY);*/
-  if (servertype == SV_TYPE_ALL) servertype &= ~SV_TYPE_DOMAIN_ENUM;
+  if ((servertype & SV_TYPE_LOCAL_LIST_ONLY) && !(servertype & SV_TYPE_DOMAIN_ENUM)) 
+    servertype = SV_TYPE_ALL & ~(SV_TYPE_DOMAIN_ENUM);
 
-  domain_request = servertype & SV_TYPE_DOMAIN_ENUM;
+  domain_request = ((servertype & SV_TYPE_DOMAIN_ENUM) != 0);
+  local_request = ((servertype & SV_TYPE_LOCAL_LIST_ONLY) != 0);
 
-  domain[0] = 0;
   p += 8;
 
   if (!prefix_ok(str1,"WrLehD")) return False;
@@ -1035,22 +1144,17 @@ static BOOL api_RNetServerEnum(int cnum, int uid, char *param, char *data,
   DEBUG(4, ("domains_req:%s ", BOOLSTR(domain_request)));
   DEBUG(4, ("local_only:%s\n", BOOLSTR(local_request)));
 
-  if (strcmp(str1, "WrLehDO") == 0)
-  {
-       domains = False;
-  }
-  else if (strcmp(str1, "WrLehDz") == 0)
-  {
-       domains = True;
+  if (strcmp(str1, "WrLehDz") == 0) {
     StrnCpy(domain, p, sizeof(fstring)-1);
+  } else {
+    StrnCpy(domain, myworkgroup, sizeof(fstring)-1);    
   }
 
   if (lp_browse_list())
-  {
-    total = get_server_info(servertype,&servers,domains,domain);
-  }
+    total = get_server_info(servertype,&servers,domain);
 
   data_len = fixed_len = string_len = 0;
+  missed = 0;
 
   qsort(servers,total,sizeof(servers[0]),QSORT_CAST srv_comp);
 
@@ -1060,22 +1164,19 @@ static BOOL api_RNetServerEnum(int cnum, int uid, char *param, char *data,
     for (i=0;i<total;i++)
     {
       struct srv_info_struct *s = &servers[i];
-      if (filter_server_info(s,domains,domain,
-                            local_request|domain_request))
-       {
-         if (lastname && strequal(lastname,s->name)) continue;
-         lastname = s->name;
-         data_len += fill_srv_info(s,uLevel,0,&f_len,0,&s_len,0);
-         DEBUG(4,("fill_srv_info %20s %8x %25s %15s\n",
-                  s->name, s->type, s->comment, s->domain));
-         
-         if (data_len <= buf_len)
-           {
-             counted++;
-             fixed_len += f_len;
-             string_len += s_len;
-           }
-       }
+      if (lastname && strequal(lastname,s->name)) continue;
+      lastname = s->name;
+      data_len += fill_srv_info(s,uLevel,0,&f_len,0,&s_len,0);
+      DEBUG(4,("fill_srv_info %20s %8x %25s %15s\n",
+              s->name, s->type, s->comment, s->domain));
+      
+      if (data_len <= buf_len) {
+         counted++;
+         fixed_len += f_len;
+         string_len += s_len;
+      } else {
+       missed++;
+      }
     }
   }
 
@@ -1094,29 +1195,26 @@ static BOOL api_RNetServerEnum(int cnum, int uid, char *param, char *data,
     for (i = 0; i < total && count2;i++)
       {
        struct srv_info_struct *s = &servers[i];
-       if (filter_server_info(s,domains,domain,local_request|domain_request))
-         {
-           if (lastname && strequal(lastname,s->name)) continue;
-           lastname = s->name;
-           fill_srv_info(s,uLevel,&p,&f_len,&p2,&s_len,*rdata);
-           DEBUG(4,("fill_srv_info %20s %8x %25s %15s\n",
-                    s->name, s->type, s->comment, s->domain));
-           count2--;
-         }
+       if (lastname && strequal(lastname,s->name)) continue;
+       lastname = s->name;
+       fill_srv_info(s,uLevel,&p,&f_len,&p2,&s_len,*rdata);
+       DEBUG(4,("fill_srv_info %20s %8x %25s %15s\n",
+                s->name, s->type, s->comment, s->domain));
+       count2--;
       }
   }
   
   *rparam_len = 8;
   *rparam = REALLOC(*rparam,*rparam_len);
-  SSVAL(*rparam,0,NERR_Success);
+  SSVAL(*rparam,0,(missed == 0 ? NERR_Success : ERROR_MORE_DATA));
   SSVAL(*rparam,2,0);
   SSVAL(*rparam,4,counted);
-  SSVAL(*rparam,6,total);
+  SSVAL(*rparam,6,counted+missed);
 
   if (servers) free(servers);
 
   DEBUG(3,("NetServerEnum domain = %s uLevel=%d counted=%d total=%d\n",
-          domain,uLevel,counted,total));
+          domain,uLevel,counted,counted+missed));
 
   return(True);
 }
@@ -1240,7 +1338,7 @@ static int fill_share_info(int cnum, int snum, int uLevel,
   return len;
 }
 
-static BOOL api_RNetShareGetInfo(int cnum,int uid, char *param,char *data,
+static BOOL api_RNetShareGetInfo(int cnum,uint16 vuid, char *param,char *data,
                                 int mdrcnt,int mprcnt,
                                 char **rdata,char **rparam,
                                 int *rdata_len,int *rparam_len)
@@ -1275,7 +1373,7 @@ static BOOL api_RNetShareGetInfo(int cnum,int uid, char *param,char *data,
 /****************************************************************************
   view list of shares available
   ****************************************************************************/
-static BOOL api_RNetShareEnum(int cnum,int uid, char *param,char *data,
+static BOOL api_RNetShareEnum(int cnum,uint16 vuid, char *param,char *data,
                              int mdrcnt,int mprcnt,
                              char **rdata,char **rparam,
                              int *rdata_len,int *rparam_len)
@@ -1339,7 +1437,7 @@ static BOOL api_RNetShareEnum(int cnum,int uid, char *param,char *data,
 /****************************************************************************
   get the time of day info
   ****************************************************************************/
-static BOOL api_NetRemoteTOD(int cnum,int uid, char *param,char *data,
+static BOOL api_NetRemoteTOD(int cnum,uint16 vuid, char *param,char *data,
                             int mdrcnt,int mprcnt,
                             char **rdata,char **rparam,
                             int *rdata_len,int *rparam_len)
@@ -1388,7 +1486,7 @@ static BOOL api_NetRemoteTOD(int cnum,int uid, char *param,char *data,
 /****************************************************************************
   set the user password
   ****************************************************************************/
-static BOOL api_SetUserPassword(int cnum,int uid, char *param,char *data,
+static BOOL api_SetUserPassword(int cnum,uint16 vuid, char *param,char *data,
                                int mdrcnt,int mprcnt,
                                char **rdata,char **rparam,
                                int *rdata_len,int *rparam_len)
@@ -1397,7 +1495,7 @@ static BOOL api_SetUserPassword(int cnum,int uid, char *param,char *data,
   fstring user;
   fstring pass1,pass2;
 
-  strcpy(user,p);
+  fstrcpy(user,p);
 
   p = skip_string(p,1);
 
@@ -1414,7 +1512,7 @@ static BOOL api_SetUserPassword(int cnum,int uid, char *param,char *data,
 
   DEBUG(3,("Set password for <%s>\n",user));
 
-  if (password_ok(user,pass1,strlen(pass1),NULL,False) &&
+  if (password_ok(user,pass1,strlen(pass1),NULL) &&
       chgpasswd(user,pass1,pass2))
   {
     SSVAL(*rparam,0,NERR_Success);
@@ -1430,7 +1528,7 @@ static BOOL api_SetUserPassword(int cnum,int uid, char *param,char *data,
   delete a print job
   Form: <W> <> 
   ****************************************************************************/
-static BOOL api_RDosPrintJobDel(int cnum,int uid, char *param,char *data,
+static BOOL api_RDosPrintJobDel(int cnum,uint16 vuid, char *param,char *data,
                                int mdrcnt,int mprcnt,
                                char **rdata,char **rparam,
                                int *rdata_len,int *rparam_len)
@@ -1439,11 +1537,10 @@ static BOOL api_RDosPrintJobDel(int cnum,int uid, char *param,char *data,
   char *str1 = param+2;
   char *str2 = skip_string(str1,1);
   char *p = skip_string(str2,1);
-  int jobid = (SVAL(p,0)&0xFF); /* the snum and jobid are encoded
-                                  by the print queue api */
-  int snum = (SVAL(p,0)>>8);  
+  int jobid, snum;
   int i, count;
 
+  printjob_decode(SVAL(p,0), &snum, &jobid);
 
   /* check it's a supported varient */
   if (!(strcsequal(str1,"W") && strcsequal(str2,"")))
@@ -1463,7 +1560,7 @@ static BOOL api_RDosPrintJobDel(int cnum,int uid, char *param,char *data,
       count = get_printqueue(snum,cnum,&queue,NULL);
   
       for (i=0;i<count;i++)
-       if ((queue[i].job%0xFF) == jobid)
+       if ((queue[i].job&0xFF) == jobid)
          {
            switch (function) {
            case 81:            /* delete */ 
@@ -1492,7 +1589,7 @@ static BOOL api_RDosPrintJobDel(int cnum,int uid, char *param,char *data,
   return(True);
 }
 
-static BOOL api_WPrintQueuePurge(int cnum,int uid, char *param,char *data,
+static BOOL api_WPrintQueuePurge(int cnum,uint16 vuid, char *param,char *data,
                                 int mdrcnt,int mprcnt,
                                 char **rdata,char **rparam,
                                 int *rdata_len,int *rparam_len)
@@ -1563,7 +1660,7 @@ static int check_printjob_info(struct pack_desc* desc,
   return True;
 }
 
-static BOOL api_PrintJobInfo(int cnum,int uid,char *param,char *data,
+static BOOL api_PrintJobInfo(int cnum,uint16 vuid,char *param,char *data,
                             int mdrcnt,int mprcnt,
                             char **rdata,char **rparam,
                             int *rdata_len,int *rparam_len)
@@ -1572,13 +1669,13 @@ static BOOL api_PrintJobInfo(int cnum,int uid,char *param,char *data,
   char *str1 = param+2;
   char *str2 = skip_string(str1,1);
   char *p = skip_string(str2,1);
-  int jobid = (SVAL(p,0)&0xFF); /* the snum and jobid are encoded
-                                  by the print queue api */
-  int snum = (SVAL(p,0)>>8);
+  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);
    
   *rparam_len = 4;
   *rparam = REALLOC(*rparam,*rparam_len);
@@ -1599,7 +1696,7 @@ static BOOL api_PrintJobInfo(int cnum,int uid,char *param,char *data,
        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;
+         if ((queue[i].job&0xFF) == jobid) break;
            
        if (i==count) {
          desc.errcode=NERR_JobNotFound;
@@ -1637,21 +1734,26 @@ static BOOL api_PrintJobInfo(int cnum,int uid,char *param,char *data,
        
        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();
              
-             if (!become_user(Files[i].cnum,uid) || 
-                 !become_service(Files[i].cnum,True))
+             if (!become_user(&Connections[fcnum], fcnum,vuid) || 
+                 !become_service(fcnum,True))
                break;
              
              if (sys_rename(Files[i].name,name) == 0)
                string_set(&Files[i].name,name);
              break;
            }
+
+         unbecome_root(True);
       }
     desc.errcode=NERR_Success;
   
@@ -1670,7 +1772,7 @@ static BOOL api_PrintJobInfo(int cnum,int uid,char *param,char *data,
 /****************************************************************************
   get info about the server
   ****************************************************************************/
-static BOOL api_RNetServerGetInfo(int cnum,int uid, char *param,char *data,
+static BOOL api_RNetServerGetInfo(int cnum,uint16 vuid, char *param,char *data,
                                  int mdrcnt,int mprcnt,
                                  char **rdata,char **rparam,
                                  int *rdata_len,int *rparam_len)
@@ -1731,22 +1833,22 @@ static BOOL api_RNetServerGetInfo(int cnum,int uid, char *param,char *data,
       struct srv_info_struct *servers=NULL;
       int i,count;
       pstring comment;
-      uint32 servertype=SV_TYPE_SERVER_UNIX|SV_TYPE_WORKSTATION|
-       SV_TYPE_SERVER|SV_TYPE_TIME_SOURCE;
+      uint32 servertype= lp_default_server_announce();
 
-      strcpy(comment,lp_serverstring());
+      pstrcpy(comment,lp_serverstring());
 
-      if ((count=get_server_info(SV_TYPE_ALL,&servers,False,NULL))>0) {
+      if ((count=get_server_info(SV_TYPE_ALL,&servers,myworkgroup))>0) {
        for (i=0;i<count;i++)
-         if (strequal(servers[i].name,local_machine)) {
+         if (strequal(servers[i].name,local_machine))
+      {
            servertype = servers[i].type;
-           strcpy(comment,servers[i].comment);     
+           pstrcpy(comment,servers[i].comment);            
          }
       }
       if (servers) free(servers);
 
-      SCVAL(p,0,MAJOR_VERSION);
-      SCVAL(p,1,MINOR_VERSION);
+      SCVAL(p,0,lp_major_announce_version());
+      SCVAL(p,1,lp_minor_announce_version());
       SIVAL(p,2,servertype);
 
       if (mdrcnt == struct_len) {
@@ -1778,7 +1880,7 @@ static BOOL api_RNetServerGetInfo(int cnum,int uid, char *param,char *data,
 /****************************************************************************
   get info about the server
   ****************************************************************************/
-static BOOL api_NetWkstaGetInfo(int cnum,int uid, char *param,char *data,
+static BOOL api_NetWkstaGetInfo(int cnum,uint16 vuid, char *param,char *data,
                                int mdrcnt,int mprcnt,
                                char **rdata,char **rparam,
                                int *rdata_len,int *rparam_len)
@@ -1808,8 +1910,10 @@ static BOOL api_NetWkstaGetInfo(int cnum,int uid, char *param,char *data,
   p = *rdata;
   p2 = p + 22;
 
-  SIVAL(p,0,PTR_DIFF(p2,*rdata));
+
+  SIVAL(p,0,PTR_DIFF(p2,*rdata)); /* host name */
   strcpy(p2,local_machine);
+  strupper(p2);
   p2 = skip_string(p2,1);
   p += 4;
 
@@ -1818,21 +1922,22 @@ static BOOL api_NetWkstaGetInfo(int cnum,int uid, char *param,char *data,
   p2 = skip_string(p2,1);
   p += 4;
 
-  SIVAL(p,0,PTR_DIFF(p2,*rdata));
-  strcpy(p2,my_workgroup());
+  SIVAL(p,0,PTR_DIFF(p2,*rdata)); /* login domain */
+  strcpy(p2,myworkgroup);
+  strupper(p2);
   p2 = skip_string(p2,1);
   p += 4;
 
-  SCVAL(p,0,MAJOR_VERSION); 
-  SCVAL(p,1,MINOR_VERSION); 
+  SCVAL(p,0,lp_major_announce_version()); /* system version - e.g 4 in 4.1 */
+  SCVAL(p,1,lp_minor_announce_version()); /* system version - e.g .1 in 4.1 */
   p += 2;
 
   SIVAL(p,0,PTR_DIFF(p2,*rdata));
-  strcpy(p2,my_workgroup());   /* login domain?? */
+  strcpy(p2,myworkgroup);      /* don't know.  login domain?? */
   p2 = skip_string(p2,1);
   p += 4;
 
-  SIVAL(p,0,PTR_DIFF(p2,*rdata));
+  SIVAL(p,0,PTR_DIFF(p2,*rdata)); /* don't know */
   strcpy(p2,"");
   p2 = skip_string(p2,1);
   p += 4;
@@ -1844,154 +1949,331 @@ static BOOL api_NetWkstaGetInfo(int cnum,int uid, char *param,char *data,
   return(True);
 }
 
-
 /****************************************************************************
   get info about a user
+
+    struct user_info_11 {
+        char                usri11_name[21];  0-20 
+        char                usri11_pad;       21 
+        char                *usri11_comment;  22-25 
+        char            *usri11_usr_comment;  26-29
+        unsigned short      usri11_priv;      30-31
+        unsigned long       usri11_auth_flags; 32-35
+        long                usri11_password_age; 36-39
+        char                *usri11_homedir; 40-43
+        char            *usri11_parms; 44-47
+        long                usri11_last_logon; 48-51
+        long                usri11_last_logoff; 52-55
+        unsigned short      usri11_bad_pw_count; 56-57
+        unsigned short      usri11_num_logons; 58-59
+        char                *usri11_logon_server; 60-63
+        unsigned short      usri11_country_code; 64-65
+        char            *usri11_workstations; 66-69
+        unsigned long       usri11_max_storage; 70-73
+        unsigned short      usri11_units_per_week; 74-75
+        unsigned char       *usri11_logon_hours; 76-79
+        unsigned short      usri11_code_page; 80-81
+    };
+
+where:
+
+  usri11_name specifies the user name for which information is retireved
+
+  usri11_pad aligns the next data structure element to a word boundary
+
+  usri11_comment is a null terminated ASCII comment
+
+  usri11_user_comment is a null terminated ASCII comment about the user
+
+  usri11_priv specifies the level of the privilege assigned to the user.
+       The possible values are:
+
+Name             Value  Description
+USER_PRIV_GUEST  0      Guest privilege
+USER_PRIV_USER   1      User privilege
+USER_PRV_ADMIN   2      Administrator privilege
+
+  usri11_auth_flags specifies the account operator privileges. The
+       possible values are:
+
+Name            Value   Description
+AF_OP_PRINT     0       Print operator
+
+
+Leach, Naik                                        [Page 28]\r\f
+
+
+INTERNET-DRAFT   CIFS Remote Admin Protocol     January 10, 1997
+
+
+AF_OP_COMM      1       Communications operator
+AF_OP_SERVER    2       Server operator
+AF_OP_ACCOUNTS  3       Accounts operator
+
+
+  usri11_password_age specifies how many seconds have elapsed since the
+       password was last changed.
+
+  usri11_home_dir points to a null terminated ASCII string that contains
+       the path name of the user's home directory.
+
+  usri11_parms points to a null terminated ASCII string that is set
+       aside for use by applications.
+
+  usri11_last_logon specifies the time when the user last logged on.
+       This value is stored as the number of seconds elapsed since
+       00:00:00, January 1, 1970.
+
+  usri11_last_logoff specifies the time when the user last logged off.
+       This value is stored as the number of seconds elapsed since
+       00:00:00, January 1, 1970. A value of 0 means the last logoff
+       time is unknown.
+
+  usri11_bad_pw_count specifies the number of incorrect passwords
+       entered since the last successful logon.
+
+  usri11_log1_num_logons specifies the number of times this user has
+       logged on. A value of -1 means the number of logons is unknown.
+
+  usri11_logon_server points to a null terminated ASCII string that
+       contains the name of the server to which logon requests are sent.
+       A null string indicates logon requests should be sent to the
+       domain controller.
+
+  usri11_country_code specifies the country code for the user's language
+       of choice.
+
+  usri11_workstations points to a null terminated ASCII string that
+       contains the names of workstations the user may log on from.
+       There may be up to 8 workstations, with the names separated by
+       commas. A null strings indicates there are no restrictions.
+
+  usri11_max_storage specifies the maximum amount of disk space the user
+       can occupy. A value of 0xffffffff indicates there are no
+       restrictions.
+
+  usri11_units_per_week specifies the equal number of time units into
+       which a week is divided. This value must be equal to 168.
+
+  usri11_logon_hours points to a 21 byte (168 bits) string that
+       specifies the time during which the user can log on. Each bit
+       represents one unique hour in a week. The first bit (bit 0, word
+       0) is Sunday, 0:00 to 0:59, the second bit (bit 1, word 0) is
+
+
+
+Leach, Naik                                        [Page 29]\r\f
+
+
+INTERNET-DRAFT   CIFS Remote Admin Protocol     January 10, 1997
+
+
+       Sunday, 1:00 to 1:59 and so on. A null pointer indicates there
+       are no restrictions.
+
+  usri11_code_page specifies the code page for the user's language of
+       choice
+
+All of the pointers in this data structure need to be treated
+specially. The  pointer is a 32 bit pointer. The higher 16 bits need
+to be ignored. The converter word returned in the parameters section
+needs to be subtracted from the lower 16 bits to calculate an offset
+into the return buffer where this ASCII string resides.
+
+There is no auxiliary data in the response.
+
   ****************************************************************************/
 
+#define usri11_name           0 
+#define usri11_pad            21
+#define usri11_comment        22
+#define usri11_usr_comment    26
+#define usri11_full_name      30
+#define usri11_priv           34
+#define usri11_auth_flags     36
+#define usri11_password_age   40
+#define usri11_homedir        44
+#define usri11_parms          48
+#define usri11_last_logon     52
+#define usri11_last_logoff    56
+#define usri11_bad_pw_count   60
+#define usri11_num_logons     62
+#define usri11_logon_server   64
+#define usri11_country_code   68
+#define usri11_workstations   70
+#define usri11_max_storage    74
+#define usri11_units_per_week 78
+#define usri11_logon_hours    80
+#define usri11_code_page      84
+#define usri11_end            86
+
 #define USER_PRIV_GUEST 0
 #define USER_PRIV_USER 1
 #define USER_PRIV_ADMIN 2
 
-static BOOL api_RNetUserGetInfo(int cnum,int uid, char *param,char *data,
+#define AF_OP_PRINT     0 
+#define AF_OP_COMM      1
+#define AF_OP_SERVER    2
+#define AF_OP_ACCOUNTS  3
+
+
+static BOOL api_RNetUserGetInfo(int cnum,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 *UserName = skip_string(str2,1);
-  char *p = skip_string(UserName,1);
-  int uLevel = SVAL(p,0);
-  char *p2;
+       char *str1 = param+2;
+       char *str2 = skip_string(str1,1);
+       char *UserName = skip_string(str2,1);
+       char *p = skip_string(UserName,1);
+       int uLevel = SVAL(p,0);
+       char *p2;
 
-  *rparam_len = 6;
-  *rparam = REALLOC(*rparam,*rparam_len);
+    /* get NIS home of a previously validated user - simeon */
+    user_struct *vuser = get_valid_user_struct(vuid);
+    DEBUG(3,("  Username of UID %d is %s\n", vuser->uid, vuser->name));
 
-  /* check it's a supported varient */
-  if (strcmp(str1,"zWrLh") != 0) return False;
-  switch( uLevel ) {
-  case 0: p2 = "B21"; break;
-  case 1: p2 = "B21BB16DWzzWz"; break;
-  case 2: p2 = "B21BB16DWzzWzDzzzzDDDDWb21WWzWW"; break;
-  case 10: p2 = "B21Bzzz"; break;
-  case 11: p2 = "B21BzzzWDDzzDDWWzWzDWb21W"; break;
-  default: return False;
-  }
-  if (strcmp(p2,str2) != 0) return False;
+    *rparam_len = 6;
+    *rparam = REALLOC(*rparam,*rparam_len);
 
-  *rdata_len = mdrcnt + 1024;
-  *rdata = REALLOC(*rdata,*rdata_len);
+    DEBUG(4,("RNetUserGetInfo level=%d\n", uLevel));
+  
+       /* check it's a supported variant */
+       if (strcmp(str1,"zWrLh") != 0) return False;
+       switch( uLevel )
+       {
+               case 0: p2 = "B21"; break;
+               case 1: p2 = "B21BB16DWzzWz"; break;
+               case 2: p2 = "B21BB16DWzzWzDzzzzDDDDWb21WWzWW"; break;
+               case 10: p2 = "B21Bzzz"; break;
+               case 11: p2 = "B21BzzzWDDzzDDWWzWzDWb21W"; break;
+               default: return False;
+       }
 
-  SSVAL(*rparam,0,NERR_Success);
-  SSVAL(*rparam,2,0);          /* converter word */
+       if (strcmp(p2,str2) != 0) return False;
 
-  p = *rdata;
-  p2 = p + 86;
+       *rdata_len = mdrcnt + 1024;
+       *rdata = REALLOC(*rdata,*rdata_len);
 
-  memset(p,0,21);
-  strcpy(p,UserName);
-  if (uLevel > 0) {
-    SCVAL(p,21,0);
-    *p2 = 0;
-    if (uLevel >= 10) {
-      SIVAL(p,22,PTR_DIFF(p2,p)); /* comment */
-      strcpy(p2,"<Comment>");
-      p2 = skip_string(p2,1);
-      SIVAL(p,26,PTR_DIFF(p2,p)); /* user_comment */
-      strcpy(p2,"<UserComment>");
-      p2 = skip_string(p2,1);
-      SIVAL(p,30,PTR_DIFF(p2,p)); /* full name */
-      strcpy(p2,"<FullName>");
-      p2 = skip_string(p2,1);
-    }
-    if (uLevel == 11) {         /* modelled after NTAS 3.51 reply */
-      SSVAL(p,34,USER_PRIV_USER); /* user privilege */
-      SIVAL(p,36,0);           /* auth flags */
-      SIVALS(p,40,-1);         /* password age */
-      SIVAL(p,44,PTR_DIFF(p2,p)); /* home dir */
-      strcpy(p2,"\\\\%L\\HOMES");
-      standard_sub_basic(p2);
-      p2 = skip_string(p2,1);
-      SIVAL(p,48,PTR_DIFF(p2,p)); /* parms */
-      strcpy(p2,"");
-      p2 = skip_string(p2,1);
-      SIVAL(p,52,0);           /* last logon */
-      SIVAL(p,56,0);           /* last logoff */
-      SSVALS(p,60,-1);         /* bad pw counts */
-      SSVALS(p,62,-1);         /* num logons */
-      SIVAL(p,64,PTR_DIFF(p2,p)); /* logon server */
-      strcpy(p2,"\\\\*");
-      p2 = skip_string(p2,1);
-      SSVAL(p,68,0);           /* country code */
-
-      SIVAL(p,70,PTR_DIFF(p2,p)); /* workstations */
-      strcpy(p2,"");
-      p2 = skip_string(p2,1);
-
-      SIVALS(p,74,-1);         /* max storage */
-      SSVAL(p,78,168);         /* units per week */
-      SIVAL(p,80,PTR_DIFF(p2,p)); /* logon hours */
-      memset(p2,-1,21);
-      SCVAL(p2,21,0);           /* fix zero termination */
-      p2 = skip_string(p2,1);
-
-      SSVAL(p,84,0);           /* code page */
-    }
-    if (uLevel == 1 || uLevel == 2) {
-      memset(p+22,' ',16);     /* password */
-      SIVALS(p,38,-1);         /* password age */
-      SSVAL(p,42,USER_PRIV_ADMIN); /* user privilege */
-      SIVAL(p,44,PTR_DIFF(p2,*rdata)); /* home dir */
-      strcpy(p2,"\\\\%L\\HOMES");
-      standard_sub_basic(p2);
-      p2 = skip_string(p2,1);
-      SIVAL(p,48,PTR_DIFF(p2,*rdata)); /* comment */
-      *p2++ = 0;
-      SSVAL(p,52,0);           /* flags */
-      SIVAL(p,54,0);           /* script_path */
-      if (uLevel == 2) {
-       SIVAL(p,60,0);          /* auth_flags */
-       SIVAL(p,64,PTR_DIFF(p2,*rdata)); /* full_name */
-       strcpy(p2,"<Full Name>");
-       p2 = skip_string(p2,1);
-       SIVAL(p,68,0);          /* urs_comment */
-       SIVAL(p,72,PTR_DIFF(p2,*rdata)); /* parms */
-       strcpy(p2,"");
-       p2 = skip_string(p2,1);
-       SIVAL(p,76,0);          /* workstations */
-       SIVAL(p,80,0);          /* last_logon */
-       SIVAL(p,84,0);          /* last_logoff */
-       SIVALS(p,88,-1);                /* acct_expires */
-       SIVALS(p,92,-1);                /* max_storage */
-       SSVAL(p,96,168);        /* units_per_week */
-       SIVAL(p,98,PTR_DIFF(p2,*rdata)); /* logon_hours */
-       memset(p2,-1,21);
-       p2 += 21;
-       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");
-       standard_sub_basic(p2);
-       p2 = skip_string(p2,1);
-       SSVAL(p,110,49);        /* country_code */
-       SSVAL(p,112,860);       /* code page */
-      }
-    }
-  }
+       SSVAL(*rparam,0,NERR_Success);
+       SSVAL(*rparam,2,0);             /* converter word */
 
-  *rdata_len = PTR_DIFF(p2,*rdata);
+       p = *rdata;
+       p2 = p + usri11_end;
 
-  SSVAL(*rparam,4,*rdata_len); /* is this right?? */
+       memset(p,0,21); 
+       fstrcpy(p+usri11_name,UserName); /* 21 bytes - user name */
 
-  return(True);
-}
+       if (uLevel > 0)
+       {
+               SCVAL(p,usri11_pad,0); /* padding - 1 byte */
+               *p2 = 0;
+       }
+       if (uLevel >= 10)
+       {
+               SIVAL(p,usri11_comment,PTR_DIFF(p2,p)); /* comment */
+               strcpy(p2,"Comment");
+               p2 = skip_string(p2,1);
+
+               SIVAL(p,usri11_usr_comment,PTR_DIFF(p2,p)); /* user_comment */
+               strcpy(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 */
+               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); 
+               SIVAL(p,usri11_auth_flags,AF_OP_PRINT);         /* auth flags */
+               SIVALS(p,usri11_password_age,0xffffffff);               /* password age */
+               SIVAL(p,usri11_homedir,PTR_DIFF(p2,p)); /* home dir */
+               strcpy(p2, lp_logon_path());
+               p2 = skip_string(p2,1);
+               SIVAL(p,usri11_parms,PTR_DIFF(p2,p)); /* parms */
+               strcpy(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 */
+               SIVAL(p,usri11_logon_server,PTR_DIFF(p2,p)); /* logon server */
+               strcpy(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,"");
+               p2 = skip_string(p2,1);
+
+               SIVALS(p,usri11_max_storage,0xffffffff);                /* max storage */
+               SSVAL(p,usri11_units_per_week,168);             /* units per week */
+               SIVAL(p,usri11_logon_hours,PTR_DIFF(p2,p)); /* logon hours */
+
+               /* a simple way to get logon hours at all times. */
+               memset(p2,0xff,21);
+               SCVAL(p2,21,0);           /* fix zero termination */
+               p2 = skip_string(p2,1);
+
+               SSVAL(p,usri11_code_page,0);            /* code page */
+       }
+       if (uLevel == 1 || uLevel == 2)
+       {
+               memset(p+22,' ',16);    /* password */
+               SIVALS(p,38,-1);                /* password age */
+               SSVAL(p,42,
+               Connections[cnum].admin_user?USER_PRIV_ADMIN:USER_PRIV_USER);
+               SIVAL(p,44,PTR_DIFF(p2,*rdata)); /* home dir */
+               strcpy(p2,lp_logon_path());
+               p2 = skip_string(p2,1);
+               SIVAL(p,48,PTR_DIFF(p2,*rdata)); /* comment */
+               *p2++ = 0;
+               SSVAL(p,52,0);          /* flags */
+               SIVAL(p,54,0);          /* script_path */
+               if (uLevel == 2)
+               {
+                       SIVAL(p,60,0);          /* auth_flags */
+                       SIVAL(p,64,PTR_DIFF(p2,*rdata)); /* full_name */
+                       strcpy(p2,vuser->real_name);    /* simeon */
+                       p2 = skip_string(p2,1);
+                       SIVAL(p,68,0);          /* urs_comment */
+                       SIVAL(p,72,PTR_DIFF(p2,*rdata)); /* parms */
+                       strcpy(p2,"");
+                       p2 = skip_string(p2,1);
+                       SIVAL(p,76,0);          /* workstations */
+                       SIVAL(p,80,0);          /* last_logon */
+                       SIVAL(p,84,0);          /* last_logoff */
+                       SIVALS(p,88,-1);                /* acct_expires */
+                       SIVALS(p,92,-1);                /* max_storage */
+                       SSVAL(p,96,168);        /* units_per_week */
+                       SIVAL(p,98,PTR_DIFF(p2,*rdata)); /* logon_hours */
+                       memset(p2,-1,21);
+                       p2 += 21;
+                       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");
+                       standard_sub_basic(p2);
+                       p2 = skip_string(p2,1);
+                       SSVAL(p,110,49);        /* country_code */
+                       SSVAL(p,112,860);       /* code page */
+               }
+       }
+
+       *rdata_len = PTR_DIFF(p2,*rdata);
+
+       SSVAL(*rparam,4,*rdata_len);    /* is this right?? */
+
+       return(True);
+}
 
 /*******************************************************************
   get groups that a user is a member of
   ******************************************************************/
-static BOOL api_NetUserGetGroups(int cnum,int uid, char *param,char *data,
+static BOOL api_NetUserGetGroups(int cnum,uint16 vuid, char *param,char *data,
                                 int mdrcnt,int mprcnt,
                                 char **rdata,char **rparam,
                                 int *rdata_len,int *rparam_len)
@@ -2038,7 +2320,7 @@ static BOOL api_NetUserGetGroups(int cnum,int uid, char *param,char *data,
 }
 
 
-static BOOL api_WWkstaUserLogon(int cnum,int uid, char *param,char *data,
+static BOOL api_WWkstaUserLogon(int cnum,uint16 vuid, char *param,char *data,
                                int mdrcnt,int mprcnt,
                                char **rdata,char **rparam,
                                int *rdata_len,int *rparam_len)
@@ -2049,6 +2331,7 @@ static BOOL api_WWkstaUserLogon(int cnum,int uid, char *param,char *data,
   int uLevel;
   struct pack_desc desc;
   char* name;
+  char* logon_script;
 
   uLevel = SVAL(p,0);
   name = p + 2;
@@ -2066,9 +2349,8 @@ static BOOL api_WWkstaUserLogon(int cnum,int uid, char *param,char *data,
   desc.subformat = NULL;
   desc.format = str2;
   
-  
-
-  if (init_package(&desc,1,0)) {
+  if (init_package(&desc,1,0))
+  {
     PACKI(&desc,"W",0);                /* code */
     PACKS(&desc,"B21",name);   /* eff. name */
     PACKS(&desc,"B","");               /* pad */
@@ -2077,7 +2359,7 @@ static BOOL api_WWkstaUserLogon(int cnum,int uid, char *param,char *data,
     PACKI(&desc,"D",0);                /* auth flags XXX */
     PACKI(&desc,"W",0);                /* num logons */
     PACKI(&desc,"W",0);                /* bad pw count */
-    PACKI(&desc,"D",-1);               /* last logon */
+    PACKI(&desc,"D",0);                /* last logon */
     PACKI(&desc,"D",-1);               /* last logoff */
     PACKI(&desc,"D",-1);               /* logoff time */
     PACKI(&desc,"D",-1);               /* kickoff time */
@@ -2091,9 +2373,16 @@ static BOOL api_WWkstaUserLogon(int cnum,int uid, char *param,char *data,
       strupper(mypath);
       PACKS(&desc,"z",mypath); /* computer */
     }
-    PACKS(&desc,"z",my_workgroup());/* domain */
-    PACKS(&desc,"z",lp_logon_script());                /* script path */
-    PACKI(&desc,"D",0);                /* reserved */
+    PACKS(&desc,"z",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 );
+    PACKS(&desc,"z", logon_script);            /* script path */
+/* End of JHT mods */
+
+    PACKI(&desc,"D",0x00000000);               /* reserved */
   }
 
   *rdata_len = desc.usedlen;
@@ -2111,7 +2400,7 @@ static BOOL api_WWkstaUserLogon(int cnum,int uid, char *param,char *data,
 /****************************************************************************
   api_WAccessGetUserPerms
   ****************************************************************************/
-static BOOL api_WAccessGetUserPerms(int cnum,int uid, char *param,char *data,
+static BOOL api_WAccessGetUserPerms(int cnum,uint16 vuid, char *param,char *data,
                                    int mdrcnt,int mprcnt,
                                    char **rdata,char **rparam,
                                    int *rdata_len,int *rparam_len)
@@ -2139,7 +2428,7 @@ static BOOL api_WAccessGetUserPerms(int cnum,int uid, char *param,char *data,
 /****************************************************************************
   api_WPrintJobEnumerate
   ****************************************************************************/
-static BOOL api_WPrintJobGetInfo(int cnum,int uid, char *param,char *data,
+static BOOL api_WPrintJobGetInfo(int cnum,uint16 vuid, char *param,char *data,
                                 int mdrcnt,int mprcnt,
                                 char **rdata,char **rparam,
                                 int *rdata_len,int *rparam_len)
@@ -2147,7 +2436,6 @@ static BOOL api_WPrintJobGetInfo(int cnum,int uid, char *param,char *data,
   char *str1 = param+2;
   char *str2 = skip_string(str1,1);
   char *p = skip_string(str2,1);
-  int uJobId = SVAL(p,0);
   int uLevel,cbBuf;
   int count;
   int i;
@@ -2163,20 +2451,19 @@ static BOOL api_WPrintJobGetInfo(int cnum,int uid, char *param,char *data,
   bzero(&desc,sizeof(desc));
   bzero(&status,sizeof(status));
 
-  DEBUG(3,("WPrintJobGetInfo uLevel=%d uJobId=0x%X\n",uLevel,uJobId));
+  DEBUG(3,("WPrintJobGetInfo uLevel=%d uJobId=0x%X\n",uLevel,SVAL(p,0)));
 
   /* check it's a supported varient */
   if (strcmp(str1,"WWrLh") != 0) return False;
   if (!check_printjob_info(&desc,uLevel,str2)) return False;
 
-  snum = (unsigned int)uJobId >> 8; /*## valid serice number??*/
-  job = uJobId & 0xFF;
+  printjob_decode(SVAL(p,0), &snum, &job);
 
   if (snum < 0 || !VALID_SNUM(snum)) return(False);
 
   count = get_printqueue(snum,cnum,&queue,&status);
   for (i = 0; i < count; i++) {
-    if ((queue[i].job % 0xFF) == job) break;
+    if ((queue[i].job & 0xFF) == job) break;
   }
   if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
   desc.base = *rdata;
@@ -2205,7 +2492,7 @@ static BOOL api_WPrintJobGetInfo(int cnum,int uid, char *param,char *data,
   return(True);
 }
 
-static BOOL api_WPrintJobEnumerate(int cnum,int uid, char *param,char *data,
+static BOOL api_WPrintJobEnumerate(int cnum,uint16 vuid, char *param,char *data,
                                   int mdrcnt,int mprcnt,
                                   char **rdata,char **rparam,
                                   int *rdata_len,int *rparam_len)
@@ -2294,7 +2581,8 @@ static void fill_printdest_info(int cnum, int snum, int uLevel,
                                struct pack_desc* desc)
 {
   char buf[100];
-  strcpy(buf,SERVICE(snum));
+  strncpy(buf,SERVICE(snum),sizeof(buf)-1);
+  buf[sizeof(buf)-1] = 0;
   strupper(buf);
   if (uLevel <= 1) {
     PACKS(desc,"B9",buf);      /* szName */
@@ -2322,7 +2610,7 @@ static void fill_printdest_info(int cnum, int snum, int uLevel,
   }
 }
 
-static BOOL api_WPrintDestGetInfo(int cnum,int uid, char *param,char *data,
+static BOOL api_WPrintDestGetInfo(int cnum,uint16 vuid, char *param,char *data,
                                  int mdrcnt,int mprcnt,
                                  char **rdata,char **rparam,
                                  int *rdata_len,int *rparam_len)
@@ -2381,7 +2669,7 @@ static BOOL api_WPrintDestGetInfo(int cnum,int uid, char *param,char *data,
   return(True);
 }
 
-static BOOL api_WPrintDestEnum(int cnum,int uid, char *param,char *data,
+static BOOL api_WPrintDestEnum(int cnum,uint16 vuid, char *param,char *data,
                               int mdrcnt,int mprcnt,
                               char **rdata,char **rparam,
                               int *rdata_len,int *rparam_len)
@@ -2439,7 +2727,7 @@ static BOOL api_WPrintDestEnum(int cnum,int uid, char *param,char *data,
   return(True);
 }
 
-static BOOL api_WPrintDriverEnum(int cnum,int uid, char *param,char *data,
+static BOOL api_WPrintDriverEnum(int cnum,uint16 vuid, char *param,char *data,
                                 int mdrcnt,int mprcnt,
                                 char **rdata,char **rparam,
                                 int *rdata_len,int *rparam_len)
@@ -2484,7 +2772,7 @@ static BOOL api_WPrintDriverEnum(int cnum,int uid, char *param,char *data,
   return(True);
 }
 
-static BOOL api_WPrintQProcEnum(int cnum,int uid, char *param,char *data,
+static BOOL api_WPrintQProcEnum(int cnum,uint16 vuid, char *param,char *data,
                                int mdrcnt,int mprcnt,
                                char **rdata,char **rparam,
                                int *rdata_len,int *rparam_len)
@@ -2530,7 +2818,7 @@ static BOOL api_WPrintQProcEnum(int cnum,int uid, char *param,char *data,
   return(True);
 }
 
-static BOOL api_WPrintPortEnum(int cnum,int uid, char *param,char *data,
+static BOOL api_WPrintPortEnum(int cnum,uint16 vuid, char *param,char *data,
                               int mdrcnt,int mprcnt,
                               char **rdata,char **rparam,
                               int *rdata_len,int *rparam_len)
@@ -2577,10 +2865,180 @@ static BOOL api_WPrintPortEnum(int cnum,int uid, char *param,char *data,
   return(True);
 }
 
+
+struct
+{
+  char * name;
+  char * pipe_clnt_name;
+#ifdef NTDOMAIN
+  char * pipe_srv_name;
+#endif
+  int subcommand;
+  BOOL (*fn) ();
+} api_fd_commands [] =
+  {
+#ifdef NTDOMAIN
+    { "TransactNmPipe",     "lsarpc",  "lsass",        0x26,   api_ntLsarpcTNP },
+    { "TransactNmPipe",     "samr",    "lsass",        0x26,   api_samrTNP },
+    { "TransactNmPipe",     "srvsvc",  "lsass",        0x26,   api_srvsvcTNP },
+    { "TransactNmPipe",     "wkssvc",  "ntsvcs",       0x26,   api_wkssvcTNP },
+    { "TransactNmPipe",     "NETLOGON",        "NETLOGON",     0x26,   api_netlogrpcTNP },
+    { NULL,                        NULL,       NULL,   -1,     (BOOL (*)())api_Unsupported }
+#else
+    { "TransactNmPipe"  ,      "lsarpc",       0x26,   api_LsarpcTNP },
+    { NULL,            NULL,           -1,     (BOOL (*)())api_Unsupported }
+#endif
+  };
+
+/****************************************************************************
+  handle remote api calls delivered to a named pipe already opened.
+  ****************************************************************************/
+static int api_fd_reply(int cnum,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 bind_req = False;
+  BOOL set_nphs = False;
+
+  int i;
+  int fd;
+  int subcommand;
+  char *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];
+  pipe_name = get_rpc_pipe_hnd_name(fd);
+
+  if (pipe_name == NULL)
+  {
+    DEBUG(1,("api_fd_reply: INVALID PIPE HANDLE: %x\n", fd));
+  }
+
+  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].pipe_clnt_name, 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);
+  
+#ifdef NTDOMAIN
+  /* RPC Pipe command 0x26. */
+  if (data != NULL && api_fd_commands[i].subcommand == 0x26)
+  {
+    RPC_HDR hdr;
+
+    /* process the rpc header */
+    char *q = smb_io_rpc_hdr(True, &hdr, data, data, 4, 0);
+    
+       /* bind request received */
+    if ((bind_req = ((q != NULL) && (hdr.pkt_type == RPC_BIND))))
+    {
+      RPC_HDR_RB hdr_rb;
+
+      /* decode the bind request */
+      char *p = smb_io_rpc_hdr_rb(True, &hdr_rb, q, data, 4, 0);
+
+      if ((bind_req = (p != NULL)))
+      {
+        RPC_HDR_BA hdr_ba;
+        fstring ack_pipe_name;
+
+        /* name has to be \PIPE\xxxxx */
+        strcpy(ack_pipe_name, "\\PIPE\\");
+        strcat(ack_pipe_name, api_fd_commands[i].pipe_srv_name);
+
+        /* make a bind acknowledgement */
+        make_rpc_hdr_ba(&hdr_ba,
+               hdr_rb.bba.max_tsize, hdr_rb.bba.max_rsize, hdr_rb.bba.assoc_gid,
+               ack_pipe_name,
+               0x1, 0x0, 0x0,
+               &(hdr_rb.transfer));
+
+        p = smb_io_rpc_hdr_ba(False, &hdr_ba, rdata + 0x10, rdata, 4, 0);
+
+               rdata_len = PTR_DIFF(p, rdata);
+
+        make_rpc_hdr(&hdr, RPC_BINDACK, 0x0, hdr.call_id, rdata_len);
+
+        p = smb_io_rpc_hdr(False, &hdr, rdata, rdata, 4, 0);
+        
+        reply = (p != NULL);
+      }
+    }
+  }
+#endif
+
+  /* Set Named Pipe Handle state */
+  if (subcommand == 0x1)
+  {
+    set_nphs = True;
+    reply = api_LsarpcSNPHS(fd, cnum, params);
+  }
+
+  if (!bind_req && !set_nphs)
+  {
+    DEBUG(10,("calling api_fd_command\n"));
+
+    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"));
+  }
+
+  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);
+}
+
+
+
 /****************************************************************************
   the buffer was too small
   ****************************************************************************/
-static BOOL api_TooSmall(int cnum,int uid, char *param,char *data,
+static BOOL api_TooSmall(int cnum,uint16 vuid, char *param,char *data,
                         int mdrcnt,int mprcnt,
                         char **rdata,char **rparam,
                         int *rdata_len,int *rparam_len)
@@ -2601,7 +3059,7 @@ static BOOL api_TooSmall(int cnum,int uid, char *param,char *data,
 /****************************************************************************
   the request is not supported
   ****************************************************************************/
-static BOOL api_Unsupported(int cnum,int uid, char *param,char *data,
+static BOOL api_Unsupported(int cnum,uint16 vuid, char *param,char *data,
                            int mdrcnt,int mprcnt,
                            char **rdata,char **rparam,
                            int *rdata_len,int *rparam_len)
@@ -2629,38 +3087,38 @@ struct
   BOOL (*fn)();
   int flags;
 } api_commands[] = {
-  {"RNetShareEnum",    0,      api_RNetShareEnum,0},
-  {"RNetShareGetInfo", 1,      api_RNetShareGetInfo,0},
-  {"RNetServerGetInfo",        13,     api_RNetServerGetInfo,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},
-  {"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},
-  {NULL,               -1,     api_Unsupported,0}};
+  {"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}};
 
 
 /****************************************************************************
   handle remote api calls
   ****************************************************************************/
-static int api_reply(int cnum,int uid,char *outbuf,char *data,char *params,
+static int api_reply(int cnum,uint16 vuid,char *outbuf,char *data,char *params,
                     int tdscnt,int tpscnt,int mdrcnt,int mprcnt)
 {
   int api_command = SVAL(params,0);
@@ -2685,21 +3143,21 @@ static int api_reply(int cnum,int uid,char *outbuf,char *data,char *params,
   rdata = (char *)malloc(1024); if (rdata) bzero(rdata,1024);
   rparam = (char *)malloc(1024); if (rparam) bzero(rparam,1024);
 
-  reply = api_commands[i].fn(cnum,uid,params,data,mdrcnt,mprcnt,
+  reply = api_commands[i].fn(cnum,vuid,params,data,mdrcnt,mprcnt,
                             &rdata,&rparam,&rdata_len,&rparam_len);
 
 
   if (rdata_len > mdrcnt ||
       rparam_len > mprcnt)
     {
-      reply = api_TooSmall(cnum,uid,params,data,mdrcnt,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,uid,params,data,mdrcnt,mprcnt,
+    api_Unsupported(cnum,vuid,params,data,mdrcnt,mprcnt,
                    &rdata,&rparam,&rdata_len,&rparam_len);
 
       
@@ -2718,26 +3176,36 @@ static int api_reply(int cnum,int uid,char *outbuf,char *data,char *params,
 /****************************************************************************
   handle named pipe commands
   ****************************************************************************/
-static int named_pipe(int cnum,int uid, char *outbuf,char *name,
+static int named_pipe(int cnum,uint16 vuid, char *outbuf,char *name,
                      uint16 *setup,char *data,char *params,
                      int suwcnt,int tdscnt,int tpscnt,
                      int msrcnt,int mdrcnt,int mprcnt)
 {
+       DEBUG(3,("named pipe command on <%s> name\n", name));
+
+       if (strequal(name,"LANMAN"))
+       {
+               return api_reply(cnum,vuid,outbuf,data,params,tdscnt,tpscnt,mdrcnt,mprcnt);
+       }
 
-  if (strequal(name,"LANMAN"))
-    return(api_reply(cnum,uid,outbuf,data,params,tdscnt,tpscnt,mdrcnt,mprcnt));
+       if (strlen(name) < 1)
+       {
+               return api_fd_reply(cnum,vuid,outbuf,setup,data,params,suwcnt,tdscnt,tpscnt,mdrcnt,mprcnt);
+       }
 
-  DEBUG(3,("named pipe command on <%s> 0x%X setup1=%d\n",
-          name,(int)setup[0],(int)setup[1]));
-  
-  return(0);
+       if (setup)
+       {
+               DEBUG(3,("unknown named pipe: setup 0x%X setup1=%d\n", (int)setup[0],(int)setup[1]));
+       }
+
+       return 0;
 }
 
 
 /****************************************************************************
   reply to a SMBtrans
   ****************************************************************************/
-int reply_trans(char *inbuf,char *outbuf)
+int reply_trans(char *inbuf,char *outbuf, int size, int bufsize)
 {
   fstring name;
 
@@ -2746,7 +3214,7 @@ int reply_trans(char *inbuf,char *outbuf)
 
   int outsize = 0;
   int cnum = SVAL(inbuf,smb_tid);
-  int uid = SVAL(inbuf,smb_uid);
+  uint16 vuid = SVAL(inbuf,smb_uid);
 
   int tpscnt = SVAL(inbuf,smb_vwv0);
   int tdscnt = SVAL(inbuf,smb_vwv1);
@@ -2761,7 +3229,12 @@ int reply_trans(char *inbuf,char *outbuf)
   int dsoff = SVAL(inbuf,smb_vwv12);
   int suwcnt = CVAL(inbuf,smb_vwv13);
 
-  StrnCpy(name,smb_buf(inbuf),sizeof(name)-1);
+  bzero(name, sizeof(name));
+  fstrcpy(name,smb_buf(inbuf));
+
+  if (dscnt > tdscnt || pscnt > tpscnt) {
+         exit_server("invalid trans parameters\n");
+  }
   
   if (tdscnt)
     {
@@ -2795,12 +3268,18 @@ int reply_trans(char *inbuf,char *outbuf)
   /* receive the rest of the trans packet */
   while (pscnt < tpscnt || dscnt < tdscnt)
     {
+      BOOL ret;
       int pcnt,poff,dcnt,doff,pdisp,ddisp;
       
-      if (!receive_smb(Client,inbuf, SMB_SECONDARY_WAIT*1000) ||
-         CVAL(inbuf, smb_com) != SMBtrans)
+      ret = receive_next_smb(Client,oplock_sock,inbuf,bufsize,SMB_SECONDARY_WAIT);
+
+      if ((ret && (CVAL(inbuf, smb_com) != SMBtrans)) || !ret)
        {
-         DEBUG(2,("Invalid secondary trans2 packet\n"));
+          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);
@@ -2823,6 +3302,10 @@ int reply_trans(char *inbuf,char *outbuf)
       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)
@@ -2831,11 +3314,18 @@ int reply_trans(char *inbuf,char *outbuf)
 
 
   DEBUG(3,("trans <%s> data=%d params=%d setup=%d\n",name,tdscnt,tpscnt,suwcnt));
-  
 
   if (strncmp(name,"\\PIPE\\",strlen("\\PIPE\\")) == 0)
-    outsize = named_pipe(cnum,uid,outbuf,name+strlen("\\PIPE\\"),setup,data,params,
+  {
+    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);
@@ -2843,7 +3333,7 @@ int reply_trans(char *inbuf,char *outbuf)
   if (setup) free(setup);
 
   if (close_on_completion)
-    close_cnum(cnum,uid);
+    close_cnum(cnum,vuid);
 
   if (one_way)
     return(-1);
@@ -2853,5 +3343,3 @@ int reply_trans(char *inbuf,char *outbuf)
 
   return(outsize);
 }
-
-