r25117: The mega-patch Jerry was waiting for. Remove all pstrings from
[tprouty/samba.git] / source / smbd / trans2.c
index 835fd0cedba87821b765f9f234b86b3230a87e93..63dcb06f5dc28e23e008e51375e2b2229bafbe5e 100644 (file)
@@ -1,9 +1,9 @@
-/* 
+/*
    Unix SMB/CIFS implementation.
    SMB transaction2 handling
    Copyright (C) Jeremy Allison                        1994-2007
    Copyright (C) Stefan (metze) Metzmacher     2003
-   Copyright (C) Volker Lendecke               2005
+   Copyright (C) Volker Lendecke               2005-2007
    Copyright (C) Steve French                  2005
    Copyright (C) James Peach                   2007
 
 
    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
-   the Free Software Foundation; either version 2 of the License, or
+   the Free Software Foundation; either version 3 of the License, or
    (at your option) any later version.
-   
+
    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.
-   
+
    You should have received a copy of the GNU General Public License
-   along with this program; if not, write to the Free Software
-   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
 
 #include "includes.h"
@@ -91,18 +90,18 @@ SMB_BIG_UINT get_allocation_size(connection_struct *conn, files_struct *fsp, con
  Utility functions for dealing with extended attributes.
 ****************************************************************************/
 
