r25117: The mega-patch Jerry was waiting for. Remove all pstrings from
[tprouty/samba.git] / source / smbd / trans2.c
index 2952c9b1dcedc703e3d469b9c792d721857b10f7..63dcb06f5dc28e23e008e51375e2b2229bafbe5e 100644 (file)
@@ -1,26 +1,26 @@
-/* 
+/*
    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
 
    Extensively modified by Andrew Tridgell, 1995
 
    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"
@@ -34,6 +34,16 @@ extern struct current_user current_user;
 #define get_file_size(sbuf) ((sbuf).st_size)
 #define DIR_ENTRY_SAFETY_MARGIN 4096
 
+static char *store_file_unix_basic(connection_struct *conn,
+                               char *pdata,
+                               files_struct *fsp,
+                               const SMB_STRUCT_STAT *psbuf);
+
+static char *store_file_unix_basic_info2(connection_struct *conn,
+                               char *pdata,
+                               files_struct *fsp,
+                               const SMB_STRUCT_STAT *psbuf);
+
 /********************************************************************
  Roundup a value to the nearest allocation roundup size boundary.
  Only do this for Windows clients.
@@ -56,7 +66,7 @@ SMB_BIG_UINT smb_roundup(connection_struct *conn, SMB_BIG_UINT val)
  account sparse files.
 ********************************************************************/
 
-SMB_BIG_UINT get_allocation_size(connection_struct *conn, files_struct *fsp, SMB_STRUCT_STAT *sbuf)
+SMB_BIG_UINT get_allocation_size(connection_struct *conn, files_struct *fsp, const SMB_STRUCT_STAT *sbuf)
 {
        SMB_BIG_UINT ret;
 
@@ -80,18 +90,18 @@ SMB_BIG_UINT get_allocation_size(connection_struct *conn, files_struct *fsp, SMB
  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++) {
@@ -136,7 +146,7 @@ static BOOL get_ea_value(TALLOC_CTX *mem_ctx, connection_struct *conn, files_str
        }
 
        DEBUG(10,("get_ea_value: EA %s is of length %u: ", ea_name, (unsigned int)sizeret));
-       dump_data(10, val, sizeret);
+       dump_data(10, (uint8 *)val, sizeret);
 
        pea->flags = 0;
        if (strnequal(ea_name, "user.", 5)) {
@@ -201,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;
@@ -476,7 +486,7 @@ struct ea_list *read_ea_list_entry(TALLOC_CTX *ctx, const char *pdata, size_t da
        }
 
        DEBUG(10,("read_ea_list_entry: read ea name %s\n", eal->ea.name));
-       dump_data(10, (const char *)eal->ea.value.data, eal->ea.value.length);
+       dump_data(10, eal->ea.value.data, eal->ea.value.length);
 
        return eal;
 }
@@ -566,13 +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(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.
@@ -588,10 +597,7 @@ int send_trans2_replies(char *outbuf,
        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(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
@@ -602,16 +608,15 @@ int send_trans2_replies(char *outbuf,
                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 */
@@ -625,7 +630,10 @@ int send_trans2_replies(char *outbuf,
        /* 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. */
 
@@ -646,11 +654,11 @@ int send_trans2_replies(char *outbuf,
 
                total_sent_thistime = MIN(total_sent_thistime, useable_space+ alignment_offset + data_alignment_offset);
 
-               set_message(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
@@ -660,53 +668,81 @@ int send_trans2_replies(char *outbuf,
                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;
 
@@ -717,20 +753,22 @@ int send_trans2_replies(char *outbuf,
                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;
@@ -745,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;
@@ -759,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);
@@ -786,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",
@@ -800,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,
@@ -819,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,
@@ -855,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);
@@ -870,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. */
@@ -882,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.
@@ -901,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;
 
@@ -939,9 +998,7 @@ static int call_trans2open(connection_struct *conn, char *inbuf, char *outbuf, i
        }
 
        /* Send the required number of replies */
-       send_trans2_replies(outbuf, bufsize, params, 30, *ppdata, 0, max_data_bytes);
-
-       return -1;
+       send_trans2_replies(req, params, 30, *ppdata, 0, max_data_bytes);
 }
 
 /*********************************************************
@@ -951,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;
@@ -1077,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;
@@ -1107,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;
 
@@ -1116,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;
@@ -1135,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
@@ -1148,64 +1217,98 @@ 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) 
+
+               if (!dname) {
                        return(False);
+               }
+
+               /*
+                * fname may get mangled, dname is never mangled.
+                * Whenever we're accessing the filesystem we use
+                * pathreal which is composed from dname.
+                */
 
-               pstrcpy(fname,dname);      
+               pathreal = NULL;
+               fname = dname;
 
-               if(!(got_match = *got_exact_match = exact_match(conn, fname, mask)))
+               /* 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);
+               }
 
                if(!got_match && check_mangled_names &&
                   !mangle_is_8_3(fname, False, conn->params)) {
-
                        /*
                         * 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.
                         */
+                       /* Force the mangling into 8.3. */
+                       if (!name_to_8_3( fname, mangled_name, False, conn->params)) {
+                               continue; /* Error - couldn't mangle. */
+                       }
 
-                       pstring newname;
-                       pstrcpy( newname, fname);
-                       mangle_map( newname, True, False, conn->params);
-                       if(!(got_match = *got_exact_match = exact_match(conn, newname, mask)))
-                               got_match = mask_match(newname, mask, conn->case_sensitive);
+                       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(fname,"..") || strequal(fname,"."));
-                       if (dont_descend && !isdots)
+               if (got_match) {
+                       BOOL isdots = (ISDOT(dname) || ISDOTDOT(dname));
+
+                       if (dont_descend && !isdots) {
                                continue;
-         
-                       pstrcpy(pathreal,conn->dirpath);
-                       if(needslash)
-                               pstrcat(pathreal,"/");
-                       pstrcat(pathreal,dname);
+                       }
+
+                       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;
+                       }
 
                        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) {
-
-                               /* 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(NULL,conn, pathreal, NULL, NULL, &sbuf)) == True)) {
-
-                                       DEBUG(5,("get_lanman2_dir_entry: Masquerading msdfs link %s as a directory\n", pathreal));
+                                  ((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));
                                        sbuf.st_mode = (sbuf.st_mode & 0xFFF) | S_IFDIR;
 
                                } else {
 
                                        DEBUG(5,("get_lanman2_dir_entry:Couldn't stat [%s] (%s)\n",
                                                pathreal,strerror(errno)));
+                                       TALLOC_FREE(pathreal);
                                        continue;
                                }
                        }
@@ -1217,12 +1320,14 @@ static BOOL get_lanman2_dir_entry(connection_struct *conn,
                        }
 
                        if (!dir_check_ftype(conn,mode,dirtype)) {
-                               DEBUG(5,("[%s] attribs didn't match %x\n",fname,dirtype));
+                               DEBUG(5,("get_lanman2_dir_entry: [%s] attribs didn't match %x\n",fname,dirtype));
+                               TALLOC_FREE(pathreal);
                                continue;
                        }
 
-                       if (!(mode & aDIR))
+                       if (!(mode & aDIR)) {
                                file_size = get_file_size(sbuf);
+                       }
                        allocation_size = get_allocation_size(conn,NULL,&sbuf);
 
                        mdate_ts = get_mtimespec(&sbuf);
@@ -1238,17 +1343,15 @@ 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));
-         
+
+                       DEBUG(5,("get_lanman2_dir_entry: found %s fname=%s\n",pathreal,fname));
+
                        found = True;
 
                        dptr_DirCacheAdd(conn->dirptr, dname, curr_dirpos);
                }
        }
 
-       mangle_map(fname,False,True,conn->params);
-
        p = pdata;
        last_entry_ptr = p;
 
@@ -1269,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 {
@@ -1305,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 {
@@ -1345,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. */
@@ -1359,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 {
@@ -1404,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);
                                }
@@ -1418,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. */
@@ -1439,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. */
@@ -1448,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;
@@ -1466,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;
 
@@ -1484,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. */
@@ -1514,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. */
@@ -1547,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);
@@ -1565,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. */
@@ -1578,53 +1705,30 @@ static BOOL get_lanman2_dir_entry(connection_struct *conn,
                /* CIFS UNIX Extension. */
 
                case SMB_FIND_FILE_UNIX:
-                       DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_UNIX\n"));
+               case SMB_FIND_FILE_UNIX_INFO2:
                        p+= 4;
                        SIVAL(p,0,reskey); p+= 4;    /* Used for continuing search. */
 
                        /* Begin of SMB_QUERY_FILE_UNIX_BASIC */
-                       SOFF_T(p,0,get_file_size(sbuf));             /* File size 64 Bit */
-                       p+= 8;
-
-                       SOFF_T(p,0,get_allocation_size(conn,NULL,&sbuf)); /* Number of bytes used on disk - 64 Bit */
-                       p+= 8;
-
-                       put_long_date_timespec(p,get_ctimespec(&sbuf));       /* Inode change Time 64 Bit */
-                       put_long_date_timespec(p+8,get_atimespec(&sbuf));     /* Last access time 64 Bit */
-                       put_long_date_timespec(p+16,get_mtimespec(&sbuf));    /* Last modification time 64 Bit */
-                       p+= 24;
-
-                       SIVAL(p,0,sbuf.st_uid);               /* user id for the owner */
-                       SIVAL(p,4,0);
-                       p+= 8;
 
-                       SIVAL(p,0,sbuf.st_gid);               /* group id of owner */
-                       SIVAL(p,4,0);
-                       p+= 8;
-
-                       SIVAL(p,0,unix_filetype(sbuf.st_mode));
-                       p+= 4;
-
-                       SIVAL(p,0,unix_dev_major(sbuf.st_rdev));   /* Major device number if type is device */
-                       SIVAL(p,4,0);
-                       p+= 8;
-
-                       SIVAL(p,0,unix_dev_minor(sbuf.st_rdev));   /* Minor device number if type is device */
-                       SIVAL(p,4,0);
-                       p+= 8;
-
-                       SINO_T_VAL(p,0,(SMB_INO_T)sbuf.st_ino);   /* inode number */
-                       p+= 8;
-
-                       SIVAL(p,0, unix_perms_to_wire(sbuf.st_mode));     /* Standard UNIX file permissions */
-                       SIVAL(p,4,0);
-                       p+= 8;
-
-                       SIVAL(p,0,sbuf.st_nlink);             /* number of hard links */
-                       SIVAL(p,4,0);
-                       p+= 8;
+                       if (info_level == SMB_FIND_FILE_UNIX) {
+                               DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_UNIX\n"));
+                               p = store_file_unix_basic(conn, p,
+                                                       NULL, &sbuf);
+                               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(base_data, flags2, p, fname,
+                                                 PTR_DIFF(end_data, p), 0);
+                               SIVAL(nameptr, 0, len);
+                       }
 
-                       len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE);
                        p += len;
                        SIVAL(p,0,0); /* Ensure any padding is null. */
 
@@ -1636,7 +1740,7 @@ static BOOL get_lanman2_dir_entry(connection_struct *conn,
 
                        break;
 
-               default:      
+               default:
                        return(False);
        }
 
@@ -1661,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
@@ -1672,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;
@@ -1679,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;
@@ -1692,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);
@@ -1708,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,
@@ -1732,42 +1838,68 @@ close_if_end = %d requires_resume_key = %d level = 0x%x, max_data_bytes = %d\n",
                case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
                        break;
                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;
        }
 
-       RESOLVE_DFSPATH_WCARD(directory, conn, inbuf, outbuf);
+       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)) {
+                       reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
+                                       ERRSRV, ERRbadpath);
+                       return;
+               }
+               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;
        }
 
