r23346: Fix offline caching with XP/Vista. It was an off-by-one
[tprouty/samba.git] / source / smbd / lanman.c
index a2ec6f34b8b5f0630ccb52db6dab81f94bd3bc52..0a9a529a85f4cc8846c608a257d48a9d378783c4 100644 (file)
@@ -2,6 +2,7 @@
    Unix SMB/CIFS implementation.
    Inter-process communication and named pipe handling
    Copyright (C) Andrew Tridgell 1992-1998
+   Copyright (C) Jeremy Allison 2007.
 
    SMB Version handling
    Copyright (C) John H Terpstra 1995-1998
@@ -50,10 +51,13 @@ extern userdom_struct current_user_info;
 
 #define SHPWLEN 8              /* share password length */
 
-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_Unsupported(connection_struct *conn, uint16 vuid,
+                               char *param, int tpscnt,
+                               char *data, int tdscnt,
+                               int mdrcnt, int mprcnt,
+                               char **rdata, char **rparam,
+                               int *rdata_len, int *rparam_len);
+
 static BOOL api_TooSmall(connection_struct *conn, uint16 vuid, char *param, char *data,
                         int mdrcnt, int mprcnt,
                         char **rdata, char **rparam,
@@ -72,7 +76,11 @@ static int CopyExpanded(connection_struct *conn,
 
        StrnCpy(buf,src,sizeof(buf)/2);
        pstring_sub(buf,"%S",lp_servicename(snum));
-       standard_sub_conn(conn,buf,sizeof(buf));
+       standard_sub_advanced(lp_servicename(SNUM(conn)), conn->user,
+                             conn->connectpath, conn->gid,
+                             get_current_username(),
+                             current_user_info.domain,
+                             buf, sizeof(buf));
        l = push_ascii(*dst,buf,*n, STR_TERMINATE);
        (*dst) += l;
        (*n) -= l;
@@ -99,7 +107,11 @@ static int StrlenExpanded(connection_struct *conn, int snum, char *s)
        }
        StrnCpy(buf,s,sizeof(buf)/2);
        pstring_sub(buf,"%S",lp_servicename(snum));
-       standard_sub_conn(conn,buf,sizeof(buf));
+       standard_sub_advanced(lp_servicename(SNUM(conn)), conn->user,
+                             conn->connectpath, conn->gid,
+                             get_current_username(),
+                             current_user_info.domain,
+                             buf, sizeof(buf));
        return strlen(buf) + 1;
 }
 
@@ -111,7 +123,11 @@ static char *Expand(connection_struct *conn, int snum, char *s)
        }
        StrnCpy(buf,s,sizeof(buf)/2);
        pstring_sub(buf,"%S",lp_servicename(snum));
-       standard_sub_conn(conn,buf,sizeof(buf));
+       standard_sub_advanced(lp_servicename(SNUM(conn)), conn->user,
+                             conn->connectpath, conn->gid,
+                             get_current_username(),
+                             current_user_info.domain,
+                             buf, sizeof(buf));
        return &buf[0];
 }
 
@@ -425,12 +441,18 @@ static int check_printq_info(struct pack_desc* desc,
                        desc->subformat = "z";
                        break;
                default:
+                       DEBUG(0,("check_printq_info: invalid level %d\n",
+                               uLevel ));
                        return False;
        }
-       if (strcmp(desc->format,id1) != 0) {
+       if (id1 == NULL || strcmp(desc->format,id1) != 0) {
+               DEBUG(0,("check_printq_info: invalid format %s\n",
+                       id1 ? id1 : "<NULL>" ));
                return False;
        }
-       if (desc->subformat && strcmp(desc->subformat,id2) != 0) {
+       if (desc->subformat && (id2 == NULL || strcmp(desc->subformat,id2) != 0)) {
+               DEBUG(0,("check_printq_info: invalid subformat %s\n",
+                       id2 ? id2 : "<NULL>" ));
                return False;
        }
        return True;
@@ -573,7 +595,7 @@ static void fill_printq_info_52(connection_struct *conn, int snum,
                        lp_servicename(snum)));
                goto err;
        }
-               
+
        if ( !W_ERROR_IS_OK(get_a_printer_driver(&driver, 3, printer->info_2->drivername, 
                "Windows 4.0", 0)) )
        {
@@ -585,17 +607,17 @@ static void fill_printq_info_52(connection_struct *conn, int snum,
        trim_string(driver.info_3->driverpath, "\\print$\\WIN40\\0\\", 0);
        trim_string(driver.info_3->datafile, "\\print$\\WIN40\\0\\", 0);
        trim_string(driver.info_3->helpfile, "\\print$\\WIN40\\0\\", 0);
-       
+
        PACKI(desc, "W", 0x0400);                     /* don't know */
        PACKS(desc, "z", driver.info_3->name);        /* long printer name */
        PACKS(desc, "z", driver.info_3->driverpath);  /* Driverfile Name */
        PACKS(desc, "z", driver.info_3->datafile);    /* Datafile name */
        PACKS(desc, "z", driver.info_3->monitorname); /* language monitor */
-       
+
        fstrcpy(location, "\\\\%L\\print$\\WIN40\\0");
-       standard_sub_basic( "", location, sizeof(location)-1 );
+       standard_sub_basic( "", "", location, sizeof(location)-1 );
        PACKS(desc,"z", location);                          /* share to retrieve files */
-       
+
        PACKS(desc,"z", driver.info_3->defaultdatatype);    /* default data type */
        PACKS(desc,"z", driver.info_3->helpfile);           /* helpfile name */
        PACKS(desc,"z", driver.info_3->driverpath);               /* driver name */
@@ -615,12 +637,12 @@ static void fill_printq_info_52(connection_struct *conn, int snum,
                PACKS(desc,"z",driver.info_3->dependentfiles[i]);         /* driver files to copy */
                DEBUG(3,("Dependent File: %s:\n",driver.info_3->dependentfiles[i]));
        }
-       
+
        /* sanity check */
        if ( i != count )
                DEBUG(3,("fill_printq_info_52: file count specified by client [%d] != number of dependent files [%i]\n",
                        count, i));
-               
+
        DEBUG(3,("fill_printq_info on <%s> gave %d entries\n", SERVICE(snum),i));
 
         desc->errcode=NERR_Success;
@@ -633,7 +655,7 @@ err:
 done:
        if ( printer )
                free_a_printer( &printer, 2 );
-               
+
        if ( driver.info_3 )
                free_a_printer_driver( driver, 3 );
 }
@@ -731,7 +753,7 @@ static int get_printerdrivernumber(int snum)
                        lp_servicename(snum)));
                goto done;
        }
-               
+
        if ( !W_ERROR_IS_OK(get_a_printer_driver(&driver, 3, printer->info_2->drivername, 
                "Windows 4.0", 0)) )
        {
@@ -739,7 +761,7 @@ static int get_printerdrivernumber(int snum)
                        printer->info_2->drivername));
                goto done;
        }
-       
+
        /* count the number of files */
        while ( driver.info_3->dependentfiles && *driver.info_3->dependentfiles[result] )
                        result++;
@@ -747,39 +769,47 @@ static int get_printerdrivernumber(int snum)
  done:
        if ( printer )
                free_a_printer( &printer, 2 );
-               
+
        if ( driver.info_3 )
                free_a_printer_driver( driver, 3 );
-               
+
        return result;
 }
 
-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)
+static BOOL api_DosPrintQGetInfo(connection_struct *conn, uint16 vuid,
+                               char *param, int tpscnt,
+                               char *data, int tdscnt,
+                               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);
+       char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
+       char *str2 = skip_string(param,tpscnt,str1);
+       char *p = skip_string(param,tpscnt,str2);
        char *QueueName = p;
        unsigned int uLevel;
        int count=0;
        int snum;
-       charstr3;
+       char *str3;
        struct pack_desc desc;
        print_queue_struct *queue=NULL;
        print_status_struct status;
        char* tmpdata=NULL;
 
+       if (!str1 || !str2 || !p) {
+               return False;
+       }
        memset((char *)&status,'\0',sizeof(status));
        memset((char *)&desc,'\0',sizeof(desc));
-       p = skip_string(p,1);
-       uLevel = SVAL(p,0);
-       str3 = p + 4;
+
+       p = skip_string(param,tpscnt,p);
+       if (!p) {
+               return False;
+       }
+       uLevel = get_safe_SVAL(param,tpscnt,p,0,-1);
+       str3 = get_safe_str_ptr(param,tpscnt,p,4);
+       /* str3 may be null here and is checked in check_printq_info(). */
+
        /* remove any trailing username */
        if ((p = strchr_m(QueueName,'%')))
                *p = 0;