-static const char *prohibited_ea_names[] = {
-       SAMBA_POSIX_INHERITANCE_EA_NAME,
-       SAMBA_XATTR_DOS_ATTRIB,
-       NULL
-};
-
 /****************************************************************************
  Refuse to allow clients to overwrite our private xattrs.
 ****************************************************************************/
 
 static BOOL samba_private_attr_name(const char *unix_ea_name)
 {
+       static const char *prohibited_ea_names[] = {
+               SAMBA_POSIX_INHERITANCE_EA_NAME,
+               SAMBA_XATTR_DOS_ATTRIB,
+               NULL
+       };
+
        int i;
 
        for (i = 0; prohibited_ea_names[i]; i++) {
@@ -212,7 +211,7 @@ static struct ea_list *get_ea_list_from_file(TALLOC_CTX *mem_ctx, connection_str
 
                        if (strnequal(p, "system.", 7) || samba_private_attr_name(p))
                                continue;
-               
+
                        listp = TALLOC_P(mem_ctx, struct ea_list);
                        if (!listp)
                                return NULL;
@@ -577,14 +576,12 @@ static struct ea_list *ea_list_union(struct ea_list *name_list, struct ea_list *
   HACK ! Always assumes smb_setup field is zero.
 ****************************************************************************/
 
-int send_trans2_replies(const char *inbuf,
-                       char *outbuf,
-                       int bufsize,
-                       const char *params, 
-                       int paramsize,
-                       const char *pdata,
-                       int datasize,
-                       int max_data_bytes)
+void send_trans2_replies(struct smb_request *req,
+                        const char *params,
+                        int paramsize,
+                        const char *pdata,
+                        int datasize,
+                        int max_data_bytes)
 {
        /* As we are using a protocol > LANMAN1 then the max_send
         variable must have been set in the sessetupX call.
@@ -600,10 +597,7 @@ int send_trans2_replies(const char *inbuf,
        int params_sent_thistime, data_sent_thistime, total_sent_thistime;
        int alignment_offset = 1; /* JRA. This used to be 3. Set to 1 to make netmon parse ok. */
        int data_alignment_offset = 0;
-
-       /* Initially set the wcnt area to be 10 - this is true for all trans2 replies */
-       
-       set_message(inbuf,outbuf,10,0,True);
+       BOOL overflow = False;
 
        /* Modify the data_to_send and datasize and set the error if
           we're trying to send more than max_data_bytes. We still send
@@ -614,16 +608,15 @@ int send_trans2_replies(const char *inbuf,
                DEBUG(5,("send_trans2_replies: max_data_bytes %d exceeded by data %d\n",
                        max_data_bytes, datasize ));
                datasize = data_to_send = max_data_bytes;
-               error_packet_set(outbuf,ERRDOS,ERRbufferoverflow,STATUS_BUFFER_OVERFLOW,__LINE__,__FILE__);
+               overflow = True;
        }
 
        /* If there genuinely are no parameters or data to send just send the empty packet */
 
        if(params_to_send == 0 && data_to_send == 0) {
-               show_msg(outbuf);
-               if (!send_smb(smbd_server_fd(),outbuf))
-                       exit_server_cleanly("send_trans2_replies: send_smb failed.");
-               return 0;
+               reply_outbuf(req, 10, 0);
+               show_msg((char *)req->outbuf);
+               return;
        }
 
        /* When sending params and data ensure that both are nicely aligned */
@@ -637,7 +630,10 @@ int send_trans2_replies(const char *inbuf,
        /* The alignment_offset is to align the param bytes on an even byte
                boundary. NT 4.0 Beta needs this to work correctly. */
 
-       useable_space = bufsize - ((smb_buf(outbuf)+ alignment_offset+data_alignment_offset) - outbuf);
+       useable_space = max_send - (smb_size
+                                   + 2 * 10 /* wct */
+                                   + alignment_offset
+                                   + data_alignment_offset);
 
        /* useable_space can never be more than max_send minus the alignment offset. */
 
@@ -658,11 +654,11 @@ int send_trans2_replies(const char *inbuf,
 
                total_sent_thistime = MIN(total_sent_thistime, useable_space+ alignment_offset + data_alignment_offset);
 
-               set_message(inbuf, outbuf, 10, total_sent_thistime, True);
+               reply_outbuf(req, 10, total_sent_thistime);
 
                /* Set total params and data to be sent */
-               SSVAL(outbuf,smb_tprcnt,paramsize);
-               SSVAL(outbuf,smb_tdrcnt,datasize);
+               SSVAL(req->outbuf,smb_tprcnt,paramsize);
+               SSVAL(req->outbuf,smb_tdrcnt,datasize);
 
                /* Calculate how many parameters and data we can fit into
                 * this packet. Parameters get precedence
@@ -672,53 +668,81 @@ int send_trans2_replies(const char *inbuf,
                data_sent_thistime = useable_space - params_sent_thistime;
                data_sent_thistime = MIN(data_sent_thistime,data_to_send);
 
-               SSVAL(outbuf,smb_prcnt, params_sent_thistime);
+               SSVAL(req->outbuf,smb_prcnt, params_sent_thistime);
 
                /* smb_proff is the offset from the start of the SMB header to the
                        parameter bytes, however the first 4 bytes of outbuf are
                        the Netbios over TCP header. Thus use smb_base() to subtract
                        them from the calculation */
 
-               SSVAL(outbuf,smb_proff,((smb_buf(outbuf)+alignment_offset) - smb_base(outbuf)));
+               SSVAL(req->outbuf,smb_proff,
+                     ((smb_buf(req->outbuf)+alignment_offset)
+                      - smb_base(req->outbuf)));
 
                if(params_sent_thistime == 0)
-                       SSVAL(outbuf,smb_prdisp,0);
+                       SSVAL(req->outbuf,smb_prdisp,0);
                else
                        /* Absolute displacement of param bytes sent in this packet */
-                       SSVAL(outbuf,smb_prdisp,pp - params);
+                       SSVAL(req->outbuf,smb_prdisp,pp - params);
 
-               SSVAL(outbuf,smb_drcnt, data_sent_thistime);
+               SSVAL(req->outbuf,smb_drcnt, data_sent_thistime);
                if(data_sent_thistime == 0) {
-                       SSVAL(outbuf,smb_droff,0);
-                       SSVAL(outbuf,smb_drdisp, 0);
+                       SSVAL(req->outbuf,smb_droff,0);
+                       SSVAL(req->outbuf,smb_drdisp, 0);
                } else {
                        /* The offset of the data bytes is the offset of the
                                parameter bytes plus the number of parameters being sent this time */
-                       SSVAL(outbuf,smb_droff,((smb_buf(outbuf)+alignment_offset) - 
-                               smb_base(outbuf)) + params_sent_thistime + data_alignment_offset);
-                       SSVAL(outbuf,smb_drdisp, pd - pdata);
+                       SSVAL(req->outbuf, smb_droff,
+                             ((smb_buf(req->outbuf)+alignment_offset)
+                              - smb_base(req->outbuf))
+                             + params_sent_thistime + data_alignment_offset);
+                       SSVAL(req->outbuf,smb_drdisp, pd - pdata);
+               }
+
+               /* Initialize the padding for alignment */
+
+               if (alignment_offset != 0) {
+                       memset(smb_buf(req->outbuf), 0, alignment_offset);
                }
 
                /* Copy the param bytes into the packet */
 
-               if(params_sent_thistime)
-                       memcpy((smb_buf(outbuf)+alignment_offset),pp,params_sent_thistime);
+               if(params_sent_thistime) {
+                       memcpy((smb_buf(req->outbuf)+alignment_offset), pp,
+                              params_sent_thistime);
+               }
 
                /* Copy in the data bytes */
-               if(data_sent_thistime)
-                       memcpy(smb_buf(outbuf)+alignment_offset+params_sent_thistime+
-                               data_alignment_offset,pd,data_sent_thistime);
+               if(data_sent_thistime) {
+                       if (data_alignment_offset != 0) {
+                               memset((smb_buf(req->outbuf)+alignment_offset+
+                                       params_sent_thistime), 0,
+                                      data_alignment_offset);
+                       }
+                       memcpy(smb_buf(req->outbuf)+alignment_offset
+                              +params_sent_thistime+data_alignment_offset,
+                              pd,data_sent_thistime);
+               }
 
                DEBUG(9,("t2_rep: params_sent_thistime = %d, data_sent_thistime = %d, useable_space = %d\n",
                        params_sent_thistime, data_sent_thistime, useable_space));
                DEBUG(9,("t2_rep: params_to_send = %d, data_to_send = %d, paramsize = %d, datasize = %d\n",
                        params_to_send, data_to_send, paramsize, datasize));
 
+               if (overflow) {
+                       error_packet_set((char *)req->outbuf,
+                                        ERRDOS,ERRbufferoverflow,
+                                        STATUS_BUFFER_OVERFLOW,
+                                        __LINE__,__FILE__);
+               }
+
                /* Send the packet */
-               show_msg(outbuf);
-               if (!send_smb(smbd_server_fd(),outbuf))
+               show_msg((char *)req->outbuf);
+               if (!send_smb(smbd_server_fd(),(char *)req->outbuf))
                        exit_server_cleanly("send_trans2_replies: send_smb failed.");
 
+               TALLOC_FREE(req->outbuf);
+
                pp += params_sent_thistime;
                pd += data_sent_thistime;
 
@@ -729,20 +753,22 @@ int send_trans2_replies(const char *inbuf,
                if(params_to_send < 0 || data_to_send < 0) {
                        DEBUG(0,("send_trans2_replies failed sanity check pts = %d, dts = %d\n!!!",
                                params_to_send, data_to_send));
-                       return -1;
+                       return;
                }
        }
 
-       return 0;
+       return;
 }
 
 /****************************************************************************
  Reply to a TRANSACT2_OPEN.
 ****************************************************************************/
 
-static int call_trans2open(connection_struct *conn, char *inbuf, char *outbuf, int bufsize,  
-                               char **pparams, int total_params, char **ppdata, int total_data,
-                               unsigned int max_data_bytes)
+static void call_trans2open(connection_struct *conn,
+                           struct smb_request *req,
+                           char **pparams, int total_params,
+                           char **ppdata, int total_data,
+                           unsigned int max_data_bytes)
 {
        char *params = *pparams;
        char *pdata = *ppdata;
@@ -757,7 +783,7 @@ static int call_trans2open(connection_struct *conn, char *inbuf, char *outbuf, i
        int open_ofun;
        uint32 open_size;
        char *pname;
-       pstring fname;
+       char *fname = NULL;
        SMB_OFF_T size=0;
        int fattr=0,mtime=0;
        SMB_INO_T inode = 0;
@@ -771,13 +797,15 @@ static int call_trans2open(connection_struct *conn, char *inbuf, char *outbuf, i
        uint32 share_mode;
        uint32 create_disposition;
        uint32 create_options = 0;
+       TALLOC_CTX *ctx = talloc_tos();
 
        /*
         * Ensure we have enough parameters to perform the operation.
         */
 
        if (total_params < 29) {
-               return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
+               reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
+               return;
        }
 
        flags = SVAL(params, 0);
@@ -798,12 +826,16 @@ static int call_trans2open(connection_struct *conn, char *inbuf, char *outbuf, i
        pname = &params[28];
 
        if (IS_IPC(conn)) {
-               return(ERROR_DOS(ERRSRV,ERRaccess));
+               reply_doserror(req, ERRSRV, ERRaccess);
+               return;
        }
 
-       srvstr_get_path(inbuf, fname, pname, sizeof(fname), total_params - 28, STR_TERMINATE, &status);
+       srvstr_get_path(ctx, params, req->flags2, &fname, pname,
+                       total_params - 28, STR_TERMINATE,
+                       &status);
        if (!NT_STATUS_IS_OK(status)) {
-               return ERROR_NT(status);
+               reply_nterror(req, status);
+               return;
        }
 
        DEBUG(3,("call_trans2open %s deny_mode=0x%x attr=%d ofun=0x%x size=%d\n",
@@ -812,18 +844,21 @@ static int call_trans2open(connection_struct *conn, char *inbuf, char *outbuf, i
 
        /* XXXX we need to handle passed times, sattr and flags */
 
-       status = unix_convert(conn, fname, False, NULL, &sbuf);
+       status = unix_convert(conn, fname, False, &fname, NULL, &sbuf);
        if (!NT_STATUS_IS_OK(status)) {
-               return ERROR_NT(status);
+               reply_nterror(req, status);
+               return;
        }
-    
+
        status = check_name(conn, fname);
        if (!NT_STATUS_IS_OK(status)) {
-               return ERROR_NT(status);
+               reply_nterror(req, status);
+               return;
        }
 
        if (open_ofun == 0) {
-               return ERROR_NT(NT_STATUS_OBJECT_NAME_COLLISION);
+               reply_nterror(req, NT_STATUS_OBJECT_NAME_COLLISION);
+               return;
        }
 
        if (!map_open_params_to_ntcreate(fname, deny_mode, open_ofun,
@@ -831,35 +866,41 @@ static int call_trans2open(connection_struct *conn, char *inbuf, char *outbuf, i
                                &share_mode,
                                &create_disposition,
                                &create_options)) {
-               return ERROR_DOS(ERRDOS, ERRbadaccess);
+               reply_doserror(req, ERRDOS, ERRbadaccess);
+               return;
        }
 
        /* Any data in this call is an EA list. */
        if (total_data && (total_data != 4) && !lp_ea_support(SNUM(conn))) {
-               return ERROR_NT(NT_STATUS_EAS_NOT_SUPPORTED);
+               reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
+               return;
        }
 
        if (total_data != 4) {
                if (total_data < 10) {
-                       return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
+                       reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
+                       return;
                }
 
                if (IVAL(pdata,0) > total_data) {
                        DEBUG(10,("call_trans2open: bad total data size (%u) > %u\n",
                                IVAL(pdata,0), (unsigned int)total_data));
-                       return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
+                       reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
+                       return;
                }
 
-               ea_list = read_ea_list(tmp_talloc_ctx(), pdata + 4,
+               ea_list = read_ea_list(talloc_tos(), pdata + 4,
                                       total_data - 4);
                if (!ea_list) {
-                       return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
+                       reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
+                       return;
                }
        } else if (IVAL(pdata,0) != 4) {
-               return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
+               reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
+               return;
        }
 
-       status = open_file_ntcreate(conn,fname,&sbuf,
+       status = open_file_ntcreate(conn, req, fname, &sbuf,
                access_mask,
                share_mode,
                create_disposition,
@@ -867,13 +908,14 @@ static int call_trans2open(connection_struct *conn, char *inbuf, char *outbuf, i
                open_attr,
                oplock_request,
                &smb_action, &fsp);
-      
+
        if (!NT_STATUS_IS_OK(status)) {
-               if (open_was_deferred(SVAL(inbuf,smb_mid))) {
+               if (open_was_deferred(req->mid)) {
                        /* We have re-scheduled this call. */
-                       return -1;
+                       return;
                }
-               return ERROR_NT(status);
+               reply_openerror(req, status);
+               return;
        }
 
        size = get_file_size(sbuf);
@@ -882,7 +924,8 @@ static int call_trans2open(connection_struct *conn, char *inbuf, char *outbuf, i
        inode = sbuf.st_ino;
        if (fattr & aDIR) {
                close_file(fsp,ERROR_CLOSE);
-               return(ERROR_DOS(ERRDOS,ERRnoaccess));
+               reply_doserror(req, ERRDOS,ERRnoaccess);
+               return;
        }
 
        /* Save the requested allocation size. */
@@ -894,11 +937,13 @@ static int call_trans2open(connection_struct *conn, char *inbuf, char *outbuf, i
                         if (fsp->is_directory) {
                                 close_file(fsp,ERROR_CLOSE);
                                 /* Can't set allocation size on a directory. */
-                                return ERROR_NT(NT_STATUS_ACCESS_DENIED);
+                               reply_nterror(req, NT_STATUS_ACCESS_DENIED);
+                               return;
                         }
                         if (vfs_allocate_file_space(fsp, fsp->initial_allocation_size) == -1) {
                                 close_file(fsp,ERROR_CLOSE);
-                                return ERROR_NT(NT_STATUS_DISK_FULL);
+                               reply_nterror(req, NT_STATUS_DISK_FULL);
+                               return;
                         }
 
                        /* Adjust size here to return the right size in the reply.
@@ -913,14 +958,16 @@ static int call_trans2open(connection_struct *conn, char *inbuf, char *outbuf, i
                status = set_ea(conn, fsp, fname, ea_list);
                if (!NT_STATUS_IS_OK(status)) {
                        close_file(fsp,ERROR_CLOSE);
-                       return ERROR_NT(status);
+                       reply_nterror(req, status);
+                       return;
                }
        }
 
        /* Realloc the size of parameters and data we will return */
        *pparams = (char *)SMB_REALLOC(*pparams, 30);
        if(*pparams == NULL ) {
-               return ERROR_NT(NT_STATUS_NO_MEMORY);
+               reply_nterror(req, NT_STATUS_NO_MEMORY);
+               return;
        }
        params = *pparams;
 
@@ -951,9 +998,7 @@ static int call_trans2open(connection_struct *conn, char *inbuf, char *outbuf, i
        }
 
        /* Send the required number of replies */
-       send_trans2_replies(inbuf, outbuf, bufsize, params, 30, *ppdata, 0, max_data_bytes);
-
-       return -1;
+       send_trans2_replies(req, params, 30, *ppdata, 0, max_data_bytes);
 }
 
 /*********************************************************
@@ -963,7 +1008,9 @@ static int call_trans2open(connection_struct *conn, char *inbuf, char *outbuf, i
  Case can be significant or not.
 **********************************************************/
 
-static BOOL exact_match(connection_struct *conn, char *str, char *mask)
+static BOOL exact_match(connection_struct *conn,
+               const char *str,
+               const char *mask)
 {
        if (mask[0] == '.' && mask[1] == 0)
                return False;
@@ -1089,21 +1136,29 @@ static NTSTATUS unix_perms_from_wire( connection_struct *conn,
  Get a level dependent lanman2 dir entry.
 ****************************************************************************/
 
-static BOOL get_lanman2_dir_entry(connection_struct *conn,
-                                 void *inbuf, char *outbuf,
-                                char *path_mask,uint32 dirtype,int info_level,
-                                int requires_resume_key,
-                                BOOL dont_descend,char **ppdata, 
-                                char *base_data, int space_remaining, 
-                                BOOL *out_of_space, BOOL *got_exact_match,
-                                int *last_entry_off, struct ea_list *name_list, TALLOC_CTX *ea_ctx)
+static BOOL get_lanman2_dir_entry(TALLOC_CTX *ctx,
+                               connection_struct *conn,
+                               uint16 flags2,
+                               const char *path_mask,
+                               uint32 dirtype,
+                               int info_level,
+                               int requires_resume_key,
+                               BOOL dont_descend,
+                               char **ppdata,
+                               char *base_data,
+                               char *end_data,
+                               int space_remaining,
+                               BOOL *out_of_space,
+                               BOOL *got_exact_match,
+                               int *last_entry_off,
+                               struct ea_list *name_list)
 {
        const char *dname;
        BOOL found = False;
        SMB_STRUCT_STAT sbuf;
-       pstring mask;
-       pstring pathreal;
-       pstring fname;
+       const char *mask = NULL;
+       char *pathreal = NULL;
+       const char *fname = NULL;
        char *p, *q, *pdata = *ppdata;
        uint32 reskey=0;
        long prev_dirpos=0;
@@ -1119,8 +1174,8 @@ static BOOL get_lanman2_dir_entry(connection_struct *conn,
        uint32 nt_extmode; /* Used for NT connections instead of mode */
        BOOL needslash = ( conn->dirpath[strlen(conn->dirpath) -1] != '/');
        BOOL check_mangled_names = lp_manglednames(conn->params);
+       char mangled_name[13]; /* mangled 8.3 name. */
 
-       *fname = 0;
        *out_of_space = False;
        *got_exact_match = False;
 
@@ -1128,18 +1183,20 @@ static BOOL get_lanman2_dir_entry(connection_struct *conn,
        ZERO_STRUCT(adate_ts);
        ZERO_STRUCT(create_date_ts);
 
-       if (!conn->dirptr)
+       if (!conn->dirptr) {
                return(False);
+       }
 
        p = strrchr_m(path_mask,'/');
        if(p != NULL) {
-               if(p[1] == '\0')
-                       pstrcpy(mask,"*.*");
-               else
-                       pstrcpy(mask, p+1);
-       } else
-               pstrcpy(mask, path_mask);
-
+               if(p[1] == '\0') {
+                       mask = talloc_strdup(ctx,"*.*");
+               } else {
+                       mask = p+1;
+               }
+       } else {
+               mask = path_mask;
+       }
 
        while (!found) {
                BOOL got_match;
@@ -1147,7 +1204,7 @@ static BOOL get_lanman2_dir_entry(connection_struct *conn,
 
                /* Needed if we run out of space */
                long curr_dirpos = prev_dirpos = dptr_TellDir(conn->dirptr);
-               dname = dptr_ReadDirName(conn->dirptr,&curr_dirpos,&sbuf);
+               dname = dptr_ReadDirName(ctx,conn->dirptr,&curr_dirpos,&sbuf);
 
                /*
                 * Due to bugs in NT client redirectors we are not using
@@ -1160,7 +1217,7 @@ static BOOL get_lanman2_dir_entry(connection_struct *conn,
 
                DEBUG(8,("get_lanman2_dir_entry:readdir on dirptr 0x%lx now at offset %ld\n",
                        (long)conn->dirptr,curr_dirpos));
-      
+
                if (!dname) {
                        return(False);
                }
@@ -1171,10 +1228,16 @@ static BOOL get_lanman2_dir_entry(connection_struct *conn,
                 * pathreal which is composed from dname.
                 */
 
-               pstrcpy(fname,dname);      
+               pathreal = NULL;
+               fname = dname;
 
-               /* This will mangle fname if it's an illegal name. */
-               mangle_map(fname,False,True,conn->params);
+               /* Mangle fname if it's an illegal name. */
+               if (mangle_must_mangle(dname,conn->params)) {
+                       if (!name_to_8_3(dname,mangled_name,True,conn->params)) {
+                               continue; /* Error - couldn't mangle. */
+                       }
+                       fname = mangled_name;
+               }
 
                if(!(got_match = *got_exact_match = exact_match(conn, fname, mask))) {
                        got_match = mask_match(fname, mask, conn->case_sensitive);
@@ -1182,51 +1245,60 @@ static BOOL get_lanman2_dir_entry(connection_struct *conn,
 
                if(!got_match && check_mangled_names &&
                   !mangle_is_8_3(fname, False, conn->params)) {
-                       pstring mangled_name;
-
                        /*
                         * It turns out that NT matches wildcards against
                         * both long *and* short names. This may explain some
                         * of the wildcard wierdness from old DOS clients
                         * that some people have been seeing.... JRA.
                         */
-
-                       pstrcpy(mangled_name, fname);
-
                        /* Force the mangling into 8.3. */
-                       mangle_map( mangled_name, True, False, conn->params);
+                       if (!name_to_8_3( fname, mangled_name, False, conn->params)) {
+                               continue; /* Error - couldn't mangle. */
+                       }
+
                        if(!(got_match = *got_exact_match = exact_match(conn, mangled_name, mask))) {
                                got_match = mask_match(mangled_name, mask, conn->case_sensitive);
                        }
                }
 
                if (got_match) {
-                       BOOL isdots = (strequal(dname,"..") || strequal(dname,"."));
+                       BOOL isdots = (ISDOT(dname) || ISDOTDOT(dname));
+
                        if (dont_descend && !isdots) {
                                continue;
                        }
-         
-                       pstrcpy(pathreal,conn->dirpath);
-                       if(needslash) {
-                               pstrcat(pathreal,"/");
+
+                       if (needslash) {
+                               pathreal = NULL;
+                               pathreal = talloc_asprintf(ctx,
+                                       "%s/%s",
+                                       conn->dirpath,
+                                       dname);
+                       } else {
+                               pathreal = talloc_asprintf(ctx,
+                                       "%s%s",
+                                       conn->dirpath,
+                                       dname);
+                       }
+
+                       if (!pathreal) {
+                               return False;
                        }
-                       pstrcat(pathreal,dname);
 
                        if (INFO_LEVEL_IS_UNIX(info_level)) {
                                if (SMB_VFS_LSTAT(conn,pathreal,&sbuf) != 0) {
                                        DEBUG(5,("get_lanman2_dir_entry:Couldn't lstat [%s] (%s)\n",
                                                pathreal,strerror(errno)));
+                                       TALLOC_FREE(pathreal);
                                        continue;
                                }
                        } else if (!VALID_STAT(sbuf) && SMB_VFS_STAT(conn,pathreal,&sbuf) != 0) {
-                               pstring link_target;
-
-                               /* Needed to show the msdfs symlinks as 
+                               /* Needed to show the msdfs symlinks as
                                 * directories */
 
-                               if(lp_host_msdfs() && 
+                               if(lp_host_msdfs() &&
                                   lp_msdfs_root(SNUM(conn)) &&
-                                  ((ms_dfs_link = is_msdfs_link(conn, pathreal, link_target, &sbuf)) == True)) {
+                                  ((ms_dfs_link = is_msdfs_link(conn, pathreal, &sbuf)) == True)) {
                                        DEBUG(5,("get_lanman2_dir_entry: Masquerading msdfs link %s "
                                                "as a directory\n",
                                                pathreal));
@@ -1236,6 +1308,7 @@ static BOOL get_lanman2_dir_entry(connection_struct *conn,
 
                                        DEBUG(5,("get_lanman2_dir_entry:Couldn't stat [%s] (%s)\n",
                                                pathreal,strerror(errno)));
+                                       TALLOC_FREE(pathreal);
                                        continue;
                                }
                        }
@@ -1248,6 +1321,7 @@ static BOOL get_lanman2_dir_entry(connection_struct *conn,
 
                        if (!dir_check_ftype(conn,mode,dirtype)) {
                                DEBUG(5,("get_lanman2_dir_entry: [%s] attribs didn't match %x\n",fname,dirtype));
+                               TALLOC_FREE(pathreal);
                                continue;
                        }
 
@@ -1269,9 +1343,9 @@ static BOOL get_lanman2_dir_entry(connection_struct *conn,
                        create_date = convert_timespec_to_time_t(create_date_ts);
                        mdate = convert_timespec_to_time_t(mdate_ts);
                        adate = convert_timespec_to_time_t(adate_ts);
-                       
+
                        DEBUG(5,("get_lanman2_dir_entry: found %s fname=%s\n",pathreal,fname));
-         
+
                        found = True;
 
                        dptr_DirCacheAdd(conn->dirptr, dname, curr_dirpos);
@@ -1298,9 +1372,11 @@ static BOOL get_lanman2_dir_entry(connection_struct *conn,
                        SSVAL(p,20,mode);
                        p += 23;
                        nameptr = p;
-                       p += align_string(outbuf, p, 0);
-                       len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE);
-                       if (SVAL(outbuf, smb_flg2) & FLAGS2_UNICODE_STRINGS) {
+                       p += align_string(pdata, p, 0);
+                       len = srvstr_push(base_data, flags2, p,
+                                         fname, PTR_DIFF(end_data, p),
+                                         STR_TERMINATE);
+                       if (flags2 & FLAGS2_UNICODE_STRINGS) {
                                if (len > 2) {
                                        SCVAL(nameptr, -1, len - 2);
                                } else {
@@ -1334,8 +1410,10 @@ static BOOL get_lanman2_dir_entry(connection_struct *conn,
                        }
                        p += 27;
                        nameptr = p - 1;
-                       len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE | STR_NOALIGN);
-                       if (SVAL(outbuf, smb_flg2) & FLAGS2_UNICODE_STRINGS) {
+                       len = srvstr_push(base_data, flags2,
+                                         p, fname, PTR_DIFF(end_data, p),
+                                         STR_TERMINATE | STR_NOALIGN);
+                       if (flags2 & FLAGS2_UNICODE_STRINGS) {
                                if (len > 2) {
                                        len -= 2;
                                } else {
@@ -1374,7 +1452,7 @@ static BOOL get_lanman2_dir_entry(connection_struct *conn,
                        SSVAL(p,20,mode);
                        p += 22; /* p now points to the EA area. */
 
-                       file_list = get_ea_list_from_file(ea_ctx, conn, NULL, pathreal, &ea_len);
+                       file_list = get_ea_list_from_file(ctx, conn, NULL, pathreal, &ea_len);
                        name_list = ea_list_union(name_list, file_list, &ea_len);
 
                        /* We need to determine if this entry will fit in the space available. */
@@ -1388,10 +1466,12 @@ static BOOL get_lanman2_dir_entry(connection_struct *conn,
                        }
 
                        /* Push the ea_data followed by the name. */
-                       p += fill_ea_buffer(ea_ctx, p, space_remaining, conn, name_list);
+                       p += fill_ea_buffer(ctx, p, space_remaining, conn, name_list);
                        nameptr = p;
-                       len = srvstr_push(outbuf, p + 1, fname, -1, STR_TERMINATE | STR_NOALIGN);
-                       if (SVAL(outbuf, smb_flg2) & FLAGS2_UNICODE_STRINGS) {
+                       len = srvstr_push(base_data, flags2,
+                                         p + 1, fname, PTR_DIFF(end_data, p),
+                                         STR_TERMINATE | STR_NOALIGN);
+                       if (flags2 & FLAGS2_UNICODE_STRINGS) {
                                if (len > 2) {
                                        len -= 2;
                                } else {
@@ -1433,12 +1513,15 @@ static BOOL get_lanman2_dir_entry(connection_struct *conn,
                         * a Win2k client bug. JRA.
                         */
                        if (!was_8_3 && check_mangled_names) {
-                               pstring mangled_name;
-                               pstrcpy(mangled_name, fname);
-                               mangle_map(mangled_name,True,True,
-                                          conn->params);
+                               if (!name_to_8_3(fname,mangled_name,True,
+                                                  conn->params)) {
+                                       /* Error - mangle failed ! */
+                                       memset(mangled_name,'\0',12);
+                               }
                                mangled_name[12] = 0;
-                               len = srvstr_push(outbuf, p+2, mangled_name, 24, STR_UPPER|STR_UNICODE);
+                               len = srvstr_push(base_data, flags2,
+                                                 p+2, mangled_name, 24,
+                                                 STR_UPPER|STR_UNICODE);
                                if (len < 24) {
                                        memset(p + 2 + len,'\0',24 - len);
                                }
@@ -1447,7 +1530,9 @@ static BOOL get_lanman2_dir_entry(connection_struct *conn,
                                memset(p,'\0',26);
                        }
                        p += 2 + 24;
-                       len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE_ASCII);
+                       len = srvstr_push(base_data, flags2, p,
+                                         fname, PTR_DIFF(end_data, p),
+                                         STR_TERMINATE_ASCII);
                        SIVAL(q,0,len);
                        p += len;
                        SIVAL(p,0,0); /* Ensure any padding is null. */
@@ -1468,7 +1553,9 @@ static BOOL get_lanman2_dir_entry(connection_struct *conn,
                        SOFF_T(p,0,file_size); p += 8;
                        SOFF_T(p,0,allocation_size); p += 8;
                        SIVAL(p,0,nt_extmode); p += 4;
-                       len = srvstr_push(outbuf, p + 4, fname, -1, STR_TERMINATE_ASCII);
+                       len = srvstr_push(base_data, flags2,
+                                         p + 4, fname, PTR_DIFF(end_data, p),
+                                         STR_TERMINATE_ASCII);
                        SIVAL(p,0,len);
                        p += 4 + len;
                        SIVAL(p,0,0); /* Ensure any padding is null. */
@@ -1477,7 +1564,7 @@ static BOOL get_lanman2_dir_entry(connection_struct *conn,
                        SIVAL(pdata,0,len);
                        p = pdata + len;
                        break;
-      
+
                case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
                        DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_FULL_DIRECTORY_INFO\n"));
                        p += 4;
@@ -1495,7 +1582,9 @@ static BOOL get_lanman2_dir_entry(connection_struct *conn,
                                SIVAL(p,0,ea_size); /* Extended attributes */
                                p +=4;
                        }
-                       len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE_ASCII);
+                       len = srvstr_push(base_data, flags2, p,
+                                         fname, PTR_DIFF(end_data, p),
+                                         STR_TERMINATE_ASCII);
                        SIVAL(q, 0, len);
                        p += len;
 
@@ -1513,7 +1602,9 @@ static BOOL get_lanman2_dir_entry(connection_struct *conn,
                        p += 4;
                        /* this must *not* be null terminated or w2k gets in a loop trying to set an
                           acl on a dir (tridge) */
-                       len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE_ASCII);
+                       len = srvstr_push(base_data, flags2, p,
+                                         fname, PTR_DIFF(end_data, p),
+                                         STR_TERMINATE_ASCII);
                        SIVAL(p, -4, len);
                        p += len;
                        SIVAL(p,0,0); /* Ensure any padding is null. */
@@ -1543,7 +1634,9 @@ static BOOL get_lanman2_dir_entry(connection_struct *conn,
                        SIVAL(p,0,0); p += 4; /* Unknown - reserved ? */
                        SIVAL(p,0,sbuf.st_ino); p += 4; /* FileIndexLow */
                        SIVAL(p,0,sbuf.st_dev); p += 4; /* FileIndexHigh */
-                       len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE_ASCII);
+                       len = srvstr_push(base_data, flags2, p,
+                                         fname, PTR_DIFF(end_data, p),
+                                         STR_TERMINATE_ASCII);
                        SIVAL(q, 0, len);
                        p += len; 
                        SIVAL(p,0,0); /* Ensure any padding is null. */
@@ -1576,12 +1669,15 @@ static BOOL get_lanman2_dir_entry(connection_struct *conn,
                         * a Win2k client bug. JRA.
                         */
                        if (!was_8_3 && check_mangled_names) {
-                               pstring mangled_name;
-                               pstrcpy(mangled_name, fname);
-                               mangle_map(mangled_name,True,True,
-                                          conn->params);
+                               if (!name_to_8_3(fname,mangled_name,True,
+                                               conn->params)) {
+                                       /* Error - mangle failed ! */
+                                       memset(mangled_name,'\0',12);
+                               }
                                mangled_name[12] = 0;
-                               len = srvstr_push(outbuf, p+2, mangled_name, 24, STR_UPPER|STR_UNICODE);
+                               len = srvstr_push(base_data, flags2,
+                                                 p+2, mangled_name, 24,
+                                                 STR_UPPER|STR_UNICODE);
                                SSVAL(p, 0, len);
                                if (len < 24) {
                                        memset(p + 2 + len,'\0',24 - len);
@@ -1594,7 +1690,9 @@ static BOOL get_lanman2_dir_entry(connection_struct *conn,
                        SSVAL(p,0,0); p += 2; /* Reserved ? */
                        SIVAL(p,0,sbuf.st_ino); p += 4; /* FileIndexLow */
                        SIVAL(p,0,sbuf.st_dev); p += 4; /* FileIndexHigh */
-                       len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE_ASCII);
+                       len = srvstr_push(base_data, flags2, p,
+                                         fname, PTR_DIFF(end_data, p),
+                                         STR_TERMINATE_ASCII);
                        SIVAL(q,0,len);
                        p += len;
                        SIVAL(p,0,0); /* Ensure any padding is null. */
@@ -1617,14 +1715,17 @@ static BOOL get_lanman2_dir_entry(connection_struct *conn,
                                DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_UNIX\n"));
                                p = store_file_unix_basic(conn, p,
                                                        NULL, &sbuf);
-                               len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE);
+                               len = srvstr_push(base_data, flags2, p,
+                                                 fname, PTR_DIFF(end_data, p),
+                                                 STR_TERMINATE);
                        } else {
                                DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_UNIX_INFO2\n"));
                                p = store_file_unix_basic_info2(conn, p,
                                                        NULL, &sbuf);
                                nameptr = p;
                                p += 4;
-                               len = srvstr_push(outbuf, p, fname, -1, 0);
+                               len = srvstr_push(base_data, flags2, p, fname,
+                                                 PTR_DIFF(end_data, p), 0);
                                SIVAL(nameptr, 0, len);
                        }
 
@@ -1639,7 +1740,7 @@ static BOOL get_lanman2_dir_entry(connection_struct *conn,
 
                        break;
 
-               default:      
+               default:
                        return(False);
        }
 
@@ -1664,9 +1765,11 @@ static BOOL get_lanman2_dir_entry(connection_struct *conn,
  Reply to a TRANS2_FINDFIRST.
 ****************************************************************************/
 
-static int call_trans2findfirst(connection_struct *conn, char *inbuf, char *outbuf, int bufsize,  
-                               char **pparams, int total_params, char **ppdata, int total_data,
-                               unsigned int max_data_bytes)
+static void call_trans2findfirst(connection_struct *conn,
+                                struct smb_request *req,
+                                char **pparams, int total_params,
+                                char **ppdata, int total_data,
+                                unsigned int max_data_bytes)
 {
        /* We must be careful here that we don't return more than the
                allowed number of data bytes. If this means returning fewer than
@@ -1675,6 +1778,7 @@ static int call_trans2findfirst(connection_struct *conn, char *inbuf, char *outb
                requested. */
        char *params = *pparams;
        char *pdata = *ppdata;
+       char *data_end;
        uint32 dirtype;
        int maxentries;
        uint16 findfirst_flags;
@@ -1682,8 +1786,8 @@ static int call_trans2findfirst(connection_struct *conn, char *inbuf, char *outb
        BOOL close_if_end;
        BOOL requires_resume_key;
        int info_level;
-       pstring directory;
-       pstring mask;
+       char *directory = NULL;
+       const char *mask = NULL;
        char *p;
        int last_entry_off=0;
        int dptr_num = -1;
@@ -1695,12 +1799,13 @@ static int call_trans2findfirst(connection_struct *conn, char *inbuf, char *outb
        int space_remaining;
        BOOL mask_contains_wcard = False;
        SMB_STRUCT_STAT sbuf;
-       TALLOC_CTX *ea_ctx = NULL;
        struct ea_list *ea_list = NULL;
        NTSTATUS ntstatus = NT_STATUS_OK;
+       TALLOC_CTX *ctx = talloc_tos();
 
        if (total_params < 13) {
-               return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
+               reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
+               return;
        }
 
        dirtype = SVAL(params,0);
@@ -1711,8 +1816,6 @@ static int call_trans2findfirst(connection_struct *conn, char *inbuf, char *outb
        requires_resume_key = (findfirst_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
        info_level = SVAL(params,6);
 
-       *directory = *mask = 0;
-
        DEBUG(3,("call_trans2findfirst: dirtype = %x, maxentries = %d, close_after_first=%d, \
 close_if_end = %d requires_resume_key = %d level = 0x%x, max_data_bytes = %d\n",
                (unsigned int)dirtype, maxentries, close_after_first, close_if_end, requires_resume_key,
@@ -1737,47 +1840,66 @@ close_if_end = %d requires_resume_key = %d level = 0x%x, max_data_bytes = %d\n",
                case SMB_FIND_FILE_UNIX:
                case SMB_FIND_FILE_UNIX_INFO2:
                        if (!lp_unix_extensions()) {
-                               return ERROR_NT(NT_STATUS_INVALID_LEVEL);
+                               reply_nterror(req, NT_STATUS_INVALID_LEVEL);
+                               return;
                        }
                        break;
                default:
-                       return ERROR_NT(NT_STATUS_INVALID_LEVEL);
+                       reply_nterror(req, NT_STATUS_INVALID_LEVEL);
+                       return;
        }
 
-       srvstr_get_path_wcard(inbuf, directory, params+12, sizeof(directory), total_params - 12, STR_TERMINATE, &ntstatus, &mask_contains_wcard);
+       srvstr_get_path_wcard(ctx, params, req->flags2, &directory,
+                             params+12, total_params - 12,
+                             STR_TERMINATE, &ntstatus, &mask_contains_wcard);
        if (!NT_STATUS_IS_OK(ntstatus)) {
-               return ERROR_NT(ntstatus);
+               reply_nterror(req, ntstatus);
+               return;
        }
 
-       ntstatus = resolve_dfspath_wcard(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, directory, &mask_contains_wcard);
+       ntstatus = resolve_dfspath_wcard(ctx, conn,
+                       req->flags2 & FLAGS2_DFS_PATHNAMES,
+                       directory,
+                       &directory,
+                       &mask_contains_wcard);
        if (!NT_STATUS_IS_OK(ntstatus)) {
                if (NT_STATUS_EQUAL(ntstatus,NT_STATUS_PATH_NOT_COVERED)) {
-                       return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath);
+                       reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
+                                       ERRSRV, ERRbadpath);
+                       return;
                }
-               return ERROR_NT(ntstatus);
+               reply_nterror(req, ntstatus);
+               return;
        }
 
-       ntstatus = unix_convert(conn, directory, True, NULL, &sbuf);
+       ntstatus = unix_convert(conn, directory, True, &directory, NULL, &sbuf);
        if (!NT_STATUS_IS_OK(ntstatus)) {
-               return ERROR_NT(ntstatus);
+               reply_nterror(req, ntstatus);
+               return;
        }
+
        ntstatus = check_name(conn, directory);
        if (!NT_STATUS_IS_OK(ntstatus)) {
-               return ERROR_NT(ntstatus);
+               reply_nterror(req, ntstatus);
+               return;
        }
 
        p = strrchr_m(directory,'/');
        if(p == NULL) {
                /* Windows and OS/2 systems treat search on the root '\' as if it were '\*' */
                if((directory[0] == '.') && (directory[1] == '\0')) {
-                       pstrcpy(mask,"*");
+                       mask = "*";
                        mask_contains_wcard = True;
                } else {
-                       pstrcpy(mask,directory);
+                       mask = directory;
+               }
+               directory = talloc_strdup(talloc_tos(), "./");
+               if (!directory) {
+                       reply_nterror(req, NT_STATUS_NO_MEMORY);
+                       return;
                }
-               pstrcpy(directory,"./");
        } else {
-               pstrcpy(mask,p+1);
+               mask = p+1;
                *p = 0;
        }
 
@@ -1787,45 +1909,45 @@ close_if_end = %d requires_resume_key = %d level = 0x%x, max_data_bytes = %d\n",
                uint32 ea_size;
 
                if (total_data < 4) {
-                       return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
+                       reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
+                       return;
                }
 
                ea_size = IVAL(pdata,0);
                if (ea_size != total_data) {
                        DEBUG(4,("call_trans2findfirst: Rejecting EA request with incorrect \
 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
-                       return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
+                       reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
+                       return;
                }
 
                if (!lp_ea_support(SNUM(conn))) {
-                       return ERROR_DOS(ERRDOS,ERReasnotsupported);
-               }
-                                                                                                                                                        
-               if ((ea_ctx = talloc_init("findnext_ea_list")) == NULL) {
-                       return ERROR_NT(NT_STATUS_NO_MEMORY);
+                       reply_doserror(req, ERRDOS, ERReasnotsupported);
+                       return;
                }
 
                /* Pull out the list of names. */
-               ea_list = read_ea_name_list(ea_ctx, pdata + 4, ea_size - 4);
+               ea_list = read_ea_name_list(ctx, pdata + 4, ea_size - 4);
                if (!ea_list) {
-                       talloc_destroy(ea_ctx);
-                       return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
+                       reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
+                       return;
                }
        }
 
        *ppdata = (char *)SMB_REALLOC(
                *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
        if(*ppdata == NULL ) {
-               talloc_destroy(ea_ctx);
-               return ERROR_NT(NT_STATUS_NO_MEMORY);
+               reply_nterror(req, NT_STATUS_NO_MEMORY);
+               return;
        }
        pdata = *ppdata;
+       data_end = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
 
        /* Realloc the params space */
        *pparams = (char *)SMB_REALLOC(*pparams, 10);
        if (*pparams == NULL) {
-               talloc_destroy(ea_ctx);
-               return ERROR_NT(NT_STATUS_NO_MEMORY);
+               reply_nterror(req, NT_STATUS_NO_MEMORY);
+               return;
        }
        params = *pparams;
 
@@ -1836,27 +1958,27 @@ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pd
                                directory,
                                False,
                                True,
-                               SVAL(inbuf,smb_pid),
+                               req->smbpid,
                                mask,
                                mask_contains_wcard,
                                dirtype,
                                &conn->dirptr);
 
        if (!NT_STATUS_IS_OK(ntstatus)) {
-               talloc_destroy(ea_ctx);
-               return ERROR_NT(ntstatus);
+               reply_nterror(req, ntstatus);
+               return;
        }
 
        dptr_num = dptr_dnum(conn->dirptr);
        DEBUG(4,("dptr_num is %d, wcard = %s, attr = %d\n", dptr_num, mask, dirtype));
 
-       /* We don't need to check for VOL here as this is returned by 
+       /* We don't need to check for VOL here as this is returned by
                a different TRANS2 call. */
-  
+
        DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n", conn->dirpath,lp_dontdescend(SNUM(conn))));
        if (in_list(conn->dirpath,lp_dontdescend(SNUM(conn)),conn->case_sensitive))
                dont_descend = True;
-    
+
        p = pdata;
        space_remaining = max_data_bytes;
        out_of_space = False;
@@ -1870,12 +1992,19 @@ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pd
                        out_of_space = True;
                        finished = False;
                } else {
-                       finished = !get_lanman2_dir_entry(conn,
-                                       inbuf, outbuf,
+                       TALLOC_CTX *sub_ctx = talloc_stackframe();
+
+                       finished = !get_lanman2_dir_entry(sub_ctx,
+                                       conn,
+                                       req->flags2,
                                        mask,dirtype,info_level,
                                        requires_resume_key,dont_descend,
-                                       &p,pdata,space_remaining, &out_of_space, &got_exact_match,
-                                       &last_entry_off, ea_list, ea_ctx);
+                                       &p,pdata,data_end,
+                                       space_remaining, &out_of_space,
+                                       &got_exact_match,
+                                       &last_entry_off, ea_list);
+
+                       TALLOC_FREE(sub_ctx);
                }
 
                if (finished && out_of_space)
@@ -1896,8 +2025,6 @@ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pd
 
                space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
        }
-  
-       talloc_destroy(ea_ctx);
 
        /* Check if we can close the dirptr */
        if(close_after_first || (finished && close_if_end)) {
@@ -1905,8 +2032,8 @@ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pd
                dptr_close(&dptr_num);
        }
 
-       /* 
-        * If there are no matching entries we must return ERRDOS/ERRbadfile - 
+       /*
+        * If there are no matching entries we must return ERRDOS/ERRbadfile -
         * from observation of NT. NB. This changes to ERRDOS,ERRnofiles if
         * the protocol level is less than NT1. Tested with smbclient. JRA.
         * This should fix the OS/2 client bug #2335.
@@ -1915,9 +2042,12 @@ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pd
        if(numentries == 0) {
                dptr_close(&dptr_num);
                if (Protocol < PROTOCOL_NT1) {
-                       return ERROR_DOS(ERRDOS,ERRnofiles);
+                       reply_doserror(req, ERRDOS, ERRnofiles);
+                       return;
                } else {
-                       return ERROR_BOTH(NT_STATUS_NO_SUCH_FILE,ERRDOS,ERRbadfile);
+                       reply_botherror(req, NT_STATUS_NO_SUCH_FILE,
+                                       ERRDOS, ERRbadfile);
+                       return;
                }
        }
 
@@ -1930,16 +2060,21 @@ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pd
        SSVAL(params,6,0); /* Never an EA error */
        SSVAL(params,8,last_entry_off);
 
-       send_trans2_replies(inbuf, outbuf, bufsize, params, 10, pdata, PTR_DIFF(p,pdata), max_data_bytes);
+       send_trans2_replies(req, params, 10, pdata, PTR_DIFF(p,pdata),
+                           max_data_bytes);
 
-       if ((! *directory) && dptr_path(dptr_num))
-               slprintf(directory,sizeof(directory)-1, "(%s)",dptr_path(dptr_num));
+       if ((! *directory) && dptr_path(dptr_num)) {
+               directory = talloc_strdup(talloc_tos(),dptr_path(dptr_num));
+               if (!directory) {
+                       reply_nterror(req, NT_STATUS_NO_MEMORY);
+               }
+       }
 
        DEBUG( 4, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
-               smb_fn_name(CVAL(inbuf,smb_com)), 
+               smb_fn_name(CVAL(req->inbuf,smb_com)),
                mask, directory, dirtype, numentries ) );
 
-       /* 
+       /*
         * Force a name mangle here to ensure that the
         * mask as an 8.3 name is top of the mangled cache.
         * The reasons for this are subtle. Don't remove
@@ -1947,19 +2082,23 @@ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pd
         * (see PR#13758). JRA.
         */
 
-       if(!mangle_is_8_3_wildcards( mask, False, conn->params))
-               mangle_map(mask, True, True, conn->params);
+       if(!mangle_is_8_3_wildcards( mask, False, conn->params)) {
+               char mangled_name[13];
+               name_to_8_3(mask, mangled_name, True, conn->params);
+       }
 
-       return(-1);
+       return;
 }
 
 /****************************************************************************
  Reply to a TRANS2_FINDNEXT.
 ****************************************************************************/
 
-static int call_trans2findnext(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
-                                       char **pparams, int total_params, char **ppdata, int total_data,
-                                       unsigned int max_data_bytes)
+static void call_trans2findnext(connection_struct *conn,
+                               struct smb_request *req,
+                               char **pparams, int total_params,
+                               char **ppdata, int total_data,
+                               unsigned int max_data_bytes)
 {
        /* We must be careful here that we don't return more than the
                allowed number of data bytes. If this means returning fewer than
@@ -1968,6 +2107,7 @@ static int call_trans2findnext(connection_struct *conn, char *inbuf, char *outbu
                requested. */
        char *params = *pparams;
        char *pdata = *ppdata;
+       char *data_end;
        int dptr_num;
        int maxentries;
        uint16 info_level;
@@ -1978,10 +2118,10 @@ static int call_trans2findnext(connection_struct *conn, char *inbuf, char *outbu
        BOOL requires_resume_key;
        BOOL continue_bit;
        BOOL mask_contains_wcard = False;
-       pstring resume_name;
-       pstring mask;
-       pstring directory;
-       char *p;
+       char *resume_name = NULL;
+       const char *mask = NULL;
+       const char *directory = NULL;
+       char *p = NULL;
        uint16 dirtype;
        int numentries = 0;
        int i, last_entry_off=0;
@@ -1989,12 +2129,13 @@ static int call_trans2findnext(connection_struct *conn, char *inbuf, char *outbu
        BOOL dont_descend = False;
        BOOL out_of_space = False;
        int space_remaining;
-       TALLOC_CTX *ea_ctx = NULL;
        struct ea_list *ea_list = NULL;
        NTSTATUS ntstatus = NT_STATUS_OK;
+       TALLOC_CTX *ctx = talloc_tos();
 
        if (total_params < 13) {
-               return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
+               reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
+               return;
        }
 
        dptr_num = SVAL(params,0);
@@ -2007,20 +2148,23 @@ static int call_trans2findnext(connection_struct *conn, char *inbuf, char *outbu
        requires_resume_key = (findnext_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
        continue_bit = (findnext_flags & FLAG_TRANS2_FIND_CONTINUE);
 
-       *mask = *directory = *resume_name = 0;
-
-       srvstr_get_path_wcard(inbuf, resume_name, params+12, sizeof(resume_name), total_params - 12, STR_TERMINATE, &ntstatus, &mask_contains_wcard);
+       srvstr_get_path_wcard(ctx, params, req->flags2, &resume_name,
+                             params+12,
+                             total_params - 12, STR_TERMINATE, &ntstatus,
+                             &mask_contains_wcard);
        if (!NT_STATUS_IS_OK(ntstatus)) {
                /* Win9x or OS/2 can send a resume name of ".." or ".". This will cause the parser to
                   complain (it thinks we're asking for the directory above the shared
                   path or an invalid name). Catch this as the resume name is only compared, never used in
                   a file access. JRA. */
-               if (NT_STATUS_EQUAL(ntstatus,NT_STATUS_OBJECT_PATH_SYNTAX_BAD)) {
-                       pstrcpy(resume_name, "..");
-               } else if (NT_STATUS_EQUAL(ntstatus,NT_STATUS_OBJECT_NAME_INVALID)) {
-                       pstrcpy(resume_name, ".");
-               } else {
-                       return ERROR_NT(ntstatus);
+               srvstr_pull_talloc(ctx, params, req->flags2,
+                               &resume_name, params+12,
+                               total_params - 12,
+                               STR_TERMINATE);
+
+               if (!resume_name || !(ISDOT(resume_name) || ISDOTDOT(resume_name))) {
+                       reply_nterror(req, ntstatus);
+                       return;
                }
        }
 
@@ -2049,65 +2193,67 @@ resume_key = %d resume name = %s continue=%d level = %d\n",
                case SMB_FIND_FILE_UNIX:
                case SMB_FIND_FILE_UNIX_INFO2:
                        if (!lp_unix_extensions()) {
-                               return ERROR_NT(NT_STATUS_INVALID_LEVEL);
+                               reply_nterror(req, NT_STATUS_INVALID_LEVEL);
+                               return;
                        }
                        break;
                default:
-                       return ERROR_NT(NT_STATUS_INVALID_LEVEL);
+                       reply_nterror(req, NT_STATUS_INVALID_LEVEL);
+                       return;
        }
 
        if (info_level == SMB_FIND_EA_LIST) {
                uint32 ea_size;
 
                if (total_data < 4) {
-                       return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
+                       reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
+                       return;
                }
 
                ea_size = IVAL(pdata,0);
                if (ea_size != total_data) {
                        DEBUG(4,("call_trans2findnext: Rejecting EA request with incorrect \
 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
-                       return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
+                       reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
+                       return;
                }
-                                                                                                                                                     
+
                if (!lp_ea_support(SNUM(conn))) {
-                       return ERROR_DOS(ERRDOS,ERReasnotsupported);
-               }
-                                                                                                                                                     
-               if ((ea_ctx = talloc_init("findnext_ea_list")) == NULL) {
-                       return ERROR_NT(NT_STATUS_NO_MEMORY);
+                       reply_doserror(req, ERRDOS, ERReasnotsupported);
+                       return;
                }
 
                /* Pull out the list of names. */
-               ea_list = read_ea_name_list(ea_ctx, pdata + 4, ea_size - 4);
+               ea_list = read_ea_name_list(ctx, pdata + 4, ea_size - 4);
                if (!ea_list) {
-                       talloc_destroy(ea_ctx);
-                       return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
+                       reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
+                       return;
                }
        }
 
        *ppdata = (char *)SMB_REALLOC(
                *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
        if(*ppdata == NULL) {
-               talloc_destroy(ea_ctx);
-               return ERROR_NT(NT_STATUS_NO_MEMORY);
+               reply_nterror(req, NT_STATUS_NO_MEMORY);
+               return;
        }
 
        pdata = *ppdata;
+       data_end = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
 
        /* Realloc the params space */
        *pparams = (char *)SMB_REALLOC(*pparams, 6*SIZEOFWORD);
        if(*pparams == NULL ) {
-               talloc_destroy(ea_ctx);
-               return ERROR_NT(NT_STATUS_NO_MEMORY);
+               reply_nterror(req, NT_STATUS_NO_MEMORY);
+               return;
        }
 
        params = *pparams;
 
        /* Check that the dptr is valid */
        if(!(conn->dirptr = dptr_fetch_lanman2(dptr_num))) {
-               talloc_destroy(ea_ctx);
-               return ERROR_DOS(ERRDOS,ERRnofiles);
+               reply_doserror(req, ERRDOS, ERRnofiles);
+               return;
        }
 
        string_set(&conn->dirpath,dptr_path(dptr_num));
@@ -2115,33 +2261,33 @@ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pd
        /* Get the wildcard mask from the dptr */
        if((p = dptr_wcard(dptr_num))== NULL) {
                DEBUG(2,("dptr_num %d has no wildcard\n", dptr_num));
-               talloc_destroy(ea_ctx);
-               return ERROR_DOS(ERRDOS,ERRnofiles);
+               reply_doserror(req, ERRDOS, ERRnofiles);
+               return;
        }
 
-       pstrcpy(mask, p);
-       pstrcpy(directory,conn->dirpath);
+       mask = p;
+       directory = conn->dirpath;
 
        /* Get the attr mask from the dptr */
        dirtype = dptr_attr(dptr_num);
 
        DEBUG(3,("dptr_num is %d, mask = %s, attr = %x, dirptr=(0x%lX,%ld)\n",
-               dptr_num, mask, dirtype, 
+               dptr_num, mask, dirtype,
                (long)conn->dirptr,
                dptr_TellDir(conn->dirptr)));
 
-       /* We don't need to check for VOL here as this is returned by 
+       /* We don't need to check for VOL here as this is returned by
                a different TRANS2 call. */
 
        DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",conn->dirpath,lp_dontdescend(SNUM(conn))));
        if (in_list(conn->dirpath,lp_dontdescend(SNUM(conn)),conn->case_sensitive))
                dont_descend = True;
-    
+
        p = pdata;
        space_remaining = max_data_bytes;
        out_of_space = False;
 
-       /* 
+       /*
         * Seek to the correct position. We no longer use the resume key but
         * depend on the last file name instead.
         */
@@ -2151,14 +2297,20 @@ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pd
 
                long current_pos = 0;
                /*
-                * Remember, mangle_map is called by
+                * Remember, name_to_8_3 is called by
                 * get_lanman2_dir_entry(), so the resume name
                 * could be mangled. Ensure we check the unmangled name.
                 */
 
                if (mangle_is_mangled(resume_name, conn->params)) {
-                       mangle_check_cache(resume_name, sizeof(resume_name)-1,
-                                          conn->params);
+                       char *new_resume_name = NULL;
+                       mangle_lookup_name_from_8_3(ctx,
+                                               resume_name,
+                                               &new_resume_name,
+                                               conn->params);
+                       if (new_resume_name) {
+                               resume_name = new_resume_name;
+                       }
                }
 
                /*
@@ -2182,12 +2334,19 @@ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pd
                        out_of_space = True;
                        finished = False;
                } else {
-                       finished = !get_lanman2_dir_entry(conn,
-                                               inbuf, outbuf,
+                       TALLOC_CTX *sub_ctx = talloc_stackframe();
+
+                       finished = !get_lanman2_dir_entry(sub_ctx,
+                                               conn,
+                                               req->flags2,
                                                mask,dirtype,info_level,
                                                requires_resume_key,dont_descend,
-                                               &p,pdata,space_remaining, &out_of_space, &got_exact_match,
-                                               &last_entry_off, ea_list, ea_ctx);
+                                               &p,pdata,data_end,
+                                               space_remaining, &out_of_space,
+                                               &got_exact_match,
+                                               &last_entry_off, ea_list);
+
+                       TALLOC_FREE(sub_ctx);
                }
 
                if (finished && out_of_space)
@@ -2208,8 +2367,10 @@ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pd
 
                space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
        }
-  
-       talloc_destroy(ea_ctx);
+
+       DEBUG( 3, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
+               smb_fn_name(CVAL(req->inbuf,smb_com)),
+               mask, directory, dirtype, numentries ) );
 
        /* Check if we can close the dirptr */
        if(close_after_request || (finished && close_if_end)) {
@@ -2223,16 +2384,10 @@ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pd
        SSVAL(params,4,0); /* Never an EA error */
        SSVAL(params,6,last_entry_off);
 
-       send_trans2_replies(inbuf, outbuf, bufsize, params, 8, pdata, PTR_DIFF(p,pdata), max_data_bytes);
-
-       if ((! *directory) && dptr_path(dptr_num))
-               slprintf(directory,sizeof(directory)-1, "(%s)",dptr_path(dptr_num));
+       send_trans2_replies(req, params, 8, pdata, PTR_DIFF(p,pdata),
+                           max_data_bytes);
 
-       DEBUG( 3, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
-               smb_fn_name(CVAL(inbuf,smb_com)), 
-               mask, directory, dirtype, numentries ) );
-
-       return(-1);
+       return;
 }
 
 unsigned char *create_volume_objectid(connection_struct *conn, unsigned char objid[16])
@@ -2245,11 +2400,13 @@ unsigned char *create_volume_objectid(connection_struct *conn, unsigned char obj
  Reply to a TRANS2_QFSINFO (query filesystem info).
 ****************************************************************************/
 
-static int call_trans2qfsinfo(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
-                                       char **pparams, int total_params, char **ppdata, int total_data,
-                                       unsigned int max_data_bytes)
+static void call_trans2qfsinfo(connection_struct *conn,
+                              struct smb_request *req,
+                              char **pparams, int total_params,
+                              char **ppdata, int total_data,
+                              unsigned int max_data_bytes)
 {
-       char *pdata;
+       char *pdata, *end_data;
        char *params = *pparams;
        uint16 info_level;
        int data_len, len;
@@ -2260,7 +2417,8 @@ static int call_trans2qfsinfo(connection_struct *conn, char *inbuf, char *outbuf
        int quota_flag = 0;
 
        if (total_params < 2) {
-               return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
+               reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
+               return;
        }
 
        info_level = SVAL(params,0);
@@ -2269,17 +2427,20 @@ static int call_trans2qfsinfo(connection_struct *conn, char *inbuf, char *outbuf
 
        if(SMB_VFS_STAT(conn,".",&st)!=0) {
                DEBUG(2,("call_trans2qfsinfo: stat of . failed (%s)\n", strerror(errno)));
-               return ERROR_DOS(ERRSRV,ERRinvdevice);
+               reply_doserror(req, ERRSRV, ERRinvdevice);
+               return;
        }
 
        *ppdata = (char *)SMB_REALLOC(
                *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
        if (*ppdata == NULL ) {
-               return ERROR_NT(NT_STATUS_NO_MEMORY);
+               reply_nterror(req, NT_STATUS_NO_MEMORY);
+               return;
        }
 
        pdata = *ppdata;
        memset((char *)pdata,'\0',max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
+       end_data = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
 
        switch (info_level) {
                case SMB_INFO_ALLOCATION:
@@ -2287,7 +2448,8 @@ static int call_trans2qfsinfo(connection_struct *conn, char *inbuf, char *outbuf
                        SMB_BIG_UINT dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
                        data_len = 18;
                        if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (SMB_BIG_UINT)-1) {
-                               return(UNIXERROR(ERRHRD,ERRgeneral));
+                               reply_unixerror(req, ERRHRD, ERRgeneral);
+                               return;
                        }
 
                        block_size = lp_block_size(snum);
@@ -2331,7 +2493,11 @@ cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)st.st_dev, (unsi
                         * this call so try fixing this by adding a terminating null to
                         * the pushed string. The change here was adding the STR_TERMINATE. JRA.
                         */
-                       len = srvstr_push(outbuf, pdata+l2_vol_szVolLabel, vname, -1, STR_NOALIGN|STR_TERMINATE);
+                       len = srvstr_push(
+                               pdata, req->flags2,
+                               pdata+l2_vol_szVolLabel, vname,
+                               PTR_DIFF(end_data, pdata+l2_vol_szVolLabel),
+                               STR_NOALIGN|STR_TERMINATE);
                        SCVAL(pdata,l2_vol_cch,len);
                        data_len = l2_vol_szVolLabel + len;
                        DEBUG(5,("call_trans2qfsinfo : time = %x, namelen = %d, name = %s\n",
@@ -2355,14 +2521,17 @@ cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)st.st_dev, (unsi
                        SIVAL(pdata,4,255); /* Max filename component length */
                        /* NOTE! the fstype must *not* be null terminated or win98 won't recognise it
                                and will think we can't do long filenames */
-                       len = srvstr_push(outbuf, pdata+12, fstype, -1, STR_UNICODE);
+                       len = srvstr_push(pdata, req->flags2, pdata+12, fstype,
+                                         PTR_DIFF(end_data, pdata+12),
+                                         STR_UNICODE);
                        SIVAL(pdata,8,len);
                        data_len = 12 + len;
                        break;
 
                case SMB_QUERY_FS_LABEL_INFO:
                case SMB_FS_LABEL_INFORMATION:
-                       len = srvstr_push(outbuf, pdata+4, vname, -1, 0);
+                       len = srvstr_push(pdata, req->flags2, pdata+4, vname,
+                                         PTR_DIFF(end_data, pdata+4), 0);
                        data_len = 4 + len;
                        SIVAL(pdata,0,len);
                        break;
@@ -2378,7 +2547,9 @@ cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)st.st_dev, (unsi
                                (str_checksum(get_local_machine_name())<<16));
 
                        /* Max label len is 32 characters. */
-                       len = srvstr_push(outbuf, pdata+18, vname, -1, STR_UNICODE);
+                       len = srvstr_push(pdata, req->flags2, pdata+18, vname,
+                                         PTR_DIFF(end_data, pdata+18),
+                                         STR_UNICODE);
                        SIVAL(pdata,12,len);
                        data_len = 18+len;
 
@@ -2392,7 +2563,8 @@ cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)st.st_dev, (unsi
                        SMB_BIG_UINT dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
                        data_len = 24;
                        if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (SMB_BIG_UINT)-1) {
-                               return(UNIXERROR(ERRHRD,ERRgeneral));
+                               reply_unixerror(req, ERRHRD, ERRgeneral);
+                               return;
                        }
                        block_size = lp_block_size(snum);
                        if (bsize < block_size) {
@@ -2424,7 +2596,8 @@ cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned
                        SMB_BIG_UINT dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
                        data_len = 32;
                        if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (SMB_BIG_UINT)-1) {
-                               return(UNIXERROR(ERRHRD,ERRgeneral));
+                               reply_unixerror(req, ERRHRD, ERRgeneral);
+                               return;
                        }
                        block_size = lp_block_size(snum);
                        if (bsize < block_size) {
@@ -2497,12 +2670,14 @@ cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned
                        if (current_user.ut.uid != 0) {
                                DEBUG(0,("set_user_quota: access_denied service [%s] user [%s]\n",
                                        lp_servicename(SNUM(conn)),conn->user));
-                               return ERROR_DOS(ERRDOS,ERRnoaccess);
+                               reply_doserror(req, ERRDOS, ERRnoaccess);
+                               return;
                        }
                        
                        if (vfs_get_ntquota(&fsp, SMB_USER_FS_QUOTA_TYPE, NULL, &quotas)!=0) {
                                DEBUG(0,("vfs_get_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn))));
-                               return ERROR_DOS(ERRSRV,ERRerror);
+                               reply_doserror(req, ERRSRV, ERRerror);
+                               return;
                        }
 
                        data_len = 48;
@@ -2545,7 +2720,8 @@ cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned
 
                case SMB_QUERY_CIFS_UNIX_INFO:
                        if (!lp_unix_extensions()) {
-                               return ERROR_NT(NT_STATUS_INVALID_LEVEL);
+                               reply_nterror(req, NT_STATUS_INVALID_LEVEL);
+                               return;
                        }
                        data_len = 12;
                        SSVAL(pdata,0,CIFS_UNIX_MAJOR_VERSION);
@@ -2568,7 +2744,8 @@ cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned
                        vfs_statvfs_struct svfs;
 
                        if (!lp_unix_extensions()) {
-                               return ERROR_NT(NT_STATUS_INVALID_LEVEL);
+                               reply_nterror(req, NT_STATUS_INVALID_LEVEL);
+                               return;
                        }
 
                        rc = SMB_VFS_STATVFS(conn, ".", &svfs);
@@ -2586,11 +2763,13 @@ cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned
                                DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_POSIX_FS_INFO succsessful\n"));
 #ifdef EOPNOTSUPP
                        } else if (rc == EOPNOTSUPP) {
-                               return ERROR_NT(NT_STATUS_INVALID_LEVEL);
+                               reply_nterror(req, NT_STATUS_INVALID_LEVEL);
+                               return;
 #endif /* EOPNOTSUPP */
                        } else {
                                DEBUG(0,("vfs_statvfs() failed for service [%s]\n",lp_servicename(SNUM(conn))));
-                               return ERROR_DOS(ERRSRV,ERRerror);
+                               reply_doserror(req, ERRSRV, ERRerror);
+                               return;
                        }
                        break;
                }
@@ -2602,11 +2781,13 @@ cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned
                        int i;
 
                        if (!lp_unix_extensions()) {
-                               return ERROR_NT(NT_STATUS_INVALID_LEVEL);
+                               reply_nterror(req, NT_STATUS_INVALID_LEVEL);
+                               return;
                        }
 
                        if (max_data_bytes < 40) {
-                               return ERROR_NT(NT_STATUS_BUFFER_TOO_SMALL);
+                               reply_nterror(req, NT_STATUS_BUFFER_TOO_SMALL);
+                               return;
                        }
 
                        /* We ARE guest if global_sid_Builtin_Guests is
@@ -2715,29 +2896,33 @@ cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned
                        }
                        /* drop through */
                default:
-                       return ERROR_NT(NT_STATUS_INVALID_LEVEL);
+                       reply_nterror(req, NT_STATUS_INVALID_LEVEL);
+                       return;
        }
 
 
-       send_trans2_replies(inbuf, outbuf, bufsize, params, 0, pdata, data_len, max_data_bytes);
+       send_trans2_replies(req, params, 0, pdata, data_len,
+                           max_data_bytes);
 
-       DEBUG( 4, ( "%s info_level = %d\n", smb_fn_name(CVAL(inbuf,smb_com)), info_level) );
+       DEBUG( 4, ( "%s info_level = %d\n",
+                   smb_fn_name(CVAL(req->inbuf,smb_com)), info_level) );
 
-       return -1;
+       return;
 }
 
 /****************************************************************************
  Reply to a TRANS2_SETFSINFO (set filesystem info).
 ****************************************************************************/
 
-static int call_trans2setfsinfo(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
-                                       char **pparams, int total_params, char **ppdata, int total_data,
-                                       unsigned int max_data_bytes)
+static void call_trans2setfsinfo(connection_struct *conn,
+                                struct smb_request *req,
+                                char **pparams, int total_params,
+                                char **ppdata, int total_data,
+                                unsigned int max_data_bytes)
 {
        char *pdata = *ppdata;
        char *params = *pparams;
        uint16 info_level;
-       int outsize;
 
        DEBUG(10,("call_trans2setfsinfo: for service [%s]\n",lp_servicename(SNUM(conn))));
 
@@ -2745,7 +2930,8 @@ static int call_trans2setfsinfo(connection_struct *conn, char *inbuf, char *outb
        if (total_params < 4) {
                DEBUG(0,("call_trans2setfsinfo: requires total_params(%d) >= 4 bytes!\n",
                        total_params));
-               return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
+               reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
+               return;
        }
 
        info_level = SVAL(params,2);
@@ -2759,12 +2945,17 @@ static int call_trans2setfsinfo(connection_struct *conn, char *inbuf, char *outb
                                uint32 client_unix_cap_high;
 
                                if (!lp_unix_extensions()) {
-                                       return ERROR_NT(NT_STATUS_INVALID_LEVEL);
+                                       reply_nterror(req,
+                                                     NT_STATUS_INVALID_LEVEL);
+                                       return;
                                }
 
                                /* There should be 12 bytes of capabilities set. */
                                if (total_data < 8) {
-                                       return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
+                                       reply_nterror(
+                                               req,
+                                               NT_STATUS_INVALID_PARAMETER);
+                                       return;
                                }
                                client_unix_major = SVAL(pdata,0);
                                client_unix_minor = SVAL(pdata,2);
@@ -2802,7 +2993,9 @@ cap_low = 0x%x, cap_high = 0x%x\n",
                                size_t data_len = total_data;
 
                                if (!lp_unix_extensions()) {
-                                       return ERROR_NT(NT_STATUS_INVALID_LEVEL);
+                                       reply_nterror(
+                                               req, NT_STATUS_INVALID_LEVEL);
+                                       return;
                                }
 
                                DEBUG( 4,("call_trans2setfsinfo: request transport encrption.\n"));
@@ -2814,13 +3007,20 @@ cap_low = 0x%x, cap_high = 0x%x\n",
                                                                        &param_len
                                                                        );
 
-                               if (NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
-                                       error_packet_set(outbuf, 0, 0, status, __LINE__,__FILE__);
-                               } else if (!NT_STATUS_IS_OK(status)) {
-                                       return ERROR_NT(status);
+                               if (!NT_STATUS_IS_OK(status)) {
+                                       /*
+                                        * TODO: Check
+                                        * MORE_PROCESSING_REQUIRED, this used
+                                        * to have special handling here.
+                                        */
+                                       reply_nterror(req, status);
+                                       return;
                                }
 
-                               send_trans2_replies(inbuf, outbuf, bufsize, *pparams, param_len, *ppdata, data_len, max_data_bytes);
+                               send_trans2_replies(req,
+                                                   *pparams, param_len,
+                                                   *ppdata, data_len,
+                                                   max_data_bytes);
 
                                if (NT_STATUS_IS_OK(status)) {
                                        /* Server-side transport encryption is now *on*. */
@@ -2829,7 +3029,7 @@ cap_low = 0x%x, cap_high = 0x%x\n",
                                                exit_server_cleanly("Failure in setting up encrypted transport");
                                        }
                                }
-                               return -1;
+                               return;
                        }
                case SMB_FS_QUOTA_INFORMATION:
                        {
@@ -2842,23 +3042,29 @@ cap_low = 0x%x, cap_high = 0x%x\n",
                                if ((current_user.ut.uid != 0)||!CAN_WRITE(conn)) {
                                        DEBUG(0,("set_user_quota: access_denied service [%s] user [%s]\n",
                                                lp_servicename(SNUM(conn)),conn->user));
-                                       return ERROR_DOS(ERRSRV,ERRaccess);
+                                       reply_doserror(req, ERRSRV, ERRaccess);
+                                       return;
                                }
 
                                /* note: normaly there're 48 bytes,
                                 * but we didn't use the last 6 bytes for now 
                                 * --metze 
                                 */
-                               fsp = file_fsp(params,0);
+                               fsp = file_fsp(SVAL(params,0));
                                if (!CHECK_NTQUOTA_HANDLE_OK(fsp,conn)) {
                                        DEBUG(3,("TRANSACT_GET_USER_QUOTA: no valid QUOTA HANDLE\n"));
-                                       return ERROR_NT(NT_STATUS_INVALID_HANDLE);
+                                       reply_nterror(
+                                               req, NT_STATUS_INVALID_HANDLE);
+                                       return;
                                }
 
                                if (total_data < 42) {
                                        DEBUG(0,("call_trans2setfsinfo: SET_FS_QUOTA: requires total_data(%d) >= 42 bytes!\n",
                                                total_data));
-                                       return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
+                                       reply_nterror(
+                                               req,
+                                               NT_STATUS_INVALID_PARAMETER);
+                                       return;
                                }
                        
                                /* unknown_1 24 NULL bytes in pdata*/
@@ -2872,7 +3078,10 @@ cap_low = 0x%x, cap_high = 0x%x\n",
                                        ((quotas.softlim != 0xFFFFFFFF)||
                                        (IVAL(pdata,28)!=0xFFFFFFFF))) {
                                        /* more than 32 bits? */
-                                       return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
+                                       reply_nterror(
+                                               req,
+                                               NT_STATUS_INVALID_PARAMETER);
+                                       return;
                                }
 #endif /* LARGE_SMB_OFF_T */
                
@@ -2885,7 +3094,10 @@ cap_low = 0x%x, cap_high = 0x%x\n",
                                        ((quotas.hardlim != 0xFFFFFFFF)||
                                        (IVAL(pdata,36)!=0xFFFFFFFF))) {
                                        /* more than 32 bits? */
-                                       return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
+                                       reply_nterror(
+                                               req,
+                                               NT_STATUS_INVALID_PARAMETER);
+                                       return;
                                }
 #endif /* LARGE_SMB_OFF_T */
                
@@ -2897,7 +3109,8 @@ cap_low = 0x%x, cap_high = 0x%x\n",
                                /* now set the quotas */
                                if (vfs_set_ntquota(fsp, SMB_USER_FS_QUOTA_TYPE, NULL, &quotas)!=0) {
                                        DEBUG(0,("vfs_set_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn))));
-                                       return ERROR_DOS(ERRSRV,ERRerror);
+                                       reply_doserror(req, ERRSRV, ERRerror);
+                                       return;
                                }
                        
                                break;
@@ -2905,7 +3118,8 @@ cap_low = 0x%x, cap_high = 0x%x\n",
                default:
                        DEBUG(3,("call_trans2setfsinfo: unknown level (0x%X) not implemented yet.\n",
                                info_level));
-                       return ERROR_NT(NT_STATUS_INVALID_LEVEL);
+                       reply_nterror(req, NT_STATUS_INVALID_LEVEL);
+                       return;
                        break;
        }
 
@@ -2914,10 +3128,8 @@ cap_low = 0x%x, cap_high = 0x%x\n",
         * but I'm not sure it's the same 
         * like windows do...
         * --metze
-        */ 
-       outsize = set_message(inbuf, outbuf,10,0,True);
-
-       return outsize;
+        */
+       reply_outbuf(req, 10, 0);
 }
 
 #if defined(HAVE_POSIX_ACLS)
@@ -2989,6 +3201,7 @@ static BOOL marshall_posix_acl(connection_struct *conn, char *pdata, SMB_STRUCT_
                                        uid_t *puid = (uid_t *)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn, entry);
                                        if (!puid) {
                                                DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
+                                               return False;
                                        }
                                        own_grp = (unsigned int)*puid;
                                        SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn, (void *)puid,tagtype);
@@ -3008,6 +3221,7 @@ static BOOL marshall_posix_acl(connection_struct *conn, char *pdata, SMB_STRUCT_
                                        gid_t *pgid= (gid_t *)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn, entry);
                                        if (!pgid) {
                                                DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
+                                               return False;
                                        }
                                        own_grp = (unsigned int)*pgid;
                                        SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn, (void *)pgid,tagtype);
@@ -3212,10 +3426,12 @@ static char *store_file_unix_basic_info2(connection_struct *conn,
  Reply to a TRANSACT2_QFILEINFO on a PIPE !
 ****************************************************************************/
 
-static int call_trans2qpipeinfo(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
-                                       unsigned int tran_call,
-                                       char **pparams, int total_params, char **ppdata, int total_data,
-                                       unsigned int max_data_bytes)
+static void call_trans2qpipeinfo(connection_struct *conn,
+                                struct smb_request *req,
+                                unsigned int tran_call,
+                                char **pparams, int total_params,
+                                char **ppdata, int total_data,
+                                unsigned int max_data_bytes)
 {
        char *params = *pparams;
        char *pdata = *ppdata;
@@ -3225,36 +3441,41 @@ static int call_trans2qpipeinfo(connection_struct *conn, char *inbuf, char *outb
        smb_np_struct *p_pipe = NULL;
 
        if (!params) {
-               return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
+               reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
+               return;
        }
 
        if (total_params < 4) {
-               return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
+               reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
+               return;
        }
 
-       p_pipe = get_rpc_pipe_p(params,0);
+       p_pipe = get_rpc_pipe_p(SVAL(params,0));
        if (p_pipe == NULL) {
-               return ERROR_NT(NT_STATUS_INVALID_HANDLE);
+               reply_nterror(req, NT_STATUS_INVALID_HANDLE);
+               return;
        }
 
        info_level = SVAL(params,2);
 
        *pparams = (char *)SMB_REALLOC(*pparams,2);
        if (*pparams == NULL) {
-               return ERROR_NT(NT_STATUS_NO_MEMORY);
+               reply_nterror(req, NT_STATUS_NO_MEMORY);
+               return;
        }
        params = *pparams;
        SSVAL(params,0,0);
        data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
        *ppdata = (char *)SMB_REALLOC(*ppdata, data_size); 
        if (*ppdata == NULL ) {
-               return ERROR_NT(NT_STATUS_NO_MEMORY);
+               reply_nterror(req, NT_STATUS_NO_MEMORY);
+               return;
        }
        pdata = *ppdata;
 
        switch (info_level) {
                case SMB_FILE_STANDARD_INFORMATION:
-                       memset(pdata,24,0);
+                       memset(pdata,0,24);
                        SOFF_T(pdata,0,4096LL);
                        SIVAL(pdata,16,1);
                        SIVAL(pdata,20,1);
@@ -3262,12 +3483,14 @@ static int call_trans2qpipeinfo(connection_struct *conn, char *inbuf, char *outb
                        break;
 
                default:
-                       return ERROR_NT(NT_STATUS_INVALID_LEVEL);
+                       reply_nterror(req, NT_STATUS_INVALID_LEVEL);
+                       return;
        }
 
-       send_trans2_replies(inbuf, outbuf, bufsize, params, param_size, *ppdata, data_size, max_data_bytes);
+       send_trans2_replies(req, params, param_size, *ppdata, data_size,
+                           max_data_bytes);
 
-       return(-1);
+       return;
 }
 
 /****************************************************************************
@@ -3275,13 +3498,16 @@ static int call_trans2qpipeinfo(connection_struct *conn, char *inbuf, char *outb
  file name or file id).
 ****************************************************************************/
 
-static int call_trans2qfilepathinfo(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
-                                       unsigned int tran_call,
-                                       char **pparams, int total_params, char **ppdata, int total_data,
-                                       unsigned int max_data_bytes)
+static void call_trans2qfilepathinfo(connection_struct *conn,
+                                    struct smb_request *req,
+                                    unsigned int tran_call,
+                                    char **pparams, int total_params,
+                                    char **ppdata, int total_data,
+                                    unsigned int max_data_bytes)
 {
        char *params = *pparams;
        char *pdata = *ppdata;
+       char *dstart, *dend;
        uint16 info_level;
        int mode=0;
        int nlink;
@@ -3290,7 +3516,8 @@ static int call_trans2qfilepathinfo(connection_struct *conn, char *inbuf, char *
        unsigned int data_size = 0;
        unsigned int param_size = 2;
        SMB_STRUCT_STAT sbuf;
-       pstring fname, dos_fname;
+       char *dos_fname = NULL;
+       char *fname = NULL;
        char *fullpathname;
        char *base_name;
        char *p;
@@ -3300,94 +3527,109 @@ static int call_trans2qfilepathinfo(connection_struct *conn, char *inbuf, char *
        time_t create_time, mtime, atime;
        struct timespec create_time_ts, mtime_ts, atime_ts;
        files_struct *fsp = NULL;
-       TALLOC_CTX *data_ctx = NULL;
+       struct file_id fileid;
        struct ea_list *ea_list = NULL;
        uint32 access_mask = 0x12019F; /* Default - GENERIC_EXECUTE mapping from Windows */
        char *lock_data = NULL;
+       TALLOC_CTX *ctx = talloc_tos();
 
-       if (!params)
-               return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
+       if (!params) {
+               reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
+               return;
+       }
 
        ZERO_STRUCT(sbuf);
 
        if (tran_call == TRANSACT2_QFILEINFO) {
                if (total_params < 4) {
-                       return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
+                       reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
+                       return;
                }
 
                if (IS_IPC(conn)) {
-                       return call_trans2qpipeinfo(conn,
-                                                       inbuf,
-                                                       outbuf,
-                                                       length,
-                                                       bufsize,
-                                                       tran_call,
-                                                       pparams,
-                                                       total_params,
-                                                       ppdata,
-                                                       total_data,
-                                                       max_data_bytes);
+                       call_trans2qpipeinfo(conn, req, tran_call,
+                                            pparams, total_params,
+                                            ppdata, total_data,
+                                            max_data_bytes);
+                       return;
                }
 
-               fsp = file_fsp(params,0);
+               fsp = file_fsp(SVAL(params,0));
                info_level = SVAL(params,2);
 
                DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QFILEINFO: level = %d\n", info_level));
 
                if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
-                       return ERROR_NT(NT_STATUS_INVALID_LEVEL);
+                       reply_nterror(req, NT_STATUS_INVALID_LEVEL);
+                       return;
                }
 
-               if(fsp && (fsp->fake_file_handle)) {
+               /* Initial check for valid fsp ptr. */
+               if (!check_fsp_open(conn, req, fsp, &current_user)) {
+                       return;
+               }
+
+               fname = talloc_strdup(talloc_tos(),fsp->fsp_name);
+               if (!fname) {
+                       reply_nterror(req, NT_STATUS_NO_MEMORY);
+                       return;
+               }
+
+               if(fsp->fake_file_handle) {
                        /*
                         * This is actually for the QUOTA_FAKE_FILE --metze
                         */
-                                               
-                       pstrcpy(fname, fsp->fsp_name);
+
                        /* We know this name is ok, it's already passed the checks. */
-                       
+
                } else if(fsp && (fsp->is_directory || fsp->fh->fd == -1)) {
                        /*
                         * This is actually a QFILEINFO on a directory
                         * handle (returned from an NT SMB). NT5.0 seems
                         * to do this call. JRA.
                         */
-                       /* We know this name is ok, it's already passed the checks. */
-                       pstrcpy(fname, fsp->fsp_name);
-                 
+
                        if (INFO_LEVEL_IS_UNIX(info_level)) {
                                /* Always do lstat for UNIX calls. */
                                if (SMB_VFS_LSTAT(conn,fname,&sbuf)) {
                                        DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",fname,strerror(errno)));
-                                       return UNIXERROR(ERRDOS,ERRbadpath);
+                                       reply_unixerror(req,ERRDOS,ERRbadpath);
+                                       return;
                                }
                        } else if (SMB_VFS_STAT(conn,fname,&sbuf)) {
                                DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_STAT of %s failed (%s)\n",fname,strerror(errno)));
-                               return UNIXERROR(ERRDOS,ERRbadpath);
+                               reply_unixerror(req, ERRDOS, ERRbadpath);
+                               return;
                        }
 
-                       delete_pending = get_delete_on_close_flag(sbuf.st_dev, sbuf.st_ino);
+                       fileid = vfs_file_id_from_sbuf(conn, &sbuf);
+                       delete_pending = get_delete_on_close_flag(fileid);
                } else {
                        /*
                         * Original code - this is an open file.
                         */
-                       CHECK_FSP(fsp,conn);
+                       if (!check_fsp(conn, req, fsp, &current_user)) {
+                               return;
+                       }
 
-                       pstrcpy(fname, fsp->fsp_name);
                        if (SMB_VFS_FSTAT(fsp,fsp->fh->fd,&sbuf) != 0) {
                                DEBUG(3,("fstat of fnum %d failed (%s)\n", fsp->fnum, strerror(errno)));
-                               return(UNIXERROR(ERRDOS,ERRbadfid));
+                               reply_unixerror(req, ERRDOS, ERRbadfid);
+                               return;
                        }
                        pos = fsp->fh->position_information;
-                       delete_pending = get_delete_on_close_flag(sbuf.st_dev, sbuf.st_ino);
+                       fileid = vfs_file_id_from_sbuf(conn, &sbuf);
+                       delete_pending = get_delete_on_close_flag(fileid);
                        access_mask = fsp->access_mask;
                }
+
        } else {
                NTSTATUS status = NT_STATUS_OK;
 
                /* qpathinfo */
                if (total_params < 7) {
-                       return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
+                       reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
+                       return;
                }
 
                info_level = SVAL(params,0);
@@ -3395,46 +3637,63 @@ static int call_trans2qfilepathinfo(connection_struct *conn, char *inbuf, char *
                DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QPATHINFO: level = %d\n", info_level));
 
                if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
-                       return ERROR_NT(NT_STATUS_INVALID_LEVEL);
+                       reply_nterror(req, NT_STATUS_INVALID_LEVEL);
+                       return;
                }
 
-               srvstr_get_path(inbuf, fname, &params[6], sizeof(fname), total_params - 6, STR_TERMINATE, &status);
+               srvstr_get_path(ctx, params, req->flags2, &fname, &params[6],
+                               total_params - 6,
+                               STR_TERMINATE, &status);
                if (!NT_STATUS_IS_OK(status)) {
-                       return ERROR_NT(status);
+                       reply_nterror(req, status);
+                       return;
                }
 
-               status = resolve_dfspath(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, fname);
+               status = resolve_dfspath(ctx,
+                                       conn,
+                                       req->flags2 & FLAGS2_DFS_PATHNAMES,
+                                       fname,
+                                       &fname);
                if (!NT_STATUS_IS_OK(status)) {
                        if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
-                               return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath);
+                               reply_botherror(req,
+                                               NT_STATUS_PATH_NOT_COVERED,
+                                               ERRSRV, ERRbadpath);
                        }
-                       return ERROR_NT(status);
+                       reply_nterror(req, status);
+                       return;
                }
 
-               status = unix_convert(conn, fname, False, NULL, &sbuf);
+               status = unix_convert(conn, fname, False, &fname, NULL, &sbuf);
                if (!NT_STATUS_IS_OK(status)) {
-                       return ERROR_NT(status);
+                       reply_nterror(req, status);
+                       return;
                }
                status = check_name(conn, fname);
                if (!NT_STATUS_IS_OK(status)) {
                        DEBUG(3,("call_trans2qfilepathinfo: fileinfo of %s failed (%s)\n",fname,nt_errstr(status)));
-                       return ERROR_NT(status);
+                       reply_nterror(req, status);
+                       return;
                }
 
                if (INFO_LEVEL_IS_UNIX(info_level)) {
                        /* Always do lstat for UNIX calls. */
                        if (SMB_VFS_LSTAT(conn,fname,&sbuf)) {
                                DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",fname,strerror(errno)));
-                               return UNIXERROR(ERRDOS,ERRbadpath);
+                               reply_unixerror(req, ERRDOS, ERRbadpath);
+                               return;
                        }
                } else if (!VALID_STAT(sbuf) && SMB_VFS_STAT(conn,fname,&sbuf) && (info_level != SMB_INFO_IS_NAME_VALID)) {
                        DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_STAT of %s failed (%s)\n",fname,strerror(errno)));
-                       return UNIXERROR(ERRDOS,ERRbadpath);
+                       reply_unixerror(req, ERRDOS, ERRbadpath);
+                       return;
                }
 
-               delete_pending = get_delete_on_close_flag(sbuf.st_dev, sbuf.st_ino);
+               fileid = vfs_file_id_from_sbuf(conn, &sbuf);
+               delete_pending = get_delete_on_close_flag(fileid);
                if (delete_pending) {
-                       return ERROR_NT(NT_STATUS_DELETE_PENDING);
+                       reply_nterror(req, NT_STATUS_DELETE_PENDING);
+                       return;
                }
        }
 
@@ -3450,13 +3709,14 @@ static int call_trans2qfilepathinfo(connection_struct *conn, char *inbuf, char *
        }
 
        if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
-               return ERROR_NT(NT_STATUS_INVALID_LEVEL);
+               reply_nterror(req, NT_STATUS_INVALID_LEVEL);
+               return;
        }
 
        DEBUG(3,("call_trans2qfilepathinfo %s (fnum = %d) level=%d call=%d total_data=%d\n",
                fname,fsp ? fsp->fnum : -1, info_level,tran_call,total_data));
 
-       p = strrchr_m(fname,'/'); 
+       p = strrchr_m(fname,'/');
        if (!p)
                base_name = fname;
        else
@@ -3478,29 +3738,32 @@ static int call_trans2qfilepathinfo(connection_struct *conn, char *inbuf, char *
                        uint32 ea_size;
 
                        if (total_data < 4) {
-                               return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
+                               reply_nterror(
+                                       req, NT_STATUS_INVALID_PARAMETER);
+                               return;
                        }
                        ea_size = IVAL(pdata,0);
 
                        if (total_data > 0 && ea_size != total_data) {
                                DEBUG(4,("call_trans2qfilepathinfo: Rejecting EA request with incorrect \
 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
-                               return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
+                               reply_nterror(
+                                       req, NT_STATUS_INVALID_PARAMETER);
+                               return;
                        }
 
                        if (!lp_ea_support(SNUM(conn))) {
-                               return ERROR_DOS(ERRDOS,ERReasnotsupported);
-                       }
-
-                       if ((data_ctx = talloc_init("ea_list")) == NULL) {
-                               return ERROR_NT(NT_STATUS_NO_MEMORY);
+                               reply_doserror(req, ERRDOS,
+                                              ERReasnotsupported);
+                               return;
                        }
 
                        /* Pull out the list of names. */
-                       ea_list = read_ea_name_list(data_ctx, pdata + 4, ea_size - 4);
+                       ea_list = read_ea_name_list(ctx, pdata + 4, ea_size - 4);
                        if (!ea_list) {
-                               talloc_destroy(data_ctx);
-                               return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
+                               reply_nterror(
+                                       req, NT_STATUS_INVALID_PARAMETER);
+                               return;
                        }
                        break;
                }
@@ -3508,23 +3771,22 @@ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pd
                case SMB_QUERY_POSIX_LOCK:
                {
                        if (fsp == NULL || fsp->fh->fd == -1) {
-                               return ERROR_NT(NT_STATUS_INVALID_HANDLE);
+                               reply_nterror(req, NT_STATUS_INVALID_HANDLE);
+                               return;
                        }
 
                        if (total_data != POSIX_LOCK_DATA_SIZE) {
-                               return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
-                       }
-
-                       if ((data_ctx = talloc_init("lock_request")) == NULL) {
-                               return ERROR_NT(NT_STATUS_NO_MEMORY);
+                               reply_nterror(
+                                       req, NT_STATUS_INVALID_PARAMETER);
+                               return;
                        }
 
                        /* Copy the lock range data. */
                        lock_data = (char *)TALLOC_MEMDUP(
-                               data_ctx, pdata, total_data);
+                               ctx, pdata, total_data);
                        if (!lock_data) {
-                               talloc_destroy(data_ctx);
-                               return ERROR_NT(NT_STATUS_NO_MEMORY);
+                               reply_nterror(req, NT_STATUS_NO_MEMORY);
+                               return;
                        }
                }
                default:
@@ -3533,18 +3795,20 @@ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pd
 
        *pparams = (char *)SMB_REALLOC(*pparams,2);
        if (*pparams == NULL) {
-               talloc_destroy(data_ctx);
-               return ERROR_NT(NT_STATUS_NO_MEMORY);
+               reply_nterror(req, NT_STATUS_NO_MEMORY);
+               return;
        }
        params = *pparams;
        SSVAL(params,0,0);
        data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
        *ppdata = (char *)SMB_REALLOC(*ppdata, data_size); 
        if (*ppdata == NULL ) {
-               talloc_destroy(data_ctx);
-               return ERROR_NT(NT_STATUS_NO_MEMORY);
+               reply_nterror(req, NT_STATUS_NO_MEMORY);
+               return;
        }
        pdata = *ppdata;
+       dstart = pdata;
+       dend = dstart + data_size - 1;
 
        create_time_ts = get_create_timespec(&sbuf,lp_fake_dir_create_times(SNUM(conn)));
        mtime_ts = get_mtimespec(&sbuf);
@@ -3558,8 +3822,10 @@ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pd
                        mtime_ts = fsp->pending_modtime;
                }
        } else {
+               files_struct *fsp1;
                /* Do we have this path open ? */
-               files_struct *fsp1 = file_find_di_first(sbuf.st_dev, sbuf.st_ino);
+               fileid = vfs_file_id_from_sbuf(conn, &sbuf);
+               fsp1 = file_find_di_first(fileid);
                if (fsp1 && !null_timespec(fsp1->pending_modtime)) {
                        /* the pending modtime overrides the current modtime */
                        mtime_ts = fsp1->pending_modtime;
@@ -3581,10 +3847,20 @@ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pd
 
        /* NT expects the name to be in an exact form of the *full*
           filename. See the trans2 torture test */
-       if (strequal(base_name,".")) {
-               pstrcpy(dos_fname, "\\");
+       if (ISDOT(base_name)) {
+               dos_fname = talloc_strdup(ctx, "\\");
+               if (!dos_fname) {
+                       reply_nterror(req, NT_STATUS_NO_MEMORY);
+                       return;
+               }
        } else {
-               pstr_sprintf(dos_fname, "\\%s", fname);
+               dos_fname = talloc_asprintf(ctx,
+                               "\\%s",
+                               fname);
+               if (!dos_fname) {
+                       reply_nterror(req, NT_STATUS_NO_MEMORY);
+                       return;
+               }
                string_replace(dos_fname, '/', '\\');
        }
 
@@ -3618,13 +3894,14 @@ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pd
                case SMB_INFO_IS_NAME_VALID:
                        DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_IS_NAME_VALID\n"));
                        if (tran_call == TRANSACT2_QFILEINFO) {
-                               /* os/2 needs this ? really ?*/      
-                               return ERROR_DOS(ERRDOS,ERRbadfunc); 
+                               /* os/2 needs this ? really ?*/
+                               reply_doserror(req, ERRDOS, ERRbadfunc);
+                               return;
                        }
                        data_size = 0;
                        param_size = 0;
                        break;
-                       
+
                case SMB_INFO_QUERY_EAS_FROM_LIST:
                {
                        size_t total_ea_len = 0;
@@ -3632,18 +3909,16 @@ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pd
 
                        DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_EAS_FROM_LIST\n"));
 
-                       ea_file_list = get_ea_list_from_file(data_ctx, conn, fsp, fname, &total_ea_len);
+                       ea_file_list = get_ea_list_from_file(ctx, conn, fsp, fname, &total_ea_len);
                        ea_list = ea_list_union(ea_list, ea_file_list, &total_ea_len);
 
                        if (!ea_list || (total_ea_len > data_size)) {
-                               talloc_destroy(data_ctx);
                                data_size = 4;
                                SIVAL(pdata,0,4);   /* EA List Length must be set to 4 if no EA's. */
                                break;
                        }
 
-                       data_size = fill_ea_buffer(data_ctx, pdata, data_size, conn, ea_list);
-                       talloc_destroy(data_ctx);
+                       data_size = fill_ea_buffer(ctx, pdata, data_size, conn, ea_list);
                        break;
                }
 
@@ -3654,21 +3929,14 @@ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pd
 
                        DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_ALL_EAS\n"));
 
-                       data_ctx = talloc_init("ea_ctx");
-                       if (!data_ctx) {
-                               return ERROR_NT(NT_STATUS_NO_MEMORY);
-                       }
-
-                       ea_list = get_ea_list_from_file(data_ctx, conn, fsp, fname, &total_ea_len);
+                       ea_list = get_ea_list_from_file(ctx, conn, fsp, fname, &total_ea_len);
                        if (!ea_list || (total_ea_len > data_size)) {
-                               talloc_destroy(data_ctx);
                                data_size = 4;
                                SIVAL(pdata,0,4);   /* EA List Length must be set to 4 if no EA's. */
                                break;
                        }
 
-                       data_size = fill_ea_buffer(data_ctx, pdata, data_size, conn, ea_list);
-                       talloc_destroy(data_ctx);
+                       data_size = fill_ea_buffer(ctx, pdata, data_size, conn, ea_list);
                        break;
                }
 
@@ -3724,15 +3992,18 @@ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pd
                case SMB_QUERY_FILE_ALT_NAME_INFO:
                case SMB_FILE_ALTERNATE_NAME_INFORMATION:
                {
-                       pstring short_name;
-
+                       char mangled_name[13];
                        DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALTERNATE_NAME_INFORMATION\n"));
-                       pstrcpy(short_name,base_name);
-                       /* Mangle if not already 8.3 */
-                       if(!mangle_is_8_3(short_name, True, conn->params)) {
-                               mangle_map(short_name,True,True,conn->params);
+                       if (!name_to_8_3(base_name,mangled_name,
+                                               True,conn->params)) {
+                               reply_nterror(
+                                       req,
+                                       NT_STATUS_NO_MEMORY);
                        }
-                       len = srvstr_push(outbuf, pdata+4, short_name, -1, STR_UNICODE);
+                       len = srvstr_push(dstart, req->flags2,
+                                         pdata+4, mangled_name,
+                                         PTR_DIFF(dend, pdata+4),
+                                         STR_UNICODE);
                        data_size = 4 + len;
                        SIVAL(pdata,0,len);
                        break;
@@ -3742,7 +4013,10 @@ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pd
                        /*
                          this must be *exactly* right for ACLs on mapped drives to work
                         */
-                       len = srvstr_push(outbuf, pdata+4, dos_fname, -1, STR_UNICODE);
+                       len = srvstr_push(dstart, req->flags2,
+                                         pdata+4, dos_fname,
+                                         PTR_DIFF(dend, pdata+4),
+                                         STR_UNICODE);
                        DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_NAME_INFO\n"));
                        data_size = 4 + len;
                        SIVAL(pdata,0,len);
@@ -3783,7 +4057,10 @@ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pd
                        pdata += 24;
                        SIVAL(pdata,0,ea_size);
                        pdata += 4; /* EA info */
-                       len = srvstr_push(outbuf, pdata+4, dos_fname, -1, STR_UNICODE);
+                       len = srvstr_push(dstart, req->flags2,
+                                         pdata+4, dos_fname,
+                                         PTR_DIFF(dend, pdata+4),
+                                         STR_UNICODE);
                        SIVAL(pdata,0,len);
                        pdata += 4 + len;
                        data_size = PTR_DIFF(pdata,(*ppdata));
@@ -3932,20 +4209,36 @@ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pd
 
                case SMB_QUERY_FILE_UNIX_LINK:
                        {
-                               pstring buffer;
+                               char *buffer = TALLOC_SIZE(ctx, 1024);
+
+                               if (!buffer) {
+                                       reply_nterror(req, NT_STATUS_NO_MEMORY);
+                                       return;
+                               }
 
                                DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_LINK\n"));
 #ifdef S_ISLNK
-                               if(!S_ISLNK(sbuf.st_mode))
-                                       return(UNIXERROR(ERRSRV,ERRbadlink));
+                               if(!S_ISLNK(sbuf.st_mode)) {
+                                       reply_unixerror(req, ERRSRV,
+                                                       ERRbadlink);
+                                       return;
+                               }
 #else
-                               return(UNIXERROR(ERRDOS,ERRbadlink));
+                               reply_unixerror(req, ERRDOS, ERRbadlink);
+                               return;
 #endif
-                               len = SMB_VFS_READLINK(conn,fullpathname, buffer, sizeof(pstring)-1);     /* read link */
-                               if (len == -1)
-                                       return(UNIXERROR(ERRDOS,ERRnoaccess));
+                               len = SMB_VFS_READLINK(conn,fullpathname,
+                                               buffer, 1023);
+                               if (len == -1) {
+                                       reply_unixerror(req, ERRDOS,
+                                                       ERRnoaccess);
+                                       return;
+                               }
                                buffer[len] = 0;
-                               len = srvstr_push(outbuf, pdata, buffer, -1, STR_TERMINATE);
+                               len = srvstr_push(dstart, req->flags2,
+                                                 pdata, buffer,
+                                                 PTR_DIFF(dend, pdata),
+                                                 STR_TERMINATE);
                                pdata += len;
                                data_size = PTR_DIFF(pdata,(*ppdata));
 
@@ -3969,7 +4262,10 @@ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pd
                                if (file_acl == NULL && no_acl_syscall_error(errno)) {
                                        DEBUG(5,("call_trans2qfilepathinfo: ACLs not implemented on filesystem containing %s\n",
                                                fname ));
-                                       return ERROR_NT(NT_STATUS_NOT_IMPLEMENTED);
+                                       reply_nterror(
+                                               req,
+                                               NT_STATUS_NOT_IMPLEMENTED);
+                                       return;
                                }
 
                                if (S_ISDIR(sbuf.st_mode)) {
@@ -3995,7 +4291,10 @@ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pd
                                        if (def_acl) {
                                                SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
                                        }
-                                       return ERROR_NT(NT_STATUS_BUFFER_TOO_SMALL);
+                                       reply_nterror(
+                                               req,
+                                               NT_STATUS_BUFFER_TOO_SMALL);
+                                       return;
                                }
 
                                SSVAL(pdata,0,SMB_POSIX_ACL_VERSION);
@@ -4008,7 +4307,9 @@ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pd
                                        if (def_acl) {
                                                SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
                                        }
-                                       return ERROR_NT(NT_STATUS_INTERNAL_ERROR);
+                                       reply_nterror(
+                                               req, NT_STATUS_INTERNAL_ERROR);
+                                       return;
                                }
                                if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE + (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE), &sbuf, def_acl)) {
                                        if (file_acl) {
@@ -4017,7 +4318,10 @@ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pd
                                        if (def_acl) {
                                                SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
                                        }
-                                       return ERROR_NT(NT_STATUS_INTERNAL_ERROR);
+                                       reply_nterror(
+                                               req,
+                                               NT_STATUS_INTERNAL_ERROR);
+                                       return;
                                }
 
                                if (file_acl) {
@@ -4041,7 +4345,9 @@ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pd
                        enum brl_type lock_type;
 
                        if (total_data != POSIX_LOCK_DATA_SIZE) {
-                               return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
+                               reply_nterror(
+                                       req, NT_STATUS_INVALID_PARAMETER);
+                               return;
                        }
 
                        switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
@@ -4054,8 +4360,10 @@ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pd
                                case POSIX_LOCK_TYPE_UNLOCK:
                                default:
                                        /* There's no point in asking for an unlock... */
-                                       talloc_destroy(data_ctx);
-                                       return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
+                                       reply_nterror(
+                                               req,
+                                               NT_STATUS_INVALID_PARAMETER);
+                                       return;
                        }
 
                        lock_pid = IVAL(pdata, POSIX_LOCK_PID_OFFSET);
@@ -4100,18 +4408,21 @@ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pd
                                memcpy(pdata, lock_data, POSIX_LOCK_DATA_SIZE);
                                SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, POSIX_LOCK_TYPE_UNLOCK);
                        } else {
-                               return ERROR_NT(status);
+                               reply_nterror(req, status);
+                               return;
                        }
                        break;
                }
 
                default:
-                       return ERROR_NT(NT_STATUS_INVALID_LEVEL);
+                       reply_nterror(req, NT_STATUS_INVALID_LEVEL);
+                       return;
        }
 
-       send_trans2_replies(inbuf, outbuf, bufsize, params, param_size, *ppdata, data_size, max_data_bytes);
+       send_trans2_replies(req, params, param_size, *ppdata, data_size,
+                           max_data_bytes);
 
-       return(-1);
+       return;
 }
 
 /****************************************************************************
@@ -4119,17 +4430,22 @@ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pd
  code.
 ****************************************************************************/
 
-NTSTATUS hardlink_internals(connection_struct *conn, pstring oldname, pstring newname)
+NTSTATUS hardlink_internals(connection_struct *conn,
+               const char *oldname_in,
+               const char *newname_in)
 {
        SMB_STRUCT_STAT sbuf1, sbuf2;
-       pstring last_component_oldname;
-       pstring last_component_newname;
+       char *last_component_oldname = NULL;
+       char *last_component_newname = NULL;
+       char *oldname = NULL;
+       char *newname = NULL;
        NTSTATUS status = NT_STATUS_OK;
 
        ZERO_STRUCT(sbuf1);
        ZERO_STRUCT(sbuf2);
 
-       status = unix_convert(conn, oldname, False, last_component_oldname, &sbuf1);
+       status = unix_convert(conn, oldname_in, False, &oldname,
+                       &last_component_oldname, &sbuf1);
        if (!NT_STATUS_IS_OK(status)) {
                return status;
        }
@@ -4144,7 +4460,8 @@ NTSTATUS hardlink_internals(connection_struct *conn, pstring oldname, pstring ne
                return NT_STATUS_OBJECT_NAME_NOT_FOUND;
        }
 
-       status = unix_convert(conn, newname, False, last_component_newname, &sbuf2);
+       status = unix_convert(conn, newname_in, False, &newname,
+                       &last_component_newname, &sbuf2);
        if (!NT_STATUS_IS_OK(status)) {
                return status;
        }
@@ -4165,7 +4482,7 @@ NTSTATUS hardlink_internals(connection_struct *conn, pstring oldname, pstring ne
        }
 
        /* Ensure this is within the share. */
-       status = reduce_name(conn, oldname);
+       status = check_reduced_name(conn, oldname);
        if (!NT_STATUS_IS_OK(status)) {
                return status;
        }
@@ -4299,6 +4616,7 @@ static NTSTATUS smb_set_file_dosmode(connection_struct *conn,
 ****************************************************************************/
 
 static NTSTATUS smb_set_file_size(connection_struct *conn,
+                                 struct smb_request *req,
                                files_struct *fsp,
                                const char *fname,
                                SMB_STRUCT_STAT *psbuf,
@@ -4328,7 +4646,7 @@ static NTSTATUS smb_set_file_size(connection_struct *conn,
                return NT_STATUS_OK;
        }
 
-       status = open_file_ntcreate(conn, fname, psbuf,
+       status = open_file_ntcreate(conn, req, fname, psbuf,
                                FILE_WRITE_DATA,
                                FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
                                FILE_OPEN,
@@ -4506,14 +4824,15 @@ static NTSTATUS smb_file_mode_information(connection_struct *conn,
 ****************************************************************************/
 
 static NTSTATUS smb_set_file_unix_link(connection_struct *conn,
-                               char *inbuf,
-                               const char *pdata,
-                               int total_data,
-                               const char *fname)
+                                      struct smb_request *req,
+                                      const char *pdata,
+                                      int total_data,
+                                      const char *fname)
 {
-       pstring link_target;
+       char *link_target = NULL;
        const char *newname = fname;
        NTSTATUS status = NT_STATUS_OK;
+       TALLOC_CTX *ctx = talloc_tos();
 
        /* Set a symbolic link. */
        /* Don't allow this if follow links is false. */
@@ -4526,26 +4845,42 @@ static NTSTATUS smb_set_file_unix_link(connection_struct *conn,
                return NT_STATUS_ACCESS_DENIED;
        }
 
-       srvstr_pull(inbuf, link_target, pdata, sizeof(link_target), total_data, STR_TERMINATE);
+       srvstr_pull_talloc(ctx, pdata, req->flags2, &link_target, pdata,
+                   total_data, STR_TERMINATE);
+
+       if (!link_target) {
+               return NT_STATUS_INVALID_PARAMETER;
+       }
 
        /* !widelinks forces the target path to be within the share. */
        /* This means we can interpret the target as a pathname. */
        if (!lp_widelinks(SNUM(conn))) {
-               pstring rel_name;
+               char *rel_name = NULL;
                char *last_dirp = NULL;
 
                if (*link_target == '/') {
                        /* No absolute paths allowed. */
                        return NT_STATUS_ACCESS_DENIED;
                }
-               pstrcpy(rel_name, newname);
+               rel_name = talloc_strdup(ctx,newname);
+               if (!rel_name) {
+                       return NT_STATUS_NO_MEMORY;
+               }
                last_dirp = strrchr_m(rel_name, '/');
                if (last_dirp) {
                        last_dirp[1] = '\0';
                } else {
-                       pstrcpy(rel_name, "./");
+                       rel_name = talloc_strdup(ctx,"./");
+                       if (!rel_name) {
+                               return NT_STATUS_NO_MEMORY;
+                       }
+               }
+               rel_name = talloc_asprintf_append(ctx,
+                               "%s",
+                               link_target);
+               if (!rel_name) {
+                       return NT_STATUS_NO_MEMORY;
                }
-               pstrcat(rel_name, link_target);
 
                status = check_name(conn, rel_name);
                if (!NT_STATUS_IS_OK(status)) {
@@ -4568,13 +4903,12 @@ static NTSTATUS smb_set_file_unix_link(connection_struct *conn,
 ****************************************************************************/
 
 static NTSTATUS smb_set_file_unix_hlink(connection_struct *conn,
-                               char *inbuf,
-                               char *outbuf,
-                               const char *pdata,
-                               int total_data,
-                               pstring fname)
+                                       struct smb_request *req,
+                                       const char *pdata, int total_data,
+                                       const char *fname)
 {
-       pstring oldname;
+       char *oldname = NULL;
+       TALLOC_CTX *ctx = talloc_tos();
        NTSTATUS status = NT_STATUS_OK;
 
        /* Set a hard link. */
@@ -4582,12 +4916,16 @@ static NTSTATUS smb_set_file_unix_hlink(connection_struct *conn,
                return NT_STATUS_INVALID_PARAMETER;
        }
 
-       srvstr_get_path(inbuf, oldname, pdata, sizeof(oldname), total_data, STR_TERMINATE, &status);
+       srvstr_get_path(ctx, pdata, req->flags2, &oldname, pdata,
+                       total_data, STR_TERMINATE, &status);
        if (!NT_STATUS_IS_OK(status)) {
                return status;
        }
 
-       status = resolve_dfspath(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, oldname);
+       status = resolve_dfspath(ctx, conn,
+                               req->flags2 & FLAGS2_DFS_PATHNAMES,
+                               oldname,
+                               &oldname);
        if (!NT_STATUS_IS_OK(status)) {
                return status;
        }
@@ -4603,40 +4941,49 @@ static NTSTATUS smb_set_file_unix_hlink(connection_struct *conn,
 ****************************************************************************/
 
 static NTSTATUS smb_file_rename_information(connection_struct *conn,
-                               char *inbuf,
-                               char *outbuf,
-                               const char *pdata,
-                               int total_data,
-                               files_struct *fsp,
-                               pstring fname)
+                                           struct smb_request *req,
+                                           const char *pdata,
+                                           int total_data,
+                                           files_struct *fsp,
+                                           const char *fname)
 {
        BOOL overwrite;
-       /* uint32 root_fid; */  /* Not used */
+       uint32 root_fid;
        uint32 len;
-       pstring newname;
-       pstring base_name;
+       char *newname = NULL;
+       char *base_name = NULL;
        BOOL dest_has_wcard = False;
        NTSTATUS status = NT_STATUS_OK;
        char *p;
+       TALLOC_CTX *ctx = talloc_tos();
 
        if (total_data < 13) {
                return NT_STATUS_INVALID_PARAMETER;
        }
 
        overwrite = (CVAL(pdata,0) ? True : False);
-       /* root_fid = IVAL(pdata,4); */
+       root_fid = IVAL(pdata,4);
        len = IVAL(pdata,8);
 
-       if (len > (total_data - 12) || (len == 0)) {
+       if (len > (total_data - 12) || (len == 0) || (root_fid != 0)) {
                return NT_STATUS_INVALID_PARAMETER;
        }
 
-       srvstr_get_path_wcard(inbuf, newname, &pdata[12], sizeof(newname), len, 0, &status, &dest_has_wcard);
+       srvstr_get_path_wcard(ctx, pdata, req->flags2, &newname, &pdata[12],
+                             len, 0, &status,
+                             &dest_has_wcard);
        if (!NT_STATUS_IS_OK(status)) {
                return status;
        }
 
-       status = resolve_dfspath_wcard(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, newname, &dest_has_wcard);
+       DEBUG(10,("smb_file_rename_information: got name |%s|\n",
+                               newname));
+
+       status = resolve_dfspath_wcard(ctx, conn,
+                                      req->flags2 & FLAGS2_DFS_PATHNAMES,
+                                      newname,
+                                      &newname,
+                                      &dest_has_wcard);
        if (!NT_STATUS_IS_OK(status)) {
                return status;
        }
@@ -4647,24 +4994,57 @@ static NTSTATUS smb_file_rename_information(connection_struct *conn,
        }
 
        /* Create the base directory. */
-       pstrcpy(base_name, fname);
+       base_name = talloc_strdup(ctx, fname);
+       if (!base_name) {
+               return NT_STATUS_NO_MEMORY;
+       }
        p = strrchr_m(base_name, '/');
        if (p) {
                p[1] = '\0';
        } else {
-               pstrcpy(base_name, "./");
+               base_name = talloc_strdup(ctx, "./");
+               if (!base_name) {
+                       return NT_STATUS_NO_MEMORY;
+               }
        }
        /* Append the new name. */
-       pstrcat(base_name, newname);
+       base_name = talloc_asprintf_append(base_name,
+                       "%s",
+                       newname);
+       if (!base_name) {
+               return NT_STATUS_NO_MEMORY;
+       }
 
        if (fsp) {
+               SMB_STRUCT_STAT sbuf;
+               char *newname_last_component = NULL;
+
+               ZERO_STRUCT(sbuf);
+
+               status = unix_convert(conn, newname, False,
+                                       &newname,
+                                       &newname_last_component,
+                                       &sbuf);
+
+               /* If an error we expect this to be
+                * NT_STATUS_OBJECT_PATH_NOT_FOUND */
+
+               if (!NT_STATUS_IS_OK(status)
+                   && !NT_STATUS_EQUAL(NT_STATUS_OBJECT_PATH_NOT_FOUND,
+                                       status)) {
+                       return status;
+               }
+
                DEBUG(10,("smb_file_rename_information: SMB_FILE_RENAME_INFORMATION (fnum %d) %s -> %s\n",
                        fsp->fnum, fsp->fsp_name, base_name ));
-               status = rename_internals_fsp(conn, fsp, base_name, 0, overwrite);
+               status = rename_internals_fsp(conn, fsp, base_name,
+                                             newname_last_component, 0,
+                                             overwrite);
        } else {
                DEBUG(10,("smb_file_rename_information: SMB_FILE_RENAME_INFORMATION %s -> %s\n",
-                       fname, newname ));
-               status = rename_internals(conn, fname, base_name, 0, overwrite, False, dest_has_wcard);
+                       fname, base_name ));
+               status = rename_internals(ctx, conn, req, fname, base_name, 0,
+                                         overwrite, False, dest_has_wcard);
        }
 
        return status;
@@ -4738,7 +5118,7 @@ static NTSTATUS smb_set_posix_acl(connection_struct *conn,
 ****************************************************************************/
 
 static NTSTATUS smb_set_posix_lock(connection_struct *conn,
-                               char *inbuf,
+                               const uint8 *inbuf,
                                int length,
                                const char *pdata,
                                int total_data,
@@ -4836,7 +5216,7 @@ static NTSTATUS smb_set_posix_lock(connection_struct *conn,
                         * onto the blocking lock queue.
                         */
                        if(push_blocking_lock_request(br_lck,
-                                               inbuf, length,
+                                               (char *)inbuf, length,
                                                fsp,
                                                -1, /* infinite timeout. */
                                                0,
@@ -4955,6 +5335,7 @@ static NTSTATUS smb_set_file_basic_info(connection_struct *conn,
 ****************************************************************************/
 
 static NTSTATUS smb_set_file_allocation_info(connection_struct *conn,
+                                            struct smb_request *req,
                                        const char *pdata,
                                        int total_data,
                                        files_struct *fsp,
@@ -4990,24 +5371,31 @@ static NTSTATUS smb_set_file_allocation_info(connection_struct *conn,
                allocation_size = smb_roundup(conn, allocation_size);
        }
 
-       if(allocation_size == get_file_size(*psbuf)) {
-               return NT_STATUS_OK;
-       }
        DEBUG(10,("smb_set_file_allocation_info: file %s : setting new allocation size to %.0f\n",
                        fname, (double)allocation_size ));
+
        if (fsp && fsp->fh->fd != -1) {
                /* Open file handle. */
-               if (vfs_allocate_file_space(fsp, allocation_size) == -1) {
-                       return map_nt_error_from_unix(errno);
+               /* Only change if needed. */
+               if (allocation_size != get_file_size(*psbuf)) {
+                       if (vfs_allocate_file_space(fsp, allocation_size) == -1) {
+                               return map_nt_error_from_unix(errno);
+                       }
+               }
+               /* But always update the time. */
+               if (null_timespec(fsp->pending_modtime)) {
+                       /*
+                        * This is equivalent to a write. Ensure it's seen immediately
+                        * if there are no pending writes.
+                        */
+                       set_filetime(fsp->conn, fsp->fsp_name, timespec_current());
                }
                return NT_STATUS_OK;
        }
 
        /* Pathname or stat or directory file. */
 
-       status = open_file_ntcreate(conn, fname, psbuf,
+       status = open_file_ntcreate(conn, req, fname, psbuf,
                                FILE_WRITE_DATA,
                                FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
                                FILE_OPEN,
@@ -5015,17 +5403,27 @@ static NTSTATUS smb_set_file_allocation_info(connection_struct *conn,
                                FILE_ATTRIBUTE_NORMAL,
                                FORCE_OPLOCK_BREAK_TO_NONE,
                                NULL, &new_fsp);
+
        if (!NT_STATUS_IS_OK(status)) {
                /* NB. We check for open_was_deferred in the caller. */
                return status;
        }
-       if (vfs_allocate_file_space(new_fsp, allocation_size) == -1) {
-               status = map_nt_error_from_unix(errno);
-               close_file(new_fsp,NORMAL_CLOSE);
-               return status;
+
+       /* Only change if needed. */
+       if (allocation_size != get_file_size(*psbuf)) {
+               if (vfs_allocate_file_space(new_fsp, allocation_size) == -1) {
+                       status = map_nt_error_from_unix(errno);
+                       close_file(new_fsp,NORMAL_CLOSE);
+                       return status;
+               }
        }
 
+       /* Changing the allocation size should set the last mod time. */
+       /* Don't need to call set_filetime as this will be flushed on
+        * close. */
+
+       fsp_set_pending_modtime(new_fsp, timespec_current());
+
        close_file(new_fsp,NORMAL_CLOSE);
        return NT_STATUS_OK;
 }
@@ -5035,6 +5433,7 @@ static NTSTATUS smb_set_file_allocation_info(connection_struct *conn,
 ****************************************************************************/
 
 static NTSTATUS smb_set_file_end_of_file_info(connection_struct *conn,
+                                             struct smb_request *req,
                                        const char *pdata,
                                        int total_data,
                                        files_struct *fsp,
@@ -5059,7 +5458,7 @@ static NTSTATUS smb_set_file_end_of_file_info(connection_struct *conn,
        DEBUG(10,("smb_set_file_end_of_file_info: Set end of file info for "
                "file %s to %.0f\n", fname, (double)size ));
 
-       return smb_set_file_size(conn,
+       return smb_set_file_size(conn, req,
                                fsp,
                                fname,
                                psbuf,
@@ -5155,6 +5554,7 @@ static NTSTATUS smb_unix_mknod(connection_struct *conn,
 ****************************************************************************/
 
 static NTSTATUS smb_set_file_unix_basic(connection_struct *conn,
+                                       struct smb_request *req,
                                        const char *pdata,
                                        int total_data,
                                        files_struct *fsp,
@@ -5306,7 +5706,7 @@ size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n",
 
        /* Deal with any size changes. */
 
-       status = smb_set_file_size(conn,
+       status = smb_set_file_size(conn, req,
                                fsp,
                                fname,
                                psbuf,
@@ -5329,6 +5729,7 @@ size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n",
 ****************************************************************************/
 
 static NTSTATUS smb_set_file_unix_info2(connection_struct *conn,
+                                       struct smb_request *req,
                                        const char *pdata,
                                        int total_data,
                                        files_struct *fsp,
@@ -5346,7 +5747,7 @@ static NTSTATUS smb_set_file_unix_info2(connection_struct *conn,
        /* Start by setting all the fields that are common between UNIX_BASIC
         * and UNIX_INFO2.
         */
-       status = smb_set_file_unix_basic(conn, pdata, total_data,
+       status = smb_set_file_unix_basic(conn, req, pdata, total_data,
                                fsp, fname, psbuf);
        if (!NT_STATUS_IS_OK(status)) {
                return status;
@@ -5390,6 +5791,7 @@ static NTSTATUS smb_set_file_unix_info2(connection_struct *conn,
 ****************************************************************************/
 
 static NTSTATUS smb_posix_mkdir(connection_struct *conn,
+                               struct smb_request *req,
                                char **ppdata,
                                int total_data,
                                const char *fname,
@@ -5422,7 +5824,7 @@ static NTSTATUS smb_posix_mkdir(connection_struct *conn,
        DEBUG(10,("smb_posix_mkdir: file %s, mode 0%o\n",
                fname, (unsigned int)unixmode ));
 
-       status = open_directory(conn,
+       status = open_directory(conn, req,
                                fname,
                                psbuf,
                                FILE_READ_ATTRIBUTES, /* Just a stat open */
@@ -5484,6 +5886,7 @@ static NTSTATUS smb_posix_mkdir(connection_struct *conn,
 ****************************************************************************/
 
 static NTSTATUS smb_posix_open(connection_struct *conn,
+                              struct smb_request *req,
                                char **ppdata,
                                int total_data,
                                const char *fname,
@@ -5519,7 +5922,7 @@ static NTSTATUS smb_posix_open(connection_struct *conn,
        wire_open_mode = IVAL(pdata,4);
 
        if (wire_open_mode == (SMB_O_CREAT|SMB_O_DIRECTORY)) {
-               return smb_posix_mkdir(conn,
+               return smb_posix_mkdir(conn, req,
                                        ppdata,
                                        total_data,
                                        fname,
@@ -5587,7 +5990,7 @@ static NTSTATUS smb_posix_open(connection_struct *conn,
                (unsigned int)wire_open_mode,
                (unsigned int)unixmode ));
 
-       status = open_file_ntcreate(conn,
+       status = open_file_ntcreate(conn, req,
                                fname,
                                psbuf,
                                access_mask,
@@ -5671,6 +6074,7 @@ static NTSTATUS smb_posix_open(connection_struct *conn,
 ****************************************************************************/
 
 static NTSTATUS smb_posix_unlink(connection_struct *conn,
+                                struct smb_request *req,
                                const char *pdata,
                                int total_data,
                                const char *fname,
@@ -5679,7 +6083,10 @@ static NTSTATUS smb_posix_unlink(connection_struct *conn,
        NTSTATUS status = NT_STATUS_OK;
        files_struct *fsp = NULL;
        uint16 flags = 0;
+       char del = 1;
        int info = 0;
+       int i;
+       struct share_mode_lock *lck = NULL;
 
        if (total_data < 2) {
                return NT_STATUS_INVALID_PARAMETER;
@@ -5701,20 +6108,19 @@ static NTSTATUS smb_posix_unlink(connection_struct *conn,
                fname));
 
        if (VALID_STAT_OF_DIR(*psbuf)) {
-               status = open_directory(conn,
+               status = open_directory(conn, req,
                                        fname,
                                        psbuf,
                                        DELETE_ACCESS,
                                        FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
                                        FILE_OPEN,
-                                       FILE_DELETE_ON_CLOSE,
+                                       0,
                                        FILE_FLAG_POSIX_SEMANTICS|0777,
-                                       &info,                          
+                                       &info,
                                        &fsp);
        } else {
-               char del = 1;
 
-               status = open_file_ntcreate(conn,
+               status = open_file_ntcreate(conn, req,
                                fname,
                                psbuf,
                                DELETE_ACCESS,
@@ -5725,26 +6131,59 @@ static NTSTATUS smb_posix_unlink(connection_struct *conn,
                                0, /* No oplock, but break existing ones. */
                                &info,
                                &fsp);
-               /* 
-                * For file opens we must set the delete on close
-                * after the open.
-                */
+       }
 
-               if (!NT_STATUS_IS_OK(status)) {
-                       return status;
-               }
+       if (!NT_STATUS_IS_OK(status)) {
+               return status;
+       }
 
-               status = smb_set_file_disposition_info(conn,
-                                                       &del,
-                                                       1,
-                                                       fsp,
-                                                       fname,
-                                                       psbuf);
+       /*
+        * Don't lie to client. If we can't really delete due to
+        * non-POSIX opens return SHARING_VIOLATION.
+        */
+
+       lck = get_share_mode_lock(NULL, fsp->file_id, NULL, NULL);
+       if (lck == NULL) {
+               DEBUG(0, ("smb_posix_unlink: Could not get share mode "
+                       "lock for file %s\n", fsp->fsp_name));
+               close_file(fsp, NORMAL_CLOSE);
+               return NT_STATUS_INVALID_PARAMETER;
        }
 
+       /*
+        * See if others still have the file open. If this is the case, then
+        * don't delete. If all opens are POSIX delete we can set the delete
+        * on close disposition.
+        */
+       for (i=0; i<lck->num_share_modes; i++) {
+               struct share_mode_entry *e = &lck->share_modes[i];
+               if (is_valid_share_mode_entry(e)) {
+                       if (e->flags & SHARE_MODE_FLAG_POSIX_OPEN) {
+                               continue;
+                       }
+                       /* Fail with sharing violation. */
+                       close_file(fsp, NORMAL_CLOSE);
+                       TALLOC_FREE(lck);
+                       return NT_STATUS_SHARING_VIOLATION;
+               }
+       }
+
+       /*
+        * Set the delete on close.
+        */
+       status = smb_set_file_disposition_info(conn,
+                                               &del,
+                                               1,
+                                               fsp,
+                                               fname,
+                                               psbuf);
+
        if (!NT_STATUS_IS_OK(status)) {
+               close_file(fsp, NORMAL_CLOSE);
+               TALLOC_FREE(lck);
                return status;
        }
+       TALLOC_FREE(lck);
        return close_file(fsp, NORMAL_CLOSE);
 }
 
@@ -5752,54 +6191,70 @@ static NTSTATUS smb_posix_unlink(connection_struct *conn,
  Reply to a TRANS2_SETFILEINFO (set file info by fileid or pathname).
 ****************************************************************************/
 
-static int call_trans2setfilepathinfo(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
-                                       unsigned int tran_call,
-                                       char **pparams, int total_params, char **ppdata, int total_data,
-                                       unsigned int max_data_bytes)
+static void call_trans2setfilepathinfo(connection_struct *conn,
+                                      struct smb_request *req,
+                                      unsigned int tran_call,
+                                      char **pparams, int total_params,
+                                      char **ppdata, int total_data,
+                                      unsigned int max_data_bytes)
 {
        char *params = *pparams;
        char *pdata = *ppdata;
        uint16 info_level;
        SMB_STRUCT_STAT sbuf;
-       pstring fname;
+       char *fname = NULL;
        files_struct *fsp = NULL;
        NTSTATUS status = NT_STATUS_OK;
        int data_return_size = 0;
+       TALLOC_CTX *ctx = talloc_tos();
 
        if (!params) {
-               return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
+               reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
+               return;
        }
 
        ZERO_STRUCT(sbuf);
 
        if (tran_call == TRANSACT2_SETFILEINFO) {
                if (total_params < 4) {
-                       return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
+                       reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
+                       return;
                }
 
-               fsp = file_fsp(params,0);
-               info_level = SVAL(params,2);    
+               fsp = file_fsp(SVAL(params,0));
+               /* Basic check for non-null fsp. */
+               if (!check_fsp_open(conn, req, fsp, &current_user)) {
+                       return;
+               }
+               info_level = SVAL(params,2);
 
-               if(fsp && (fsp->is_directory || fsp->fh->fd == -1)) {
+               fname = talloc_strdup(talloc_tos(),fsp->fsp_name);
+               if (!fname) {
+                       reply_nterror(req, NT_STATUS_NO_MEMORY);
+                       return;
+               }
+
+               if(fsp->is_directory || fsp->fh->fd == -1) {
                        /*
                         * This is actually a SETFILEINFO on a directory
                         * handle (returned from an NT SMB). NT5.0 seems
                         * to do this call. JRA.
                         */
-                       pstrcpy(fname, fsp->fsp_name);
                        if (INFO_LEVEL_IS_UNIX(info_level)) {
                                /* Always do lstat for UNIX calls. */
                                if (SMB_VFS_LSTAT(conn,fname,&sbuf)) {
                                        DEBUG(3,("call_trans2setfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",fname,strerror(errno)));
-                                       return UNIXERROR(ERRDOS,ERRbadpath);
+                                       reply_unixerror(req,ERRDOS,ERRbadpath);
+                                       return;
                                }
                        } else {
                                if (SMB_VFS_STAT(conn,fname,&sbuf) != 0) {
                                        DEBUG(3,("call_trans2setfilepathinfo: fileinfo of %s failed (%s)\n",fname,strerror(errno)));
-                                       return UNIXERROR(ERRDOS,ERRbadpath);
+                                       reply_unixerror(req,ERRDOS,ERRbadpath);
+                                       return;
                                }
                        }
-               } else if (fsp && fsp->print_file) {
+               } else if (fsp->print_file) {
                        /*
                         * Doing a DELETE_ON_CLOSE should cancel a print job.
                         */
@@ -5807,53 +6262,71 @@ static int call_trans2setfilepathinfo(connection_struct *conn, char *inbuf, char
                                fsp->fh->private_options |= FILE_DELETE_ON_CLOSE;
 
                                DEBUG(3,("call_trans2setfilepathinfo: Cancelling print job (%s)\n", fsp->fsp_name ));
-       
+
                                SSVAL(params,0,0);
-                               send_trans2_replies(inbuf, outbuf, bufsize, params, 2, *ppdata, 0, max_data_bytes);
-                               return(-1);
-                       } else
-                               return (UNIXERROR(ERRDOS,ERRbadpath));
-           } else {
+                               send_trans2_replies(req, params, 2,
+                                                   *ppdata, 0,
+                                                   max_data_bytes);
+                               return;
+                       } else {
+                               reply_unixerror(req, ERRDOS, ERRbadpath);
+                               return;
+                       }
+               } else {
                        /*
                         * Original code - this is an open file.
                         */
-                       CHECK_FSP(fsp,conn);
-
-                       pstrcpy(fname, fsp->fsp_name);
+                       if (!check_fsp(conn, req, fsp, &current_user)) {
+                               return;
+                       }
 
                        if (SMB_VFS_FSTAT(fsp, fsp->fh->fd, &sbuf) != 0) {
                                DEBUG(3,("call_trans2setfilepathinfo: fstat of fnum %d failed (%s)\n",fsp->fnum, strerror(errno)));
-                               return(UNIXERROR(ERRDOS,ERRbadfid));
+                               reply_unixerror(req, ERRDOS, ERRbadfid);
+                               return;
                        }
                }
        } else {
                /* set path info */
                if (total_params < 7) {
-                       return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
+                       reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
+                       return;
                }
 
-               info_level = SVAL(params,0);    
-               srvstr_get_path(inbuf, fname, &params[6], sizeof(fname), total_params - 6, STR_TERMINATE, &status);
+               info_level = SVAL(params,0);
+               srvstr_get_path(ctx, params, req->flags2, &fname, &params[6],
+                               total_params - 6, STR_TERMINATE,
+                               &status);
                if (!NT_STATUS_IS_OK(status)) {
-                       return ERROR_NT(status);
+                       reply_nterror(req, status);
+                       return;
                }
 
-               status = resolve_dfspath(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, fname);
+               status = resolve_dfspath(ctx, conn,
+                                        req->flags2 & FLAGS2_DFS_PATHNAMES,
+                                        fname,
+                                        &fname);
                if (!NT_STATUS_IS_OK(status)) {
                        if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
-                               return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath);
+                               reply_botherror(req,
+                                               NT_STATUS_PATH_NOT_COVERED,
+                                               ERRSRV, ERRbadpath);
+                               return;
                        }
-                       return ERROR_NT(status);
+                       reply_nterror(req, status);
+                       return;
                }
 
-               status = unix_convert(conn, fname, False, NULL, &sbuf);
+               status = unix_convert(conn, fname, False, &fname, NULL, &sbuf);
                if (!NT_STATUS_IS_OK(status)) {
-                       return ERROR_NT(status);
+                       reply_nterror(req, status);
+                       return;
                }
 
                status = check_name(conn, fname);
                if (!NT_STATUS_IS_OK(status)) {
-                       return ERROR_NT(status);
+                       reply_nterror(req, status);
+                       return;
                }
 
                if (INFO_LEVEL_IS_UNIX(info_level)) {
@@ -5866,16 +6339,19 @@ static int call_trans2setfilepathinfo(connection_struct *conn, char *inbuf, char
 
                } else if (!VALID_STAT(sbuf) && SMB_VFS_STAT(conn,fname,&sbuf)) {
                        DEBUG(3,("call_trans2setfilepathinfo: SMB_VFS_STAT of %s failed (%s)\n",fname,strerror(errno)));
-                       return UNIXERROR(ERRDOS,ERRbadpath);
+                       reply_unixerror(req, ERRDOS, ERRbadpath);
+                       return;
                }
        }
 
        if (!CAN_WRITE(conn)) {
-               return ERROR_DOS(ERRSRV,ERRaccess);
+               reply_doserror(req, ERRSRV, ERRaccess);
+               return;
        }
 
        if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
-               return ERROR_NT(NT_STATUS_INVALID_LEVEL);
+               reply_nterror(req, NT_STATUS_INVALID_LEVEL);
+               return;
        }
 
        DEBUG(3,("call_trans2setfilepathinfo(%d) %s (fnum %d) info_level=%d totdata=%d\n",
@@ -5884,7 +6360,8 @@ static int call_trans2setfilepathinfo(connection_struct *conn, char *inbuf, char
        /* Realloc the parameter size */
        *pparams = (char *)SMB_REALLOC(*pparams,2);
        if (*pparams == NULL) {
-               return ERROR_NT(NT_STATUS_NO_MEMORY);
+               reply_nterror(req, NT_STATUS_NO_MEMORY);
+               return;
        }
        params = *pparams;
 
@@ -5933,7 +6410,7 @@ static int call_trans2setfilepathinfo(connection_struct *conn, char *inbuf, char
                case SMB_FILE_ALLOCATION_INFORMATION:
                case SMB_SET_FILE_ALLOCATION_INFO:
                {
-                       status = smb_set_file_allocation_info(conn,
+                       status = smb_set_file_allocation_info(conn, req,
                                                                pdata,
                                                                total_data,
                                                                fsp,
@@ -5945,7 +6422,7 @@ static int call_trans2setfilepathinfo(connection_struct *conn, char *inbuf, char
                case SMB_FILE_END_OF_FILE_INFORMATION:
                case SMB_SET_FILE_END_OF_FILE_INFO:
                {
-                       status = smb_set_file_end_of_file_info(conn,
+                       status = smb_set_file_end_of_file_info(conn, req,
                                                                pdata,
                                                                total_data,
                                                                fsp,
@@ -6004,7 +6481,7 @@ static int call_trans2setfilepathinfo(connection_struct *conn, char *inbuf, char
 
                case SMB_SET_FILE_UNIX_BASIC:
                {
-                       status = smb_set_file_unix_basic(conn,
+                       status = smb_set_file_unix_basic(conn, req,
                                                        pdata,
                                                        total_data,
                                                        fsp,
@@ -6015,7 +6492,7 @@ static int call_trans2setfilepathinfo(connection_struct *conn, char *inbuf, char
 
                case SMB_SET_FILE_UNIX_INFO2:
                {
-                       status = smb_set_file_unix_info2(conn,
+                       status = smb_set_file_unix_info2(conn, req,
                                                        pdata,
                                                        total_data,
                                                        fsp,
@@ -6028,13 +6505,11 @@ static int call_trans2setfilepathinfo(connection_struct *conn, char *inbuf, char
                {
                        if (tran_call != TRANSACT2_SETPATHINFO) {
                                /* We must have a pathname for this. */
-                               return ERROR_NT(NT_STATUS_INVALID_LEVEL);
+                               reply_nterror(req, NT_STATUS_INVALID_LEVEL);
+                               return;
                        }
-                       status = smb_set_file_unix_link(conn,
-                                               inbuf,
-                                               pdata,
-                                               total_data,
-                                               fname);
+                       status = smb_set_file_unix_link(conn, req, pdata,
+                                                       total_data, fname);
                        break;
                }
 
@@ -6042,26 +6517,20 @@ static int call_trans2setfilepathinfo(connection_struct *conn, char *inbuf, char
                {
                        if (tran_call != TRANSACT2_SETPATHINFO) {
                                /* We must have a pathname for this. */
-                               return ERROR_NT(NT_STATUS_INVALID_LEVEL);
+                               reply_nterror(req, NT_STATUS_INVALID_LEVEL);
+                               return;
                        }
-                       status = smb_set_file_unix_hlink(conn,
-                                               inbuf,
-                                               outbuf,
-                                               pdata,
-                                               total_data,
-                                               fname);
+                       status = smb_set_file_unix_hlink(conn, req,
+                                                        pdata, total_data,
+                                                        fname);
                        break;
                }
 
                case SMB_FILE_RENAME_INFORMATION:
                {
-                       status = smb_file_rename_information(conn,
-                                                       inbuf,
-                                                       outbuf,
-                                                       pdata,
-                                                       total_data,
-                                                       fsp,
-                                                       fname);
+                       status = smb_file_rename_information(conn, req,
+                                                            pdata, total_data,
+                                                            fsp, fname);
                        break;
                }
 
@@ -6081,14 +6550,12 @@ static int call_trans2setfilepathinfo(connection_struct *conn, char *inbuf, char
                case SMB_SET_POSIX_LOCK:
                {
                        if (tran_call != TRANSACT2_SETFILEINFO) {
-                               return ERROR_NT(NT_STATUS_INVALID_LEVEL);
+                               reply_nterror(req, NT_STATUS_INVALID_LEVEL);
+                               return;
                        }
-                       status = smb_set_posix_lock(conn,
-                                               inbuf,
-                                               length,
-                                               pdata,
-                                               total_data,
-                                               fsp);
+                       status = smb_set_posix_lock(conn, req->inbuf,
+                                                   smb_len(req->inbuf) + 4,
+                                                   pdata, total_data, fsp);
                        break;
                }
 
@@ -6096,10 +6563,11 @@ static int call_trans2setfilepathinfo(connection_struct *conn, char *inbuf, char
                {
                        if (tran_call != TRANSACT2_SETPATHINFO) {
                                /* We must have a pathname for this. */
-                               return ERROR_NT(NT_STATUS_INVALID_LEVEL);
+                               reply_nterror(req, NT_STATUS_INVALID_LEVEL);
+                               return;
                        }
 
-                       status = smb_posix_open(conn,
+                       status = smb_posix_open(conn, req,
                                                ppdata,
                                                total_data,
                                                fname,
@@ -6112,10 +6580,11 @@ static int call_trans2setfilepathinfo(connection_struct *conn, char *inbuf, char
                {
                        if (tran_call != TRANSACT2_SETPATHINFO) {
                                /* We must have a pathname for this. */
-                               return ERROR_NT(NT_STATUS_INVALID_LEVEL);
+                               reply_nterror(req, NT_STATUS_INVALID_LEVEL);
+                               return;
                        }
 
-                       status = smb_posix_unlink(conn,
+                       status = smb_posix_unlink(conn, req,
                                                pdata,
                                                total_data,
                                                fname,
@@ -6124,74 +6593,95 @@ static int call_trans2setfilepathinfo(connection_struct *conn, char *inbuf, char
                }
 
                default:
-                       return ERROR_NT(NT_STATUS_INVALID_LEVEL);
+                       reply_nterror(req, NT_STATUS_INVALID_LEVEL);
+                       return;
        }
 
        
        if (!NT_STATUS_IS_OK(status)) {
-               if (open_was_deferred(SVAL(inbuf,smb_mid))) {
+               if (open_was_deferred(req->mid)) {
                        /* We have re-scheduled this call. */
-                       return -1;
+                       return;
                }
-               if (blocking_lock_was_deferred(SVAL(inbuf,smb_mid))) {
+               if (blocking_lock_was_deferred(req->mid)) {
                        /* We have re-scheduled this call. */
-                       return -1;
+                       return;
                }
                if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
-                       return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath);
+                       reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
+                                       ERRSRV, ERRbadpath);
+                       return;
+               }
+               if (info_level == SMB_POSIX_PATH_OPEN) {
+                       reply_openerror(req, status);
+                       return;
                }
-               return ERROR_NT(status);
+
+               reply_nterror(req, status);
+               return;
        }
 
        SSVAL(params,0,0);
-       send_trans2_replies(inbuf, outbuf, bufsize, params, 2, *ppdata, data_return_size, max_data_bytes);
+       send_trans2_replies(req, params, 2, *ppdata, data_return_size,
+                           max_data_bytes);
   
-       return -1;
+       return;
 }
 
 /****************************************************************************
  Reply to a TRANS2_MKDIR (make directory with extended attributes).
 ****************************************************************************/
 
-static int call_trans2mkdir(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
-                                       char **pparams, int total_params, char **ppdata, int total_data,
-                                       unsigned int max_data_bytes)
+static void call_trans2mkdir(connection_struct *conn, struct smb_request *req,
+                            char **pparams, int total_params,
+                            char **ppdata, int total_data,
+                            unsigned int max_data_bytes)
 {
        char *params = *pparams;
        char *pdata = *ppdata;
-       pstring directory;
+       char *directory = NULL;
        SMB_STRUCT_STAT sbuf;
        NTSTATUS status = NT_STATUS_OK;
        struct ea_list *ea_list = NULL;
+       TALLOC_CTX *ctx = talloc_tos();
 
-       if (!CAN_WRITE(conn))
-               return ERROR_DOS(ERRSRV,ERRaccess);
+       if (!CAN_WRITE(conn)) {
+               reply_doserror(req, ERRSRV, ERRaccess);
+               return;
+       }
 
        if (total_params < 5) {
-               return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
+               reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
+               return;
        }
 
-       srvstr_get_path(inbuf, directory, &params[4], sizeof(directory), total_params - 4, STR_TERMINATE, &status);
+       srvstr_get_path(ctx, params, req->flags2, &directory, &params[4],
+                       total_params - 4, STR_TERMINATE,
+                       &status);
        if (!NT_STATUS_IS_OK(status)) {
-               return ERROR_NT(status);
+               reply_nterror(req, status);
+               return;
        }
 
        DEBUG(3,("call_trans2mkdir : name = %s\n", directory));
 
-       status = unix_convert(conn, directory, False, NULL, &sbuf);
+       status = unix_convert(conn, directory, False, &directory, NULL, &sbuf);
        if (!NT_STATUS_IS_OK(status)) {
-               return ERROR_NT(status);
+               reply_nterror(req, status);
+               return;
        }
 
        status = check_name(conn, directory);
        if (!NT_STATUS_IS_OK(status)) {
                DEBUG(5,("call_trans2mkdir error (%s)\n", nt_errstr(status)));
-               return ERROR_NT(status);
+               reply_nterror(req, status);
+               return;
        }
 
        /* Any data in this call is an EA list. */
        if (total_data && (total_data != 4) && !lp_ea_support(SNUM(conn))) {
-               return ERROR_NT(NT_STATUS_EAS_NOT_SUPPORTED);
+               reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
+               return;
        }
 
        /*
@@ -6202,50 +6692,57 @@ static int call_trans2mkdir(connection_struct *conn, char *inbuf, char *outbuf,
 
        if (total_data != 4) {
                if (total_data < 10) {
-                       return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
+                       reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
+                       return;
                }
 
                if (IVAL(pdata,0) > total_data) {
                        DEBUG(10,("call_trans2mkdir: bad total data size (%u) > %u\n",
                                IVAL(pdata,0), (unsigned int)total_data));
-                       return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
+                       reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
+                       return;
                }
 
-               ea_list = read_ea_list(tmp_talloc_ctx(), pdata + 4,
+               ea_list = read_ea_list(talloc_tos(), pdata + 4,
                                       total_data - 4);
                if (!ea_list) {
-                       return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
+                       reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
+                       return;
                }
        } else if (IVAL(pdata,0) != 4) {
-               return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
+               reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
+               return;
        }
 
        status = create_directory(conn, directory);
 
        if (!NT_STATUS_IS_OK(status)) {
-               return ERROR_NT(status);
+               reply_nterror(req, status);
+               return;
        }
   
        /* Try and set any given EA. */
        if (ea_list) {
                status = set_ea(conn, NULL, directory, ea_list);
                if (!NT_STATUS_IS_OK(status)) {
-                       return ERROR_NT(status);
+                       reply_nterror(req, status);
+                       return;
                }
        }
 
        /* Realloc the parameter and data sizes */
        *pparams = (char *)SMB_REALLOC(*pparams,2);
        if(*pparams == NULL) {
-               return ERROR_NT(NT_STATUS_NO_MEMORY);
+               reply_nterror(req, NT_STATUS_NO_MEMORY);
+               return;
        }
        params = *pparams;
 
        SSVAL(params,0,0);
 
-       send_trans2_replies(inbuf, outbuf, bufsize, params, 2, *ppdata, 0, max_data_bytes);
+       send_trans2_replies(req, params, 2, *ppdata, 0, max_data_bytes);
   
-       return(-1);
+       return;
 }
 
 /****************************************************************************
@@ -6253,16 +6750,19 @@ static int call_trans2mkdir(connection_struct *conn, char *inbuf, char *outbuf,
  We don't actually do this - we just send a null response.
 ****************************************************************************/
 
-static int call_trans2findnotifyfirst(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
-                                       char **pparams, int total_params, char **ppdata, int total_data,
-                                       unsigned int max_data_bytes)
+static void call_trans2findnotifyfirst(connection_struct *conn,
+                                      struct smb_request *req,
+                                      char **pparams, int total_params,
+                                      char **ppdata, int total_data,
+                                      unsigned int max_data_bytes)
 {
        static uint16 fnf_handle = 257;
        char *params = *pparams;
        uint16 info_level;
 
        if (total_params < 6) {
-               return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
+               reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
+               return;
        }
 
        info_level = SVAL(params,4);
@@ -6273,13 +6773,15 @@ static int call_trans2findnotifyfirst(connection_struct *conn, char *inbuf, char
                case 2:
                        break;
                default:
-                       return ERROR_NT(NT_STATUS_INVALID_LEVEL);
+                       reply_nterror(req, NT_STATUS_INVALID_LEVEL);
+                       return;
        }
 
        /* Realloc the parameter and data sizes */
        *pparams = (char *)SMB_REALLOC(*pparams,6);
        if (*pparams == NULL) {
-               return ERROR_NT(NT_STATUS_NO_MEMORY);
+               reply_nterror(req, NT_STATUS_NO_MEMORY);
+               return;
        }
        params = *pparams;
 
@@ -6292,9 +6794,9 @@ static int call_trans2findnotifyfirst(connection_struct *conn, char *inbuf, char
        if(fnf_handle == 0)
                fnf_handle = 257;
 
-       send_trans2_replies(inbuf, outbuf, bufsize, params, 6, *ppdata, 0, max_data_bytes);
+       send_trans2_replies(req, params, 6, *ppdata, 0, max_data_bytes);
   
-       return(-1);
+       return;
 }
 
 /****************************************************************************
@@ -6302,9 +6804,11 @@ static int call_trans2findnotifyfirst(connection_struct *conn, char *inbuf, char
  changes). Currently this does nothing.
 ****************************************************************************/
 
-static int call_trans2findnotifynext(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
-                                       char **pparams, int total_params, char **ppdata, int total_data,
-                                       unsigned int max_data_bytes)
+static void call_trans2findnotifynext(connection_struct *conn,
+                                     struct smb_request *req,
+                                     char **pparams, int total_params,
+                                     char **ppdata, int total_data,
+                                     unsigned int max_data_bytes)
 {
        char *params = *pparams;
 
@@ -6313,51 +6817,67 @@ static int call_trans2findnotifynext(connection_struct *conn, char *inbuf, char
        /* Realloc the parameter and data sizes */
        *pparams = (char *)SMB_REALLOC(*pparams,4);
        if (*pparams == NULL) {
-               return ERROR_NT(NT_STATUS_NO_MEMORY);
+               reply_nterror(req, NT_STATUS_NO_MEMORY);
+               return;
        }
        params = *pparams;
 
        SSVAL(params,0,0); /* No changes */
        SSVAL(params,2,0); /* No EA errors */
 
-       send_trans2_replies(inbuf, outbuf, bufsize, params, 4, *ppdata, 0, max_data_bytes);
+       send_trans2_replies(req, params, 4, *ppdata, 0, max_data_bytes);
   
-       return(-1);
+       return;
 }
 
 /****************************************************************************
  Reply to a TRANS2_GET_DFS_REFERRAL - Shirish Kalele <kalele@veritas.com>.
 ****************************************************************************/
 
-static int call_trans2getdfsreferral(connection_struct *conn, char* inbuf, char* outbuf, int length, int bufsize,
-                                       char **pparams, int total_params, char **ppdata, int total_data,
-                                       unsigned int max_data_bytes)
+static void call_trans2getdfsreferral(connection_struct *conn,
+                                     struct smb_request *req,
+                                     char **pparams, int total_params,
+                                     char **ppdata, int total_data,
+                                     unsigned int max_data_bytes)
 {
        char *params = *pparams;
-       pstring pathname;
+       char *pathname = NULL;
        int reply_size = 0;
        int max_referral_level;
        NTSTATUS status = NT_STATUS_OK;
+       TALLOC_CTX *ctx = talloc_tos();
 
        DEBUG(10,("call_trans2getdfsreferral\n"));
 
        if (total_params < 3) {
-               return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
+               reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
+               return;
        }
 
        max_referral_level = SVAL(params,0);
 
-       if(!lp_host_msdfs())
-               return ERROR_DOS(ERRDOS,ERRbadfunc);
+       if(!lp_host_msdfs()) {
+               reply_doserror(req, ERRDOS, ERRbadfunc);
+               return;
+       }
+
+       srvstr_pull_talloc(ctx, params, req->flags2, &pathname, &params[2],
+                   total_params - 2, STR_TERMINATE);
+       if (!pathname) {
+               reply_nterror(req, NT_STATUS_NOT_FOUND);
+               return;
+       }
+       if((reply_size = setup_dfs_referral(conn, pathname, max_referral_level,
+                                           ppdata,&status)) < 0) {
+               reply_nterror(req, status);
+               return;
+       }
 
-       srvstr_pull(inbuf, pathname, &params[2], sizeof(pathname), total_params - 2, STR_TERMINATE);
-       if((reply_size = setup_dfs_referral(conn, pathname,max_referral_level,ppdata,&status)) < 0)
-               return ERROR_NT(status);
-    
-       SSVAL(outbuf,smb_flg2,SVAL(outbuf,smb_flg2) | FLAGS2_DFS_PATHNAMES);
-       send_trans2_replies(inbuf, outbuf,bufsize,0,0,*ppdata,reply_size, max_data_bytes);
+       SSVAL(req->inbuf, smb_flg2,
+             SVAL(req->inbuf,smb_flg2) | FLAGS2_DFS_PATHNAMES);
+       send_trans2_replies(req,0,0,*ppdata,reply_size, max_data_bytes);
 
-       return(-1);
+       return;
 }
 
 #define LMCAT_SPL       0x53
@@ -6367,23 +6887,28 @@ static int call_trans2getdfsreferral(connection_struct *conn, char* inbuf, char*
  Reply to a TRANS2_IOCTL - used for OS/2 printing.
 ****************************************************************************/
 
-static int call_trans2ioctl(connection_struct *conn, char* inbuf, char* outbuf, int length, int bufsize,
-                                       char **pparams, int total_params, char **ppdata, int total_data,
-                                       unsigned int max_data_bytes)
+static void call_trans2ioctl(connection_struct *conn,
+                            struct smb_request *req,
+                            char **pparams, int total_params,
+                            char **ppdata, int total_data,
+                            unsigned int max_data_bytes)
 {
        char *pdata = *ppdata;
-       files_struct *fsp = file_fsp(inbuf,smb_vwv15);
+       files_struct *fsp = file_fsp(SVAL(req->inbuf,smb_vwv15));
 
        /* check for an invalid fid before proceeding */
-       
-       if (!fsp)                                
-               return(ERROR_DOS(ERRDOS,ERRbadfid));  
 
-       if ((SVAL(inbuf,(smb_setup+4)) == LMCAT_SPL) &&
-                       (SVAL(inbuf,(smb_setup+6)) == LMFUNC_GETJOBID)) {
+       if (!fsp) {
+               reply_doserror(req, ERRDOS, ERRbadfid);
+               return;
+       }
+
+       if ((SVAL(req->inbuf,(smb_setup+4)) == LMCAT_SPL)
+           && (SVAL(req->inbuf,(smb_setup+6)) == LMFUNC_GETJOBID)) {
                *ppdata = (char *)SMB_REALLOC(*ppdata, 32);
                if (*ppdata == NULL) {
-                       return ERROR_NT(NT_STATUS_NO_MEMORY);
+                       reply_nterror(req, NT_STATUS_NO_MEMORY);
+                       return;
                }
                pdata = *ppdata;
 
@@ -6391,51 +6916,68 @@ static int call_trans2ioctl(connection_struct *conn, char* inbuf, char* outbuf,
                        CAN ACCEPT THIS IN UNICODE. JRA. */
 
                SSVAL(pdata,0,fsp->rap_print_jobid);                     /* Job number */
-               srvstr_push( outbuf, pdata + 2, global_myname(), 15, STR_ASCII|STR_TERMINATE); /* Our NetBIOS name */
-               srvstr_push( outbuf, pdata+18, lp_servicename(SNUM(conn)), 13, STR_ASCII|STR_TERMINATE); /* Service name */
-               send_trans2_replies(inbuf, outbuf,bufsize,*pparams,0,*ppdata,32, max_data_bytes);
-               return(-1);
-       } else {
-               DEBUG(2,("Unknown TRANS2_IOCTL\n"));
-               return ERROR_DOS(ERRSRV,ERRerror);
-       }
+               srvstr_push(pdata, req->flags2, pdata + 2,
+                           global_myname(), 15,
+                           STR_ASCII|STR_TERMINATE); /* Our NetBIOS name */
+               srvstr_push(pdata, req->flags2, pdata+18,
+                           lp_servicename(SNUM(conn)), 13,
+                           STR_ASCII|STR_TERMINATE); /* Service name */
+               send_trans2_replies(req, *pparams, 0, *ppdata, 32,
+                                   max_data_bytes);
+               return;
+       }
+
+       DEBUG(2,("Unknown TRANS2_IOCTL\n"));
+       reply_doserror(req, ERRSRV, ERRerror);
 }
 
 /****************************************************************************
  Reply to a SMBfindclose (stop trans2 directory search).
 ****************************************************************************/
 
-int reply_findclose(connection_struct *conn,
-                   char *inbuf,char *outbuf,int length,int bufsize)
+void reply_findclose(connection_struct *conn, struct smb_request *req)
 {
-       int outsize = 0;
-       int dptr_num=SVALS(inbuf,smb_vwv0);
+       int dptr_num;
+
        START_PROFILE(SMBfindclose);
 
+       if (req->wct < 1) {
+               reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
+               END_PROFILE(SMBfindclose);
+               return;
+       }
+
+       dptr_num = SVALS(req->inbuf,smb_vwv0);
+
        DEBUG(3,("reply_findclose, dptr_num = %d\n", dptr_num));
 
        dptr_close(&dptr_num);
 
-       outsize = set_message(inbuf, outbuf,0,0,False);
+       reply_outbuf(req, 0, 0);
 
        DEBUG(3,("SMBfindclose dptr_num = %d\n", dptr_num));
 
        END_PROFILE(SMBfindclose);
-       return(outsize);
+       return;
 }
 
 /****************************************************************************
  Reply to a SMBfindnclose (stop FINDNOTIFYFIRST directory search).
 ****************************************************************************/
 
-int reply_findnclose(connection_struct *conn, 
-                    char *inbuf,char *outbuf,int length,int bufsize)
+void reply_findnclose(connection_struct *conn, struct smb_request *req)
 {
-       int outsize = 0;
-       int dptr_num= -1;
+       int dptr_num;
+
        START_PROFILE(SMBfindnclose);
+
+       if (req->wct < 1) {
+               reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
+               END_PROFILE(SMBfindnclose);
+               return;
+       }
        
-       dptr_num = SVAL(inbuf,smb_vwv0);
+       dptr_num = SVAL(req->inbuf,smb_vwv0);
 
        DEBUG(3,("reply_findnclose, dptr_num = %d\n", dptr_num));
 
@@ -6443,22 +6985,20 @@ int reply_findnclose(connection_struct *conn,
           findnotifyfirst - so any dptr_num is ok here. 
           Just ignore it. */
 
-       outsize = set_message(inbuf, outbuf,0,0,False);
+       reply_outbuf(req, 0, 0);
 
        DEBUG(3,("SMB_findnclose dptr_num = %d\n", dptr_num));
 
        END_PROFILE(SMBfindnclose);
-       return(outsize);
+       return;
 }
 
-int handle_trans2(connection_struct *conn,
-                 struct trans_state *state,
-                 char *inbuf, char *outbuf, int size, int bufsize)
+static void handle_trans2(connection_struct *conn, struct smb_request *req,
+                         struct trans_state *state)
 {
-       int outsize;
-
        if (Protocol >= PROTOCOL_NT1) {
-               SSVAL(outbuf,smb_flg2,SVAL(outbuf,smb_flg2) | 0x40); /* IS_LONG_NAME */
+               req->flags2 |= 0x40; /* IS_LONG_NAME */
+               SSVAL(req->inbuf,smb_flg2,req->flags2);
        }
 
        /* Now we must call the relevant TRANS2 function */
@@ -6466,11 +7006,10 @@ int handle_trans2(connection_struct *conn,
        case TRANSACT2_OPEN:
        {
                START_PROFILE(Trans2_open);
-               outsize = call_trans2open(
-                       conn, inbuf, outbuf, bufsize, 
-                       &state->param, state->total_param,
-                       &state->data, state->total_data,
-                       state->max_data_return);
+               call_trans2open(conn, req,
+                               &state->param, state->total_param,
+                               &state->data, state->total_data,
+                               state->max_data_return);
                END_PROFILE(Trans2_open);
                break;
        }
@@ -6478,11 +7017,10 @@ int handle_trans2(connection_struct *conn,
        case TRANSACT2_FINDFIRST:
        {
                START_PROFILE(Trans2_findfirst);
-               outsize = call_trans2findfirst(
-                       conn, inbuf, outbuf, bufsize,
-                       &state->param, state->total_param,
-                       &state->data, state->total_data,
-                       state->max_data_return);
+               call_trans2findfirst(conn, req,
+                                    &state->param, state->total_param,
+                                    &state->data, state->total_data,
+                                    state->max_data_return);
                END_PROFILE(Trans2_findfirst);
                break;
        }
@@ -6490,11 +7028,10 @@ int handle_trans2(connection_struct *conn,
        case TRANSACT2_FINDNEXT:
        {
                START_PROFILE(Trans2_findnext);
-               outsize = call_trans2findnext(
-                       conn, inbuf, outbuf, size, bufsize, 
-                       &state->param, state->total_param,
-                       &state->data, state->total_data,
-                       state->max_data_return);
+               call_trans2findnext(conn, req,
+                                   &state->param, state->total_param,
+                                   &state->data, state->total_data,
+                                   state->max_data_return);
                END_PROFILE(Trans2_findnext);
                break;
        }
@@ -6502,11 +7039,10 @@ int handle_trans2(connection_struct *conn,
        case TRANSACT2_QFSINFO:
        {
                START_PROFILE(Trans2_qfsinfo);
-               outsize = call_trans2qfsinfo(
-                       conn, inbuf, outbuf, size, bufsize,
-                       &state->param, state->total_param,
-                       &state->data, state->total_data,
-                       state->max_data_return);
+               call_trans2qfsinfo(conn, req,
+                                  &state->param, state->total_param,
+                                  &state->data, state->total_data,
+                                  state->max_data_return);
                END_PROFILE(Trans2_qfsinfo);
            break;
        }
@@ -6514,11 +7050,10 @@ int handle_trans2(connection_struct *conn,
        case TRANSACT2_SETFSINFO:
        {
                START_PROFILE(Trans2_setfsinfo);
-               outsize = call_trans2setfsinfo(
-                       conn, inbuf, outbuf, size, bufsize, 
-                       &state->param, state->total_param,
-                       &state->data, state->total_data,
-                       state->max_data_return);
+               call_trans2setfsinfo(conn, req,
+                                    &state->param, state->total_param,
+                                    &state->data, state->total_data,
+                                    state->max_data_return);
                END_PROFILE(Trans2_setfsinfo);
                break;
        }
@@ -6527,11 +7062,10 @@ int handle_trans2(connection_struct *conn,
        case TRANSACT2_QFILEINFO:
        {
                START_PROFILE(Trans2_qpathinfo);
-               outsize = call_trans2qfilepathinfo(
-                       conn, inbuf, outbuf, size, bufsize, state->call,
-                       &state->param, state->total_param,
-                       &state->data, state->total_data,
-                       state->max_data_return);
+               call_trans2qfilepathinfo(conn, req, state->call,
+                                        &state->param, state->total_param,
+                                        &state->data, state->total_data,
+                                        state->max_data_return);
                END_PROFILE(Trans2_qpathinfo);
                break;
        }
@@ -6540,11 +7074,10 @@ int handle_trans2(connection_struct *conn,
        case TRANSACT2_SETFILEINFO:
        {
                START_PROFILE(Trans2_setpathinfo);
-               outsize = call_trans2setfilepathinfo(
-                       conn, inbuf, outbuf, size, bufsize, state->call,
-                       &state->param, state->total_param,
-                       &state->data, state->total_data,
-                       state->max_data_return);
+               call_trans2setfilepathinfo(conn, req, state->call,
+                                          &state->param, state->total_param,
+                                          &state->data, state->total_data,
+                                          state->max_data_return);
                END_PROFILE(Trans2_setpathinfo);
                break;
        }
@@ -6552,11 +7085,10 @@ int handle_trans2(connection_struct *conn,
        case TRANSACT2_FINDNOTIFYFIRST:
        {
                START_PROFILE(Trans2_findnotifyfirst);
-               outsize = call_trans2findnotifyfirst(
-                       conn, inbuf, outbuf, size, bufsize, 
-                       &state->param, state->total_param,
-                       &state->data, state->total_data,
-                       state->max_data_return);
+               call_trans2findnotifyfirst(conn, req,
+                                          &state->param, state->total_param,
+                                          &state->data, state->total_data,
+                                          state->max_data_return);
                END_PROFILE(Trans2_findnotifyfirst);
                break;
        }
@@ -6564,11 +7096,10 @@ int handle_trans2(connection_struct *conn,
        case TRANSACT2_FINDNOTIFYNEXT:
        {
                START_PROFILE(Trans2_findnotifynext);
-               outsize = call_trans2findnotifynext(
-                       conn, inbuf, outbuf, size, bufsize, 
-                       &state->param, state->total_param,
-                       &state->data, state->total_data,
-                       state->max_data_return);
+               call_trans2findnotifynext(conn, req,
+                                         &state->param, state->total_param,
+                                         &state->data, state->total_data,
+                                         state->max_data_return);
                END_PROFILE(Trans2_findnotifynext);
                break;
        }
@@ -6576,11 +7107,10 @@ int handle_trans2(connection_struct *conn,
        case TRANSACT2_MKDIR:
        {
                START_PROFILE(Trans2_mkdir);
-               outsize = call_trans2mkdir(
-                       conn, inbuf, outbuf, size, bufsize,
-                       &state->param, state->total_param,
-                       &state->data, state->total_data,
-                       state->max_data_return);
+               call_trans2mkdir(conn, req,
+                                &state->param, state->total_param,
+                                &state->data, state->total_data,
+                                state->max_data_return);
                END_PROFILE(Trans2_mkdir);
                break;
        }
@@ -6588,11 +7118,10 @@ int handle_trans2(connection_struct *conn,
        case TRANSACT2_GET_DFS_REFERRAL:
        {
                START_PROFILE(Trans2_get_dfs_referral);
-               outsize = call_trans2getdfsreferral(
-                       conn, inbuf, outbuf, size, bufsize,
-                       &state->param, state->total_param,
-                       &state->data, state->total_data,
-                       state->max_data_return);
+               call_trans2getdfsreferral(conn, req,
+                                         &state->param, state->total_param,
+                                         &state->data, state->total_data,
+                                         state->max_data_return);
                END_PROFILE(Trans2_get_dfs_referral);
                break;
        }
@@ -6600,11 +7129,10 @@ int handle_trans2(connection_struct *conn,
        case TRANSACT2_IOCTL:
        {
                START_PROFILE(Trans2_ioctl);
-               outsize = call_trans2ioctl(
-                       conn, inbuf, outbuf, size, bufsize,
-                       &state->param, state->total_param,
-                       &state->data, state->total_data,
-                       state->max_data_return);
+               call_trans2ioctl(conn, req,
+                                &state->param, state->total_param,
+                                &state->data, state->total_data,
+                                state->max_data_return);
                END_PROFILE(Trans2_ioctl);
                break;
        }
@@ -6612,66 +7140,79 @@ int handle_trans2(connection_struct *conn,
        default:
                /* Error in request */
                DEBUG(2,("Unknown request %d in trans2 call\n", state->call));
-               outsize = ERROR_DOS(ERRSRV,ERRerror);
+               reply_doserror(req, ERRSRV,ERRerror);
        }
-
-       return outsize;
 }
 
 /****************************************************************************
  Reply to a SMBtrans2.
  ****************************************************************************/
 
-int reply_trans2(connection_struct *conn, char *inbuf,char *outbuf,
-                int size, int bufsize)
+void reply_trans2(connection_struct *conn, struct smb_request *req)
 {
-       int outsize = 0;
-       unsigned int dsoff = SVAL(inbuf, smb_dsoff);
-       unsigned int dscnt = SVAL(inbuf, smb_dscnt);
-       unsigned int psoff = SVAL(inbuf, smb_psoff);
-       unsigned int pscnt = SVAL(inbuf, smb_pscnt);
-       unsigned int tran_call = SVAL(inbuf, smb_setup0);
+       unsigned int dsoff;
+       unsigned int dscnt;
+       unsigned int psoff;
+       unsigned int pscnt;
+       unsigned int tran_call;
+       int size;
        struct trans_state *state;
        NTSTATUS result;
 
        START_PROFILE(SMBtrans2);
 
-       result = allow_new_trans(conn->pending_trans, SVAL(inbuf, smb_mid));
+       if (req->wct < 14) {
+               reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
+               END_PROFILE(SMBtrans2);
+               return;
+       }
+
+       dsoff = SVAL(req->inbuf, smb_dsoff);
+       dscnt = SVAL(req->inbuf, smb_dscnt);
+       psoff = SVAL(req->inbuf, smb_psoff);
+       pscnt = SVAL(req->inbuf, smb_pscnt);
+       tran_call = SVAL(req->inbuf, smb_setup0);
+       size = smb_len(req->inbuf) + 4;
+
+       result = allow_new_trans(conn->pending_trans, req->mid);
        if (!NT_STATUS_IS_OK(result)) {
                DEBUG(2, ("Got invalid trans2 request: %s\n",
                          nt_errstr(result)));
+               reply_nterror(req, result);
                END_PROFILE(SMBtrans2);
-               return ERROR_NT(result);
+               return;
        }
 
        if (IS_IPC(conn) && (tran_call != TRANSACT2_OPEN)
             && (tran_call != TRANSACT2_GET_DFS_REFERRAL)
             && (tran_call != TRANSACT2_QFILEINFO)) {
+               reply_doserror(req, ERRSRV, ERRaccess);
                END_PROFILE(SMBtrans2);
-               return ERROR_DOS(ERRSRV,ERRaccess);
+               return;
        }
 
        if ((state = TALLOC_P(conn->mem_ctx, struct trans_state)) == NULL) {
                DEBUG(0, ("talloc failed\n"));
+               reply_nterror(req, NT_STATUS_NO_MEMORY);
                END_PROFILE(SMBtrans2);
-               return ERROR_NT(NT_STATUS_NO_MEMORY);
+               return;
        }
 
        state->cmd = SMBtrans2;
 
-       state->mid = SVAL(inbuf, smb_mid);
-       state->vuid = SVAL(inbuf, smb_uid);
-       state->setup_count = SVAL(inbuf, smb_suwcnt);
+       state->mid = req->mid;
+       state->vuid = req->vuid;
+       state->setup_count = SVAL(req->inbuf, smb_suwcnt);
        state->setup = NULL;
-       state->total_param = SVAL(inbuf, smb_tpscnt);
+       state->total_param = SVAL(req->inbuf, smb_tpscnt);
        state->param = NULL;
-       state->total_data =  SVAL(inbuf, smb_tdscnt);
+       state->total_data =  SVAL(req->inbuf, smb_tdscnt);
        state->data = NULL;
-       state->max_param_return = SVAL(inbuf, smb_mprcnt);
-       state->max_data_return  = SVAL(inbuf, smb_mdrcnt);
-       state->max_setup_return = SVAL(inbuf, smb_msrcnt);
-       state->close_on_completion = BITSETW(inbuf+smb_vwv5,0);
-       state->one_way = BITSETW(inbuf+smb_vwv5,1);
+       state->max_param_return = SVAL(req->inbuf, smb_mprcnt);
+       state->max_data_return  = SVAL(req->inbuf, smb_mdrcnt);
+       state->max_setup_return = SVAL(req->inbuf, smb_msrcnt);
+       state->close_on_completion = BITSETW(req->inbuf+smb_vwv5,0);
+       state->one_way = BITSETW(req->inbuf+smb_vwv5,1);
 
        state->call = tran_call;
 
@@ -6686,16 +7227,18 @@ int reply_trans2(connection_struct *conn, char *inbuf,char *outbuf,
                 *  Until DosPrintSetJobInfo with PRJINFO3 is supported,
                 *  outbuf doesn't have to be set(only job id is used).
                 */
-               if ( (state->setup_count == 4) && (tran_call == TRANSACT2_IOCTL) &&
-                               (SVAL(inbuf,(smb_setup+4)) == LMCAT_SPL) &&
-                               (SVAL(inbuf,(smb_setup+6)) == LMFUNC_GETJOBID)) {
+               if ( (state->setup_count == 4)
+                    && (tran_call == TRANSACT2_IOCTL)
+                    && (SVAL(req->inbuf,(smb_setup+4)) == LMCAT_SPL)
+                    && (SVAL(req->inbuf,(smb_setup+6)) == LMFUNC_GETJOBID)) {
                        DEBUG(2,("Got Trans2 DevIOctl jobid\n"));
                } else {
                        DEBUG(2,("Invalid smb_sucnt in trans2 call(%u)\n",state->setup_count));
                        DEBUG(2,("Transaction is %d\n",tran_call));
                        TALLOC_FREE(state);
+                       reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
                        END_PROFILE(SMBtrans2);
-                       return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
+                       return;
                }
        }
 
@@ -6710,16 +7253,18 @@ int reply_trans2(connection_struct *conn, char *inbuf,char *outbuf,
                        DEBUG(0,("reply_trans2: data malloc fail for %u "
                                 "bytes !\n", (unsigned int)state->total_data));
                        TALLOC_FREE(state);
+                       reply_nterror(req, NT_STATUS_NO_MEMORY);
                        END_PROFILE(SMBtrans2);
-                       return(ERROR_DOS(ERRDOS,ERRnomem));
+                       return;
                }
                if ((dsoff+dscnt < dsoff) || (dsoff+dscnt < dscnt))
                        goto bad_param;
-               if ((smb_base(inbuf)+dsoff+dscnt > inbuf + size) ||
-                   (smb_base(inbuf)+dsoff+dscnt < smb_base(inbuf)))
+               if ((smb_base(req->inbuf)+dsoff+dscnt
+                    > (char *)req->inbuf + size) ||
+                   (smb_base(req->inbuf)+dsoff+dscnt < smb_base(req->inbuf)))
                        goto bad_param;
 
-               memcpy(state->data,smb_base(inbuf)+dsoff,dscnt);
+               memcpy(state->data,smb_base(req->inbuf)+dsoff,dscnt);
        }
 
        if (state->total_param) {
@@ -6731,16 +7276,18 @@ int reply_trans2(connection_struct *conn, char *inbuf,char *outbuf,
                                 "bytes !\n", (unsigned int)state->total_param));
                        SAFE_FREE(state->data);
                        TALLOC_FREE(state);
+                       reply_nterror(req, NT_STATUS_NO_MEMORY);
                        END_PROFILE(SMBtrans2);
-                       return(ERROR_DOS(ERRDOS,ERRnomem));
+                       return;
                } 
                if ((psoff+pscnt < psoff) || (psoff+pscnt < pscnt))
                        goto bad_param;
-               if ((smb_base(inbuf)+psoff+pscnt > inbuf + size) ||
-                   (smb_base(inbuf)+psoff+pscnt < smb_base(inbuf)))
+               if ((smb_base(req->inbuf)+psoff+pscnt
+                    > (char *)req->inbuf + size) ||
+                   (smb_base(req->inbuf)+psoff+pscnt < smb_base(req->inbuf)))
                        goto bad_param;
 
-               memcpy(state->param,smb_base(inbuf)+psoff,pscnt);
+               memcpy(state->param,smb_base(req->inbuf)+psoff,pscnt);
        }
 
        state->received_data  = dscnt;
@@ -6749,23 +7296,23 @@ int reply_trans2(connection_struct *conn, char *inbuf,char *outbuf,
        if ((state->received_param == state->total_param) &&
            (state->received_data == state->total_data)) {
 
-               outsize = handle_trans2(conn, state, inbuf, outbuf,
-                                       size, bufsize);
+               handle_trans2(conn, req, state);
+
                SAFE_FREE(state->data);
                SAFE_FREE(state->param);
                TALLOC_FREE(state);
                END_PROFILE(SMBtrans2);
-               return outsize;
+               return;
        }
 
        DLIST_ADD(conn->pending_trans, state);
 
        /* We need to send an interim response then receive the rest
           of the parameter/data bytes */
-       outsize = set_message(inbuf, outbuf,0,0,False);
-       show_msg(outbuf);
+       reply_outbuf(req, 0, 0);
+       show_msg((char *)req->outbuf);
        END_PROFILE(SMBtrans2);
-       return outsize;
+       return;
 
   bad_param:
 
@@ -6774,7 +7321,7 @@ int reply_trans2(connection_struct *conn, char *inbuf,char *outbuf,
        SAFE_FREE(state->param);
        TALLOC_FREE(state);
        END_PROFILE(SMBtrans2);
-       return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
+       reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
 }
 
 
@@ -6782,44 +7329,52 @@ int reply_trans2(connection_struct *conn, char *inbuf,char *outbuf,
  Reply to a SMBtranss2
  ****************************************************************************/
 
-int reply_transs2(connection_struct *conn,
-                 char *inbuf,char *outbuf,int size,int bufsize)
+void reply_transs2(connection_struct *conn, struct smb_request *req)
 {
-       int outsize = 0;
        unsigned int pcnt,poff,dcnt,doff,pdisp,ddisp;
        struct trans_state *state;
+       int size;
 
        START_PROFILE(SMBtranss2);
 
-       show_msg(inbuf);
+       show_msg((char *)req->inbuf);
+
+       if (req->wct < 8) {
+               reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
+               END_PROFILE(SMBtranss2);
+               return;
+       }
+
+       size = smb_len(req->inbuf)+4;
 
        for (state = conn->pending_trans; state != NULL;
             state = state->next) {
-               if (state->mid == SVAL(inbuf,smb_mid)) {
+               if (state->mid == req->mid) {
                        break;
                }
        }
 
        if ((state == NULL) || (state->cmd != SMBtrans2)) {
+               reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
                END_PROFILE(SMBtranss2);
-               return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
+               return;
        }
 
        /* Revise state->total_param and state->total_data in case they have
           changed downwards */
 
-       if (SVAL(inbuf, smb_tpscnt) < state->total_param)
-               state->total_param = SVAL(inbuf, smb_tpscnt);
-       if (SVAL(inbuf, smb_tdscnt) < state->total_data)
-               state->total_data = SVAL(inbuf, smb_tdscnt);
+       if (SVAL(req->inbuf, smb_tpscnt) < state->total_param)
+               state->total_param = SVAL(req->inbuf, smb_tpscnt);
+       if (SVAL(req->inbuf, smb_tdscnt) < state->total_data)
+               state->total_data = SVAL(req->inbuf, smb_tdscnt);
 
-       pcnt = SVAL(inbuf, smb_spscnt);
-       poff = SVAL(inbuf, smb_spsoff);
-       pdisp = SVAL(inbuf, smb_spsdisp);
+       pcnt = SVAL(req->inbuf, smb_spscnt);
+       poff = SVAL(req->inbuf, smb_spsoff);
+       pdisp = SVAL(req->inbuf, smb_spsdisp);
 
-       dcnt = SVAL(inbuf, smb_sdscnt);
-       doff = SVAL(inbuf, smb_sdsoff);
-       ddisp = SVAL(inbuf, smb_sdsdisp);
+       dcnt = SVAL(req->inbuf, smb_sdscnt);
+       doff = SVAL(req->inbuf, smb_sdsoff);
+       ddisp = SVAL(req->inbuf, smb_sdsdisp);
 
        state->received_param += pcnt;
        state->received_data += dcnt;
@@ -6835,13 +7390,14 @@ int reply_transs2(connection_struct *conn,
                        goto bad_param;
                if (pdisp > state->total_param)
                        goto bad_param;
-               if ((smb_base(inbuf) + poff + pcnt > inbuf + size) ||
-                   (smb_base(inbuf) + poff + pcnt < smb_base(inbuf)))
+               if ((smb_base(req->inbuf) + poff + pcnt
+                    > (char *)req->inbuf + size) ||
+                   (smb_base(req->inbuf) + poff + pcnt < smb_base(req->inbuf)))
                        goto bad_param;
                if (state->param + pdisp < state->param)
                        goto bad_param;
 
-               memcpy(state->param+pdisp,smb_base(inbuf)+poff,
+               memcpy(state->param+pdisp,smb_base(req->inbuf)+poff,
                       pcnt);
        }
 
@@ -6852,41 +7408,38 @@ int reply_transs2(connection_struct *conn,
                        goto bad_param;
                if (ddisp > state->total_data)
                        goto bad_param;
-               if ((smb_base(inbuf) + doff + dcnt > inbuf + size) ||
-                   (smb_base(inbuf) + doff + dcnt < smb_base(inbuf)))
+               if ((smb_base(req->inbuf) + doff + dcnt
+                    > (char *)req->inbuf + size) ||
+                   (smb_base(req->inbuf) + doff + dcnt < smb_base(req->inbuf)))
                        goto bad_param;
                if (state->data + ddisp < state->data)
                        goto bad_param;
 
-               memcpy(state->data+ddisp, smb_base(inbuf)+doff,
+               memcpy(state->data+ddisp, smb_base(req->inbuf)+doff,
                       dcnt);      
        }
 
        if ((state->received_param < state->total_param) ||
            (state->received_data < state->total_data)) {
                END_PROFILE(SMBtranss2);
-               return -1;
+               return;
        }
 
-       /* construct_reply_common has done us the favor to pre-fill the
-        * command field with SMBtranss2 which is wrong :-)
+       /*
+        * construct_reply_common will copy smb_com from inbuf to
+        * outbuf. SMBtranss2 is wrong here.
         */
-       SCVAL(outbuf,smb_com,SMBtrans2);
+       SCVAL(req->inbuf,smb_com,SMBtrans2);
 
-       outsize = handle_trans2(conn, state, inbuf, outbuf, size, bufsize);
+       handle_trans2(conn, req, state);
 
        DLIST_REMOVE(conn->pending_trans, state);
        SAFE_FREE(state->data);
        SAFE_FREE(state->param);
        TALLOC_FREE(state);
 
-       if (outsize == 0) {
-               END_PROFILE(SMBtranss2);
-               return(ERROR_DOS(ERRSRV,ERRnosupport));
-       }
-       
        END_PROFILE(SMBtranss2);
-       return(outsize);
+       return;
 
   bad_param:
 
@@ -6895,6 +7448,7 @@ int reply_transs2(connection_struct *conn,
        SAFE_FREE(state->data);
        SAFE_FREE(state->param);
        TALLOC_FREE(state);
+       reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
        END_PROFILE(SMBtranss2);
-       return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
+       return;
 }