@@ -1777,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;
 
@@ -1826,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;
@@ -1860,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)
@@ -1886,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)) {
@@ -1895,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.
@@ -1905,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;
                }
        }
 
@@ -1920,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( 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
@@ -1937,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
@@ -1958,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;
@@ -1968,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;
@@ -1979,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);
@@ -1997,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;
                }
        }
 
@@ -2037,66 +2191,69 @@ resume_key = %d resume name = %s continue=%d level = %d\n",
                case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
                        break;
                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));
@@ -2104,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.
         */
@@ -2140,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;
+                       }
                }
 
                /*
@@ -2171,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)
@@ -2197,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)) {
@@ -2212,38 +2384,41 @@ 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( outbuf, bufsize, params, 8, pdata, PTR_DIFF(p,pdata), max_data_bytes);
+       send_trans2_replies(req, 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));
-
-       DEBUG( 3, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
-               smb_fn_name(CVAL(inbuf,smb_com)), 
-               mask, directory, dirtype, numentries ) );
+       return;
+}
 
-       return(-1);
+unsigned char *create_volume_objectid(connection_struct *conn, unsigned char objid[16])
+{
+       E_md4hash(lp_servicename(SNUM(conn)),objid);
+       return objid;
 }
 
 /****************************************************************************
  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 = *ppdata;
+       char *pdata, *end_data;
        char *params = *pparams;
        uint16 info_level;
        int data_len, len;
        SMB_STRUCT_STAT st;
-       char *vname = volume_label(SNUM(conn));
+       const char *vname = volume_label(SNUM(conn));
        int snum = SNUM(conn);
        char *fstype = lp_fstype(SNUM(conn));
        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);
@@ -2252,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:
@@ -2270,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);
@@ -2314,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",
@@ -2331,19 +2514,24 @@ cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)st.st_dev, (unsi
 
                        SIVAL(pdata,0,FILE_CASE_PRESERVED_NAMES|FILE_CASE_SENSITIVE_SEARCH|
                                (lp_nt_acl_support(SNUM(conn)) ? FILE_PERSISTENT_ACLS : 0)|
+                               FILE_SUPPORTS_OBJECT_IDS|
+                               FILE_UNICODE_ON_DISK|
                                quota_flag); /* FS ATTRIBUTES */
 
                        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;
@@ -2358,9 +2546,13 @@ cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)st.st_dev, (unsi
                        SIVAL(pdata,8,str_checksum(lp_servicename(snum)) ^ 
                                (str_checksum(get_local_machine_name())<<16));
 
-                       len = srvstr_push(outbuf, pdata+18, vname, -1, STR_UNICODE);
+                       /* Max label len is 32 characters. */
+                       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;
+
                        DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_VOLUME_INFO namelen = %d, vol=%s serv=%s\n", 
                                (int)strlen(vname),vname, lp_servicename(snum)));
                        break;
@@ -2371,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) {
@@ -2403,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) {
@@ -2476,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;
@@ -2510,8 +2706,12 @@ cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned
                }
 #endif /* HAVE_SYS_QUOTAS */
                case SMB_FS_OBJECTID_INFORMATION:
+               {
+                       unsigned char objid[16];
+                       memcpy(pdata,create_volume_objectid(conn, objid),16);
                        data_len = 64;
                        break;
+               }
 
                /*
                 * Query the version and capabilities of the CIFS UNIX extensions
@@ -2520,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);
@@ -2530,7 +2731,11 @@ cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned
                                        CIFS_UNIX_POSIX_ACLS_CAP|
                                        CIFS_UNIX_POSIX_PATHNAMES_CAP|
                                        CIFS_UNIX_FCNTL_LOCKS_CAP|
-                                       CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP)));
+                                       CIFS_UNIX_EXTATTR_CAP|
+                                       CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP|
+                                       /* Ensure we don't do this on signed or sealed data. */
+                                       (srv_is_signing_active() ? 0 : CIFS_UNIX_LARGE_READ_CAP)
+                                       )));
                        break;
 
                case SMB_QUERY_POSIX_FS_INFO:
@@ -2539,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);
@@ -2557,12 +2763,124 @@ 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;
+               }
+
+               case SMB_QUERY_POSIX_WHOAMI:
+               {
+                       uint32_t flags = 0;
+                       uint32_t sid_bytes;
+                       int i;
+
+                       if (!lp_unix_extensions()) {
+                               reply_nterror(req, NT_STATUS_INVALID_LEVEL);
+                               return;
+                       }
+
+                       if (max_data_bytes < 40) {
+                               reply_nterror(req, NT_STATUS_BUFFER_TOO_SMALL);
+                               return;
+                       }
+
+                       /* We ARE guest if global_sid_Builtin_Guests is
+                        * in our list of SIDs.
+                        */
+                       if (nt_token_check_sid(&global_sid_Builtin_Guests,
+                                   current_user.nt_user_token)) {
+                               flags |= SMB_WHOAMI_GUEST;
+                       }
+
+                       /* We are NOT guest if global_sid_Authenticated_Users
+                        * is in our list of SIDs.
+                        */
+                       if (nt_token_check_sid(&global_sid_Authenticated_Users,
+                                   current_user.nt_user_token)) {
+                               flags &= ~SMB_WHOAMI_GUEST;
+                       }
+
+                       /* NOTE: 8 bytes for UID/GID, irrespective of native
+                        * platform size. This matches
+                        * SMB_QUERY_FILE_UNIX_BASIC and friends.
+                        */
+                       data_len = 4 /* flags */
+                           + 4 /* flag mask */
+                           + 8 /* uid */
+                           + 8 /* gid */
+                           + 4 /* ngroups */
+                           + 4 /* num_sids */
+                           + 4 /* SID bytes */
+                           + 4 /* pad/reserved */
+                           + (current_user.ut.ngroups * 8)
+                               /* groups list */
+                           + (current_user.nt_user_token->num_sids *
+                                   SID_MAX_SIZE)
+                               /* SID list */;
+
+                       SIVAL(pdata, 0, flags);
+                       SIVAL(pdata, 4, SMB_WHOAMI_MASK);
+                       SBIG_UINT(pdata, 8, (SMB_BIG_UINT)current_user.ut.uid);
+                       SBIG_UINT(pdata, 16, (SMB_BIG_UINT)current_user.ut.gid);
+
+
+                       if (data_len >= max_data_bytes) {
+                               /* Potential overflow, skip the GIDs and SIDs. */
+
+                               SIVAL(pdata, 24, 0); /* num_groups */
+                               SIVAL(pdata, 28, 0); /* num_sids */
+                               SIVAL(pdata, 32, 0); /* num_sid_bytes */
+                               SIVAL(pdata, 36, 0); /* reserved */
+
+                               data_len = 40;
+                               break;
+                       }
+
+                       SIVAL(pdata, 24, current_user.ut.ngroups);
+                       SIVAL(pdata, 28,
+                               current_user.nt_user_token->num_sids);
+
+                       /* We walk the SID list twice, but this call is fairly
+                        * infrequent, and I don't expect that it's performance
+                        * sensitive -- jpeach
+                        */
+                       for (i = 0, sid_bytes = 0;
+                           i < current_user.nt_user_token->num_sids; ++i) {
+                               sid_bytes +=
+                                   sid_size(&current_user.nt_user_token->user_sids[i]);
+                       }
+
+                       /* SID list byte count */
+                       SIVAL(pdata, 32, sid_bytes);
+
+                       /* 4 bytes pad/reserved - must be zero */
+                       SIVAL(pdata, 36, 0);
+                       data_len = 40;
+
+                       /* GID list */
+                       for (i = 0; i < current_user.ut.ngroups; ++i) {
+                               SBIG_UINT(pdata, data_len,
+                                       (SMB_BIG_UINT)current_user.ut.groups[i]);
+                               data_len += 8;
+                       }
+
+                       /* SID list */
+                       for (i = 0;
+                           i < current_user.nt_user_token->num_sids; ++i) {
+                               int sid_len =
+                                   sid_size(&current_user.nt_user_token->user_sids[i]);
+
+                               sid_linearize(pdata + data_len, sid_len,
+                                   &current_user.nt_user_token->user_sids[i]);
+                               data_len += sid_len;
                        }
+
                        break;
                }
 
@@ -2578,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( 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))));
 
@@ -2608,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);
@@ -2622,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);
@@ -2658,6 +2986,51 @@ cap_low = 0x%x, cap_high = 0x%x\n",
                                }
                                break;
                        }
+               case SMB_REQUEST_TRANSPORT_ENCRYPTION:
+                       {
+                               NTSTATUS status;
+                               size_t param_len = 0;
+                               size_t data_len = total_data;
+
+                               if (!lp_unix_extensions()) {
+                                       reply_nterror(
+                                               req, NT_STATUS_INVALID_LEVEL);
+                                       return;
+                               }
+
+                               DEBUG( 4,("call_trans2setfsinfo: request transport encrption.\n"));
+
+                               status = srv_request_encryption_setup(conn,
+                                                                       (unsigned char **)ppdata,
+                                                                       &data_len,
+                                                                       (unsigned char **)pparams,
+                                                                       &param_len
+                                                                       );
+
+                               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(req,
+                                                   *pparams, param_len,
+                                                   *ppdata, data_len,
+                                                   max_data_bytes);
+
+                               if (NT_STATUS_IS_OK(status)) {
+                                       /* Server-side transport encryption is now *on*. */
+                                       status = srv_encryption_start(conn);
+                                       if (!NT_STATUS_IS_OK(status)) {
+                                               exit_server_cleanly("Failure in setting up encrypted transport");
+                                       }
+                               }
+                               return;
+                       }
                case SMB_FS_QUOTA_INFORMATION:
                        {
                                files_struct *fsp = NULL;
@@ -2669,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*/
@@ -2699,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 */
                
@@ -2712,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 */
                
@@ -2724,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;
@@ -2732,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;
        }
 
@@ -2741,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(outbuf,10,0,True);
-
-       return outsize;
+        */
+       reply_outbuf(req, 10, 0);
 }
 
 #if defined(HAVE_POSIX_ACLS)
@@ -2816,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);
@@ -2835,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);
@@ -2871,7 +3258,7 @@ static BOOL marshall_posix_acl(connection_struct *conn, char *pdata, SMB_STRUCT_
 static char *store_file_unix_basic(connection_struct *conn,
                                char *pdata,
                                files_struct *fsp,
-                               SMB_STRUCT_STAT *psbuf)
+                               const SMB_STRUCT_STAT *psbuf)
 {
        DEBUG(10,("store_file_unix_basic: SMB_QUERY_FILE_UNIX_BASIC\n"));
        DEBUG(4,("store_file_unix_basic: st_mode=%o\n",(int)psbuf->st_mode));
@@ -2920,143 +3307,393 @@ static char *store_file_unix_basic(connection_struct *conn,
        return pdata;
 }
 
+/* Forward and reverse mappings from the UNIX_INFO2 file flags field and
+ * the chflags(2) (or equivalent) flags.
+ *
+ * XXX: this really should be behind the VFS interface. To do this, we would
+ * need to alter SMB_STRUCT_STAT so that it included a flags and a mask field.
+ * Each VFS module could then implement it's own mapping as appropriate for the
+ * platform. We would then pass the SMB flags into SMB_VFS_CHFLAGS.
+ */
+static const struct {unsigned stat_fflag; unsigned smb_fflag;}
+       info2_flags_map[] =
+{
+#ifdef UF_NODUMP
+    { UF_NODUMP, EXT_DO_NOT_BACKUP },
+#endif
+
+#ifdef UF_IMMUTABLE
+    { UF_IMMUTABLE, EXT_IMMUTABLE },
+#endif
+
+#ifdef UF_APPEND
+    { UF_APPEND, EXT_OPEN_APPEND_ONLY },
+#endif
+
+#ifdef UF_HIDDEN
+    { UF_HIDDEN, EXT_HIDDEN },
+#endif
+
+    /* Do not remove. We need to guarantee that this array has at least one
+     * entry to build on HP-UX.
+     */
+    { 0, 0 }
+
+};
+
+static void map_info2_flags_from_sbuf(const SMB_STRUCT_STAT *psbuf,
+                               uint32 *smb_fflags, uint32 *smb_fmask)
+{
+#ifdef HAVE_STAT_ST_FLAGS
+       int i;
+
+       for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
+           *smb_fmask |= info2_flags_map[i].smb_fflag;
+           if (psbuf->st_flags & info2_flags_map[i].stat_fflag) {
+                   *smb_fflags |= info2_flags_map[i].smb_fflag;
+           }
+       }
+#endif /* HAVE_STAT_ST_FLAGS */
+}
+
+static BOOL map_info2_flags_to_sbuf(const SMB_STRUCT_STAT *psbuf,
+                               const uint32 smb_fflags,
+                               const uint32 smb_fmask,
+                               int *stat_fflags)
+{
+#ifdef HAVE_STAT_ST_FLAGS
+       uint32 max_fmask = 0;
+       int i;
+
+       *stat_fflags = psbuf->st_flags;
+
+       /* For each flags requested in smb_fmask, check the state of the
+        * corresponding flag in smb_fflags and set or clear the matching
+        * stat flag.
+        */
+
+       for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
+           max_fmask |= info2_flags_map[i].smb_fflag;
+           if (smb_fmask & info2_flags_map[i].smb_fflag) {
+                   if (smb_fflags & info2_flags_map[i].smb_fflag) {
+                           *stat_fflags |= info2_flags_map[i].stat_fflag;
+                   } else {
+                           *stat_fflags &= ~info2_flags_map[i].stat_fflag;
+                   }
+           }
+       }
+
+       /* If smb_fmask is asking to set any bits that are not supported by
+        * our flag mappings, we should fail.
+        */
+       if ((smb_fmask & max_fmask) != smb_fmask) {
+               return False;
+       }
+
+       return True;
+#else
+       return False;
+#endif /* HAVE_STAT_ST_FLAGS */
+}
+
+
+/* Just like SMB_QUERY_FILE_UNIX_BASIC, but with the addition
+ * of file flags and birth (create) time.
+ */
+static char *store_file_unix_basic_info2(connection_struct *conn,
+                               char *pdata,
+                               files_struct *fsp,
+                               const SMB_STRUCT_STAT *psbuf)
+{
+       uint32 file_flags = 0;
+       uint32 flags_mask = 0;
+
+       pdata = store_file_unix_basic(conn, pdata, fsp, psbuf);
+
+       /* Create (birth) time 64 bit */
+       put_long_date_timespec(pdata, get_create_timespec(psbuf, False));
+       pdata += 8;
+
+       map_info2_flags_from_sbuf(psbuf, &file_flags, &flags_mask);
+       SIVAL(pdata, 0, file_flags); /* flags */
+       SIVAL(pdata, 4, flags_mask); /* mask */
+       pdata += 8;
+
+       return pdata;
+}
+
 /****************************************************************************
- Reply to a TRANS2_QFILEPATHINFO or TRANSACT2_QFILEINFO (query file info by
- file name or file id).
+ Reply to a TRANSACT2_QFILEINFO on a PIPE !
 ****************************************************************************/
 