@@ -798,6 +828,9 @@ static BOOL api_DosPrintQGetInfo(connection_struct *conn,
                *rdata_len = 0;
                *rparam_len = 6;
                *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
+               if (!*rparam) {
+                       return False;
+               }
                SSVALS(*rparam,0,ERRunknownlevel);
                SSVAL(*rparam,2,0);
                SSVAL(*rparam,4,0);
@@ -817,6 +850,9 @@ static BOOL api_DosPrintQGetInfo(connection_struct *conn,
 
        if (mdrcnt > 0) {
                *rdata = SMB_REALLOC_LIMIT(*rdata,mdrcnt);
+               if (!*rdata) {
+                       return False;
+               }
                desc.base = *rdata;
                desc.buflen = mdrcnt;
        } else {
@@ -846,6 +882,9 @@ static BOOL api_DosPrintQGetInfo(connection_struct *conn,
        *rdata_len = desc.usedlen;
        *rparam_len = 6;
        *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
+       if (!*rparam) {
+               return False;
+       }
        SSVALS(*rparam,0,desc.errcode);
        SSVAL(*rparam,2,0);
        SSVAL(*rparam,4,desc.neededlen);
@@ -862,16 +901,18 @@ static BOOL api_DosPrintQGetInfo(connection_struct *conn,
  View list of all print jobs on all queues.
 ****************************************************************************/
 
-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)
+static BOOL api_DosPrintQEnum(connection_struct *conn, uint16 vuid,
+                               char *param, int tpscnt,
+                               char *data, int tdscnt,
+                               int mdrcnt, int mprcnt,
+                               char **rdata, char** rparam,
+                               int *rdata_len, int *rparam_len)
 {
-       char *param_format = param+2;
-       char *output_format1 = skip_string(param_format,1);
-       char *p = skip_string(output_format1,1);
-       unsigned int uLevel = SVAL(p,0);
-       char *output_format2 = p + 4;
+       char *param_format = get_safe_str_ptr(param,tpscnt,param,2);
+       char *output_format1 = skip_string(param,tpscnt,param_format);
+       char *p = skip_string(param,tpscnt,output_format1);
+       unsigned int uLevel = get_safe_SVAL(param,tpscnt,p,0,-1);
+       char *output_format2 = get_safe_str_ptr(param,tpscnt,p,4);
        int services = lp_numservices();
        int i, n;
        struct pack_desc desc;
@@ -880,6 +921,10 @@ static BOOL api_DosPrintQEnum(connection_struct *conn, uint16 vuid, char* param,
        int *subcntarr = NULL;
        int queuecnt = 0, subcnt = 0, succnt = 0;
  
+       if (!param_format || !output_format1 || !p) {
+               return False;
+       }
+
        memset((char *)&desc,'\0',sizeof(desc));
 
        DEBUG(3,("DosPrintQEnum uLevel=%d\n",uLevel));
@@ -896,6 +941,9 @@ static BOOL api_DosPrintQEnum(connection_struct *conn, uint16 vuid, char* param,
                *rdata_len = 0;
                *rparam_len = 6;
                *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
+               if (!*rparam) {
+                       return False;
+               }
                SSVALS(*rparam,0,ERRunknownlevel);
                SSVAL(*rparam,2,0);
                SSVAL(*rparam,4,0);
@@ -1066,15 +1114,12 @@ static int get_server_info(uint32 servertype,
                }
     
                if (count == alloced) {
-                       struct srv_info_struct *ts;
-      
                        alloced += 10;
-                       ts = SMB_REALLOC_ARRAY(*servers,struct srv_info_struct, alloced);
-                       if (!ts) {
+                       *servers = SMB_REALLOC_ARRAY(*servers,struct srv_info_struct, alloced);
+                       if (!*servers) {
                                DEBUG(0,("get_server_info: failed to enlarge servers info struct!\n"));
+                               file_lines_free(lines);
                                return 0;
-                       } else {
-                               *servers = ts;
                        }
                        memset((char *)((*servers)+count),'\0',sizeof(**servers)*(alloced-count));
                }
@@ -1174,12 +1219,8 @@ static int fill_srv_info(struct srv_info_struct *service,
                                break;
                }
 
-               if (buflen) {
-                       *buflen = struct_len;
-               }
-               if (stringspace) {
-                       *stringspace = len;
-               }
+               *buflen = struct_len;
+               *stringspace = len;
                return struct_len + len;
        }
   
@@ -1235,16 +1276,18 @@ static BOOL srv_comp(struct srv_info_struct *s1,struct srv_info_struct *s2)
  extracted from lists saved by nmbd on the local host.
 ****************************************************************************/
 
-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)
+static BOOL api_RNetServerEnum(connection_struct *conn, uint16 vuid,
+                               char *param, int tpscnt,
+                               char *data, int tdscnt,
+                               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);
-       uint32 servertype = IVAL(p,4);
+       char *str1 = get_safe_str_ptr(param, tpscnt, param, 2);
+       char *str2 = skip_string(param,tpscnt,str1);
+       char *p = skip_string(param,tpscnt,str2);
+       int uLevel = get_safe_SVAL(param, tpscnt, p, 0, -1);
+       int buf_len = get_safe_SVAL(param,tpscnt, p, 2, 0);
+       uint32 servertype = get_safe_IVAL(param,tpscnt,p,4, 0);
        char *p2;
        int data_len, fixed_len, string_len;
        int f_len = 0, s_len = 0;
@@ -1255,6 +1298,10 @@ static BOOL api_RNetServerEnum(connection_struct *conn, uint16 vuid, char *param
        BOOL domain_request;
        BOOL local_request;
 
+       if (!str1 || !str2 || !p) {
+               return False;
+       }
+
        /* 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. */
@@ -1290,6 +1337,9 @@ static BOOL api_RNetServerEnum(connection_struct *conn, uint16 vuid, char *param
        DEBUG(4, ("local_only:%s\n", BOOLSTR(local_request)));
 
        if (strcmp(str1, "WrLehDz") == 0) {
+               if (skip_string(param,tpscnt,p) == NULL) {
+                       return False;
+               }
                pull_ascii_fstring(domain, p);
        } else {
                fstrcpy(domain, lp_workgroup());
@@ -1332,6 +1382,9 @@ static BOOL api_RNetServerEnum(connection_struct *conn, uint16 vuid, char *param
 
        *rdata_len = fixed_len + string_len;
        *rdata = SMB_REALLOC_LIMIT(*rdata,*rdata_len);
+       if (!*rdata) {
+               return False;
+       }
        memset(*rdata,'\0',*rdata_len);
   
        p2 = (*rdata) + fixed_len;      /* auxilliary data (strings) will go here */
@@ -1359,6 +1412,9 @@ static BOOL api_RNetServerEnum(connection_struct *conn, uint16 vuid, char *param
   
        *rparam_len = 8;
        *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
+       if (!*rparam) {
+               return False;
+       }
        SSVAL(*rparam,0,(missed == 0 ? NERR_Success : ERRmoredata));
        SSVAL(*rparam,2,0);
        SSVAL(*rparam,4,counted);
@@ -1376,18 +1432,24 @@ static BOOL api_RNetServerEnum(connection_struct *conn, uint16 vuid, char *param
   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)
+static BOOL api_RNetGroupGetUsers(connection_struct *conn, uint16 vuid,
+                               char *param, int tpscnt,
+                               char *data, int tdscnt,
+                               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);
+       char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
+       char *str2 = skip_string(param,tpscnt,str1);
+       char *p = skip_string(param,tpscnt,str2);
+       int uLevel = get_safe_SVAL(param,tpscnt,p,0,-1);
+       int buf_len = get_safe_SVAL(param,tpscnt,p,2,0);
        int counted=0;
        int missed=0;
 
+       if (!str1 || !str2 || !p) {
+               return False;
+       }
+
        DEBUG(5,("RNetGroupGetUsers: %s %s %s %d %d\n",
                str1, str2, p, uLevel, buf_len));
 
@@ -1399,6 +1461,9 @@ static BOOL api_RNetGroupGetUsers(connection_struct *conn, uint16 vuid, char *pa
   
        *rparam_len = 8;
        *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
+       if (!*rparam) {
+               return False;
+       }
 
        SSVAL(*rparam,0,0x08AC); /* informational warning message */
        SSVAL(*rparam,2,0);
@@ -1556,18 +1621,25 @@ static int fill_share_info(connection_struct *conn, int snum, int uLevel,
        return len;
 }
 
-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)
+static BOOL api_RNetShareGetInfo(connection_struct *conn,uint16 vuid,
+                               char *param, int tpscnt,
+                               char *data, int tdscnt,
+                               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 *netname = skip_string(str2,1);
-       char *p = skip_string(netname,1);
-       int uLevel = SVAL(p,0);
-       int snum = find_service(netname);
+       char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
+       char *str2 = skip_string(param,tpscnt,str1);
+       char *netname = skip_string(param,tpscnt,str2);
+       char *p = skip_string(param,tpscnt,netname);
+       int uLevel = get_safe_SVAL(param,tpscnt,p,0,-1);
+       int snum;
   
+       if (!str1 || !str2 || !netname || !p) {
+               return False;
+       }
+
+       snum = find_service(netname);
        if (snum < 0) {
                return False;
        }
@@ -1581,6 +1653,9 @@ static BOOL api_RNetShareGetInfo(connection_struct *conn,uint16 vuid, char *para
        }
  
        *rdata = SMB_REALLOC_LIMIT(*rdata,mdrcnt);
+       if (!*rdata) {
+               return False;
+       }
        p = *rdata;
        *rdata_len = fill_share_info(conn,snum,uLevel,&p,&mdrcnt,0,0,0);
        if (*rdata_len < 0) {
@@ -1589,6 +1664,9 @@ static BOOL api_RNetShareGetInfo(connection_struct *conn,uint16 vuid, char *para
  
        *rparam_len = 6;
        *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
+       if (!*rparam) {
+               return False;
+       }
        SSVAL(*rparam,0,NERR_Success);
        SSVAL(*rparam,2,0);             /* converter word */
        SSVAL(*rparam,4,*rdata_len);
@@ -1606,22 +1684,21 @@ static BOOL api_RNetShareGetInfo(connection_struct *conn,uint16 vuid, char *para
   Share names longer than 12 bytes must be skipped.
  ****************************************************************************/
 
-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 )
+static BOOL api_RNetShareEnum( connection_struct *conn, uint16 vuid,
+                               char *param, int tpscnt,
+                               char *data, int tdscnt,
+                               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);
+       char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
+       char *str2 = skip_string(param,tpscnt,str1);
+       char *p = skip_string(param,tpscnt,str2);
+       int uLevel = get_safe_SVAL(param,tpscnt,p,0,-1);
+       int buf_len = get_safe_SVAL(param,tpscnt,p,2,0);
        char *p2;
        int count = 0;
        int total=0,counted=0;
@@ -1630,6 +1707,10 @@ static BOOL api_RNetShareEnum( connection_struct *conn,
        int data_len, fixed_len, string_len;
        int f_len = 0, s_len = 0;
  
+       if (!str1 || !str2 || !p) {
+               return False;
+       }
+
        if (!prefix_ok(str1,"WrLeh")) {
                return False;
        }
@@ -1639,6 +1720,7 @@ static BOOL api_RNetShareEnum( connection_struct *conn,
   
        /* Ensure all the usershares are loaded. */
        become_root();
+       load_registry_shares();
        count = load_usershare_shares();
        unbecome_root();
 
@@ -1665,6 +1747,9 @@ static BOOL api_RNetShareEnum( connection_struct *conn,
 
        *rdata_len = fixed_len + string_len;
        *rdata = SMB_REALLOC_LIMIT(*rdata,*rdata_len);
+       if (!*rdata) {
+               return False;
+       }
        memset(*rdata,0,*rdata_len);
   
        p2 = (*rdata) + fixed_len;      /* auxiliary data (strings) will go here */
@@ -1688,6 +1773,9 @@ static BOOL api_RNetShareEnum( connection_struct *conn,
   
        *rparam_len = 8;
        *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
+       if (!*rparam) {
+               return False;
+       }
        SSVAL(*rparam,0,missed ? ERRmoredata : NERR_Success);
        SSVAL(*rparam,2,0);
        SSVAL(*rparam,4,counted);
@@ -1704,15 +1792,17 @@ static BOOL api_RNetShareEnum( connection_struct *conn,
   Add a share
   ****************************************************************************/
 
-static BOOL api_RNetShareAdd(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_RNetShareAdd(connection_struct *conn,uint16 vuid,
+                               char *param, int tpscnt,
+                               char *data, int tdscnt,
+                               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);
+       char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
+       char *str2 = skip_string(param,tpscnt,str1);
+       char *p = skip_string(param,tpscnt,str2);
+       int uLevel = get_safe_SVAL(param,tpscnt,p,0,-1);
        fstring sharename;
        fstring comment;
        pstring pathname;
@@ -1721,6 +1811,10 @@ static BOOL api_RNetShareAdd(connection_struct *conn,uint16 vuid, char *param,ch
        int snum;
        int res = ERRunsup;
   
+       if (!str1 || !str2 || !p) {
+               return False;
+       }
+
        /* check it's a supported varient */
        if (!prefix_ok(str1,RAP_WShareAdd_REQ)) {
                return False;
@@ -1732,6 +1826,10 @@ static BOOL api_RNetShareAdd(connection_struct *conn,uint16 vuid, char *param,ch
                return False;
        }
 
+       /* Do we have a string ? */
+       if (skip_string(data,mdrcnt,data) == NULL) {
+               return False;
+       }
        pull_ascii_fstring(sharename,data);
        snum = find_service(sharename);
        if (snum >= 0) { /* already exists */
@@ -1739,6 +1837,10 @@ static BOOL api_RNetShareAdd(connection_struct *conn,uint16 vuid, char *param,ch
                goto error_exit;
        }
 
+       if (mdrcnt < 28) {
+               return False;
+       }
+
        /* only support disk share adds */
        if (SVAL(data,14)!=STYPE_DISKTREE) {
                return False;
@@ -1750,6 +1852,10 @@ static BOOL api_RNetShareAdd(connection_struct *conn,uint16 vuid, char *param,ch
                goto error_exit;
        }
 
+       /* Do we have a string ? */
+       if (skip_string(data,mdrcnt,data+offset) == NULL) {
+               return False;
+       }
        pull_ascii_fstring(comment, offset? (data+offset) : "");
 
        offset = IVAL(data, 26);
@@ -1759,6 +1865,10 @@ static BOOL api_RNetShareAdd(connection_struct *conn,uint16 vuid, char *param,ch
                goto error_exit;
        }
 
+       /* Do we have a string ? */
+       if (skip_string(data,mdrcnt,data+offset) == NULL) {
+               return False;
+       }
        pull_ascii_pstring(pathname, offset? (data+offset) : "");
 
        string_replace(sharename, '"', ' ');
@@ -1784,7 +1894,8 @@ static BOOL api_RNetShareAdd(connection_struct *conn,uint16 vuid, char *param,ch
                        goto error_exit;
                } else {
                        SAFE_FREE(command);
-                       message_send_all(conn_tdb_ctx(), MSG_SMB_CONF_UPDATED, NULL, 0, False, NULL);
+                       message_send_all(smbd_messaging_context(),
+                                        MSG_SMB_CONF_UPDATED, NULL, 0, NULL);
                }
        } else {
                return False;
@@ -1792,6 +1903,9 @@ static BOOL api_RNetShareAdd(connection_struct *conn,uint16 vuid, char *param,ch
 
        *rparam_len = 6;
        *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
+       if (!*rparam) {
+               return False;
+       }
        SSVAL(*rparam,0,NERR_Success);
        SSVAL(*rparam,2,0);             /* converter word */
        SSVAL(*rparam,4,*rdata_len);
@@ -1803,6 +1917,9 @@ static BOOL api_RNetShareAdd(connection_struct *conn,uint16 vuid, char *param,ch
 
        *rparam_len = 4;
        *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
+       if (!*rparam) {
+               return False;
+       }
        *rdata_len = 0;
        SSVAL(*rparam,0,res);
        SSVAL(*rparam,2,0);
@@ -1813,23 +1930,29 @@ static BOOL api_RNetShareAdd(connection_struct *conn,uint16 vuid, char *param,ch
   view list of groups available
   ****************************************************************************/
 
-static BOOL api_RNetGroupEnum(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_RNetGroupEnum(connection_struct *conn,uint16 vuid,
+                               char *param, int tpscnt,
+                               char *data, int tdscnt,
+                               int mdrcnt,int mprcnt,
+                               char **rdata,char **rparam,
+                               int *rdata_len,int *rparam_len)
 {
        int i;
        int errflags=0;
        int resume_context, cli_buf_size;
-       char *str1 = param+2;
-       char *str2 = skip_string(str1,1);
-       char *p = skip_string(str2,1);
+       char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
+       char *str2 = skip_string(param,tpscnt,str1);
+       char *p = skip_string(param,tpscnt,str2);
 
        struct pdb_search *search;
        struct samr_displayentry *entries;
 
        int num_entries;
  
+       if (!str1 || !str2 || !p) {
+               return False;
+       }
+
        if (strcmp(str1,"WrLeh") != 0) {
                return False;
        }
@@ -1856,8 +1979,8 @@ static BOOL api_RNetGroupEnum(connection_struct *conn,uint16 vuid, char *param,c
                return False;
        }
 
-       resume_context = SVAL(p,0); 
-       cli_buf_size=SVAL(p+2,0);
+       resume_context = get_safe_SVAL(param,tpscnt,p,0,-1);
+       cli_buf_size= get_safe_SVAL(param,tpscnt,p,2,0);
        DEBUG(10,("api_RNetGroupEnum:resume context: %d, client buffer size: "
                  "%d\n", resume_context, cli_buf_size));
 
@@ -1868,6 +1991,9 @@ static BOOL api_RNetGroupEnum(connection_struct *conn,uint16 vuid, char *param,c
 
        *rdata_len = cli_buf_size;
        *rdata = SMB_REALLOC_LIMIT(*rdata,*rdata_len);
+       if (!*rdata) {
+               return False;
+       }
 
        p = *rdata;
 
@@ -1895,7 +2021,9 @@ static BOOL api_RNetGroupEnum(connection_struct *conn,uint16 vuid, char *param,c
 
        *rparam_len = 8;
        *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
-
+       if (!*rparam) {
+               return False;
+       }
        SSVAL(*rparam, 0, errflags);
        SSVAL(*rparam, 2, 0);           /* converter word */
        SSVAL(*rparam, 4, i);   /* is this right?? */
@@ -1908,19 +2036,21 @@ static BOOL api_RNetGroupEnum(connection_struct *conn,uint16 vuid, char *param,c
  Get groups that a user is a member of.
 ******************************************************************/
 
-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)
+static BOOL api_NetUserGetGroups(connection_struct *conn,uint16 vuid,
+                               char *param, int tpscnt,
+                               char *data, int tdscnt,
+                               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 *str1 = get_safe_str_ptr(param,tpscnt,param,2);
+       char *str2 = skip_string(param,tpscnt,str1);
+       char *UserName = skip_string(param,tpscnt,str2);
+       char *p = skip_string(param,tpscnt,UserName);
+       int uLevel = get_safe_SVAL(param,tpscnt,p,0,-1);
        const char *level_string;
        int count=0;
-       SAM_ACCOUNT *sampw = NULL;
+       struct samu *sampw = NULL;
        BOOL ret = False;
        DOM_SID *sids;
        gid_t *gids;
@@ -1928,11 +2058,18 @@ static BOOL api_NetUserGetGroups(connection_struct *conn,uint16 vuid, char *para
        size_t i;
        NTSTATUS result;
        DOM_SID user_sid;
-       enum SID_NAME_USE type;
+       enum lsa_SidType type;
        TALLOC_CTX *mem_ctx;
 
+       if (!str1 || !str2 || !UserName || !p) {
+               return False;
+       }
+
        *rparam_len = 8;
        *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
+       if (!*rparam) {
+               return False;
+       }
   
        /* check it's a supported varient */
        
@@ -1952,7 +2089,9 @@ static BOOL api_NetUserGetGroups(connection_struct *conn,uint16 vuid, char *para
 
        *rdata_len = mdrcnt + 1024;
        *rdata = SMB_REALLOC_LIMIT(*rdata,*rdata_len);
-
+       if (!*rdata) {
+               return False;
+       }
        SSVAL(*rparam,0,NERR_Success);
        SSVAL(*rparam,2,0);             /* converter word */
 
@@ -1964,6 +2103,12 @@ static BOOL api_NetUserGetGroups(connection_struct *conn,uint16 vuid, char *para
                return False;
        }
 
+       if ( !(sampw = samu_new(mem_ctx)) ) {
+               DEBUG(0, ("samu_new() failed!\n"));
+               TALLOC_FREE(mem_ctx);
+               return False;
+       }
+
        /* Lookup the user information; This should only be one of 
           our accounts (not remote domains) */
 
@@ -1981,11 +2126,6 @@ static BOOL api_NetUserGetGroups(connection_struct *conn,uint16 vuid, char *para
                goto done;
        }
 
-       if (!NT_STATUS_IS_OK(pdb_init_sam_talloc(mem_ctx, &sampw))) {
-               DEBUG(10, ("pdb_init_sam_talloc failed\n"));
-               goto done;
-       }
-
        if ( !pdb_getsampwsid(sampw, &user_sid) ) {
                DEBUG(10, ("pdb_getsampwsid(%s) failed for user %s\n",
                           sid_string_static(&user_sid), UserName));
@@ -2026,7 +2166,7 @@ static BOOL api_NetUserGetGroups(connection_struct *conn,uint16 vuid, char *para
 done:
        unbecome_root();                                /* END ROOT BLOCK */
 
-       talloc_free(mem_ctx);
+       TALLOC_FREE(mem_ctx);
 
        return ret;
 }
@@ -2035,10 +2175,12 @@ done:
  Get all users.
 ******************************************************************/
 
-static BOOL api_RNetUserEnum(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_RNetUserEnum(connection_struct *conn, uint16 vuid,
+                               char *param, int tpscnt,
+                               char *data, int tdscnt,
+                               int mdrcnt,int mprcnt,
+                               char **rdata,char **rparam,
+                               int *rdata_len,int *rparam_len)
 {
        int count_sent=0;
        int num_users=0;
@@ -2047,9 +2189,13 @@ static BOOL api_RNetUserEnum(connection_struct *conn,uint16 vuid, char *param,ch
        struct pdb_search *search;
        struct samr_displayentry *users;
 
-       char *str1 = param+2;
-       char *str2 = skip_string(str1,1);
-       char *p = skip_string(str2,1);
+       char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
+       char *str2 = skip_string(param,tpscnt,str1);
+       char *p = skip_string(param,tpscnt,str2);
+
+       if (!str1 || !str2 || !p) {
+               return False;
+       }
 
        if (strcmp(str1,"WrLeh") != 0)
                return False;
@@ -2061,13 +2207,16 @@ static BOOL api_RNetUserEnum(connection_struct *conn,uint16 vuid, char *param,ch
          * h -> return parameter total number of users
          */
   
-       resume_context = SVAL(p,0);
-       cli_buf_size=SVAL(p+2,0);
+       resume_context = get_safe_SVAL(param,tpscnt,p,0,-1);
+       cli_buf_size= get_safe_SVAL(param,tpscnt,p,2,0);
        DEBUG(10,("api_RNetUserEnum:resume context: %d, client buffer size: %d\n",
                        resume_context, cli_buf_size));
 
        *rparam_len = 8;
        *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
+       if (!*rparam) {
+               return False;
+       }
 
        /* check it's a supported varient */
        if (strcmp("B21",str2) != 0)
@@ -2075,6 +2224,9 @@ static BOOL api_RNetUserEnum(connection_struct *conn,uint16 vuid, char *param,ch
 
        *rdata_len = cli_buf_size;
        *rdata = SMB_REALLOC_LIMIT(*rdata,*rdata_len);
+       if (!*rdata) {
+               return False;
+       }
 
        p = *rdata;
 
@@ -2127,10 +2279,12 @@ static BOOL api_RNetUserEnum(connection_struct *conn,uint16 vuid, char *param,ch
  Get the time of day info.
 ****************************************************************************/
 
-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)
+static BOOL api_NetRemoteTOD(connection_struct *conn,uint16 vuid,
+                               char *param, int tpscnt,
+                               char *data, int tdscnt,
+                               int mdrcnt,int mprcnt,
+                               char **rdata,char **rparam,
+                               int *rdata_len,int *rparam_len)
 {
        struct tm *t;
        time_t unixdate = time(NULL);
@@ -2138,9 +2292,15 @@ static BOOL api_NetRemoteTOD(connection_struct *conn,uint16 vuid, char *param,ch
 
        *rparam_len = 4;
        *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
+       if (!*rparam) {
+               return False;
+       }
 
        *rdata_len = 21;
        *rdata = SMB_REALLOC_LIMIT(*rdata,*rdata_len);
+       if (!*rdata) {
+               return False;
+       }
 
        SSVAL(*rparam,0,NERR_Success);
        SSVAL(*rparam,2,0);             /* converter word */
@@ -2154,6 +2314,9 @@ static BOOL api_NetRemoteTOD(connection_struct *conn,uint16 vuid, char *param,ch
        /* the client expects to get localtime, not GMT, in this bit 
                (I think, this needs testing) */
        t = localtime(&unixdate);
+       if (!t) {
+               return False;
+       }
 
        SIVAL(p,4,0);           /* msecs ? */
        SCVAL(p,8,t->tm_hour);
@@ -2174,26 +2337,54 @@ static BOOL api_NetRemoteTOD(connection_struct *conn,uint16 vuid, char *param,ch
  Set the user password.
 *****************************************************************************/
 
-static BOOL api_SetUserPassword(connection_struct *conn,uint16 vuid, char *param,char *data,
+static BOOL api_SetUserPassword(connection_struct *conn,uint16 vuid,
+                               char *param, int tpscnt,
+                               char *data, int tdscnt,
                                int mdrcnt,int mprcnt,
                                char **rdata,char **rparam,
                                int *rdata_len,int *rparam_len)
 {
-       char *p = skip_string(param+2,2);
+       char *np = get_safe_str_ptr(param,tpscnt,param,2);
+       char *p = NULL;
        fstring user;
        fstring pass1,pass2;
 
+       /* Skip 2 strings. */
+       p = skip_string(param,tpscnt,np);
+       p = skip_string(param,tpscnt,p);
+
+       if (!np || !p) {
+               return False;
+       }
+
+       /* Do we have a string ? */
+       if (skip_string(param,tpscnt,p) == NULL) {
+               return False;
+       }
        pull_ascii_fstring(user,p);
 
-       p = skip_string(p,1);
+       p = skip_string(param,tpscnt,p);
+       if (!p) {
+               return False;
+       }
 
        memset(pass1,'\0',sizeof(pass1));
        memset(pass2,'\0',sizeof(pass2));
+       /*
+        * We use 31 here not 32 as we're checking
+        * the last byte we want to access is safe.
+        */
+       if (!is_offset_safe(param,tpscnt,p,31)) {
+               return False;
+       }
        memcpy(pass1,p,16);
        memcpy(pass2,p+16,16);
 
        *rparam_len = 4;
        *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
+       if (!*rparam) {
+               return False;
+       }
 
        *rdata_len = 0;
 
@@ -2219,7 +2410,7 @@ static BOOL api_SetUserPassword(connection_struct *conn,uint16 vuid, char *param
                        }
                        unbecome_root();
 
-                       talloc_free(server_info);
+                       TALLOC_FREE(server_info);
                }
                data_blob_clear_free(&password);
        }
@@ -2235,7 +2426,7 @@ static BOOL api_SetUserPassword(connection_struct *conn,uint16 vuid, char *param
         */
 
        if(SVAL(*rparam,0) != NERR_Success) {
-               SAM_ACCOUNT *hnd = NULL;
+               struct samu *hnd = NULL;
 
                if (check_lanman_password(user,(unsigned char *)pass1,(unsigned char *)pass2, &hnd)) {
                        become_root();
@@ -2243,7 +2434,7 @@ static BOOL api_SetUserPassword(connection_struct *conn,uint16 vuid, char *param
                                SSVAL(*rparam,0,NERR_Success);
                        }
                        unbecome_root();
-                       pdb_free_sam(&hnd);
+                       TALLOC_FREE(hnd);
                }
        }
 
@@ -2257,16 +2448,24 @@ static BOOL api_SetUserPassword(connection_struct *conn,uint16 vuid, char *param
   Set the user password (SamOEM version - gets plaintext).
 ****************************************************************************/
 
-static BOOL api_SamOEMChangePassword(connection_struct *conn,uint16 vuid, char *param,char *data,
+static BOOL api_SamOEMChangePassword(connection_struct *conn,uint16 vuid,
+                               char *param, int tpscnt,
+                               char *data, int tdscnt,
                                int mdrcnt,int mprcnt,
                                char **rdata,char **rparam,
                                int *rdata_len,int *rparam_len)
 {
        fstring user;
-       char *p = param + 2;
+       char *p = get_safe_str_ptr(param,tpscnt,param,2);
        *rparam_len = 2;
        *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
+       if (!*rparam) {
+               return False;
+       }
 
+       if (!p) {
+               return False;
+       }
        *rdata_len = 0;
 
        SSVAL(*rparam,0,NERR_badpass);
@@ -2275,17 +2474,35 @@ static BOOL api_SamOEMChangePassword(connection_struct *conn,uint16 vuid, char *
         * Check the parameter definition is correct.
         */
 
-       if(!strequal(param + 2, "zsT")) {
-               DEBUG(0,("api_SamOEMChangePassword: Invalid parameter string %s\n", param + 2));
+       /* Do we have a string ? */
+       if (skip_string(param,tpscnt,p) == 0) {
+               return False;
+       }
+       if(!strequal(p, "zsT")) {
+               DEBUG(0,("api_SamOEMChangePassword: Invalid parameter string %s\n", p));
+               return False;
+       }
+       p = skip_string(param, tpscnt, p);
+       if (!p) {
                return False;
        }
-       p = skip_string(p, 1);
 
+       /* Do we have a string ? */
+       if (skip_string(param,tpscnt,p) == 0) {
+               return False;
+       }
        if(!strequal(p, "B516B16")) {
                DEBUG(0,("api_SamOEMChangePassword: Invalid data parameter string %s\n", p));
                return False;
        }
-       p = skip_string(p,1);
+       p = skip_string(param,tpscnt,p);
+       if (!p) {
+               return False;
+       }
+       /* Do we have a string ? */
+       if (skip_string(param,tpscnt,p) == 0) {
+               return False;
+       }
        p += pull_ascii_fstring(user,p);
 
        DEBUG(3,("api_SamOEMChangePassword: Change password for <%s>\n",user));
@@ -2309,21 +2526,33 @@ static BOOL api_SamOEMChangePassword(connection_struct *conn,uint16 vuid, char *
   Form: <W> <> 
   ****************************************************************************/
 
-static BOOL api_RDosPrintJobDel(connection_struct *conn,uint16 vuid, char *param,char *data,
+static BOOL api_RDosPrintJobDel(connection_struct *conn,uint16 vuid,
+                               char *param, int tpscnt,
+                               char *data, int tdscnt,
                                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 *p = skip_string(str2,1);
+       int function = get_safe_SVAL(param,tpscnt,param,0,0);
+       char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
+       char *str2 = skip_string(param,tpscnt,str1);
+       char *p = skip_string(param,tpscnt,str2);
        uint32 jobid;
        int snum;
        fstring sharename;
        int errcode;
        WERROR werr = WERR_OK;
 
+       if (!str1 || !str2 || !p) {
+               return False;
+       }
+       /*
+        * We use 1 here not 2 as we're checking
+        * the last byte we want to access is safe.
+        */
+       if (!is_offset_safe(param,tpscnt,p,1)) {
+               return False;
+       }
        if(!rap_to_pjobid(SVAL(p,0), sharename, &jobid))
                return False;
 
@@ -2333,6 +2562,9 @@ static BOOL api_RDosPrintJobDel(connection_struct *conn,uint16 vuid, char *param
 
        *rparam_len = 4;
        *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);       
+       if (!*rparam) {
+               return False;
+       }
        *rdata_len = 0;
 
        if (!print_job_exists(sharename, jobid)) {
@@ -2377,27 +2609,39 @@ static BOOL api_RDosPrintJobDel(connection_struct *conn,uint16 vuid, char *param
   Purge a print queue - or pause or resume it.
   ****************************************************************************/
 
-static BOOL api_WPrintQueueCtrl(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_WPrintQueueCtrl(connection_struct *conn,uint16 vuid,
+                               char *param, int tpscnt,
+                               char *data, int tdscnt,
+                               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);
+       int function = get_safe_SVAL(param,tpscnt,param,0,0);
+       char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
+       char *str2 = skip_string(param,tpscnt,str1);
+       char *QueueName = skip_string(param,tpscnt,str2);
        int errcode = NERR_notsupported;
        int snum;
        WERROR werr = WERR_OK;
 
+       if (!str1 || !str2 || !QueueName) {
+               return False;
+       }
+
        /* check it's a supported varient */
        if (!(strcsequal(str1,"z") && strcsequal(str2,"")))
                return(False);
 
        *rparam_len = 4;
        *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
+       if (!*rparam) {
+               return False;
+       }
        *rdata_len = 0;
 
+       if (skip_string(param,tpscnt,QueueName) == NULL) {
+               return False;
+       }
        snum = print_queue_snum(QueueName);
 
        if (snum == -1) {
@@ -2444,36 +2688,57 @@ static int check_printjob_info(struct pack_desc* desc,
        case 2: desc->format = "WWzWWDDzz"; break;
        case 3: desc->format = "WWzWWDDzzzzzzzzzzlz"; break;
        case 4: desc->format = "WWzWWDDzzzzzDDDDDDD"; break;
-       default: return False;
+       default:
+               DEBUG(0,("check_printjob_info: invalid level %d\n",
+                       uLevel ));
+               return False;
+       }
+       if (id == NULL || strcmp(desc->format,id) != 0) {
+               DEBUG(0,("check_printjob_info: invalid format %s\n",
+                       id ? id : "<NULL>" ));
+               return False;
        }
-       if (strcmp(desc->format,id) != 0) return False;
        return True;
 }
 
-static BOOL api_PrintJobInfo(connection_struct *conn,uint16 vuid,char *param,char *data,
-                            int mdrcnt,int mprcnt,
-                            char **rdata,char **rparam,
-                            int *rdata_len,int *rparam_len)
+static BOOL api_PrintJobInfo(connection_struct *conn, uint16 vuid,
+                               char *param, int tpscnt,
+                               char *data, int tdscnt,
+                               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);
+       char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
+       char *str2 = skip_string(param,tpscnt,str1);
+       char *p = skip_string(param,tpscnt,str2);
        uint32 jobid;
-       int snum;
        fstring sharename;
-       int uLevel = SVAL(p,2);
-       int function = SVAL(p,4);
+       int uLevel = get_safe_SVAL(param,tpscnt,p,2,-1);
+       int function = get_safe_SVAL(param,tpscnt,p,4,-1);
        int place, errcode;
 
+       if (!str1 || !str2 || !p) {
+               return False;
+       }
+       /*
+        * We use 1 here not 2 as we're checking
+        * the last byte we want to access is safe.
+        */
+       if (!is_offset_safe(param,tpscnt,p,1)) {
+               return False;
+       }
        if(!rap_to_pjobid(SVAL(p,0), sharename, &jobid))
                return False;
        *rparam_len = 4;
        *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
+       if (!*rparam) {
+               return False;
+       }
 
-       if ( (snum = lp_servicenumber(sharename)) == -1 ) {
-               DEBUG(0,("api_PrintJobInfo: unable to get service number from sharename [%s]\n",
-                       sharename));
+       if (!share_defined(sharename)) {
+               DEBUG(0,("api_PrintJobInfo: sharen [%s] not defined\n",
+                        sharename));
                return False;
        }
   
@@ -2496,14 +2761,14 @@ static BOOL api_PrintJobInfo(connection_struct *conn,uint16 vuid,char *param,cha
                /* change job place in the queue, 
                   data gives the new place */
                place = SVAL(data,0);
-               if (print_job_set_place(snum, jobid, place)) {
+               if (print_job_set_place(sharename, jobid, place)) {
                        errcode=NERR_Success;
                }
                break;
 
        case 0xb:   
                /* change print job name, data gives the name */
-               if (print_job_set_name(snum, jobid, data)) {
+               if (print_job_set_name(sharename, jobid, data)) {
                        errcode=NERR_Success;
                }
                break;
@@ -2524,18 +2789,24 @@ static BOOL api_PrintJobInfo(connection_struct *conn,uint16 vuid,char *param,cha
  Get info about the server.
 ****************************************************************************/
 
-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)
+static BOOL api_RNetServerGetInfo(connection_struct *conn,uint16 vuid,
+                               char *param, int tpscnt,
+                               char *data, int tdscnt,
+                               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);
+       char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
+       char *str2 = skip_string(param,tpscnt,str1);
+       char *p = skip_string(param,tpscnt,str2);
+       int uLevel = get_safe_SVAL(param,tpscnt,p,0,-1);
        char *p2;
        int struct_len;
 
+       if (!str1 || !str2 || !p) {
+               return False;
+       }
+
        DEBUG(4,("NetServerGetInfo level %d\n",uLevel));
 
        /* check it's a supported varient */
@@ -2586,11 +2857,14 @@ static BOOL api_RNetServerGetInfo(connection_struct *conn,uint16 vuid, char *par
 
        *rdata_len = mdrcnt;
        *rdata = SMB_REALLOC_LIMIT(*rdata,*rdata_len);
+       if (!*rdata) {
+               return False;
+       }
 
        p = *rdata;
        p2 = p + struct_len;
        if (uLevel != 20) {
-               srvstr_push(NULL, p,get_local_machine_name(),16, 
+               srvstr_push(NULL, p,global_myname(),16, 
                        STR_ASCII|STR_UPPER|STR_TERMINATE);
        }
        p += 16;
@@ -2604,7 +2878,7 @@ static BOOL api_RNetServerGetInfo(connection_struct *conn,uint16 vuid, char *par
 
                if ((count=get_server_info(SV_TYPE_ALL,&servers,lp_workgroup()))>0) {
                        for (i=0;i<count;i++) {
-                               if (strequal(servers[i].name,get_local_machine_name())) {
+                               if (strequal(servers[i].name,global_myname())) {
                                        servertype = servers[i].type;
                                        push_ascii(comment,servers[i].comment,sizeof(pstring),STR_TERMINATE);
                                }
@@ -2621,9 +2895,16 @@ static BOOL api_RNetServerGetInfo(connection_struct *conn,uint16 vuid, char *par
                        SIVAL(p,6,0);
                } else {
                        SIVAL(p,6,PTR_DIFF(p2,*rdata));
-                       standard_sub_conn(conn,comment,sizeof(comment));
+                       standard_sub_advanced(lp_servicename(SNUM(conn)), conn->user,
+                                             conn->connectpath, conn->gid,
+                                             get_current_username(),
+                                             current_user_info.domain,
+                                             comment, sizeof(comment));
                        StrnCpy(p2,comment,MAX(mdrcnt - struct_len,0));
-                       p2 = skip_string(p2,1);
+                       p2 = skip_string(*rdata,*rdata_len,p2);
+                       if (!p2) {
+                               return False;
+                       }
                }
        }
 
@@ -2635,6 +2916,9 @@ static BOOL api_RNetServerGetInfo(connection_struct *conn,uint16 vuid, char *par
 
        *rparam_len = 6;
        *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
+       if (!*rparam) {
+               return False;
+       }
        SSVAL(*rparam,0,NERR_Success);
        SSVAL(*rparam,2,0);             /* converter word */
        SSVAL(*rparam,4,*rdata_len);
@@ -2646,21 +2930,30 @@ static BOOL api_RNetServerGetInfo(connection_struct *conn,uint16 vuid, char *par
  Get info about the server.
 ****************************************************************************/
 
-static BOOL api_NetWkstaGetInfo(connection_struct *conn,uint16 vuid, char *param,char *data,
+static BOOL api_NetWkstaGetInfo(connection_struct *conn,uint16 vuid,
+                               char *param, int tpscnt,
+                               char *data, int tdscnt,
                                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);
+       char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
+       char *str2 = skip_string(param,tpscnt,str1);
+       char *p = skip_string(param,tpscnt,str2);
        char *p2;
-       int level = SVAL(p,0);
+       int level = get_safe_SVAL(param,tpscnt,p,0,-1);
+
+       if (!str1 || !str2 || !p) {
+               return False;
+       }
 
        DEBUG(4,("NetWkstaGetInfo level %d\n",level));
 
        *rparam_len = 6;
        *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
+       if (!*rparam) {
+               return False;
+       }
 
        /* check it's a supported varient */
        if (!(level==10 && strcsequal(str1,"WrLh") && strcsequal(str2,"zzzBBzz"))) {
@@ -2669,28 +2962,43 @@ static BOOL api_NetWkstaGetInfo(connection_struct *conn,uint16 vuid, char *param
 
        *rdata_len = mdrcnt + 1024;
        *rdata = SMB_REALLOC_LIMIT(*rdata,*rdata_len);
+       if (!*rdata) {
+               return False;
+       }
 
        SSVAL(*rparam,0,NERR_Success);
        SSVAL(*rparam,2,0);             /* converter word */
 
        p = *rdata;
-       p2 = p + 22;
+       p2 = get_safe_ptr(*rdata,*rdata_len,p,22);
+       if (!p2) {
+               return False;
+       }
 
        SIVAL(p,0,PTR_DIFF(p2,*rdata)); /* host name */
        pstrcpy(p2,get_local_machine_name());
        strupper_m(p2);
-       p2 = skip_string(p2,1);
+       p2 = skip_string(*rdata,*rdata_len,p2);
+       if (!p2) {
+               return False;
+       }
        p += 4;
 
        SIVAL(p,0,PTR_DIFF(p2,*rdata));
        pstrcpy(p2,current_user_info.smb_name);
-       p2 = skip_string(p2,1);
+       p2 = skip_string(*rdata,*rdata_len,p2);
+       if (!p2) {
+               return False;
+       }
        p += 4;
 
        SIVAL(p,0,PTR_DIFF(p2,*rdata)); /* login domain */
        pstrcpy(p2,lp_workgroup());
        strupper_m(p2);
-       p2 = skip_string(p2,1);
+       p2 = skip_string(*rdata,*rdata_len,p2);
+       if (!p2) {
+               return False;
+       }
        p += 4;
 
        SCVAL(p,0,lp_major_announce_version()); /* system version - e.g 4 in 4.1 */
@@ -2699,12 +3007,18 @@ static BOOL api_NetWkstaGetInfo(connection_struct *conn,uint16 vuid, char *param
 
        SIVAL(p,0,PTR_DIFF(p2,*rdata));
        pstrcpy(p2,lp_workgroup());     /* don't know.  login domain?? */
-       p2 = skip_string(p2,1);
+       p2 = skip_string(*rdata,*rdata_len,p2);
+       if (!p2) {
+               return False;
+       }
        p += 4;
 
        SIVAL(p,0,PTR_DIFF(p2,*rdata)); /* don't know */
        pstrcpy(p2,"");
-       p2 = skip_string(p2,1);
+       p2 = skip_string(*rdata,*rdata_len,p2);
+       if (!p2) {
+               return False;
+       }
        p += 4;
 
        *rdata_len = PTR_DIFF(p2,*rdata);
@@ -2884,16 +3198,18 @@ There is no auxiliary data in the response.
 #define AF_OP_ACCOUNTS  3
 
 
-static BOOL api_RNetUserGetInfo(connection_struct *conn,uint16 vuid, char *param,char *data,
+static BOOL api_RNetUserGetInfo(connection_struct *conn, uint16 vuid,
+                               char *param, int tpscnt,
+                               char *data, int tdscnt,
                                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 *str1 = get_safe_str_ptr(param,tpscnt,param,2);
+       char *str2 = skip_string(param,tpscnt,str1);
+       char *UserName = skip_string(param,tpscnt,str2);
+       char *p = skip_string(param,tpscnt,UserName);
+       int uLevel = get_safe_SVAL(param,tpscnt,p,0,-1);
        char *p2;
        const char *level_string;
 
@@ -2906,8 +3222,15 @@ static BOOL api_RNetUserGetInfo(connection_struct *conn,uint16 vuid, char *param
                        vuser->user.unix_name));
        }
 
+       if (!str1 || !str2 || !UserName || !p) {
+               return False;
+       }
+
        *rparam_len = 6;
        *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
+       if (!*rparam) {
+               return False;
+       }
 
        DEBUG(4,("RNetUserGetInfo level=%d\n", uLevel));
   
@@ -2930,12 +3253,18 @@ static BOOL api_RNetUserGetInfo(connection_struct *conn,uint16 vuid, char *param
 
        *rdata_len = mdrcnt + 1024;
        *rdata = SMB_REALLOC_LIMIT(*rdata,*rdata_len);
+       if (!*rdata) {
+               return False;
+       }
 
        SSVAL(*rparam,0,NERR_Success);
        SSVAL(*rparam,2,0);             /* converter word */
 
        p = *rdata;
-       p2 = p + usri11_end;
+       p2 = get_safe_ptr(*rdata,*rdata_len,p,usri11_end);
+       if (!p2) {
+               return False;
+       }
 
        memset(p,0,21); 
        fstrcpy(p+usri11_name,UserName); /* 21 bytes - user name */
@@ -2948,16 +3277,25 @@ static BOOL api_RNetUserGetInfo(connection_struct *conn,uint16 vuid, char *param
        if (uLevel >= 10) {
                SIVAL(p,usri11_comment,PTR_DIFF(p2,p)); /* comment */
                pstrcpy(p2,"Comment");
-               p2 = skip_string(p2,1);
+               p2 = skip_string(*rdata,*rdata_len,p2);
+               if (!p2) {
+                       return False;
+               }
 
                SIVAL(p,usri11_usr_comment,PTR_DIFF(p2,p)); /* user_comment */
                pstrcpy(p2,"UserComment");
-               p2 = skip_string(p2,1);
+               p2 = skip_string(*rdata,*rdata_len,p2);
+               if (!p2) {
+                       return False;
+               }
 
                /* EEK! the cifsrap.txt doesn't have this in!!!! */
                SIVAL(p,usri11_full_name,PTR_DIFF(p2,p)); /* full name */
                pstrcpy(p2,((vuser != NULL) ? vuser->user.full_name : UserName));
-               p2 = skip_string(p2,1);
+               p2 = skip_string(*rdata,*rdata_len,p2);
+               if (!p2) {
+                       return False;
+               }
        }
 
        if (uLevel == 11) {
@@ -2967,22 +3305,34 @@ static BOOL api_RNetUserGetInfo(connection_struct *conn,uint16 vuid, char *param
                SIVALS(p,usri11_password_age,-1);               /* password age */
                SIVAL(p,usri11_homedir,PTR_DIFF(p2,p)); /* home dir */
                pstrcpy(p2, vuser && vuser->homedir ? vuser->homedir : "");
-               p2 = skip_string(p2,1);
+               p2 = skip_string(*rdata,*rdata_len,p2);
+               if (!p2) {
+                       return False;
+               }
                SIVAL(p,usri11_parms,PTR_DIFF(p2,p)); /* parms */
                pstrcpy(p2,"");
-               p2 = skip_string(p2,1);
+               p2 = skip_string(*rdata,*rdata_len,p2);
+               if (!p2) {
+                       return False;
+               }
                SIVAL(p,usri11_last_logon,0);           /* last logon */
                SIVAL(p,usri11_last_logoff,0);          /* last logoff */
                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 */
                pstrcpy(p2,"\\\\*");
-               p2 = skip_string(p2,1);
+               p2 = skip_string(*rdata,*rdata_len,p2);
+               if (!p2) {
+                       return False;
+               }
                SSVAL(p,usri11_country_code,0);         /* country code */
 
                SIVAL(p,usri11_workstations,PTR_DIFF(p2,p)); /* workstations */
                pstrcpy(p2,"");
-               p2 = skip_string(p2,1);
+               p2 = skip_string(*rdata,*rdata_len,p2);
+               if (!p2) {
+                       return False;
+               }
 
                SIVALS(p,usri11_max_storage,-1);                /* max storage */
                SSVAL(p,usri11_units_per_week,168);             /* units per week */
@@ -2991,7 +3341,10 @@ static BOOL api_RNetUserGetInfo(connection_struct *conn,uint16 vuid, char *param
                /* 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);
+               p2 = skip_string(*rdata,*rdata_len,p2);
+               if (!p2) {
+                       return False;
+               }
 
                SSVAL(p,usri11_code_page,0);            /* code page */
        }
@@ -3003,22 +3356,34 @@ static BOOL api_RNetUserGetInfo(connection_struct *conn,uint16 vuid, char *param
                conn->admin_user?USER_PRIV_ADMIN:USER_PRIV_USER);
                SIVAL(p,44,PTR_DIFF(p2,*rdata)); /* home dir */
                pstrcpy(p2, vuser && vuser->homedir ? vuser->homedir : "");
-               p2 = skip_string(p2,1);
+               p2 = skip_string(*rdata,*rdata_len,p2);
+               if (!p2) {
+                       return False;
+               }
                SIVAL(p,48,PTR_DIFF(p2,*rdata)); /* comment */
                *p2++ = 0;
                SSVAL(p,52,0);          /* flags */
                SIVAL(p,54,PTR_DIFF(p2,*rdata));                /* script_path */
                pstrcpy(p2,vuser && vuser->logon_script ? vuser->logon_script : "");
-               p2 = skip_string(p2,1);
+               p2 = skip_string(*rdata,*rdata_len,p2);
+               if (!p2) {
+                       return False;
+               }
                if (uLevel == 2) {
                        SIVAL(p,60,0);          /* auth_flags */
                        SIVAL(p,64,PTR_DIFF(p2,*rdata)); /* full_name */
                        pstrcpy(p2,((vuser != NULL) ? vuser->user.full_name : UserName));
-                       p2 = skip_string(p2,1);
+                       p2 = skip_string(*rdata,*rdata_len,p2);
+                       if (!p2) {
+                               return False;
+                       }
                        SIVAL(p,68,0);          /* urs_comment */
                        SIVAL(p,72,PTR_DIFF(p2,*rdata)); /* parms */
                        pstrcpy(p2,"");
-                       p2 = skip_string(p2,1);
+                       p2 = skip_string(*rdata,*rdata_len,p2);
+                       if (!p2) {
+                               return False;
+                       }
                        SIVAL(p,76,0);          /* workstations */
                        SIVAL(p,80,0);          /* last_logon */
                        SIVAL(p,84,0);          /* last_logoff */
@@ -3031,9 +3396,16 @@ static BOOL api_RNetUserGetInfo(connection_struct *conn,uint16 vuid, char *param
                        SSVALS(p,102,-1);       /* bad_pw_count */
                        SSVALS(p,104,-1);       /* num_logons */
                        SIVAL(p,106,PTR_DIFF(p2,*rdata)); /* logon_server */
-                       pstrcpy(p2,"\\\\%L");
-                       standard_sub_conn(conn, p2,0);
-                       p2 = skip_string(p2,1);
+                       {
+                               pstring tmp;
+                               pstrcpy(tmp, "\\\\%L");
+                               standard_sub_basic("", "", tmp, sizeof(tmp));
+                               pstrcpy(p2, tmp);
+                       }
+                       p2 = skip_string(*rdata,*rdata_len,p2);
+                       if (!p2) {
+                               return False;
+                       }
                        SSVAL(p,110,49);        /* country_code */
                        SSVAL(p,112,860);       /* code page */
                }
@@ -3046,14 +3418,16 @@ static BOOL api_RNetUserGetInfo(connection_struct *conn,uint16 vuid, char *param
        return(True);
 }
 
-static BOOL api_WWkstaUserLogon(connection_struct *conn,uint16 vuid, char *param,char *data,
+static BOOL api_WWkstaUserLogon(connection_struct *conn,uint16 vuid,
+                               char *param, int tpscnt,
+                               char *data, int tdscnt,
                                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);
+       char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
+       char *str2 = skip_string(param,tpscnt,str1);
+       char *p = skip_string(param,tpscnt,str2);
        int uLevel;
        struct pack_desc desc;
        char* name;
@@ -3061,13 +3435,20 @@ static BOOL api_WWkstaUserLogon(connection_struct *conn,uint16 vuid, char *param
                   Don't depend on vuser being non-null !!. JRA */
        user_struct *vuser = get_valid_user_struct(vuid);
 
+       if (!str1 || !str2 || !p) {
+               return False;
+       }
+
        if(vuser != NULL) {
                DEBUG(3,("  Username of UID %d is %s\n", (int)vuser->uid, 
                        vuser->user.unix_name));
        }
 
-       uLevel = SVAL(p,0);
-       name = p + 2;
+       uLevel = get_safe_SVAL(param,tpscnt,p,0,-1);
+       name = get_safe_str_ptr(param,tpscnt,p,2);
+       if (!name) {
+               return False;
+       }
 
        memset((char *)&desc,'\0',sizeof(desc));
 
@@ -3082,6 +3463,9 @@ static BOOL api_WWkstaUserLogon(connection_struct *conn,uint16 vuid, char *param
        }
        if (mdrcnt > 0) {
                *rdata = SMB_REALLOC_LIMIT(*rdata,mdrcnt);
+               if (!*rdata) {
+                       return False;
+               }
        }
 
        desc.base = *rdata;
@@ -3121,6 +3505,9 @@ static BOOL api_WWkstaUserLogon(connection_struct *conn,uint16 vuid, char *param
        *rdata_len = desc.usedlen;
        *rparam_len = 6;
        *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
+       if (!*rparam) {
+               return False;
+       }
        SSVALS(*rparam,0,desc.errcode);
        SSVAL(*rparam,2,0);
        SSVAL(*rparam,4,desc.neededlen);
@@ -3134,16 +3521,25 @@ static BOOL api_WWkstaUserLogon(connection_struct *conn,uint16 vuid, char *param
  api_WAccessGetUserPerms
 ****************************************************************************/
 
-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)
+static BOOL api_WAccessGetUserPerms(connection_struct *conn,uint16 vuid,
+                               char *param, int tpscnt,
+                               char *data, int tdscnt,
+                               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 *user = skip_string(str2,1);
-       char *resource = skip_string(user,1);
+       char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
+       char *str2 = skip_string(param,tpscnt,str1);
+       char *user = skip_string(param,tpscnt,str2);
+       char *resource = skip_string(param,tpscnt,user);
 
+       if (!str1 || !str2 || !user || !resource) {
+               return False;
+       }
+
+       if (skip_string(param,tpscnt,resource) == NULL) {
+               return False;
+       }
        DEBUG(3,("WAccessGetUserPerms user=%s resource=%s\n",user,resource));
 
        /* check it's a supported varient */
@@ -3156,6 +3552,9 @@ static BOOL api_WAccessGetUserPerms(connection_struct *conn,uint16 vuid, char *p
 
        *rparam_len = 6;
        *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
+       if (!*rparam) {
+               return False;
+       }
        SSVALS(*rparam,0,0);            /* errorcode */
        SSVAL(*rparam,2,0);             /* converter word */
        SSVAL(*rparam,4,0x7f);  /* permission flags */
@@ -3167,14 +3566,16 @@ static BOOL api_WAccessGetUserPerms(connection_struct *conn,uint16 vuid, char *p
   api_WPrintJobEnumerate
   ****************************************************************************/
 
-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)
+static BOOL api_WPrintJobGetInfo(connection_struct *conn, uint16 vuid,
+                               char *param, int tpscnt,
+                               char *data, int tdscnt,
+                               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);
+       char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
+       char *str2 = skip_string(param,tpscnt,str1);
+       char *p = skip_string(param,tpscnt,str2);
        int uLevel;
        int count;
        int i;
@@ -3186,7 +3587,11 @@ static BOOL api_WPrintJobGetInfo(connection_struct *conn,uint16 vuid, char *para
        print_status_struct status;
        char *tmpdata=NULL;
 
-       uLevel = SVAL(p,2);
+       if (!str1 || !str2 || !p) {
+               return False;
+       }
+
+       uLevel = get_safe_SVAL(param,tpscnt,p,2,-1);
 
        memset((char *)&desc,'\0',sizeof(desc));
        memset((char *)&status,'\0',sizeof(status));
@@ -3219,6 +3624,9 @@ static BOOL api_WPrintJobGetInfo(connection_struct *conn,uint16 vuid, char *para
 
        if (mdrcnt > 0) {
                *rdata = SMB_REALLOC_LIMIT(*rdata,mdrcnt);
+               if (!*rdata) {
+                       return False;
+               }
                desc.base = *rdata;
                desc.buflen = mdrcnt;
        } else {
@@ -3242,6 +3650,9 @@ static BOOL api_WPrintJobGetInfo(connection_struct *conn,uint16 vuid, char *para
 
        *rparam_len = 6;
        *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
+       if (!*rparam) {
+               return False;
+       }
        SSVALS(*rparam,0,desc.errcode);
        SSVAL(*rparam,2,0);
        SSVAL(*rparam,4,desc.neededlen);
@@ -3254,15 +3665,17 @@ static BOOL api_WPrintJobGetInfo(connection_struct *conn,uint16 vuid, char *para
        return True;
 }
 
-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)
+static BOOL api_WPrintJobEnumerate(connection_struct *conn, uint16 vuid,
+                               char *param, int tpscnt,
+                               char *data, int tdscnt,
+                               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);
-       charname = p;
+       char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
+       char *str2 = skip_string(param,tpscnt,str1);
+       char *p = skip_string(param,tpscnt,str2);
+       char *name = p;
        int uLevel;
        int count;
        int i, succnt=0;
@@ -3271,11 +3684,18 @@ static BOOL api_WPrintJobEnumerate(connection_struct *conn,uint16 vuid, char *pa
        print_queue_struct *queue=NULL;
        print_status_struct status;
 
+       if (!str1 || !str2 || !p) {
+               return False;
+       }
+
        memset((char *)&desc,'\0',sizeof(desc));
        memset((char *)&status,'\0',sizeof(status));
 
-       p = skip_string(p,1);
-       uLevel = SVAL(p,0);
+       p = skip_string(param,tpscnt,p);
+       if (!p) {
+               return False;
+       }
+       uLevel = get_safe_SVAL(param,tpscnt,p,0,-1);
 
        DEBUG(3,("WPrintJobEnumerate uLevel=%d name=%s\n",uLevel,name));
 
@@ -3300,6 +3720,9 @@ static BOOL api_WPrintJobEnumerate(connection_struct *conn,uint16 vuid, char *pa
        count = print_queue_status(snum,&queue,&status);
        if (mdrcnt > 0) {
                *rdata = SMB_REALLOC_LIMIT(*rdata,mdrcnt);
+               if (!*rdata) {
+                       return False;
+               }
        }
        desc.base = *rdata;
        desc.buflen = mdrcnt;
@@ -3318,6 +3741,9 @@ static BOOL api_WPrintJobEnumerate(connection_struct *conn,uint16 vuid, char *pa
 
        *rparam_len = 8;
        *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
+       if (!*rparam) {
+               return False;
+       }
        SSVALS(*rparam,0,desc.errcode);
        SSVAL(*rparam,2,0);
        SSVAL(*rparam,4,succnt);
@@ -3348,9 +3774,13 @@ static int check_printdest_info(struct pack_desc* desc,
                        desc->format = "zzzWWzzzWW";
                        break;
                default:
+                       DEBUG(0,("check_printdest_info: invalid level %d\n",
+                               uLevel));
                        return False;
        }
-       if (strcmp(desc->format,id) != 0) {
+       if (id == NULL || strcmp(desc->format,id) != 0) {
+               DEBUG(0,("check_printdest_info: invalid string %s\n", 
+                       id ? id : "<NULL>" ));
                return False;
        }
        return True;
@@ -3392,24 +3822,33 @@ static void fill_printdest_info(connection_struct *conn, int snum, int uLevel,
        }
 }
 
-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)
+static BOOL api_WPrintDestGetInfo(connection_struct *conn, uint16 vuid,
+                               char *param, int tpscnt,
+                               char *data, int tdscnt,
+                               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);
+       char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
+       char *str2 = skip_string(param,tpscnt,str1);
+       char *p = skip_string(param,tpscnt,str2);
        char* PrinterName = p;
        int uLevel;
        struct pack_desc desc;
        int snum;
        char *tmpdata=NULL;
 
+       if (!str1 || !str2 || !p) {
+               return False;
+       }
+
        memset((char *)&desc,'\0',sizeof(desc));
 
-       p = skip_string(p,1);
-       uLevel = SVAL(p,0);
+       p = skip_string(param,tpscnt,p);
+       if (!p) {
+               return False;
+       }
+       uLevel = get_safe_SVAL(param,tpscnt,p,0,-1);
 
        DEBUG(3,("WPrintDestGetInfo uLevel=%d PrinterName=%s\n",uLevel,PrinterName));
 
@@ -3429,6 +3868,9 @@ static BOOL api_WPrintDestGetInfo(connection_struct *conn,uint16 vuid, char *par
        } else {
                if (mdrcnt > 0) {
                        *rdata = SMB_REALLOC_LIMIT(*rdata,mdrcnt);
+                       if (!*rdata) {
+                               return False;
+                       }
                        desc.base = *rdata;
                        desc.buflen = mdrcnt;
                } else {
@@ -3447,6 +3889,9 @@ static BOOL api_WPrintDestGetInfo(connection_struct *conn,uint16 vuid, char *par
 
        *rparam_len = 6;
        *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
+       if (!*rparam) {
+               return False;
+       }
        SSVALS(*rparam,0,desc.errcode);
        SSVAL(*rparam,2,0);
        SSVAL(*rparam,4,desc.neededlen);
@@ -3457,23 +3902,29 @@ static BOOL api_WPrintDestGetInfo(connection_struct *conn,uint16 vuid, char *par
        return True;
 }
 
-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)
+static BOOL api_WPrintDestEnum(connection_struct *conn, uint16 vuid,
+                               char *param, int tpscnt,
+                               char *data, int tdscnt,
+                               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);
+       char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
+       char *str2 = skip_string(param,tpscnt,str1);
+       char *p = skip_string(param,tpscnt,str2);
        int uLevel;
        int queuecnt;
        int i, n, succnt=0;
        struct pack_desc desc;
        int services = lp_numservices();
 
+       if (!str1 || !str2 || !p) {
+               return False;
+       }
+
        memset((char *)&desc,'\0',sizeof(desc));
 
-       uLevel = SVAL(p,0);
+       uLevel = get_safe_SVAL(param,tpscnt,p,0,-1);
 
        DEBUG(3,("WPrintDestEnum uLevel=%d\n",uLevel));
 
@@ -3494,6 +3945,9 @@ static BOOL api_WPrintDestEnum(connection_struct *conn,uint16 vuid, char *param,
 
        if (mdrcnt > 0) {
                *rdata = SMB_REALLOC_LIMIT(*rdata,mdrcnt);
+               if (!*rdata) {
+                       return False;
+               }
        }
 
        desc.base = *rdata;
@@ -3516,6 +3970,9 @@ static BOOL api_WPrintDestEnum(connection_struct *conn,uint16 vuid, char *param,
 
        *rparam_len = 8;
        *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
+       if (!*rparam) {
+               return False;
+       }
        SSVALS(*rparam,0,desc.errcode);
        SSVAL(*rparam,2,0);
        SSVAL(*rparam,4,succnt);
@@ -3526,21 +3983,27 @@ static BOOL api_WPrintDestEnum(connection_struct *conn,uint16 vuid, char *param,
        return True;
 }
 
-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)
+static BOOL api_WPrintDriverEnum(connection_struct *conn, uint16 vuid,
+                               char *param, int tpscnt,
+                               char *data, int tdscnt,
+                               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);
+       char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
+       char *str2 = skip_string(param,tpscnt,str1);
+       char *p = skip_string(param,tpscnt,str2);
        int uLevel;
        int succnt;
        struct pack_desc desc;
 
+       if (!str1 || !str2 || !p) {
+               return False;
+       }
+
        memset((char *)&desc,'\0',sizeof(desc));
 
-       uLevel = SVAL(p,0);
+       uLevel = get_safe_SVAL(param,tpscnt,p,0,-1);
 
        DEBUG(3,("WPrintDriverEnum uLevel=%d\n",uLevel));
 
@@ -3554,6 +4017,9 @@ static BOOL api_WPrintDriverEnum(connection_struct *conn,uint16 vuid, char *para
 
        if (mdrcnt > 0) {
                *rdata = SMB_REALLOC_LIMIT(*rdata,mdrcnt);
+               if (!*rdata) {
+                       return False;
+               }
        }
        desc.base = *rdata;
        desc.buflen = mdrcnt;
@@ -3567,6 +4033,9 @@ static BOOL api_WPrintDriverEnum(connection_struct *conn,uint16 vuid, char *para
 
        *rparam_len = 8;
        *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
+       if (!*rparam) {
+               return False;
+       }
        SSVALS(*rparam,0,desc.errcode);
        SSVAL(*rparam,2,0);
        SSVAL(*rparam,4,succnt);
@@ -3577,21 +4046,26 @@ static BOOL api_WPrintDriverEnum(connection_struct *conn,uint16 vuid, char *para
        return True;
 }
 
-static BOOL api_WPrintQProcEnum(connection_struct *conn,uint16 vuid, char *param,char *data,
+static BOOL api_WPrintQProcEnum(connection_struct *conn, uint16 vuid,
+                               char *param, int tpscnt,
+                               char *data, int tdscnt,
                                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);
+       char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
+       char *str2 = skip_string(param,tpscnt,str1);
+       char *p = skip_string(param,tpscnt,str2);
        int uLevel;
        int succnt;
        struct pack_desc desc;
 
+       if (!str1 || !str2 || !p) {
+               return False;
+       }
        memset((char *)&desc,'\0',sizeof(desc));
 
-       uLevel = SVAL(p,0);
+       uLevel = get_safe_SVAL(param,tpscnt,p,0,-1);
 
        DEBUG(3,("WPrintQProcEnum uLevel=%d\n",uLevel));
 
@@ -3605,6 +4079,9 @@ static BOOL api_WPrintQProcEnum(connection_struct *conn,uint16 vuid, char *param
 
        if (mdrcnt > 0) {
                *rdata = SMB_REALLOC_LIMIT(*rdata,mdrcnt);
+               if (!*rdata) {
+                       return False;
+               }
        }
        desc.base = *rdata;
        desc.buflen = mdrcnt;
@@ -3619,6 +4096,9 @@ static BOOL api_WPrintQProcEnum(connection_struct *conn,uint16 vuid, char *param
 
        *rparam_len = 8;
        *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
+       if (!*rparam) {
+               return False;
+       }
        SSVALS(*rparam,0,desc.errcode);
        SSVAL(*rparam,2,0);
        SSVAL(*rparam,4,succnt);
@@ -3629,21 +4109,27 @@ static BOOL api_WPrintQProcEnum(connection_struct *conn,uint16 vuid, char *param
        return True;
 }
 
-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)
+static BOOL api_WPrintPortEnum(connection_struct *conn, uint16 vuid,
+                               char *param, int tpscnt,
+                               char *data, int tdscnt,
+                               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);
+       char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
+       char *str2 = skip_string(param,tpscnt,str1);
+       char *p = skip_string(param,tpscnt,str2);
        int uLevel;
        int succnt;
        struct pack_desc desc;
 
+       if (!str1 || !str2 || !p) {
+               return False;
+       }
+
        memset((char *)&desc,'\0',sizeof(desc));
 
-       uLevel = SVAL(p,0);
+       uLevel = get_safe_SVAL(param,tpscnt,p,0,-1);
 
        DEBUG(3,("WPrintPortEnum uLevel=%d\n",uLevel));
 
@@ -3657,6 +4143,9 @@ static BOOL api_WPrintPortEnum(connection_struct *conn,uint16 vuid, char *param,
 
        if (mdrcnt > 0) {
                *rdata = SMB_REALLOC_LIMIT(*rdata,mdrcnt);
+               if (!*rdata) {
+                       return False;
+               }
        }
        memset((char *)&desc,'\0',sizeof(desc));
        desc.base = *rdata;
@@ -3672,6 +4161,9 @@ static BOOL api_WPrintPortEnum(connection_struct *conn,uint16 vuid, char *param,
 
        *rparam_len = 8;
        *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
+       if (!*rparam) {
+               return False;
+       }
        SSVALS(*rparam,0,desc.errcode);
        SSVAL(*rparam,2,0);
        SSVAL(*rparam,4,succnt);
@@ -3682,27 +4174,33 @@ static BOOL api_WPrintPortEnum(connection_struct *conn,uint16 vuid, char *param,
        return True;
 }
 
-
 /****************************************************************************
  List open sessions
  ****************************************************************************/
-static BOOL api_RNetSessionEnum(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_RNetSessionEnum(connection_struct *conn, uint16 vuid,
+                               char *param, int tpscnt,
+                               char *data, int tdscnt,
+                               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);
+       char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
+       char *str2 = skip_string(param,tpscnt,str1);
+       char *p = skip_string(param,tpscnt,str2);
        int uLevel;
        struct pack_desc desc;
        struct sessionid *session_list;
        int i, num_sessions;
 
+       if (!str1 || !str2 || !p) {
+               return False;
+       }
+
        memset((char *)&desc,'\0',sizeof(desc));
 
-       uLevel = SVAL(p,0);
+       uLevel = get_safe_SVAL(param,tpscnt,p,0,-1);
 
        DEBUG(3,("RNetSessionEnum uLevel=%d\n",uLevel));
        DEBUG(7,("RNetSessionEnum req string=%s\n",str1));
@@ -3716,10 +4214,13 @@ static BOOL api_RNetSessionEnum(connection_struct *conn,uint16 vuid, char *param
                return False;
        }
 
-       num_sessions = list_sessions(&session_list);
+       num_sessions = list_sessions(tmp_talloc_ctx(), &session_list);
 
        if (mdrcnt > 0) {
                *rdata = SMB_REALLOC_LIMIT(*rdata,mdrcnt);
+               if (!*rdata) {
+                       return False;
+               }
        }
        memset((char *)&desc,'\0',sizeof(desc));
        desc.base = *rdata;
@@ -3745,6 +4246,9 @@ static BOOL api_RNetSessionEnum(connection_struct *conn,uint16 vuid, char *param
 
        *rparam_len = 8;
        *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
+       if (!*rparam) {
+               return False;
+       }
        SSVALS(*rparam,0,desc.errcode);
        SSVAL(*rparam,2,0); /* converter */
        SSVAL(*rparam,4,num_sessions); /* count */
@@ -3766,6 +4270,9 @@ static BOOL api_TooSmall(connection_struct *conn,uint16 vuid, char *param, char
 {
        *rparam_len = MIN(*rparam_len,mprcnt);
        *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
+       if (!*rparam) {
+               return False;
+       }
 
        *rdata_len = 0;
 
@@ -3780,13 +4287,18 @@ static BOOL api_TooSmall(connection_struct *conn,uint16 vuid, char *param, char
  The request is not supported.
  ****************************************************************************/
 
-static BOOL api_Unsupported(connection_struct *conn, uint16 vuid, char *param, char *data,
-                           int mdrcnt, int mprcnt,
-                           char **rdata, char **rparam,
-                           int *rdata_len, int *rparam_len)
+static BOOL api_Unsupported(connection_struct *conn, uint16 vuid,
+                               char *param, int tpscnt,
+                               char *data, int tdscnt,
+                               int mdrcnt, int mprcnt,
+                               char **rdata, char **rparam,
+                               int *rdata_len, int *rparam_len)
 {
        *rparam_len = 4;
        *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
+       if (!*rparam) {
+               return False;
+       }
 
        *rdata_len = 0;
 
@@ -3801,7 +4313,9 @@ static BOOL api_Unsupported(connection_struct *conn, uint16 vuid, char *param, c
 static const struct {
        const char *name;
        int id;
-       BOOL (*fn)(connection_struct *,uint16,char *,char *,
+       BOOL (*fn)(connection_struct *, uint16,
+                       char *, int,
+                       char *, int,
                        int,int,char **,char **,int *,int *);
        BOOL auth_user;         /* Deny anonymous access? */
 } api_commands[] = {
@@ -3847,15 +4361,25 @@ static const struct {
 
 
 /****************************************************************************
- Handle remote api calls
- ****************************************************************************/
+ Handle remote api calls.
+****************************************************************************/
 
-int api_reply(connection_struct *conn,uint16 vuid,char *outbuf,char *data,char *params,
-                    int tdscnt,int tpscnt,int mdrcnt,int mprcnt)
+int api_reply(connection_struct *conn,
+               uint16 vuid,
+               const char *inbuf,
+               char *outbuf,
+               char *data,
+               char *params,
+               int tdscnt,
+               int tpscnt,
+               int mdrcnt,
+               int mprcnt)
 {
        int api_command;
        char *rdata = NULL;
        char *rparam = NULL;
+       const char *name1 = NULL;
+       const char *name2 = NULL;
        int rdata_len = 0;
        int rparam_len = 0;
        BOOL reply=False;
@@ -3866,12 +4390,25 @@ int api_reply(connection_struct *conn,uint16 vuid,char *outbuf,char *data,char *
                return 0;
        }
 
+       if (tpscnt < 2) {
+               return 0;
+       }
        api_command = SVAL(params,0);
+       /* Is there a string at position params+2 ? */
+       if (skip_string(params,tpscnt,params+2)) {
+               name1 = params + 2;
+       } else {
+               name1 = "";
+       }
+       name2 = skip_string(params,tpscnt,params+2);
+       if (!name2) {
+               name2 = "";
+       }
 
        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),
+               name1,
+               name2,
                tdscnt,tpscnt,mdrcnt,mprcnt));
 
        for (i=0;api_commands[i].name;i++) {
@@ -3908,7 +4445,11 @@ int api_reply(connection_struct *conn,uint16 vuid,char *outbuf,char *data,char *
                return -1;
        }
 
-       reply = api_commands[i].fn(conn,vuid,params,data,mdrcnt,mprcnt,
+       reply = api_commands[i].fn(conn,
+                               vuid,
+                               params,tpscnt,  /* params + length */
+                               data,tdscnt,    /* data + length */
+                               mdrcnt,mprcnt,
                                &rdata,&rparam,&rdata_len,&rparam_len);
 
 
@@ -3919,11 +4460,20 @@ int api_reply(connection_struct *conn,uint16 vuid,char *outbuf,char *data,char *
 
        /* if we get False back then it's actually unsupported */
        if (!reply) {
-               api_Unsupported(conn,vuid,params,data,mdrcnt,mprcnt,
+               reply = api_Unsupported(conn,vuid,params,tpscnt,data,tdscnt,mdrcnt,mprcnt,
                        &rdata,&rparam,&rdata_len,&rparam_len);
        }
 
-       send_trans_reply(outbuf, rparam, rparam_len, rdata, rdata_len, False);
+       /* If api_Unsupported returns false we can't return anything. */
+       if (reply) {
+               send_trans_reply(inbuf,
+                               outbuf,
+                               rparam,
+                               rparam_len,
+                               rdata,
+                               rdata_len,
+                               False);
+       }
 
        SAFE_FREE(rdata);
        SAFE_FREE(rparam);