-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_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;
-       uint16 info_level;
-       int mode=0;
-       int nlink;
-       SMB_OFF_T file_size=0;
-       SMB_BIG_UINT allocation_size=0;
        unsigned int data_size = 0;
        unsigned int param_size = 2;
-       SMB_STRUCT_STAT sbuf;
-       pstring fname, dos_fname;
-       char *fullpathname;
-       char *base_name;
-       char *p;
-       SMB_OFF_T pos = 0;
-       BOOL delete_pending = False;
-       int len;
-       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 ea_list *ea_list = NULL;
-       uint32 access_mask = 0x12019F; /* Default - GENERIC_EXECUTE mapping from Windows */
-       char *lock_data = NULL;
+       uint16 info_level;
+       smb_np_struct *p_pipe = NULL;
 
-       if (!params)
-               return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
+       if (!params) {
+               reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
+               return;
+       }
 
-       ZERO_STRUCT(sbuf);
+       if (total_params < 4) {
+               reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
+               return;
+       }
 
-       if (tran_call == TRANSACT2_QFILEINFO) {
-               if (total_params < 4) {
-                       return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
-               }
+       p_pipe = get_rpc_pipe_p(SVAL(params,0));
+       if (p_pipe == NULL) {
+               reply_nterror(req, NT_STATUS_INVALID_HANDLE);
+               return;
+       }
+
+       info_level = SVAL(params,2);
+
+       *pparams = (char *)SMB_REALLOC(*pparams,2);
+       if (*pparams == NULL) {
+               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 ) {
+               reply_nterror(req, NT_STATUS_NO_MEMORY);
+               return;
+       }
+       pdata = *ppdata;
+
+       switch (info_level) {
+               case SMB_FILE_STANDARD_INFORMATION:
+                       memset(pdata,0,24);
+                       SOFF_T(pdata,0,4096LL);
+                       SIVAL(pdata,16,1);
+                       SIVAL(pdata,20,1);
+                       data_size = 24;
+                       break;
+
+               default:
+                       reply_nterror(req, NT_STATUS_INVALID_LEVEL);
+                       return;
+       }
+
+       send_trans2_replies(req, params, param_size, *ppdata, data_size,
+                           max_data_bytes);
+
+       return;
+}
 
-               fsp = file_fsp(params,0);
+/****************************************************************************
+ Reply to a TRANS2_QFILEPATHINFO or TRANSACT2_QFILEINFO (query file info by
+ file name or file id).
+****************************************************************************/
+
+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;
+       SMB_OFF_T file_size=0;
+       SMB_BIG_UINT allocation_size=0;
+       unsigned int data_size = 0;
+       unsigned int param_size = 2;
+       SMB_STRUCT_STAT sbuf;
+       char *dos_fname = NULL;
+       char *fname = NULL;
+       char *fullpathname;
+       char *base_name;
+       char *p;
+       SMB_OFF_T pos = 0;
+       BOOL delete_pending = False;
+       int len;
+       time_t create_time, mtime, atime;
+       struct timespec create_time_ts, mtime_ts, atime_ts;
+       files_struct *fsp = 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) {
+               reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
+               return;
+       }
+
+       ZERO_STRUCT(sbuf);
+
+       if (tran_call == TRANSACT2_QFILEINFO) {
+               if (total_params < 4) {
+                       reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
+                       return;
+               }
+
+               if (IS_IPC(conn)) {
+                       call_trans2qpipeinfo(conn, req, tran_call,
+                                            pparams, total_params,
+                                            ppdata, total_data,
+                                            max_data_bytes);
+                       return;
+               }
+
+               fsp = file_fsp(SVAL(params,0));
                info_level = SVAL(params,2);
 
                DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QFILEINFO: level = %d\n", info_level));
 
-               if(fsp && (fsp->fake_file_handle)) {
+               if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
+                       reply_nterror(req, NT_STATUS_INVALID_LEVEL);
+                       return;
+               }
+
+               /* 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);
 
                DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QPATHINFO: level = %d\n", info_level));
 
-               srvstr_get_path(inbuf, fname, &params[6], sizeof(fname), total_params - 6, STR_TERMINATE, &status);
+               if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
+                       reply_nterror(req, NT_STATUS_INVALID_LEVEL);
+                       return;
+               }
+
+               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;
                }
 
-               RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
+               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)) {
+                               reply_botherror(req,
+                                               NT_STATUS_PATH_NOT_COVERED,
+                                               ERRSRV, ERRbadpath);
+                       }
+                       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;
                }
        }
 
@@ -3072,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
@@ -3100,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;
                }
@@ -3130,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);
+                       lock_data = (char *)TALLOC_MEMDUP(
+                               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:
@@ -3155,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);
@@ -3175,18 +3817,18 @@ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pd
        allocation_size = get_allocation_size(conn,fsp,&sbuf);
 
        if (fsp) {
-               if (fsp->pending_modtime) {
+               if (!null_timespec(fsp->pending_modtime)) {
                        /* the pending modtime overrides the current modtime */
-                       mtime_ts.tv_sec = fsp->pending_modtime;
-                       mtime_ts.tv_nsec = 0;
+                       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);
-               if (fsp1 && fsp1->pending_modtime) {
+               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.tv_sec = fsp1->pending_modtime;
-                       mtime_ts.tv_nsec = 0;
+                       mtime_ts = fsp1->pending_modtime;
                }
                if (fsp1 && fsp1->initial_allocation_size) {
                        allocation_size = get_allocation_size(conn, fsp1, &sbuf);
@@ -3205,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, '/', '\\');
        }
 
@@ -3242,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;
@@ -3256,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;
                }
 
@@ -3278,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;
                }
 
@@ -3348,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;
@@ -3366,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);
@@ -3407,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));
@@ -3484,8 +4137,7 @@ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pd
                                SIVAL(pdata,0,0); /* ??? */
                                SIVAL(pdata,4,byte_len); /* Byte length of unicode string ::$DATA */
                                SOFF_T(pdata,8,file_size);
-                               SIVAL(pdata,16,allocation_size);
-                               SIVAL(pdata,20,0); /* ??? */
+                               SOFF_T(pdata,16,allocation_size);
                                data_size = 24 + byte_len;
                        }
                        break;
@@ -3505,7 +4157,7 @@ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pd
                        put_long_date_timespec(pdata+8,atime_ts);
                        put_long_date_timespec(pdata+16,mtime_ts); /* write time */
                        put_long_date_timespec(pdata+24,mtime_ts); /* change time */
-                       SIVAL(pdata,32,allocation_size);
+                       SOFF_T(pdata,32,allocation_size);
                        SOFF_T(pdata,40,file_size);
                        SIVAL(pdata,48,mode);
                        SIVAL(pdata,52,0); /* ??? */
@@ -3539,22 +4191,54 @@ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pd
 
                        break;
 
+               case SMB_QUERY_FILE_UNIX_INFO2:
+
+                       pdata = store_file_unix_basic_info2(conn, pdata, fsp, &sbuf);
+                       data_size = PTR_DIFF(pdata,(*ppdata));
+
+                       {
+                               int i;
+                               DEBUG(4,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_INFO2 "));
+
+                               for (i=0; i<100; i++)
+                                       DEBUG(4,("%d=%x, ",i, (*ppdata)[i]));
+                               DEBUG(4,("\n"));
+                       }
+
+                       break;
+
                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));
 
@@ -3578,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)) {
@@ -3604,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);
@@ -3617,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) {
@@ -3626,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) {
@@ -3650,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)) {
@@ -3663,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);
@@ -3709,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(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;
 }
 
 /****************************************************************************
@@ -3728,17 +4430,27 @@ 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;
+       }
+
+       status = check_name(conn, oldname);
        if (!NT_STATUS_IS_OK(status)) {
                return status;
        }
@@ -3748,12 +4460,13 @@ NTSTATUS hardlink_internals(connection_struct *conn, pstring oldname, pstring ne
                return NT_STATUS_OBJECT_NAME_NOT_FOUND;
        }
 
-       status = check_name(conn, oldname);
+       status = unix_convert(conn, newname_in, False, &newname,
+                       &last_component_newname, &sbuf2);
        if (!NT_STATUS_IS_OK(status)) {
-               return NT_STATUS_ACCESS_DENIED;
+               return status;
        }
 
-       status = unix_convert(conn, newname, False, last_component_newname, &sbuf2);
+       status = check_name(conn, newname);
        if (!NT_STATUS_IS_OK(status)) {
                return status;
        }
@@ -3763,18 +4476,13 @@ NTSTATUS hardlink_internals(connection_struct *conn, pstring oldname, pstring ne
                return NT_STATUS_OBJECT_NAME_COLLISION;
        }
 
-       status = check_name(conn, newname);
-       if (!NT_STATUS_IS_OK(status)) {
-               return NT_STATUS_ACCESS_DENIED;
-       }
-
        /* No links from a directory. */
        if (S_ISDIR(sbuf1.st_mode)) {
                return NT_STATUS_FILE_IS_A_DIRECTORY;
        }
 
        /* 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;
        }
@@ -3798,7 +4506,7 @@ static NTSTATUS smb_set_file_time(connection_struct *conn,
                                files_struct *fsp,
                                const char *fname,
                                const SMB_STRUCT_STAT *psbuf,
-                               struct utimbuf tvs)
+                               struct timespec ts[2])
 {
        uint32 action =
                FILE_NOTIFY_CHANGE_LAST_ACCESS
@@ -3810,26 +4518,30 @@ static NTSTATUS smb_set_file_time(connection_struct *conn,
        }
 
        /* get some defaults (no modifications) if any info is zero or -1. */
-       if (null_mtime(tvs.actime)) {
-               tvs.actime = psbuf->st_atime;
+       if (null_timespec(ts[0])) {
+               ts[0] = get_atimespec(psbuf);
                action &= ~FILE_NOTIFY_CHANGE_LAST_ACCESS;
        }
 
-       if (null_mtime(tvs.modtime)) {
-               tvs.modtime = psbuf->st_mtime;
+       if (null_timespec(ts[1])) {
+               ts[1] = get_mtimespec(psbuf);
                action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
        }
 
-       DEBUG(6,("smb_set_file_time: actime: %s " , ctime(&tvs.actime)));
-       DEBUG(6,("smb_set_file_time: modtime: %s ", ctime(&tvs.modtime)));
+       DEBUG(6,("smb_set_file_time: actime: %s " , time_to_asc(convert_timespec_to_time_t(ts[0])) ));
+       DEBUG(6,("smb_set_file_time: modtime: %s ", time_to_asc(convert_timespec_to_time_t(ts[1])) ));
 
        /*
         * Try and set the times of this file if
         * they are different from the current values.
         */
 
-       if (psbuf->st_mtime == tvs.modtime && psbuf->st_atime == tvs.actime) {
-               return NT_STATUS_OK;
+       {
+               struct timespec mts = get_mtimespec(psbuf);
+               struct timespec ats = get_atimespec(psbuf);
+               if ((timespec_compare(&ts[0], &ats) == 0) && (timespec_compare(&ts[1], &mts) == 0)) {
+                       return NT_STATUS_OK;
+               }
        }
 
        if(fsp != NULL) {
@@ -3843,15 +4555,16 @@ static NTSTATUS smb_set_file_time(connection_struct *conn,
                 * away and will set it on file close and after a write. JRA.
                 */
 
-               if (tvs.modtime != (time_t)0 && tvs.modtime != (time_t)-1) {
-                       DEBUG(10,("smb_set_file_time: setting pending modtime to %s\n", ctime(&tvs.modtime) ));
-                       fsp_set_pending_modtime(fsp, tvs.modtime);
+               if (!null_timespec(ts[1])) {
+                       DEBUG(10,("smb_set_file_time: setting pending modtime to %s\n",
+                               time_to_asc(convert_timespec_to_time_t(ts[1])) ));
+                       fsp_set_pending_modtime(fsp, ts[1]);
                }
 
        }
        DEBUG(10,("smb_set_file_time: setting utimes to modified values.\n"));
 
-       if(file_utime(conn, fname, &tvs)!=0) {
+       if(file_ntimes(conn, fname, ts)!=0) {
                return map_nt_error_from_unix(errno);
        }
        if (action != 0) {
@@ -3903,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,
@@ -3932,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,
@@ -4030,6 +4744,12 @@ static NTSTATUS smb_set_file_disposition_info(connection_struct *conn,
        delete_on_close = (CVAL(pdata,0) ? True : False);
        dosmode = dos_mode(conn, fname, psbuf);
 
+       DEBUG(10,("smb_set_file_disposition_info: file %s, dosmode = %u, "
+               "delete_on_close = %u\n",
+               fsp->fsp_name,
+               (unsigned int)dosmode,
+               (unsigned int)delete_on_close ));
+
        status = can_set_delete_on_close(fsp, delete_on_close, dosmode);
  
        if (!NT_STATUS_IS_OK(status)) {
@@ -4104,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. */
@@ -4124,27 +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;
 
-               unix_format(link_target);
                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)) {
@@ -4167,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. */
@@ -4181,12 +4916,19 @@ 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;
        }
 
-       RESOLVE_DFSPATH_STATUS(oldname, conn, inbuf, outbuf);
+       status = resolve_dfspath(ctx, conn,
+                               req->flags2 & FLAGS2_DFS_PATHNAMES,
+                               oldname,
+                               &oldname);
+       if (!NT_STATUS_IS_OK(status)) {
+               return status;
+       }
 
        DEBUG(10,("smb_set_file_unix_hlink: SMB_SET_FILE_UNIX_LINK doing hard link %s -> %s\n",
                fname, oldname));
@@ -4199,39 +4941,52 @@ 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(inbuf, newname, &pdata[12], sizeof(newname), len, 0, &status);
+       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;
        }
 
-       RESOLVE_DFSPATH_STATUS(newname, conn, inbuf, outbuf);
+       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;
+       }
 
        /* Check the new name has no '/' characters. */
        if (strchr_m(newname, '/')) {
@@ -4239,23 +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 = '\0';
+               p[1] = '\0';
+       } else {
+               base_name = talloc_strdup(ctx, "./");
+               if (!base_name) {
+                       return NT_STATUS_NO_MEMORY;
+               }
        }
        /* Append the new name. */
-       pstrcat(base_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);
+                       fname, base_name ));
+               status = rename_internals(ctx, conn, req, fname, base_name, 0,
+                                         overwrite, False, dest_has_wcard);
        }
 
        return status;
@@ -4305,6 +5094,11 @@ static NTSTATUS smb_set_posix_acl(connection_struct *conn,
                return NT_STATUS_INVALID_PARAMETER;
        }
 
+       DEBUG(10,("smb_set_posix_acl: file %s num_file_acls = %u, num_def_acls = %u\n",
+               fname ? fname : fsp->fsp_name,
+               (unsigned int)num_file_acls,
+               (unsigned int)num_def_acls));
+
        if (valid_file_acls && !set_unix_posix_acl(conn, fsp, fname, num_file_acls,
                        pdata + SMB_POSIX_ACL_HEADER_SIZE)) {
                return map_nt_error_from_unix(errno);
@@ -4324,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,
@@ -4386,21 +5180,34 @@ static NTSTATUS smb_set_posix_lock(connection_struct *conn,
        count = (SMB_BIG_UINT)IVAL(pdata,POSIX_LOCK_LEN_OFFSET);
 #endif /* HAVE_LONGLONG */
 
+       DEBUG(10,("smb_set_posix_lock: file %s, lock_type = %u,"
+                       "lock_pid = %u, count = %.0f, offset = %.0f\n",
+               fsp->fsp_name,
+               (unsigned int)lock_type,
+               (unsigned int)lock_pid,
+               (double)count,
+               (double)offset ));
+
        if (lock_type == UNLOCK_LOCK) {
-               status = do_unlock(fsp,
+               status = do_unlock(smbd_messaging_context(),
+                               fsp,
                                lock_pid,
                                count,
                                offset,
                                POSIX_LOCK);
        } else {
-               struct byte_range_lock *br_lck = do_lock(fsp,
+               uint32 block_smbpid;
+
+               struct byte_range_lock *br_lck = do_lock(smbd_messaging_context(),
+                                                       fsp,
                                                        lock_pid,
                                                        count,
                                                        offset,
                                                        lock_type,
                                                        POSIX_LOCK,
                                                        blocking_lock,
-                                                       &status);
+                                                       &status,
+                                                       &block_smbpid);
 
                if (br_lck && blocking_lock && ERROR_WAS_LOCK_DENIED(status)) {
                        /*
@@ -4409,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,
@@ -4417,7 +5224,8 @@ static NTSTATUS smb_set_posix_lock(connection_struct *conn,
                                                lock_type,
                                                POSIX_LOCK,
                                                offset,
-                                               count)) {
+                                               count,
+                                               block_smbpid)) {
                                TALLOC_FREE(br_lck);
                                return status;
                        }
@@ -4439,22 +5247,25 @@ static NTSTATUS smb_set_info_standard(connection_struct *conn,
                                        const char *fname,
                                        const SMB_STRUCT_STAT *psbuf)
 {
-       struct utimbuf tvs;
+       struct timespec ts[2];
 
        if (total_data < 12) {
                return NT_STATUS_INVALID_PARAMETER;
        }
 
        /* access time */
-       tvs.actime = srv_make_unix_date2(pdata+l1_fdateLastAccess);
+       ts[0] = convert_time_t_to_timespec(srv_make_unix_date2(pdata+l1_fdateLastAccess));
        /* write time */
-       tvs.modtime = srv_make_unix_date2(pdata+l1_fdateLastWrite);
+       ts[1] = convert_time_t_to_timespec(srv_make_unix_date2(pdata+l1_fdateLastWrite));
+
+       DEBUG(10,("smb_set_info_standard: file %s\n",
+               fname ? fname : fsp->fsp_name ));
 
        return smb_set_file_time(conn,
                                fsp,
                                fname,
                                psbuf,
-                               tvs);
+                               ts);
 }
 
 /****************************************************************************
@@ -4469,10 +5280,10 @@ static NTSTATUS smb_set_file_basic_info(connection_struct *conn,
                                        SMB_STRUCT_STAT *psbuf)
 {
        /* Patch to do this correctly from Paul Eggert <eggert@twinsun.com>. */
-       time_t write_time;
-       time_t changed_time;
+       struct timespec write_time;
+       struct timespec changed_time;
        uint32 dosmode = 0;
-       struct utimbuf tvs;
+       struct timespec ts[2];
        NTSTATUS status = NT_STATUS_OK;
 
        if (total_data < 36) {
@@ -4492,26 +5303,31 @@ static NTSTATUS smb_set_file_basic_info(connection_struct *conn,
        /* Ignore create time at offset pdata. */
 
        /* access time */
-       tvs.actime = convert_timespec_to_time_t(interpret_long_date(pdata+8));
+       ts[0] = interpret_long_date(pdata+8);
 
-       write_time = convert_timespec_to_time_t(interpret_long_date(pdata+16));
-       changed_time = convert_timespec_to_time_t(interpret_long_date(pdata+24));
+       write_time = interpret_long_date(pdata+16);
+       changed_time = interpret_long_date(pdata+24);
 
-       tvs.modtime = MIN(write_time, changed_time);
+       /* mtime */
+       ts[1] = timespec_min(&write_time, &changed_time);
 
-       if (write_time > tvs.modtime && write_time != (time_t)-1) {
-               tvs.modtime = write_time;
+       if ((timespec_compare(&write_time, &ts[1]) == 1) && !null_timespec(write_time)) {
+               ts[1] = write_time;
        }
+
        /* Prefer a defined time to an undefined one. */
-       if (null_mtime(tvs.modtime)) {
-               tvs.modtime = null_mtime(write_time) ? changed_time : write_time;
+       if (null_timespec(ts[1])) {
+               ts[1] = null_timespec(write_time) ? changed_time : write_time;
        }
 
+       DEBUG(10,("smb_set_file_basic_info: file %s\n",
+               fname ? fname : fsp->fsp_name ));
+
        return smb_set_file_time(conn,
                                fsp,
                                fname,
                                psbuf,
-                               tvs);
+                               ts);
 }
 
 /****************************************************************************
@@ -4519,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,
@@ -4554,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,
@@ -4579,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;
 }
@@ -4599,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,
@@ -4623,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,
@@ -4719,13 +5554,14 @@ 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,
                                        const char *fname,
                                        SMB_STRUCT_STAT *psbuf)
 {
-       struct utimbuf tvs;
+       struct timespec ts[2];
        uint32 raw_unixmode;
        mode_t unixmode;
        SMB_OFF_T size = 0;
@@ -4752,8 +5588,8 @@ static NTSTATUS smb_set_file_unix_basic(connection_struct *conn,
 #endif /* LARGE_SMB_OFF_T */
        }
 
-       tvs.actime = convert_timespec_to_time_t(interpret_long_date(pdata+24)); /* access_time */
-       tvs.modtime = convert_timespec_to_time_t(interpret_long_date(pdata+32)); /* modification_time */
+       ts[0] = interpret_long_date(pdata+24); /* access_time */
+       ts[1] = interpret_long_date(pdata+32); /* modification_time */
        set_owner = (uid_t)IVAL(pdata,40);
        set_grp = (gid_t)IVAL(pdata,48);
        raw_unixmode = IVAL(pdata,84);
@@ -4796,8 +5632,8 @@ size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n",
                /* Ensure we don't try and change anything else. */
                raw_unixmode = SMB_MODE_NO_CHANGE;
                size = get_file_size(*psbuf);
-               tvs.modtime = psbuf->st_mtime;
-               tvs.actime = psbuf->st_atime;
+               ts[0] = get_atimespec(psbuf);
+               ts[1] = get_mtimespec(psbuf);
                /* 
                 * We continue here as we might want to change the 
                 * owner uid/gid.
@@ -4832,9 +5668,18 @@ size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n",
         */
 
        if ((set_owner != (uid_t)SMB_UID_NO_CHANGE) && (psbuf->st_uid != set_owner)) {
-               DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC changing owner %u for file %s\n",
+               int ret;
+
+               DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC changing owner %u for path %s\n",
                        (unsigned int)set_owner, fname ));
-               if (SMB_VFS_CHOWN(conn, fname, set_owner, (gid_t)-1) != 0) {
+
+               if (S_ISLNK(psbuf->st_mode)) {
+                       ret = SMB_VFS_LCHOWN(conn, fname, set_owner, (gid_t)-1);
+               } else {
+                       ret = SMB_VFS_CHOWN(conn, fname, set_owner, (gid_t)-1);
+               }
+
+               if (ret != 0) {
                        status = map_nt_error_from_unix(errno);
                        if (delete_on_fail) {
                                SMB_VFS_UNLINK(conn,fname);
@@ -4861,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,
@@ -4876,7 +5721,69 @@ size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n",
                                fsp,
                                fname,
                                psbuf,
-                               tvs);
+                               ts);
+}
+
+/****************************************************************************
+ Deal with SMB_SET_FILE_UNIX_INFO2.
+****************************************************************************/
+
+static NTSTATUS smb_set_file_unix_info2(connection_struct *conn,
+                                       struct smb_request *req,
+                                       const char *pdata,
+                                       int total_data,
+                                       files_struct *fsp,
+                                       const char *fname,
+                                       SMB_STRUCT_STAT *psbuf)
+{
+       NTSTATUS status;
+       uint32 smb_fflags;
+       uint32 smb_fmask;
+
+       if (total_data < 116) {
+               return NT_STATUS_INVALID_PARAMETER;
+       }
+
+       /* Start by setting all the fields that are common between UNIX_BASIC
+        * and UNIX_INFO2.
+        */
+       status = smb_set_file_unix_basic(conn, req, pdata, total_data,
+                               fsp, fname, psbuf);
+       if (!NT_STATUS_IS_OK(status)) {
+               return status;
+       }
+
+       smb_fflags = IVAL(pdata, 108);
+       smb_fmask = IVAL(pdata, 112);
+
+       /* NB: We should only attempt to alter the file flags if the client
+        * sends a non-zero mask.
+        */
+       if (smb_fmask != 0) {
+               int stat_fflags = 0;
+
+               if (!map_info2_flags_to_sbuf(psbuf, smb_fflags, smb_fmask,
+                           &stat_fflags)) {
+                       /* Client asked to alter a flag we don't understand. */
+                       return NT_STATUS_INVALID_PARAMETER;
+               }
+
+               if (fsp && fsp->fh->fd != -1) {
+                       /* XXX: we should be  using SMB_VFS_FCHFLAGS here. */
+                       return NT_STATUS_NOT_SUPPORTED;
+               } else {
+                       if (SMB_VFS_CHFLAGS(conn, fname, stat_fflags) != 0) {
+                               return map_nt_error_from_unix(errno);
+                       }
+               }
+       }
+
+       /* XXX: need to add support for changing the create_time here. You
+        * can do this for paths on Darwin with setattrlist(2). The right way
+        * to hook this up is probably by extending the VFS utimes interface.
+        */
+
+       return NT_STATUS_OK;
 }
 
 /****************************************************************************
@@ -4884,6 +5791,7 @@ size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n",
 ****************************************************************************/
 
 static NTSTATUS smb_posix_mkdir(connection_struct *conn,
+                               struct smb_request *req,
                                char **ppdata,
                                int total_data,
                                const char *fname,
@@ -4896,13 +5804,16 @@ static NTSTATUS smb_posix_mkdir(connection_struct *conn,
        mode_t unixmode = (mode_t)0;
        files_struct *fsp = NULL;
        uint16 info_level_return = 0;
+       int info;
        char *pdata = *ppdata;
 
-       if (total_data < 10) {
+       if (total_data < 18) {
                return NT_STATUS_INVALID_PARAMETER;
        }
 
        raw_unixmode = IVAL(pdata,8);
+       /* Next 4 bytes are not yet defined. */
+
        status = unix_perms_from_wire(conn, psbuf, raw_unixmode, PERM_NEW_DIR, &unixmode);
        if (!NT_STATUS_IS_OK(status)) {
                return status;
@@ -4910,7 +5821,10 @@ static NTSTATUS smb_posix_mkdir(connection_struct *conn,
 
        mod_unixmode = (uint32)unixmode | FILE_FLAG_POSIX_SEMANTICS;
 
-       status = open_directory(conn,
+       DEBUG(10,("smb_posix_mkdir: file %s, mode 0%o\n",
+               fname, (unsigned int)unixmode ));
+
+       status = open_directory(conn, req,
                                fname,
                                psbuf,
                                FILE_READ_ATTRIBUTES, /* Just a stat open */
@@ -4918,19 +5832,21 @@ static NTSTATUS smb_posix_mkdir(connection_struct *conn,
                                FILE_CREATE,
                                0,
                                mod_unixmode,
-                               NULL,
+                               &info,
                                &fsp);
 
         if (NT_STATUS_IS_OK(status)) {
                 close_file(fsp, NORMAL_CLOSE);
         }
 
-       info_level_return = SVAL(pdata,12);
+       info_level_return = SVAL(pdata,16);
  
        if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
-               *pdata_return_size = 8 + SMB_FILE_UNIX_BASIC_SIZE;
+               *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
+       } else if (info_level_return ==  SMB_QUERY_FILE_UNIX_INFO2) {
+               *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
        } else {
-               *pdata_return_size = 8;
+               *pdata_return_size = 12;
        }
 
        /* Realloc the data size */
@@ -4939,17 +5855,27 @@ static NTSTATUS smb_posix_mkdir(connection_struct *conn,
                *pdata_return_size = 0;
                return NT_STATUS_NO_MEMORY;
        }
+       pdata = *ppdata;
 
        SSVAL(pdata,0,NO_OPLOCK_RETURN);
-       SSVAL(pdata,2,0);
+       SSVAL(pdata,2,0); /* No fnum. */
+       SIVAL(pdata,4,info); /* Was directory created. */
 
-       if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
-               SSVAL(pdata,4,SMB_QUERY_FILE_UNIX_BASIC);
-               SSVAL(pdata,6,0); /* Padding. */
-               store_file_unix_basic(conn, pdata + 8, fsp, psbuf);
-       } else {
-               SSVAL(pdata,4,SMB_NO_INFO_LEVEL_RETURNED);
-               SSVAL(pdata,6,0); /* Padding. */
+       switch (info_level_return) {
+               case SMB_QUERY_FILE_UNIX_BASIC:
+                       SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
+                       SSVAL(pdata,10,0); /* Padding. */
+                       store_file_unix_basic(conn, pdata + 12, fsp, psbuf);
+                       break;
+               case SMB_QUERY_FILE_UNIX_INFO2:
+                       SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
+                       SSVAL(pdata,10,0); /* Padding. */
+                       store_file_unix_basic_info2(conn, pdata + 12, fsp, psbuf);
+                       break;
+               default:
+                       SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
+                       SSVAL(pdata,10,0); /* Padding. */
+                       break;
        }
 
        return status;
@@ -4960,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,
@@ -4982,7 +5909,7 @@ static NTSTATUS smb_posix_open(connection_struct *conn,
        int info = 0;
        uint16 info_level_return = 0;
 
-       if (total_data < 14) {
+       if (total_data < 18) {
                return NT_STATUS_INVALID_PARAMETER;
        }
 
@@ -4995,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,
@@ -5034,6 +5961,8 @@ static NTSTATUS smb_posix_open(connection_struct *conn,
        }
 
        raw_unixmode = IVAL(pdata,8);
+       /* Next 4 bytes are not yet defined. */
+
        status = unix_perms_from_wire(conn,
                                psbuf,
                                raw_unixmode,
@@ -5056,7 +5985,12 @@ static NTSTATUS smb_posix_open(connection_struct *conn,
                mod_unixmode |= FILE_FLAG_NO_BUFFERING;
        }
 
-       status = open_file_ntcreate(conn,
+       DEBUG(10,("smb_posix_open: file %s, smb_posix_flags = %u, mode 0%o\n",
+               fname,
+               (unsigned int)wire_open_mode,
+               (unsigned int)unixmode ));
+
+       status = open_file_ntcreate(conn, req,
                                fname,
                                psbuf,
                                access_mask,
@@ -5080,12 +6014,16 @@ static NTSTATUS smb_posix_open(connection_struct *conn,
                extended_oplock_granted = True;
        }
 
-       info_level_return = SVAL(pdata,12);
+       info_level_return = SVAL(pdata,16);
  
+       /* Allocate the correct return size. */
+
        if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
-               *pdata_return_size = 8 + SMB_FILE_UNIX_BASIC_SIZE;
+               *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
+       } else if (info_level_return ==  SMB_QUERY_FILE_UNIX_INFO2) {
+               *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
        } else {
-               *pdata_return_size = 8;
+               *pdata_return_size = 12;
        }
 
        /* Realloc the data size */
@@ -5095,6 +6033,7 @@ static NTSTATUS smb_posix_open(connection_struct *conn,
                *pdata_return_size = 0;
                return NT_STATUS_NO_MEMORY;
        }
+       pdata = *ppdata;
 
        if (extended_oplock_granted) {
                if (flags & REQUEST_BATCH_OPLOCK) {
@@ -5109,13 +6048,23 @@ static NTSTATUS smb_posix_open(connection_struct *conn,
        }
 
        SSVAL(pdata,2,fsp->fnum);
-       if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
-               SSVAL(pdata,4,SMB_QUERY_FILE_UNIX_BASIC);
-               SSVAL(pdata,6,0); /* padding. */
-               store_file_unix_basic(conn, pdata + 8, fsp, psbuf);
-       } else {
-               SSVAL(pdata,4,SMB_NO_INFO_LEVEL_RETURNED);
-               SSVAL(pdata,6,0); /* padding. */
+       SIVAL(pdata,4,info); /* Was file created etc. */
+
+       switch (info_level_return) {
+               case SMB_QUERY_FILE_UNIX_BASIC:
+                       SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
+                       SSVAL(pdata,10,0); /* padding. */
+                       store_file_unix_basic(conn, pdata + 12, fsp, psbuf);
+                       break;
+               case SMB_QUERY_FILE_UNIX_INFO2:
+                       SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
+                       SSVAL(pdata,10,0); /* padding. */
+                       store_file_unix_basic_info2(conn, pdata + 12, fsp, psbuf);
+                       break;
+               default:
+                       SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
+                       SSVAL(pdata,10,0); /* padding. */
+                       break;
        }
        return NT_STATUS_OK;
 }
@@ -5125,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,
@@ -5133,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;
@@ -5150,27 +6103,32 @@ static NTSTATUS smb_posix_unlink(connection_struct *conn,
                return NT_STATUS_NOT_A_DIRECTORY;
        }
 
+       DEBUG(10,("smb_posix_unlink: %s %s\n",
+               (flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) ? "directory" : "file",
+               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 {
-               status = open_file_ntcreate(conn,
+
+               status = open_file_ntcreate(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,
-                               INTERNAL_OPEN_ONLY,
+                               0, /* No oplock, but break existing ones. */
                                &info,
                                &fsp);
        }
@@ -5178,6 +6136,54 @@ static NTSTATUS smb_posix_unlink(connection_struct *conn,
        if (!NT_STATUS_IS_OK(status)) {
                return status;
        }
+
+       /*
+        * 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);
 }
 
@@ -5185,46 +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(SVAL(params,0));
+               /* Basic check for non-null fsp. */
+               if (!check_fsp_open(conn, req, fsp, &current_user)) {
+                       return;
                }
+               info_level = SVAL(params,2);
 
-               fsp = file_fsp(params,0);
-               info_level = SVAL(params,2);    
+               fname = talloc_strdup(talloc_tos(),fsp->fsp_name);
+               if (!fname) {
+                       reply_nterror(req, NT_STATUS_NO_MEMORY);
+                       return;
+               }
 
-               if(fsp && (fsp->is_directory || fsp->fh->fd == -1)) {
+               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 (SMB_VFS_STAT(conn,fname,&sbuf) != 0) {
-                               DEBUG(3,("call_trans2setfilepathinfo: fileinfo of %s failed (%s)\n",fname,strerror(errno)));
-                               return UNIXERROR(ERRDOS,ERRbadpath);
+                       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)));
+                                       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)));
+                                       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.
                         */
@@ -5232,66 +6262,96 @@ 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(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;
                }
 
-               RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
-
-               status = unix_convert(conn, fname, False, NULL, &sbuf);
+               status = resolve_dfspath(ctx, conn,
+                                        req->flags2 & FLAGS2_DFS_PATHNAMES,
+                                        fname,
+                                        &fname);
                if (!NT_STATUS_IS_OK(status)) {
-                       return ERROR_NT(status);
+                       if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
+                               reply_botherror(req,
+                                               NT_STATUS_PATH_NOT_COVERED,
+                                               ERRSRV, ERRbadpath);
+                               return;
+                       }
+                       reply_nterror(req, status);
+                       return;
                }
 
-               /*
-                * For CIFS UNIX extensions the target name may not exist.
-                */
-
-               if(!VALID_STAT(sbuf) && !INFO_LEVEL_IS_UNIX(info_level)) {
-                       DEBUG(3,("call_trans2setfilepathinfo: stat of %s failed (%s)\n", fname, strerror(errno)));
-                       return UNIXERROR(ERRDOS,ERRbadpath);
-               }    
+               status = unix_convert(conn, fname, False, &fname, NULL, &sbuf);
+               if (!NT_STATUS_IS_OK(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)) {
+                       /*
+                        * For CIFS UNIX extensions the target name may not exist.
+                        */
+
+                       /* Always do lstat for UNIX calls. */
+                       SMB_VFS_LSTAT(conn,fname,&sbuf);
+
+               } 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)));
+                       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",
@@ -5300,15 +6360,16 @@ 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;
 
        SSVAL(params,0,0);
 
-       if (fsp && fsp->pending_modtime) {
+       if (fsp && !null_timespec(fsp->pending_modtime)) {
                /* the pending modtime overrides the current modtime */
-               sbuf.st_mtime = fsp->pending_modtime;
+               set_mtimespec(&sbuf, fsp->pending_modtime);
        }
 
        switch (info_level) {
@@ -5349,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,
@@ -5361,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,
@@ -5420,7 +6481,18 @@ 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,
+                                                       fname,
+                                                       &sbuf);
+                       break;
+               }
+
+               case SMB_SET_FILE_UNIX_INFO2:
+               {
+                       status = smb_set_file_unix_info2(conn, req,
                                                        pdata,
                                                        total_data,
                                                        fsp,
@@ -5433,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;
                }
 
@@ -5447,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;
                }
 
@@ -5486,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;
                }
 
@@ -5501,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,
@@ -5517,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,
@@ -5529,68 +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(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)));
+               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;
        }
 
        /*
@@ -5601,56 +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);
-       }
-
-       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, 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(outbuf, bufsize, params, 2, *ppdata, 0, max_data_bytes);
+       send_trans2_replies(req, params, 2, *ppdata, 0, max_data_bytes);
   
-       return(-1);
+       return;
 }
 
 /****************************************************************************
@@ -5658,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);
@@ -5678,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;
 
@@ -5697,9 +6794,9 @@ static int call_trans2findnotifyfirst(connection_struct *conn, char *inbuf, char
        if(fnf_handle == 0)
                fnf_handle = 257;
 
-       send_trans2_replies(outbuf, bufsize, params, 6, *ppdata, 0, max_data_bytes);
+       send_trans2_replies(req, params, 6, *ppdata, 0, max_data_bytes);
   
-       return(-1);
+       return;
 }
 
 /****************************************************************************
@@ -5707,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;
 
@@ -5718,50 +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(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)) < 0)
-               return UNIXERROR(ERRDOS,ERRbadfile);
-    
-       SSVAL(outbuf,smb_flg2,SVAL(outbuf,smb_flg2) | FLAGS2_DFS_PATHNAMES);
-       send_trans2_replies(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
@@ -5771,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;
 
@@ -5795,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(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(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));
 
@@ -5847,22 +6985,20 @@ int reply_findnclose(connection_struct *conn,
           findnotifyfirst - so any dptr_num is ok here. 
           Just ignore it. */
 
-       outsize = set_message(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 */
@@ -5870,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;
        }
@@ -5882,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;
        }
@@ -5894,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;
        }
@@ -5906,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;
        }
@@ -5918,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;
        }
@@ -5931,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;
        }
@@ -5944,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;
        }
@@ -5956,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;
        }
@@ -5968,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;
        }
@@ -5980,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;
        }
@@ -5992,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;
        }
@@ -6004,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;
        }
@@ -6016,65 +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_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;
 
@@ -6089,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;
                }
        }
 
@@ -6113,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) {
@@ -6134,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;
@@ -6152,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(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:
 
@@ -6177,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);
 }
 
 
@@ -6185,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;
@@ -6238,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);
        }
 
@@ -6255,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:
 
@@ -6298,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;
 }