Remove redundant parameter fd from SMB_VFS_LSEEK().
[ira/wip.git] / source / smbd / reply.c
index 30b90a6459155a0f46f5a0f81cb0ff5d2ec6774b..910e3a27a6b9c55ebb8c8a3ae2d64440630676b2 100644 (file)
@@ -1,4 +1,4 @@
-/* 
+/*
    Unix SMB/CIFS implementation.
    Main SMB reply routines
    Copyright (C) Andrew Tridgell 1992-1998
    it under the terms of the GNU General Public License as published by
    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, see <http://www.gnu.org/licenses/>.
 */
@@ -33,7 +33,7 @@ unsigned int smb_echo_count = 0;
 extern uint32 global_client_caps;
 
 extern struct current_user current_user;
-extern BOOL global_encrypted_passwords_negotiated;
+extern bool global_encrypted_passwords_negotiated;
 
 /****************************************************************************
  Ensure we check the path in *exactly* the same way as W2K for a findfirst/findnext
@@ -47,13 +47,13 @@ extern BOOL global_encrypted_passwords_negotiated;
 #define IS_PATH_SEP(c,posix_only) ((c) == '/' || (!(posix_only) && (c) == '\\'))
 
 static NTSTATUS check_path_syntax_internal(char *path,
-                                          BOOL posix_path,
-                                          BOOL *p_last_component_contains_wcard)
+                                          bool posix_path,
+                                          bool *p_last_component_contains_wcard)
 {
        char *d = path;
        const char *s = path;
        NTSTATUS ret = NT_STATUS_OK;
-       BOOL start_of_name_component = True;
+       bool start_of_name_component = True;
 
        *p_last_component_contains_wcard = False;
 
@@ -177,7 +177,7 @@ static NTSTATUS check_path_syntax_internal(char *path,
 
 NTSTATUS check_path_syntax(char *path)
 {
-       BOOL ignore;
+       bool ignore;
        return check_path_syntax_internal(path, False, &ignore);
 }
 
@@ -187,7 +187,7 @@ NTSTATUS check_path_syntax(char *path)
  a wildcard.
 ****************************************************************************/
 
-NTSTATUS check_path_syntax_wcard(char *path, BOOL *p_contains_wcard)
+NTSTATUS check_path_syntax_wcard(char *path, bool *p_contains_wcard)
 {
        return check_path_syntax_internal(path, False, p_contains_wcard);
 }
@@ -200,7 +200,7 @@ NTSTATUS check_path_syntax_wcard(char *path, BOOL *p_contains_wcard)
 
 NTSTATUS check_path_syntax_posix(char *path)
 {
-       BOOL ignore;
+       bool ignore;
        return check_path_syntax_internal(path, True, &ignore);
 }
 
@@ -208,27 +208,46 @@ NTSTATUS check_path_syntax_posix(char *path)
  Pull a string and check the path allowing a wilcard - provide for error return.
 ****************************************************************************/
 
-size_t srvstr_get_path_wcard(const char *inbuf, uint16 smb_flags2, char *dest,
-                            const char *src, size_t dest_len, size_t src_len,
-                            int flags, NTSTATUS *err, BOOL *contains_wcard)
+size_t srvstr_get_path_wcard(TALLOC_CTX *ctx,
+                       const char *inbuf,
+                       uint16 smb_flags2,
+                       char **pp_dest,
+                       const char *src,
+                       size_t src_len,
+                       int flags,
+                       NTSTATUS *err,
+                       bool *contains_wcard)
 {
        size_t ret;
-#ifdef DEVELOPER
-       SMB_ASSERT(dest_len == sizeof(pstring));
-#endif
+
+       *pp_dest = NULL;
 
        if (src_len == 0) {
-               ret = srvstr_pull_buf(inbuf, smb_flags2, dest, src,
-                                     dest_len, flags);
+               ret = srvstr_pull_buf_talloc(ctx,
+                               inbuf,
+                               smb_flags2,
+                               pp_dest,
+                               src,
+                               flags);
        } else {
-               ret = srvstr_pull(inbuf, smb_flags2, dest, src,
-                                 dest_len, src_len, flags);
+               ret = srvstr_pull_talloc(ctx,
+                               inbuf,
+                               smb_flags2,
+                               pp_dest,
+                               src,
+                               src_len,
+                               flags);
+       }
+
+       if (!*pp_dest) {
+               *err = NT_STATUS_INVALID_PARAMETER;
+               return ret;
        }
 
        *contains_wcard = False;
 
        if (smb_flags2 & FLAGS2_DFS_PATHNAMES) {
-               /* 
+               /*
                 * For a DFS path the function parse_dfs_path()
                 * will do the path processing, just make a copy.
                 */
@@ -237,9 +256,9 @@ size_t srvstr_get_path_wcard(const char *inbuf, uint16 smb_flags2, char *dest,
        }
 
        if (lp_posix_pathnames()) {
-               *err = check_path_syntax_posix(dest);
+               *err = check_path_syntax_posix(*pp_dest);
        } else {
-               *err = check_path_syntax_wcard(dest, contains_wcard);
+               *err = check_path_syntax_wcard(*pp_dest, contains_wcard);
        }
 
        return ret;
@@ -249,25 +268,43 @@ size_t srvstr_get_path_wcard(const char *inbuf, uint16 smb_flags2, char *dest,
  Pull a string and check the path - provide for error return.
 ****************************************************************************/
 
-size_t srvstr_get_path(const char *inbuf, uint16 smb_flags2, char *dest,
-                      const char *src, size_t dest_len, size_t src_len,
-                      int flags, NTSTATUS *err)
+size_t srvstr_get_path(TALLOC_CTX *ctx,
+                       const char *inbuf,
+                       uint16 smb_flags2,
+                       char **pp_dest,
+                       const char *src,
+                       size_t src_len,
+                       int flags,
+                       NTSTATUS *err)
 {
        size_t ret;
-#ifdef DEVELOPER
-       SMB_ASSERT(dest_len == sizeof(pstring));
-#endif
+
+       *pp_dest = NULL;
 
        if (src_len == 0) {
-               ret = srvstr_pull_buf(inbuf, smb_flags2, dest, src,
-                                     dest_len, flags);
+               ret = srvstr_pull_buf_talloc(ctx,
+                                       inbuf,
+                                       smb_flags2,
+                                       pp_dest,
+                                       src,
+                                       flags);
        } else {
-               ret = srvstr_pull(inbuf, smb_flags2, dest, src,
-                                 dest_len, src_len, flags);
+               ret = srvstr_pull_talloc(ctx,
+                               inbuf,
+                               smb_flags2,
+                               pp_dest,
+                               src,
+                               src_len,
+                               flags);
+       }
+
+       if (!*pp_dest) {
+               *err = NT_STATUS_INVALID_PARAMETER;
+               return ret;
        }
 
        if (smb_flags2 & FLAGS2_DFS_PATHNAMES) {
-               /* 
+               /*
                 * For a DFS path the function parse_dfs_path()
                 * will do the path processing, just make a copy.
                 */
@@ -276,29 +313,43 @@ size_t srvstr_get_path(const char *inbuf, uint16 smb_flags2, char *dest,
        }
 
        if (lp_posix_pathnames()) {
-               *err = check_path_syntax_posix(dest);
+               *err = check_path_syntax_posix(*pp_dest);
        } else {
-               *err = check_path_syntax(dest);
+               *err = check_path_syntax(*pp_dest);
        }
 
        return ret;
 }
 
 /****************************************************************************
- Check if we have a correct fsp pointing to a file. Replacement for the
- CHECK_FSP macro.
+ Check if we have a correct fsp pointing to a file. Basic check for open fsp.
 ****************************************************************************/
-BOOL check_fsp(connection_struct *conn, struct smb_request *req,
+
+bool check_fsp_open(connection_struct *conn, struct smb_request *req,
               files_struct *fsp, struct current_user *user)
 {
        if (!(fsp) || !(conn)) {
                reply_nterror(req, NT_STATUS_INVALID_HANDLE);
                return False;
        }
-       if (((conn) != (fsp)->conn) || current_user.vuid != (fsp)->vuid) {
+       if (((conn) != (fsp)->conn) || user->vuid != (fsp)->vuid) {
                reply_nterror(req, NT_STATUS_INVALID_HANDLE);
                return False;
        }
+       return True;
+}
+
+/****************************************************************************
+ Check if we have a correct fsp pointing to a file. Replacement for the
+ CHECK_FSP macro.
+****************************************************************************/
+
+bool check_fsp(connection_struct *conn, struct smb_request *req,
+              files_struct *fsp, struct current_user *user)
+{
+       if (!check_fsp_open(conn, req, fsp, user)) {
+               return False;
+       }
        if ((fsp)->is_directory) {
                reply_nterror(req, NT_STATUS_INVALID_DEVICE_REQUEST);
                return False;
@@ -311,6 +362,22 @@ BOOL check_fsp(connection_struct *conn, struct smb_request *req,
        return True;
 }
 
+/****************************************************************************
+ Check if we have a correct fsp. Replacement for the FSP_BELONGS_CONN macro
+****************************************************************************/
+
+bool fsp_belongs_conn(connection_struct *conn, struct smb_request *req,
+                     files_struct *fsp, struct current_user *user)
+{
+       if ((fsp) && (conn) && ((conn)==(fsp)->conn)
+           && (current_user.vuid==(fsp)->vuid)) {
+               return True;
+       }
+
+       reply_nterror(req, NT_STATUS_INVALID_HANDLE);
+       return False;
+}
+
 /****************************************************************************
  Reply to a (netbios-level) special message.
 ****************************************************************************/
@@ -324,18 +391,18 @@ void reply_special(char *inbuf)
 
        /*
         * We only really use 4 bytes of the outbuf, but for the smb_setlen
-        * calculation & friends (send_smb uses that) we need the full smb
+        * calculation & friends (srv_send_smb uses that) we need the full smb
         * header.
         */
        char outbuf[smb_size];
        
-       static BOOL already_got_session = False;
+       static bool already_got_session = False;
 
        *name1 = *name2 = 0;
        
        memset(outbuf, '\0', sizeof(outbuf));
 
-       smb_setlen(inbuf,outbuf,0);
+       smb_setlen(outbuf,0);
        
        switch (msg_type) {
        case 0x81: /* session request */
@@ -403,7 +470,7 @@ void reply_special(char *inbuf)
        DEBUG(5,("init msg_type=0x%x msg_flags=0x%x\n",
                    msg_type, msg_flags));
 
-       send_smb(smbd_server_fd(), outbuf);
+       srv_send_smb(smbd_server_fd(), outbuf, false);
        return;
 }
 
@@ -412,42 +479,40 @@ void reply_special(char *inbuf)
  conn POINTER CAN BE NULL HERE !
 ****************************************************************************/
 
-int reply_tcon(connection_struct *conn,
-              char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
+void reply_tcon(struct smb_request *req)
 {
-       TALLOC_CTX *ctx;
+       connection_struct *conn = req->conn;
        const char *service;
        char *service_buf = NULL;
        char *password = NULL;
        char *dev = NULL;
-       int outsize = 0;
-       uint16 vuid = SVAL(inbuf,smb_uid);
        int pwlen=0;
        NTSTATUS nt_status;
        char *p;
        DATA_BLOB password_blob;
+       TALLOC_CTX *ctx = talloc_tos();
 
        START_PROFILE(SMBtcon);
 
-       ctx = talloc_init("reply_tcon");
-       if (!ctx) {
+       if (smb_buflen(req->inbuf) < 4) {
+               reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
                END_PROFILE(SMBtcon);
-               return ERROR_NT(NT_STATUS_NO_MEMORY);
+               return;
        }
 
-       p = smb_buf(inbuf)+1;
-       p += srvstr_pull_buf_talloc(ctx, inbuf, SVAL(inbuf, smb_flg2),
-                       &service_buf, p, STR_TERMINATE) + 1;
-       pwlen = srvstr_pull_buf_talloc(ctx, inbuf, SVAL(inbuf, smb_flg2),
-                       &password, p, STR_TERMINATE) + 1;
+       p = smb_buf(req->inbuf)+1;
+       p += srvstr_pull_buf_talloc(ctx, req->inbuf, req->flags2,
+                                   &service_buf, p, STR_TERMINATE) + 1;
+       pwlen = srvstr_pull_buf_talloc(ctx, req->inbuf, req->flags2,
+                                      &password, p, STR_TERMINATE) + 1;
        p += pwlen;
-       p += srvstr_pull_buf_talloc(ctx, inbuf, SVAL(inbuf, smb_flg2),
-                       &dev, p, STR_TERMINATE) + 1;
+       p += srvstr_pull_buf_talloc(ctx, req->inbuf, req->flags2,
+                                   &dev, p, STR_TERMINATE) + 1;
 
        if (service_buf == NULL || password == NULL || dev == NULL) {
-               TALLOC_FREE(ctx);
+               reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
                END_PROFILE(SMBtcon);
-               return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
+               return;
        }
        p = strrchr_m(service_buf,'\\');
        if (p) {
@@ -458,27 +523,27 @@ int reply_tcon(connection_struct *conn,
 
        password_blob = data_blob(password, pwlen+1);
 
-       conn = make_connection(service,password_blob,dev,vuid,&nt_status);
+       conn = make_connection(service,password_blob,dev,req->vuid,&nt_status);
+       req->conn = conn;
 
        data_blob_clear_free(&password_blob);
 
        if (!conn) {
-               TALLOC_FREE(ctx);
+               reply_nterror(req, nt_status);
                END_PROFILE(SMBtcon);
-               return ERROR_NT(nt_status);
+               return;
        }
 
-       outsize = set_message(inbuf,outbuf,2,0,True);
-       SSVAL(outbuf,smb_vwv0,max_recv);
-       SSVAL(outbuf,smb_vwv1,conn->cnum);
-       SSVAL(outbuf,smb_tid,conn->cnum);
+       reply_outbuf(req, 2, 0);
+       SSVAL(req->outbuf,smb_vwv0,max_recv);
+       SSVAL(req->outbuf,smb_vwv1,conn->cnum);
+       SSVAL(req->outbuf,smb_tid,conn->cnum);
 
-       DEBUG(3,("tcon service=%s cnum=%d\n", 
+       DEBUG(3,("tcon service=%s cnum=%d\n",
                 service, conn->cnum));
 
        END_PROFILE(SMBtcon);
-       TALLOC_FREE(ctx);
-       return(outsize);
+       return;
 }
 
 /****************************************************************************
@@ -486,12 +551,12 @@ int reply_tcon(connection_struct *conn,
  conn POINTER CAN BE NULL HERE !
 ****************************************************************************/
 
-void reply_tcon_and_X(connection_struct *conn, struct smb_request *req)
+void reply_tcon_and_X(struct smb_request *req)
 {
+       connection_struct *conn = req->conn;
        char *service = NULL;
        DATA_BLOB password;
-
-       TALLOC_CTX *ctx = NULL;
+       TALLOC_CTX *ctx = talloc_tos();
        /* what the cleint thinks the device is */
        char *client_devicetype = NULL;
        /* what the server tells the client the share represents */
@@ -516,6 +581,8 @@ void reply_tcon_and_X(connection_struct *conn, struct smb_request *req)
        /* we might have to close an old one */
        if ((tcon_flags & 0x1) && conn) {
                close_cnum(conn,req->vuid);
+               req->conn = NULL;
+               conn = NULL;
        }
 
        if ((passlen > MAX_PASS_LEN) || (passlen >= smb_buflen(req->inbuf))) {
@@ -542,19 +609,11 @@ void reply_tcon_and_X(connection_struct *conn, struct smb_request *req)
                p = smb_buf(req->inbuf) + passlen + 1;
        }
 
-       ctx = talloc_init("reply_tcon_and_X");
-       if (!ctx) {
-               data_blob_clear_free(&password);
-               reply_nterror(req, NT_STATUS_NO_MEMORY);
-               END_PROFILE(SMBtconX);
-               return;
-       }
        p += srvstr_pull_buf_talloc(ctx, req->inbuf, req->flags2, &path, p,
                             STR_TERMINATE);
 
        if (path == NULL) {
                data_blob_clear_free(&password);
-               TALLOC_FREE(ctx);
                reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
                END_PROFILE(SMBtconX);
                return;
@@ -568,7 +627,6 @@ void reply_tcon_and_X(connection_struct *conn, struct smb_request *req)
                q = strchr_m(path+2,'\\');
                if (!q) {
                        data_blob_clear_free(&password);
-                       TALLOC_FREE(ctx);
                        reply_doserror(req, ERRDOS, ERRnosuchshare);
                        END_PROFILE(SMBtconX);
                        return;
@@ -584,7 +642,6 @@ void reply_tcon_and_X(connection_struct *conn, struct smb_request *req)
 
        if (client_devicetype == NULL) {
                data_blob_clear_free(&password);
-               TALLOC_FREE(ctx);
                reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
                END_PROFILE(SMBtconX);
                return;
@@ -594,11 +651,11 @@ void reply_tcon_and_X(connection_struct *conn, struct smb_request *req)
 
        conn = make_connection(service, password, client_devicetype,
                               req->vuid, &nt_status);
+       req->conn =conn;
 
        data_blob_clear_free(&password);
 
        if (!conn) {
-               TALLOC_FREE(ctx);
                reply_nterror(req, nt_status);
                END_PROFILE(SMBtconX);
                return;
@@ -615,7 +672,6 @@ void reply_tcon_and_X(connection_struct *conn, struct smb_request *req)
                reply_outbuf(req, 2, 0);
                if (message_push_string(&req->outbuf, server_devicetype,
                                        STR_TERMINATE|STR_ASCII) == -1) {
-                       TALLOC_FREE(ctx);
                        reply_nterror(req, NT_STATUS_NO_MEMORY);
                        END_PROFILE(SMBtconX);
                        return;
@@ -650,7 +706,6 @@ void reply_tcon_and_X(connection_struct *conn, struct smb_request *req)
                                         STR_TERMINATE|STR_ASCII) == -1)
                    || (message_push_string(&req->outbuf, fstype,
                                            STR_TERMINATE) == -1)) {
-                       TALLOC_FREE(ctx);
                        reply_nterror(req, NT_STATUS_NO_MEMORY);
                        END_PROFILE(SMBtconX);
                        return;
@@ -672,10 +727,9 @@ void reply_tcon_and_X(connection_struct *conn, struct smb_request *req)
        SSVAL(req->inbuf,smb_tid,conn->cnum);
        SSVAL(req->outbuf,smb_tid,conn->cnum);
 
-       TALLOC_FREE(ctx);
        END_PROFILE(SMBtconX);
 
-       chain_reply_new(req);
+       chain_reply(req);
        return;
 }
 
@@ -683,17 +737,6 @@ void reply_tcon_and_X(connection_struct *conn, struct smb_request *req)
  Reply to an unknown type.
 ****************************************************************************/
 
-int reply_unknown(char *inbuf,char *outbuf)
-{
-       int type;
-       type = CVAL(inbuf,smb_com);
-  
-       DEBUG(0,("unknown command type (%s): type=%d (0x%X)\n",
-                smb_fn_name(type), type, type));
-  
-       return(ERROR_DOS(ERRSRV,ERRunknownsmb));
-}
-
 void reply_unknown_new(struct smb_request *req, uint8 type)
 {
        DEBUG(0, ("unknown command type (%s): type=%d (0x%X)\n",
@@ -707,56 +750,74 @@ void reply_unknown_new(struct smb_request *req, uint8 type)
  conn POINTER CAN BE NULL HERE !
 ****************************************************************************/
 
-int reply_ioctl(connection_struct *conn,
-               char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
+void reply_ioctl(struct smb_request *req)
 {
-       uint16 device     = SVAL(inbuf,smb_vwv1);
-       uint16 function   = SVAL(inbuf,smb_vwv2);
-       uint32 ioctl_code = (device << 16) + function;
-       int replysize, outsize;
+       connection_struct *conn = req->conn;
+       uint16 device;
+       uint16 function;
+       uint32 ioctl_code;
+       int replysize;
        char *p;
+
        START_PROFILE(SMBioctl);
 
+       if (req->wct < 3) {
+               reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
+               END_PROFILE(SMBioctl);
+               return;
+       }
+
+       device     = SVAL(req->inbuf,smb_vwv1);
+       function   = SVAL(req->inbuf,smb_vwv2);
+       ioctl_code = (device << 16) + function;
+
        DEBUG(4, ("Received IOCTL (code 0x%x)\n", ioctl_code));
 
        switch (ioctl_code) {
            case IOCTL_QUERY_JOB_INFO:
-               replysize = 32;
-               break;
+                   replysize = 32;
+                   break;
            default:
-               END_PROFILE(SMBioctl);
-               return(ERROR_DOS(ERRSRV,ERRnosupport));
+                   reply_doserror(req, ERRSRV, ERRnosupport);
+                   END_PROFILE(SMBioctl);
+                   return;
        }
 
-       outsize = set_message(inbuf,outbuf,8,replysize+1,True);
-       SSVAL(outbuf,smb_vwv1,replysize); /* Total data bytes returned */
-       SSVAL(outbuf,smb_vwv5,replysize); /* Data bytes this buffer */
-       SSVAL(outbuf,smb_vwv6,52);        /* Offset to data */
-       p = smb_buf(outbuf) + 1;          /* Allow for alignment */
+       reply_outbuf(req, 8, replysize+1);
+       SSVAL(req->outbuf,smb_vwv1,replysize); /* Total data bytes returned */
+       SSVAL(req->outbuf,smb_vwv5,replysize); /* Data bytes this buffer */
+       SSVAL(req->outbuf,smb_vwv6,52);        /* Offset to data */
+       p = smb_buf(req->outbuf);
+       memset(p, '\0', replysize+1); /* valgrind-safe. */
+       p += 1;          /* Allow for alignment */
 
        switch (ioctl_code) {
                case IOCTL_QUERY_JOB_INFO:                  
                {
-                       files_struct *fsp = file_fsp(SVAL(inbuf,smb_vwv0));
+                       files_struct *fsp = file_fsp(SVAL(req->inbuf,
+                                                         smb_vwv0));
                        if (!fsp) {
+                               reply_doserror(req, ERRDOS, ERRbadfid);
                                END_PROFILE(SMBioctl);
-                               return(UNIXERROR(ERRDOS,ERRbadfid));
+                               return;
                        }
                        SSVAL(p,0,fsp->rap_print_jobid);             /* Job number */
-                       srvstr_push(outbuf, SVAL(outbuf, smb_flg2), p+2,
+                       srvstr_push((char *)req->outbuf, req->flags2, p+2,
                                    global_myname(), 15,
                                    STR_TERMINATE|STR_ASCII);
                        if (conn) {
-                               srvstr_push(outbuf, SVAL(outbuf, smb_flg2),
+                               srvstr_push((char *)req->outbuf, req->flags2,
                                            p+18, lp_servicename(SNUM(conn)),
                                            13, STR_TERMINATE|STR_ASCII);
+                       } else {
+                               memset(p+18, 0, 13);
                        }
                        break;
                }
        }
 
        END_PROFILE(SMBioctl);
-       return outsize;
+       return;
 }
 
 /****************************************************************************
@@ -774,21 +835,23 @@ static NTSTATUS map_checkpath_error(const char *inbuf, NTSTATUS status)
        }
        return status;
 }
-       
+
 /****************************************************************************
  Reply to a checkpath.
 ****************************************************************************/
 
-void reply_checkpath(connection_struct *conn, struct smb_request *req)
+void reply_checkpath(struct smb_request *req)
 {
-       pstring name;
+       connection_struct *conn = req->conn;
+       char *name = NULL;
        SMB_STRUCT_STAT sbuf;
        NTSTATUS status;
+       TALLOC_CTX *ctx = talloc_tos();
 
        START_PROFILE(SMBcheckpath);
 
-       srvstr_get_path((char *)req->inbuf, req->flags2, name,
-                       smb_buf(req->inbuf) + 1, sizeof(name), 0,
+       srvstr_get_path(ctx,(char *)req->inbuf, req->flags2, &name,
+                       smb_buf(req->inbuf) + 1, 0,
                        STR_TERMINATE, &status);
        if (!NT_STATUS_IS_OK(status)) {
                status = map_checkpath_error((char *)req->inbuf, status);
@@ -797,7 +860,10 @@ void reply_checkpath(connection_struct *conn, struct smb_request *req)
                return;
        }
 
-       status = resolve_dfspath(conn, req->flags2 & FLAGS2_DFS_PATHNAMES, name);
+       status = resolve_dfspath(ctx, conn,
+                       req->flags2 & FLAGS2_DFS_PATHNAMES,
+                       name,
+                       &name);
        if (!NT_STATUS_IS_OK(status)) {
                if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
                        reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
@@ -810,7 +876,7 @@ void reply_checkpath(connection_struct *conn, struct smb_request *req)
 
        DEBUG(3,("reply_checkpath %s mode=%d\n", name, (int)SVAL(req->inbuf,smb_vwv0)));
 
-       status = unix_convert(conn, name, False, NULL, &sbuf);
+       status = unix_convert(ctx, conn, name, False, &name, NULL, &sbuf);
        if (!NT_STATUS_IS_OK(status)) {
                goto path_err;
        }
@@ -869,36 +935,45 @@ void reply_checkpath(connection_struct *conn, struct smb_request *req)
  Reply to a getatr.
 ****************************************************************************/
 
-int reply_getatr(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
+void reply_getatr(struct smb_request *req)
 {
-       pstring fname;
-       int outsize = 0;
+       connection_struct *conn = req->conn;
+       char *fname = NULL;
        SMB_STRUCT_STAT sbuf;
        int mode=0;
        SMB_OFF_T size=0;
        time_t mtime=0;
        char *p;
        NTSTATUS status;
+       TALLOC_CTX *ctx = talloc_tos();
 
        START_PROFILE(SMBgetatr);
 
-       p = smb_buf(inbuf) + 1;
-       p += srvstr_get_path(inbuf, SVAL(inbuf,smb_flg2), fname, p,
-                            sizeof(fname), 0, STR_TERMINATE, &status);
+       p = smb_buf(req->inbuf) + 1;
+       p += srvstr_get_path(ctx, (char *)req->inbuf, req->flags2, &fname, p,
+                            0, STR_TERMINATE, &status);
        if (!NT_STATUS_IS_OK(status)) {
+               reply_nterror(req, status);
                END_PROFILE(SMBgetatr);
-               return ERROR_NT(status);
+               return;
        }
 
-       status = resolve_dfspath(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, fname);
+       status = resolve_dfspath(ctx, conn,
+                               req->flags2 & FLAGS2_DFS_PATHNAMES,
+                               fname,
+                               &fname);
        if (!NT_STATUS_IS_OK(status)) {
-               END_PROFILE(SMBgetatr);
                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);
+                       END_PROFILE(SMBgetatr);
+                       return;
                }
-               return ERROR_NT(status);
+               reply_nterror(req, status);
+               END_PROFILE(SMBgetatr);
+               return;
        }
-  
+
        /* dos smetimes asks for a stat of "" - it returns a "hidden directory"
                under WfWg - weird! */
        if (*fname == '\0') {
@@ -909,20 +984,24 @@ int reply_getatr(connection_struct *conn, char *inbuf,char *outbuf, int dum_size
                size = 0;
                mtime = 0;
        } else {
-               status = unix_convert(conn, fname, False, NULL,&sbuf);
+               status = unix_convert(ctx, conn, fname, False, &fname, NULL,&sbuf);
                if (!NT_STATUS_IS_OK(status)) {
+                       reply_nterror(req, status);
                        END_PROFILE(SMBgetatr);
-                       return ERROR_NT(status);
+                       return;
                }
                status = check_name(conn, fname);
                if (!NT_STATUS_IS_OK(status)) {
                        DEBUG(3,("reply_getatr: check_name of %s failed (%s)\n",fname,nt_errstr(status)));
+                       reply_nterror(req, status);
                        END_PROFILE(SMBgetatr);
-                       return ERROR_NT(status);
+                       return;
                }
                if (!VALID_STAT(sbuf) && (SMB_VFS_STAT(conn,fname,&sbuf) != 0)) {
                        DEBUG(3,("reply_getatr: stat of %s failed (%s)\n",fname,strerror(errno)));
-                       return UNIXERROR(ERRDOS,ERRbadfile);
+                       reply_unixerror(req, ERRDOS,ERRbadfile);
+                       END_PROFILE(SMBgetatr);
+                       return;
                }
 
                mode = dos_mode(conn,fname,&sbuf);
@@ -932,70 +1011,87 @@ int reply_getatr(connection_struct *conn, char *inbuf,char *outbuf, int dum_size
                        size = 0;
                }
        }
-  
-       outsize = set_message(inbuf,outbuf,10,0,True);
 
-       SSVAL(outbuf,smb_vwv0,mode);
+       reply_outbuf(req, 10, 0);
+
+       SSVAL(req->outbuf,smb_vwv0,mode);
        if(lp_dos_filetime_resolution(SNUM(conn)) ) {
-               srv_put_dos_date3(outbuf,smb_vwv1,mtime & ~1);
+               srv_put_dos_date3((char *)req->outbuf,smb_vwv1,mtime & ~1);
        } else {
-               srv_put_dos_date3(outbuf,smb_vwv1,mtime);
+               srv_put_dos_date3((char *)req->outbuf,smb_vwv1,mtime);
        }
-       SIVAL(outbuf,smb_vwv3,(uint32)size);
+       SIVAL(req->outbuf,smb_vwv3,(uint32)size);
 
        if (Protocol >= PROTOCOL_NT1) {
-               SSVAL(outbuf,smb_flg2,SVAL(outbuf, smb_flg2) | FLAGS2_IS_LONG_NAME);
+               SSVAL(req->outbuf, smb_flg2,
+                     SVAL(req->outbuf, smb_flg2) | FLAGS2_IS_LONG_NAME);
        }
   
        DEBUG(3,("reply_getatr: name=%s mode=%d size=%u\n", fname, mode, (unsigned int)size ) );
-  
+
        END_PROFILE(SMBgetatr);
-       return(outsize);
+       return;
 }
 
 /****************************************************************************
  Reply to a setatr.
 ****************************************************************************/
 
-int reply_setatr(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
+void reply_setatr(struct smb_request *req)
 {
-       pstring fname;
-       int outsize = 0;
+       connection_struct *conn = req->conn;
+       char *fname = NULL;
        int mode;
        time_t mtime;
        SMB_STRUCT_STAT sbuf;
        char *p;
        NTSTATUS status;
+       TALLOC_CTX *ctx = talloc_tos();
 
        START_PROFILE(SMBsetatr);
 
-       p = smb_buf(inbuf) + 1;
-       p += srvstr_get_path(inbuf, SVAL(inbuf,smb_flg2), fname, p,
-                            sizeof(fname), 0, STR_TERMINATE, &status);
+       if (req->wct < 2) {
+               reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
+               return;
+       }
+
+       p = smb_buf(req->inbuf) + 1;
+       p += srvstr_get_path(ctx, (char *)req->inbuf, req->flags2, &fname, p,
+                               0, STR_TERMINATE, &status);
        if (!NT_STATUS_IS_OK(status)) {
+               reply_nterror(req, status);
                END_PROFILE(SMBsetatr);
-               return ERROR_NT(status);
+               return;
        }
 
-       status = resolve_dfspath(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, fname);
+       status = resolve_dfspath(ctx, conn,
+                               req->flags2 & FLAGS2_DFS_PATHNAMES,
+                               fname,
+                               &fname);
        if (!NT_STATUS_IS_OK(status)) {
-               END_PROFILE(SMBsetatr);
                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);
+                       END_PROFILE(SMBsetatr);
+                       return;
                }
-               return ERROR_NT(status);
+               reply_nterror(req, status);
+               END_PROFILE(SMBsetatr);
+               return;
        }
-  
-       status = unix_convert(conn, fname, False, NULL, &sbuf);
+
+       status = unix_convert(ctx, conn, fname, False, &fname, NULL, &sbuf);
        if (!NT_STATUS_IS_OK(status)) {
+               reply_nterror(req, status);
                END_PROFILE(SMBsetatr);
-               return ERROR_NT(status);
+               return;
        }
 
        status = check_name(conn, fname);
        if (!NT_STATUS_IS_OK(status)) {
+               reply_nterror(req, status);
                END_PROFILE(SMBsetatr);
-               return ERROR_NT(status);
+               return;
        }
 
        if (fname[0] == '.' && fname[1] == '\0') {
@@ -1003,44 +1099,48 @@ int reply_setatr(connection_struct *conn, char *inbuf,char *outbuf, int dum_size
                 * Not sure here is the right place to catch this
                 * condition. Might be moved to somewhere else later -- vl
                 */
+               reply_nterror(req, NT_STATUS_ACCESS_DENIED);
                END_PROFILE(SMBsetatr);
-               return ERROR_NT(NT_STATUS_ACCESS_DENIED);
+               return;
        }
 
-       mode = SVAL(inbuf,smb_vwv0);
-       mtime = srv_make_unix_date3(inbuf+smb_vwv1);
-  
+       mode = SVAL(req->inbuf,smb_vwv0);
+       mtime = srv_make_unix_date3(req->inbuf+smb_vwv1);
+
        if (mode != FILE_ATTRIBUTE_NORMAL) {
                if (VALID_STAT_OF_DIR(sbuf))
                        mode |= aDIR;
                else
                        mode &= ~aDIR;
 
-               if (file_set_dosmode(conn,fname,mode,&sbuf,False) != 0) {
+               if (file_set_dosmode(conn,fname,mode,&sbuf,NULL,false) != 0) {
+                       reply_unixerror(req, ERRDOS, ERRnoaccess);
                        END_PROFILE(SMBsetatr);
-                       return UNIXERROR(ERRDOS, ERRnoaccess);
+                       return;
                }
        }
 
        if (!set_filetime(conn,fname,convert_time_t_to_timespec(mtime))) {
+               reply_unixerror(req, ERRDOS, ERRnoaccess);
                END_PROFILE(SMBsetatr);
-               return UNIXERROR(ERRDOS, ERRnoaccess);
+               return;
        }
+
+       reply_outbuf(req, 0, 0);
  
-       outsize = set_message(inbuf,outbuf,0,0,False);
-  
        DEBUG( 3, ( "setatr name=%s mode=%d\n", fname, mode ) );
   
        END_PROFILE(SMBsetatr);
-       return(outsize);
+       return;
 }
 
 /****************************************************************************
  Reply to a dskattr.
 ****************************************************************************/
 
-void reply_dskattr(connection_struct *conn, struct smb_request *req)
+void reply_dskattr(struct smb_request *req)
 {
+       connection_struct *conn = req->conn;
        SMB_BIG_UINT dfree,dsize,bsize;
        START_PROFILE(SMBdskattr);
 
@@ -1063,8 +1163,8 @@ void reply_dskattr(connection_struct *conn, struct smb_request *req)
                total_space = dsize * (double)bsize;
                free_space = dfree * (double)bsize;
 
-               dsize = (total_space+63*512) / (64*512);
-               dfree = (free_space+63*512) / (64*512);
+               dsize = (SMB_BIG_UINT)((total_space+63*512) / (64*512));
+               dfree = (SMB_BIG_UINT)((free_space+63*512) / (64*512));
                
                if (dsize > 0xFFFF) dsize = 0xFFFF;
                if (dfree > 0xFFFF) dfree = 0xFFFF;
@@ -1091,101 +1191,150 @@ void reply_dskattr(connection_struct *conn, struct smb_request *req)
  Can be called from SMBsearch, SMBffirst or SMBfunique.
 ****************************************************************************/
 
-int reply_search(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
+void reply_search(struct smb_request *req)
 {
-       pstring mask;
-       pstring directory;
-       pstring fname;
+       connection_struct *conn = req->conn;
+       char *mask = NULL;
+       char *directory = NULL;
+       char *fname = NULL;
        SMB_OFF_T size;
        uint32 mode;
        time_t date;
        uint32 dirtype;
-       int outsize = 0;
        unsigned int numentries = 0;
        unsigned int maxentries = 0;
-       BOOL finished = False;
+       bool finished = False;
        char *p;
        int status_len;
-       pstring path;
+       char *path = NULL;
        char status[21];
        int dptr_num= -1;
-       BOOL check_descend = False;
-       BOOL expect_close = False;
+       bool check_descend = False;
+       bool expect_close = False;
        NTSTATUS nt_status;
-       BOOL mask_contains_wcard = False;
-       BOOL allow_long_path_components = (SVAL(inbuf,smb_flg2) & FLAGS2_LONG_PATH_COMPONENTS) ? True : False;
+       bool mask_contains_wcard = False;
+       bool allow_long_path_components = (req->flags2 & FLAGS2_LONG_PATH_COMPONENTS) ? True : False;
+       TALLOC_CTX *ctx = talloc_tos();
 
        START_PROFILE(SMBsearch);
 
-       if (lp_posix_pathnames()) {
+       if (req->wct < 2) {
+               reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
                END_PROFILE(SMBsearch);
-               return reply_unknown(inbuf, outbuf);
+               return;
        }
 
-       *mask = *directory = *fname = 0;
+       if (lp_posix_pathnames()) {
+               reply_unknown_new(req, CVAL(req->inbuf, smb_com));
+               END_PROFILE(SMBsearch);
+               return;
+       }
 
        /* If we were called as SMBffirst then we must expect close. */
-       if(CVAL(inbuf,smb_com) == SMBffirst) {
+       if(CVAL(req->inbuf,smb_com) == SMBffirst) {
                expect_close = True;
        }
-  
-       outsize = set_message(inbuf,outbuf,1,3,True);
-       maxentries = SVAL(inbuf,smb_vwv0); 
-       dirtype = SVAL(inbuf,smb_vwv1);
-       p = smb_buf(inbuf) + 1;
-       p += srvstr_get_path_wcard(inbuf, SVAL(inbuf,smb_flg2), path, p,
-                                  sizeof(path), 0, STR_TERMINATE, &nt_status,
-                                  &mask_contains_wcard);
+
+       reply_outbuf(req, 1, 3);
+       maxentries = SVAL(req->inbuf,smb_vwv0);
+       dirtype = SVAL(req->inbuf,smb_vwv1);
+       p = smb_buf(req->inbuf) + 1;
+       p += srvstr_get_path_wcard(ctx,
+                               (char *)req->inbuf,
+                               req->flags2,
+                               &path,
+                               p,
+                               0,
+                               STR_TERMINATE,
+                               &nt_status,
+                               &mask_contains_wcard);
        if (!NT_STATUS_IS_OK(nt_status)) {
+               reply_nterror(req, nt_status);
                END_PROFILE(SMBsearch);
-               return ERROR_NT(nt_status);
+               return;
        }
 
-       nt_status = resolve_dfspath_wcard(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, path, &mask_contains_wcard);
+       nt_status = resolve_dfspath_wcard(ctx, conn,
+                                         req->flags2 & FLAGS2_DFS_PATHNAMES,
+                                         path,
+                                         &path,
+                                         &mask_contains_wcard);
        if (!NT_STATUS_IS_OK(nt_status)) {
-               END_PROFILE(SMBsearch);
                if (NT_STATUS_EQUAL(nt_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);
+                       END_PROFILE(SMBsearch);
+                       return;
                }
-               return ERROR_NT(nt_status);
+               reply_nterror(req, nt_status);
+               END_PROFILE(SMBsearch);
+               return;
        }
-  
+
        p++;
        status_len = SVAL(p, 0);
        p += 2;
-  
+
        /* dirtype &= ~aDIR; */
 
        if (status_len == 0) {
                SMB_STRUCT_STAT sbuf;
 
-               pstrcpy(directory,path);
-               nt_status = unix_convert(conn, directory, True, NULL, &sbuf);
+               nt_status = unix_convert(ctx, conn, path, True,
+                               &directory, NULL, &sbuf);
                if (!NT_STATUS_IS_OK(nt_status)) {
+                       reply_nterror(req, nt_status);
                        END_PROFILE(SMBsearch);
-                       return ERROR_NT(nt_status);
+                       return;
                }
 
                nt_status = check_name(conn, directory);
                if (!NT_STATUS_IS_OK(nt_status)) {
+                       reply_nterror(req, nt_status);
                        END_PROFILE(SMBsearch);
-                       return ERROR_NT(nt_status);
+                       return;
                }
 
                p = strrchr_m(directory,'/');
                if (!p) {
-                       pstrcpy(mask,directory);
-                       pstrcpy(directory,".");
+                       mask = directory;
+                       directory = talloc_strdup(ctx,".");
+                       if (!directory) {
+                               reply_nterror(req, NT_STATUS_NO_MEMORY);
+                               END_PROFILE(SMBsearch);
+                               return;
+                       }
                } else {
                        *p = 0;
-                       pstrcpy(mask,p+1);
+                       mask = p+1;
                }
 
                if (*directory == '\0') {
-                       pstrcpy(directory,".");
+                       directory = talloc_strdup(ctx,".");
+                       if (!directory) {
+                               reply_nterror(req, NT_STATUS_NO_MEMORY);
+                               END_PROFILE(SMBsearch);
+                               return;
+                       }
                }
                memset((char *)status,'\0',21);
                SCVAL(status,0,(dirtype & 0x1F));
+
+               nt_status = dptr_create(conn,
+                                       directory,
+                                       True,
+                                       expect_close,
+                                       req->smbpid,
+                                       mask,
+                                       mask_contains_wcard,
+                                       dirtype,
+                                       &conn->dirptr);
+               if (!NT_STATUS_IS_OK(nt_status)) {
+                       reply_nterror(req, nt_status);
+                       END_PROFILE(SMBsearch);
+                       return;
+               }
+               dptr_num = dptr_dnum(conn->dirptr);
        } else {
                int status_dirtype;
 
@@ -1195,55 +1344,54 @@ int reply_search(connection_struct *conn, char *inbuf,char *outbuf, int dum_size
                        dirtype = status_dirtype;
                }
 
-               conn->dirptr = dptr_fetch(status+12,&dptr_num);      
+               conn->dirptr = dptr_fetch(status+12,&dptr_num);
                if (!conn->dirptr) {
                        goto SearchEmpty;
                }
                string_set(&conn->dirpath,dptr_path(dptr_num));
-               pstrcpy(mask, dptr_wcard(dptr_num));
+               mask = dptr_wcard(dptr_num);
+               if (!mask) {
+                       goto SearchEmpty;
+               }
                /*
                 * For a 'continue' search we have no string. So
                 * check from the initial saved string.
                 */
                mask_contains_wcard = ms_has_wild(mask);
-       }
-
-       p = smb_buf(outbuf) + 3;
-     
-       if (status_len == 0) {
-               nt_status = dptr_create(conn,
-                                       directory,
-                                       True,
-                                       expect_close,
-                                       SVAL(inbuf,smb_pid),
-                                       mask,
-                                       mask_contains_wcard,
-                                       dirtype,
-                                       &conn->dirptr);
-               if (!NT_STATUS_IS_OK(nt_status)) {
-                       return ERROR_NT(nt_status);
-               }
-               dptr_num = dptr_dnum(conn->dirptr);
-       } else {
                dirtype = dptr_attr(dptr_num);
        }
 
        DEBUG(4,("dptr_num is %d\n",dptr_num));
 
-       if ((dirtype&0x1F) == aVOLID) {   
-               memcpy(p,status,21);
-               make_dir_struct(p,"???????????",volume_label(SNUM(conn)),
-                               0,aVOLID,0,!allow_long_path_components);
-               dptr_fill(p+12,dptr_num);
-               if (dptr_zero(p+12) && (status_len==0)) {
+       if ((dirtype&0x1F) == aVOLID) {
+               char buf[DIR_STRUCT_SIZE];
+               memcpy(buf,status,21);
+               if (!make_dir_struct(ctx,buf,"???????????",volume_label(SNUM(conn)),
+                               0,aVOLID,0,!allow_long_path_components)) {
+                       reply_nterror(req, NT_STATUS_NO_MEMORY);
+                       END_PROFILE(SMBsearch);
+                       return;
+               }
+               dptr_fill(buf+12,dptr_num);
+               if (dptr_zero(buf+12) && (status_len==0)) {
                        numentries = 1;
                } else {
                        numentries = 0;
                }
-               p += DIR_STRUCT_SIZE;
+               if (message_push_blob(&req->outbuf,
+                                     data_blob_const(buf, sizeof(buf)))
+                   == -1) {
+                       reply_nterror(req, NT_STATUS_NO_MEMORY);
+                       END_PROFILE(SMBsearch);
+                       return;
+               }
        } else {
                unsigned int i;
-               maxentries = MIN(maxentries, ((BUFFER_SIZE - (p - outbuf))/DIR_STRUCT_SIZE));
+               maxentries = MIN(
+                       maxentries,
+                       ((BUFFER_SIZE -
+                         ((uint8 *)smb_buf(req->outbuf) + 3 - req->outbuf))
+                        /DIR_STRUCT_SIZE));
 
                DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
                        conn->dirpath,lp_dontdescend(SNUM(conn))));
@@ -1252,16 +1400,34 @@ int reply_search(connection_struct *conn, char *inbuf,char *outbuf, int dum_size
                }
 
                for (i=numentries;(i<maxentries) && !finished;i++) {
-                       finished = !get_dir_entry(conn,mask,dirtype,fname,&size,&mode,&date,check_descend);
+                       finished = !get_dir_entry(ctx,conn,mask,dirtype,&fname,
+                                       &size,&mode,&date,check_descend);
                        if (!finished) {
-                               memcpy(p,status,21);
-                               make_dir_struct(p,mask,fname,size, mode,date,
-                                               !allow_long_path_components);
-                               if (!dptr_fill(p+12,dptr_num)) {
+                               char buf[DIR_STRUCT_SIZE];
+                               memcpy(buf,status,21);
+                               if (!make_dir_struct(ctx,
+                                               buf,
+                                               mask,
+                                               fname,
+                                               size,
+                                               mode,
+                                               date,
+                                               !allow_long_path_components)) {
+                                       reply_nterror(req, NT_STATUS_NO_MEMORY);
+                                       END_PROFILE(SMBsearch);
+                                       return;
+                               }
+                               if (!dptr_fill(buf+12,dptr_num)) {
                                        break;
                                }
+                               if (message_push_blob(&req->outbuf,
+                                                     data_blob_const(buf, sizeof(buf)))
+                                   == -1) {
+                                       reply_nterror(req, NT_STATUS_NO_MEMORY);
+                                       END_PROFILE(SMBsearch);
+                                       return;
+                               }
                                numentries++;
-                               p += DIR_STRUCT_SIZE;
                        }
                }
        }
@@ -1280,80 +1446,96 @@ int reply_search(connection_struct *conn, char *inbuf,char *outbuf, int dum_size
        }
 
        /* If we were called as SMBfunique, then we can close the dirptr now ! */
-       if(dptr_num >= 0 && CVAL(inbuf,smb_com) == SMBfunique) {
+       if(dptr_num >= 0 && CVAL(req->inbuf,smb_com) == SMBfunique) {
                dptr_close(&dptr_num);
        }
 
        if ((numentries == 0) && !mask_contains_wcard) {
-               return ERROR_BOTH(STATUS_NO_MORE_FILES,ERRDOS,ERRnofiles);
+               reply_botherror(req, STATUS_NO_MORE_FILES, ERRDOS, ERRnofiles);
+               END_PROFILE(SMBsearch);
+               return;
        }
 
-       SSVAL(outbuf,smb_vwv0,numentries);
-       SSVAL(outbuf,smb_vwv1,3 + numentries * DIR_STRUCT_SIZE);
-       SCVAL(smb_buf(outbuf),0,5);
-       SSVAL(smb_buf(outbuf),1,numentries*DIR_STRUCT_SIZE);
+       SSVAL(req->outbuf,smb_vwv0,numentries);
+       SSVAL(req->outbuf,smb_vwv1,3 + numentries * DIR_STRUCT_SIZE);
+       SCVAL(smb_buf(req->outbuf),0,5);
+       SSVAL(smb_buf(req->outbuf),1,numentries*DIR_STRUCT_SIZE);
 
        /* The replies here are never long name. */
-       SSVAL(outbuf,smb_flg2,SVAL(outbuf, smb_flg2) & (~FLAGS2_IS_LONG_NAME));
+       SSVAL(req->outbuf, smb_flg2,
+             SVAL(req->outbuf, smb_flg2) & (~FLAGS2_IS_LONG_NAME));
        if (!allow_long_path_components) {
-               SSVAL(outbuf,smb_flg2,SVAL(outbuf, smb_flg2) & (~FLAGS2_LONG_PATH_COMPONENTS));
+               SSVAL(req->outbuf, smb_flg2,
+                     SVAL(req->outbuf, smb_flg2)
+                     & (~FLAGS2_LONG_PATH_COMPONENTS));
        }
 
        /* This SMB *always* returns ASCII names. Remove the unicode bit in flags2. */
-       SSVAL(outbuf,smb_flg2, (SVAL(outbuf, smb_flg2) & (~FLAGS2_UNICODE_STRINGS)));
-         
-       outsize += DIR_STRUCT_SIZE*numentries;
-       smb_setlen(inbuf,outbuf,outsize - 4);
-  
-       if ((! *directory) && dptr_path(dptr_num))
-               slprintf(directory, sizeof(directory)-1, "(%s)",dptr_path(dptr_num));
+       SSVAL(req->outbuf, smb_flg2,
+             (SVAL(req->outbuf, smb_flg2) & (~FLAGS2_UNICODE_STRINGS)));
+
+       if (!directory) {
+               directory = dptr_path(dptr_num);
+       }
 
-       DEBUG( 4, ( "%s mask=%s path=%s dtype=%d nument=%u of %u\n",
-               smb_fn_name(CVAL(inbuf,smb_com)), 
-               mask, directory, dirtype, numentries, maxentries ) );
+       DEBUG(4,("%s mask=%s path=%s dtype=%d nument=%u of %u\n",
+               smb_fn_name(CVAL(req->inbuf,smb_com)),
+               mask,
+               directory ? directory : "./",
+               dirtype,
+               numentries,
+               maxentries ));
 
        END_PROFILE(SMBsearch);
-       return(outsize);
+       return;
 }
 
 /****************************************************************************
  Reply to a fclose (stop directory search).
 ****************************************************************************/
 
-int reply_fclose(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
+void reply_fclose(struct smb_request *req)
 {
-       int outsize = 0;
        int status_len;
-       pstring path;
        char status[21];
        int dptr_num= -2;
        char *p;
+       char *path = NULL;
        NTSTATUS err;
-       BOOL path_contains_wcard = False;
+       bool path_contains_wcard = False;
+       TALLOC_CTX *ctx = talloc_tos();
 
        START_PROFILE(SMBfclose);
 
        if (lp_posix_pathnames()) {
+               reply_unknown_new(req, CVAL(req->inbuf, smb_com));
                END_PROFILE(SMBfclose);
-               return reply_unknown(inbuf, outbuf);
+               return;
        }
 
-       outsize = set_message(inbuf,outbuf,1,0,True);
-       p = smb_buf(inbuf) + 1;
-       p += srvstr_get_path_wcard(inbuf, SVAL(inbuf,smb_flg2), path, p,
-                                  sizeof(path), 0, STR_TERMINATE, &err,
-                                  &path_contains_wcard);
+       p = smb_buf(req->inbuf) + 1;
+       p += srvstr_get_path_wcard(ctx,
+                               (char *)req->inbuf,
+                               req->flags2,
+                               &path,
+                               p,
+                               0,
+                               STR_TERMINATE,
+                               &err,
+                               &path_contains_wcard);
        if (!NT_STATUS_IS_OK(err)) {
+               reply_nterror(req, err);
                END_PROFILE(SMBfclose);
-               return ERROR_NT(err);
+               return;
        }
        p++;
        status_len = SVAL(p,0);
        p += 2;
 
        if (status_len == 0) {
+               reply_doserror(req, ERRSRV, ERRsrverror);
                END_PROFILE(SMBfclose);
-               return ERROR_DOS(ERRSRV,ERRsrverror);
+               return;
        }
 
        memcpy(status,p,21);
@@ -1363,94 +1545,94 @@ int reply_fclose(connection_struct *conn, char *inbuf,char *outbuf, int dum_size
                dptr_close(&dptr_num);
        }
 
-       SSVAL(outbuf,smb_vwv0,0);
+       reply_outbuf(req, 1, 0);
+       SSVAL(req->outbuf,smb_vwv0,0);
 
        DEBUG(3,("search close\n"));
 
        END_PROFILE(SMBfclose);
-       return(outsize);
+       return;
 }
 
 /****************************************************************************
  Reply to an open.
 ****************************************************************************/
 
-int reply_open(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
+void reply_open(struct smb_request *req)
 {
-       pstring fname;
-       int outsize = 0;
+       connection_struct *conn = req->conn;
+       char *fname = NULL;
        uint32 fattr=0;
        SMB_OFF_T size = 0;
        time_t mtime=0;
        int info;
        SMB_STRUCT_STAT sbuf;
        files_struct *fsp;
-       int oplock_request = CORE_OPLOCK_REQUEST(inbuf);
+       int oplock_request;
        int deny_mode;
-       uint32 dos_attr = SVAL(inbuf,smb_vwv1);
+       uint32 dos_attr;
        uint32 access_mask;
        uint32 share_mode;
        uint32 create_disposition;
        uint32 create_options = 0;
        NTSTATUS status;
-       struct smb_request req;
+       TALLOC_CTX *ctx = talloc_tos();
 
        START_PROFILE(SMBopen);
 
-       init_smb_request(&req, (uint8 *)inbuf);
-       deny_mode = SVAL(inbuf,smb_vwv0);
-
-       srvstr_get_path(inbuf, SVAL(inbuf,smb_flg2), fname, smb_buf(inbuf)+1,
-                       sizeof(fname), 0, STR_TERMINATE, &status);
-       if (!NT_STATUS_IS_OK(status)) {
+       if (req->wct < 2) {
+               reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
                END_PROFILE(SMBopen);
-               return ERROR_NT(status);
+               return;
        }
 
-       status = resolve_dfspath(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, fname);
-       if (!NT_STATUS_IS_OK(status)) {
-               END_PROFILE(SMBopen);
-               if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
-                       return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath);
-               }
-               return ERROR_NT(status);
-       }
+       oplock_request = CORE_OPLOCK_REQUEST(req->inbuf);
+       deny_mode = SVAL(req->inbuf,smb_vwv0);
+       dos_attr = SVAL(req->inbuf,smb_vwv1);
 
-       status = unix_convert(conn, fname, False, NULL, &sbuf);
-       if (!NT_STATUS_IS_OK(status)) {
-               END_PROFILE(SMBopen);
-               return ERROR_NT(status);
-       }
-    
-       status = check_name(conn, fname);
+       srvstr_get_path(ctx, (char *)req->inbuf, req->flags2, &fname,
+                       smb_buf(req->inbuf)+1, 0,
+                       STR_TERMINATE, &status);
        if (!NT_STATUS_IS_OK(status)) {
+               reply_nterror(req, status);
                END_PROFILE(SMBopen);
-               return ERROR_NT(status);
+               return;
        }
 
-       if (!map_open_params_to_ntcreate(fname, deny_mode, OPENX_FILE_EXISTS_OPEN,
-                       &access_mask, &share_mode, &create_disposition, &create_options)) {
+       if (!map_open_params_to_ntcreate(
+                   fname, deny_mode, OPENX_FILE_EXISTS_OPEN, &access_mask,
+                   &share_mode, &create_disposition, &create_options)) {
+               reply_nterror(req, NT_STATUS_DOS(ERRDOS, ERRbadaccess));
                END_PROFILE(SMBopen);
-               return ERROR_NT(NT_STATUS_DOS(ERRDOS, ERRbadaccess));
+               return;
        }
 
-       status = open_file_ntcreate(conn, &req, fname, &sbuf,
-                       access_mask,
-                       share_mode,
-                       create_disposition,
-                       create_options,
-                       dos_attr,
-                       oplock_request,
-                       &info, &fsp);
+       status = create_file(conn,                      /* conn */
+                            req,                       /* req */
+                            0,                         /* root_dir_fid */
+                            fname,                     /* fname */
+                            access_mask,               /* access_mask */
+                            share_mode,                /* share_access */
+                            create_disposition,        /* create_disposition*/
+                            create_options,            /* create_options */
+                            dos_attr,                  /* file_attributes */
+                            oplock_request,            /* oplock_request */
+                            0,                         /* allocation_size */
+                            NULL,                      /* sd */
+                            NULL,                      /* ea_list */
+                            &fsp,                      /* result */
+                            &info,                     /* pinfo */
+                            &sbuf);                    /* psbuf */
 
        if (!NT_STATUS_IS_OK(status)) {
-               END_PROFILE(SMBopen);
-               if (open_was_deferred(SVAL(inbuf,smb_mid))) {
+               if (open_was_deferred(req->mid)) {
                        /* We have re-scheduled this call. */
-                       return -1;
+                       END_PROFILE(SMBopen);
+                       return;
                }
-               return ERROR_NT(status);
+               reply_openerror(req, status);
+               END_PROFILE(SMBopen);
+               return;
        }
 
        size = sbuf.st_size;
@@ -1460,39 +1642,43 @@ int reply_open(connection_struct *conn, char *inbuf,char *outbuf, int dum_size,
        if (fattr & aDIR) {
                DEBUG(3,("attempt to open a directory %s\n",fname));
                close_file(fsp,ERROR_CLOSE);
+               reply_doserror(req, ERRDOS,ERRnoaccess);
                END_PROFILE(SMBopen);
-               return ERROR_DOS(ERRDOS,ERRnoaccess);
+               return;
        }
-  
-       outsize = set_message(inbuf,outbuf,7,0,True);
-       SSVAL(outbuf,smb_vwv0,fsp->fnum);
-       SSVAL(outbuf,smb_vwv1,fattr);
+
+       reply_outbuf(req, 7, 0);
+       SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
+       SSVAL(req->outbuf,smb_vwv1,fattr);
        if(lp_dos_filetime_resolution(SNUM(conn)) ) {
-               srv_put_dos_date3(outbuf,smb_vwv2,mtime & ~1);
+               srv_put_dos_date3((char *)req->outbuf,smb_vwv2,mtime & ~1);
        } else {
-               srv_put_dos_date3(outbuf,smb_vwv2,mtime);
+               srv_put_dos_date3((char *)req->outbuf,smb_vwv2,mtime);
        }
-       SIVAL(outbuf,smb_vwv4,(uint32)size);
-       SSVAL(outbuf,smb_vwv6,deny_mode);
+       SIVAL(req->outbuf,smb_vwv4,(uint32)size);
+       SSVAL(req->outbuf,smb_vwv6,deny_mode);
 
        if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
-               SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
+               SCVAL(req->outbuf,smb_flg,
+                     CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
        }
     
        if(EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
-               SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
+               SCVAL(req->outbuf,smb_flg,
+                     CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
        }
        END_PROFILE(SMBopen);
-       return(outsize);
+       return;
 }
 
 /****************************************************************************
  Reply to an open and X.
 ****************************************************************************/
 
-void reply_open_and_X(connection_struct *conn, struct smb_request *req)
+void reply_open_and_X(struct smb_request *req)
 {
-       pstring fname;
+       connection_struct *conn = req->conn;
+       char *fname = NULL;
        uint16 open_flags;
        int deny_mode;
        uint32 smb_attr;
@@ -1518,6 +1704,7 @@ void reply_open_and_X(connection_struct *conn, struct smb_request *req)
        uint32 share_mode;
        uint32 create_disposition;
        uint32 create_options = 0;
+       TALLOC_CTX *ctx = talloc_tos();
 
        START_PROFILE(SMBopenX);
 
@@ -1548,8 +1735,8 @@ void reply_open_and_X(connection_struct *conn, struct smb_request *req)
        }
 
        /* XXXX we need to handle passed times, sattr and flags */
-       srvstr_get_path((char *)req->inbuf, req->flags2, fname,
-                       smb_buf(req->inbuf), sizeof(fname), 0, STR_TERMINATE,
+       srvstr_get_path(ctx, (char *)req->inbuf, req->flags2, &fname,
+                       smb_buf(req->inbuf), 0, STR_TERMINATE,
                        &status);
        if (!NT_STATUS_IS_OK(status)) {
                reply_nterror(req, status);
@@ -1557,59 +1744,38 @@ void reply_open_and_X(connection_struct *conn, struct smb_request *req)
                return;
        }
 
-       status = resolve_dfspath(conn, req->flags2 & FLAGS2_DFS_PATHNAMES,
-                                fname);
-       if (!NT_STATUS_IS_OK(status)) {
-               END_PROFILE(SMBopenX);
-               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;
-       }
-
-       status = unix_convert(conn, fname, False, NULL, &sbuf);
-       if (!NT_STATUS_IS_OK(status)) {
-               reply_nterror(req, status);
-               END_PROFILE(SMBopenX);
-               return;
-       }
-
-       status = check_name(conn, fname);
-       if (!NT_STATUS_IS_OK(status)) {
-               reply_nterror(req, status);
+       if (!map_open_params_to_ntcreate(
+                   fname, deny_mode, smb_ofun, &access_mask,
+                   &share_mode, &create_disposition, &create_options)) {
+               reply_nterror(req, NT_STATUS_DOS(ERRDOS, ERRbadaccess));
                END_PROFILE(SMBopenX);
                return;
        }
 
-       if (!map_open_params_to_ntcreate(fname, deny_mode, smb_ofun,
-                               &access_mask,
-                               &share_mode,
-                               &create_disposition,
-                               &create_options)) {
-               reply_nterror(req, NT_STATUS_DOS(ERRDOS, ERRbadaccess));
-               END_PROFILE(SMBopenX);
-               return;
-       }
+       status = create_file(conn,                      /* conn */
+                            req,                       /* req */
+                            0,                         /* root_dir_fid */
+                            fname,                     /* fname */
+                            access_mask,               /* access_mask */
+                            share_mode,                /* share_access */
+                            create_disposition,        /* create_disposition*/
+                            create_options,            /* create_options */
+                            smb_attr,                  /* file_attributes */
+                            oplock_request,            /* oplock_request */
+                            0,                         /* allocation_size */
+                            NULL,                      /* sd */
+                            NULL,                      /* ea_list */
+                            &fsp,                      /* result */
+                            &smb_action,               /* pinfo */
+                            &sbuf);                    /* psbuf */
 
-       status = open_file_ntcreate(conn, req, fname, &sbuf,
-                       access_mask,
-                       share_mode,
-                       create_disposition,
-                       create_options,
-                       smb_attr,
-                       oplock_request,
-                       &smb_action, &fsp);
-      
        if (!NT_STATUS_IS_OK(status)) {
                END_PROFILE(SMBopenX);
                if (open_was_deferred(req->mid)) {
                        /* We have re-scheduled this call. */
                        return;
                }
-               reply_nterror(req, status);
+               reply_openerror(req, status);
                return;
        }
 
@@ -1692,16 +1858,15 @@ void reply_open_and_X(connection_struct *conn, struct smb_request *req)
        }
 
        END_PROFILE(SMBopenX);
-       chain_reply_new(req);
+       chain_reply(req);
        return;
 }
 
 /****************************************************************************
  Reply to a SMBulogoffX.
- conn POINTER CAN BE NULL HERE !
 ****************************************************************************/
 
-void reply_ulogoffX(connection_struct *conn, struct smb_request *req)
+void reply_ulogoffX(struct smb_request *req)
 {
        user_struct *vuser;
 
@@ -1727,68 +1892,58 @@ void reply_ulogoffX(connection_struct *conn, struct smb_request *req)
        DEBUG( 3, ( "ulogoffX vuid=%d\n", req->vuid ) );
 
        END_PROFILE(SMBulogoffX);
-       chain_reply_new(req);
+       chain_reply(req);
 }
 
 /****************************************************************************
  Reply to a mknew or a create.
 ****************************************************************************/
 
-int reply_mknew(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
+void reply_mknew(struct smb_request *req)
 {
-       pstring fname;
+       connection_struct *conn = req->conn;
+       char *fname = NULL;
        int com;
-       int outsize = 0;
-       uint32 fattr = SVAL(inbuf,smb_vwv0);
+       uint32 fattr = 0;
        struct timespec ts[2];
        files_struct *fsp;
-       int oplock_request = CORE_OPLOCK_REQUEST(inbuf);
+       int oplock_request = 0;
        SMB_STRUCT_STAT sbuf;
        NTSTATUS status;
        uint32 access_mask = FILE_GENERIC_READ | FILE_GENERIC_WRITE;
        uint32 share_mode = FILE_SHARE_READ|FILE_SHARE_WRITE;
        uint32 create_disposition;
        uint32 create_options = 0;
-       struct smb_request req;
+       TALLOC_CTX *ctx = talloc_tos();
 
        START_PROFILE(SMBcreate);
 
-       init_smb_request(&req, (uint8 *)inbuf);
-       com = SVAL(inbuf,smb_com);
-
-       ts[1] = convert_time_t_to_timespec(srv_make_unix_date3(inbuf + smb_vwv1)); /* mtime. */
-
-       srvstr_get_path(inbuf, SVAL(inbuf,smb_flg2), fname, smb_buf(inbuf) + 1,
-                       sizeof(fname), 0, STR_TERMINATE, &status);
-       if (!NT_STATUS_IS_OK(status)) {
+        if (req->wct < 3) {
+               reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
                END_PROFILE(SMBcreate);
-               return ERROR_NT(status);
+               return;
        }
 
-       status = resolve_dfspath(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, fname);
-       if (!NT_STATUS_IS_OK(status)) {
-               END_PROFILE(SMBcreate);
-               if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
-                       return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath);
-               }
-               return ERROR_NT(status);
-       }
+       fattr = SVAL(req->inbuf,smb_vwv0);
+       oplock_request = CORE_OPLOCK_REQUEST(req->inbuf);
+       com = SVAL(req->inbuf,smb_com);
 
-       status = unix_convert(conn, fname, False, NULL, &sbuf);
-       if (!NT_STATUS_IS_OK(status)) {
-               END_PROFILE(SMBcreate);
-               return ERROR_NT(status);
-       }
+       ts[1] =convert_time_t_to_timespec(
+                       srv_make_unix_date3(req->inbuf + smb_vwv1));
+                       /* mtime. */
 
-       status = check_name(conn, fname);
+       srvstr_get_path(ctx, (char *)req->inbuf, req->flags2, &fname,
+                        smb_buf(req->inbuf) + 1, 0,
+                       STR_TERMINATE, &status);
        if (!NT_STATUS_IS_OK(status)) {
+               reply_nterror(req, status);
                END_PROFILE(SMBcreate);
-               return ERROR_NT(status);
+               return;
        }
 
        if (fattr & aVOLID) {
-               DEBUG(0,("Attempt to create file (%s) with volid set - please report this\n",fname));
+               DEBUG(0,("Attempt to create file (%s) with volid set - "
+                       "please report this\n", fname));
        }
 
        if(com == SMBmknew) {
@@ -1799,111 +1954,148 @@ int reply_mknew(connection_struct *conn, char *inbuf,char *outbuf, int dum_size,
                create_disposition = FILE_OVERWRITE_IF;
        }
 
-       /* Open file using ntcreate. */
-       status = open_file_ntcreate(conn, &req, fname, &sbuf,
-                               access_mask,
-                               share_mode,
-                               create_disposition,
-                               create_options,
-                               fattr,
-                               oplock_request,
-                               NULL, &fsp);
-  
+       status = create_file(conn,                      /* conn */
+                            req,                       /* req */
+                            0,                         /* root_dir_fid */
+                            fname,                     /* fname */
+                            access_mask,               /* access_mask */
+                            share_mode,                /* share_access */
+                            create_disposition,        /* create_disposition*/
+                            create_options,            /* create_options */
+                            fattr,                     /* file_attributes */
+                            oplock_request,            /* oplock_request */
+                            0,                         /* allocation_size */
+                            NULL,                      /* sd */
+                            NULL,                      /* ea_list */
+                            &fsp,                      /* result */
+                            NULL,                      /* pinfo */
+                            &sbuf);                    /* psbuf */
+
        if (!NT_STATUS_IS_OK(status)) {
                END_PROFILE(SMBcreate);
-               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;
        }
+
        ts[0] = get_atimespec(&sbuf); /* atime. */
        file_ntimes(conn, fname, ts);
 
-       outsize = set_message(inbuf,outbuf,1,0,True);
-       SSVAL(outbuf,smb_vwv0,fsp->fnum);
+       reply_outbuf(req, 1, 0);
+       SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
 
        if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
-               SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
+               SCVAL(req->outbuf,smb_flg,
+                               CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
        }
+
        if(EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
-               SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
+               SCVAL(req->outbuf,smb_flg,
+                               CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
        }
+
        DEBUG( 2, ( "reply_mknew: file %s\n", fname ) );
-       DEBUG( 3, ( "reply_mknew %s fd=%d dmode=0x%x\n", fname, fsp->fh->fd, (unsigned int)fattr ) );
+       DEBUG( 3, ( "reply_mknew %s fd=%d dmode=0x%x\n",
+                               fname, fsp->fh->fd, (unsigned int)fattr ) );
 
        END_PROFILE(SMBcreate);
-       return(outsize);
+       return;
 }
 
 /****************************************************************************
  Reply to a create temporary file.
 ****************************************************************************/
 
-int reply_ctemp(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
+void reply_ctemp(struct smb_request *req)
 {
-       pstring fname;
-       int outsize = 0;
-       uint32 fattr = SVAL(inbuf,smb_vwv0);
+       connection_struct *conn = req->conn;
+       char *fname = NULL;
+       uint32 fattr;
        files_struct *fsp;
-       int oplock_request = CORE_OPLOCK_REQUEST(inbuf);
+       int oplock_request;
        int tmpfd;
        SMB_STRUCT_STAT sbuf;
-       char *p, *s;
+       char *s;
        NTSTATUS status;
-       unsigned int namelen;
-       struct smb_request req;
+       TALLOC_CTX *ctx = talloc_tos();
 
        START_PROFILE(SMBctemp);
 
-       init_smb_request(&req, (uint8 *)inbuf);
+       if (req->wct < 3) {
+               reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
+               END_PROFILE(SMBctemp);
+               return;
+       }
+
+       fattr = SVAL(req->inbuf,smb_vwv0);
+       oplock_request = CORE_OPLOCK_REQUEST(req->inbuf);
 
-       srvstr_get_path(inbuf, SVAL(inbuf,smb_flg2), fname, smb_buf(inbuf)+1,
-                       sizeof(fname), 0, STR_TERMINATE, &status);
+       srvstr_get_path(ctx, (char *)req->inbuf, req->flags2, &fname,
+                       smb_buf(req->inbuf)+1, 0, STR_TERMINATE,
+                       &status);
        if (!NT_STATUS_IS_OK(status)) {
+               reply_nterror(req, status);
                END_PROFILE(SMBctemp);
-               return ERROR_NT(status);
+               return;
        }
        if (*fname) {
-               pstrcat(fname,"/TMXXXXXX");
+               fname = talloc_asprintf(ctx,
+                               "%s/TMXXXXXX",
+                               fname);
        } else {
-               pstrcat(fname,"TMXXXXXX");
+               fname = talloc_strdup(ctx, "TMXXXXXX");
        }
 
-       status = resolve_dfspath(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, fname);
-       if (!NT_STATUS_IS_OK(status)) {
+       if (!fname) {
+               reply_nterror(req, NT_STATUS_NO_MEMORY);
                END_PROFILE(SMBctemp);
+               return;
+       }
+
+       status = resolve_dfspath(ctx, conn,
+                               req->flags2 & FLAGS2_DFS_PATHNAMES,
+                               fname,
+                               &fname);
+       if (!NT_STATUS_IS_OK(status)) {
                if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
-                       return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath);
+                       reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
+                                       ERRSRV, ERRbadpath);
+                       END_PROFILE(SMBctemp);
+                       return;
                }
-               return ERROR_NT(status);
+               reply_nterror(req, status);
+               END_PROFILE(SMBctemp);
+               return;
        }
 
-       status = unix_convert(conn, fname, False, NULL, &sbuf);
+       status = unix_convert(ctx, conn, fname, False, &fname, NULL, &sbuf);
        if (!NT_STATUS_IS_OK(status)) {
+               reply_nterror(req, status);
                END_PROFILE(SMBctemp);
-               return ERROR_NT(status);
+               return;
        }
 
-       status = check_name(conn, fname);
+       status = check_name(conn, CONST_DISCARD(char *,fname));
        if (!NT_STATUS_IS_OK(status)) {
+               reply_nterror(req, status);
                END_PROFILE(SMBctemp);
-               return ERROR_NT(status);
+               return;
        }
-  
+
        tmpfd = smb_mkstemp(fname);
        if (tmpfd == -1) {
+               reply_unixerror(req, ERRDOS, ERRnoaccess);
                END_PROFILE(SMBctemp);
-               return(UNIXERROR(ERRDOS,ERRnoaccess));
+               return;
        }
 
        SMB_VFS_STAT(conn,fname,&sbuf);
 
        /* We should fail if file does not exist. */
-       status = open_file_ntcreate(conn, &req, fname, &sbuf,
+       status = open_file_ntcreate(conn, req, fname, &sbuf,
                                FILE_GENERIC_READ | FILE_GENERIC_WRITE,
                                FILE_SHARE_READ|FILE_SHARE_WRITE,
                                FILE_OPEN,
@@ -1916,16 +2108,18 @@ int reply_ctemp(connection_struct *conn, char *inbuf,char *outbuf, int dum_size,
        close(tmpfd);
 
        if (!NT_STATUS_IS_OK(status)) {
-               END_PROFILE(SMBctemp);
-               if (open_was_deferred(SVAL(inbuf,smb_mid))) {
+               if (open_was_deferred(req->mid)) {
                        /* We have re-scheduled this call. */
-                       return -1;
+                       END_PROFILE(SMBctemp);
+                       return;
                }
-               return ERROR_NT(status);
+               reply_openerror(req, status);
+               END_PROFILE(SMBctemp);
+               return;
        }
 
-       outsize = set_message(inbuf,outbuf,1,0,True);
-       SSVAL(outbuf,smb_vwv0,fsp->fnum);
+       reply_outbuf(req, 1, 0);
+       SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
 
        /* the returned filename is relative to the directory */
        s = strrchr_m(fname, '/');
@@ -1935,23 +2129,26 @@ int reply_ctemp(connection_struct *conn, char *inbuf,char *outbuf, int dum_size,
                s++;
        }
 
-       p = smb_buf(outbuf);
 #if 0
        /* Tested vs W2K3 - this doesn't seem to be here - null terminated filename is the only
           thing in the byte section. JRA */
        SSVALS(p, 0, -1); /* what is this? not in spec */
 #endif
-       namelen = srvstr_push(outbuf, SVAL(outbuf, smb_flg2), p, s, -1,
-                             STR_ASCII|STR_TERMINATE);
-       p += namelen;
-       outsize = set_message_end(inbuf,outbuf, p);
+       if (message_push_string(&req->outbuf, s, STR_ASCII|STR_TERMINATE)
+           == -1) {
+               reply_nterror(req, NT_STATUS_NO_MEMORY);
+               END_PROFILE(SMBctemp);
+               return;
+       }
 
        if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
-               SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
+               SCVAL(req->outbuf, smb_flg,
+                     CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
        }
   
        if (EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
-               SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
+               SCVAL(req->outbuf, smb_flg,
+                     CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
        }
 
        DEBUG( 2, ( "reply_ctemp: created temp file %s\n", fname ) );
@@ -1959,7 +2156,7 @@ int reply_ctemp(connection_struct *conn, char *inbuf,char *outbuf, int dum_size,
                        (unsigned int)sbuf.st_mode ) );
 
        END_PROFILE(SMBctemp);
-       return(outsize);
+       return;
 }
 
 /*******************************************************************
@@ -1995,8 +2192,10 @@ static NTSTATUS can_rename(connection_struct *conn, files_struct *fsp,
  * unlink a file with all relevant access checks
  *******************************************************************/
 
-static NTSTATUS do_unlink(connection_struct *conn, struct smb_request *req,
-                         char *fname, uint32 dirtype)
+static NTSTATUS do_unlink(connection_struct *conn,
+                       struct smb_request *req,
+                       const char *fname,
+                       uint32 dirtype)
 {
        SMB_STRUCT_STAT sbuf;
        uint32 fattr;
@@ -2118,32 +2317,35 @@ static NTSTATUS do_unlink(connection_struct *conn, struct smb_request *req,
 ****************************************************************************/
 
 NTSTATUS unlink_internals(connection_struct *conn, struct smb_request *req,
-                         uint32 dirtype, char *name, BOOL has_wild)
+                         uint32 dirtype, const char *name_in, bool has_wild)
 {
-       pstring directory;
-       pstring mask;
-       char *p;
+       const char *directory = NULL;
+       char *mask = NULL;
+       char *name = NULL;
+       char *p = NULL;
        int count=0;
        NTSTATUS status = NT_STATUS_OK;
        SMB_STRUCT_STAT sbuf;
-       
-       *directory = *mask = 0;
-       
-       status = unix_convert(conn, name, has_wild, NULL, &sbuf);
+       TALLOC_CTX *ctx = talloc_tos();
+
+       status = unix_convert(ctx, conn, name_in, has_wild, &name, NULL, &sbuf);
        if (!NT_STATUS_IS_OK(status)) {
                return status;
        }
-       
+
        p = strrchr_m(name,'/');
        if (!p) {
-               pstrcpy(directory,".");
-               pstrcpy(mask,name);
+               directory = talloc_strdup(ctx, ".");
+               if (!directory) {
+                       return NT_STATUS_NO_MEMORY;
+               }
+               mask = name;
        } else {
                *p = 0;
-               pstrcpy(directory,name);
-               pstrcpy(mask,p+1);
+               directory = name;
+               mask = p+1;
        }
-       
+
        /*
         * We should only check the mangled cache
         * here if unix_convert failed. This means
@@ -2152,13 +2354,26 @@ NTSTATUS unlink_internals(connection_struct *conn, struct smb_request *req,
         * for a possible mangle. This patch from
         * Tine Smukavec <valentin.smukavec@hermes.si>.
         */
-       
-       if (!VALID_STAT(sbuf) && mangle_is_mangled(mask,conn->params))
-               mangle_check_cache( mask, sizeof(pstring)-1, conn->params );
-       
+
+       if (!VALID_STAT(sbuf) && mangle_is_mangled(mask,conn->params)) {
+               char *new_mask = NULL;
+               mangle_lookup_name_from_8_3(ctx,
+                               mask,
+                               &new_mask,
+                               conn->params );
+               if (new_mask) {
+                       mask = new_mask;
+               }
+       }
+
        if (!has_wild) {
-               pstrcat(directory,"/");
-               pstrcat(directory,mask);
+               directory = talloc_asprintf(ctx,
+                               "%s/%s",
+                               directory,
+                               mask);
+               if (!directory) {
+                       return NT_STATUS_NO_MEMORY;
+               }
                if (dirtype == 0) {
                        dirtype = FILE_ATTRIBUTE_NORMAL;
                }
@@ -2178,13 +2393,14 @@ NTSTATUS unlink_internals(connection_struct *conn, struct smb_request *req,
                struct smb_Dir *dir_hnd = NULL;
                long offset = 0;
                const char *dname;
-               
+
                if ((dirtype & SAMBA_ATTRIBUTES_MASK) == aDIR) {
                        return NT_STATUS_OBJECT_NAME_INVALID;
                }
 
                if (strequal(mask,"????????.???")) {
-                       pstrcpy(mask,"*");
+                       mask[0] = '*';
+                       mask[1] = '\0';
                }
 
                status = check_name(conn, directory);
@@ -2196,35 +2412,37 @@ NTSTATUS unlink_internals(connection_struct *conn, struct smb_request *req,
                if (dir_hnd == NULL) {
                        return map_nt_error_from_unix(errno);
                }
-               
+
                /* XXXX the CIFS spec says that if bit0 of the flags2 field is set then
                   the pattern matches against the long name, otherwise the short name 
                   We don't implement this yet XXXX
                */
-               
+
                status = NT_STATUS_NO_SUCH_FILE;
 
                while ((dname = ReadDirName(dir_hnd, &offset))) {
                        SMB_STRUCT_STAT st;
-                       pstring fname;
-                       pstrcpy(fname,dname);
+                       char *fname = NULL;
 
                        if (!is_visible_file(conn, directory, dname, &st, True)) {
                                continue;
                        }
 
                        /* Quick check for "." and ".." */
-                       if (fname[0] == '.') {
-                               if (!fname[1] || (fname[1] == '.' && !fname[2])) {
-                                       continue;
-                               }
+                       if (ISDOT(dname) || ISDOTDOT(dname)) {
+                               continue;
                        }
 
-                       if(!mask_match(fname, mask, conn->case_sensitive)) {
+                       if(!mask_match(dname, mask, conn->case_sensitive)) {
                                continue;
                        }
-                               
-                       slprintf(fname,sizeof(fname)-1, "%s/%s",directory,dname);
+
+                       fname = talloc_asprintf(ctx, "%s/%s",
+                                       directory,
+                                       dname);
+                       if (!fname) {
+                               return NT_STATUS_NO_MEMORY;
+                       }
 
                        status = check_name(conn, fname);
                        if (!NT_STATUS_IS_OK(status)) {
@@ -2234,16 +2452,19 @@ NTSTATUS unlink_internals(connection_struct *conn, struct smb_request *req,
 
                        status = do_unlink(conn, req, fname, dirtype);
                        if (!NT_STATUS_IS_OK(status)) {
+                               TALLOC_FREE(fname);
                                continue;
                        }
 
                        count++;
                        DEBUG(3,("unlink_internals: succesful unlink [%s]\n",
                                 fname));
+
+                       TALLOC_FREE(fname);
                }
                CloseDir(dir_hnd);
        }
-       
+
        if (count == 0 && NT_STATUS_IS_OK(status)) {
                status = map_nt_error_from_unix(errno);
        }
@@ -2255,12 +2476,14 @@ NTSTATUS unlink_internals(connection_struct *conn, struct smb_request *req,
  Reply to a unlink
 ****************************************************************************/
 
-void reply_unlink(connection_struct *conn, struct smb_request *req)
+void reply_unlink(struct smb_request *req)
 {
-       pstring name;
+       connection_struct *conn = req->conn;
+       char *name = NULL;
        uint32 dirtype;
        NTSTATUS status;
-       BOOL path_contains_wcard = False;
+       bool path_contains_wcard = False;
+       TALLOC_CTX *ctx = talloc_tos();
 
        START_PROFILE(SMBunlink);
 
@@ -2271,9 +2494,9 @@ void reply_unlink(connection_struct *conn, struct smb_request *req)
        }
 
        dirtype = SVAL(req->inbuf,smb_vwv0);
-       
-       srvstr_get_path_wcard((char *)req->inbuf, req->flags2, name,
-                             smb_buf(req->inbuf) + 1, sizeof(name), 0,
+
+       srvstr_get_path_wcard(ctx, (char *)req->inbuf, req->flags2, &name,
+                             smb_buf(req->inbuf) + 1, 0,
                              STR_TERMINATE, &status, &path_contains_wcard);
        if (!NT_STATUS_IS_OK(status)) {
                reply_nterror(req, status);
@@ -2281,9 +2504,11 @@ void reply_unlink(connection_struct *conn, struct smb_request *req)
                return;
        }
 
-       status = resolve_dfspath_wcard(conn,
+       status = resolve_dfspath_wcard(ctx, conn,
                                       req->flags2 & FLAGS2_DFS_PATHNAMES,
-                                      name, &path_contains_wcard);
+                                      name,
+                                      &name,
+                                      &path_contains_wcard);
        if (!NT_STATUS_IS_OK(status)) {
                if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
                        reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
@@ -2295,9 +2520,9 @@ void reply_unlink(connection_struct *conn, struct smb_request *req)
                END_PROFILE(SMBunlink);
                return;
        }
-       
+
        DEBUG(3,("reply_unlink : %s\n",name));
-       
+
        status = unlink_internals(conn, req, dirtype, name,
                                  path_contains_wcard);
        if (!NT_STATUS_IS_OK(status)) {
@@ -2323,9 +2548,12 @@ void reply_unlink(connection_struct *conn, struct smb_request *req)
 
 static void fail_readraw(void)
 {
-       pstring errstr;
-       slprintf(errstr, sizeof(errstr)-1, "FAIL ! reply_readbraw: socket write fail (%s)",
-               strerror(errno) );
+       const char *errstr = talloc_asprintf(talloc_tos(),
+                       "FAIL ! reply_readbraw: socket write fail (%s)",
+                       strerror(errno));
+       if (!errstr) {
+               errstr = "";
+       }
        exit_server_cleanly(errstr);
 }
 
@@ -2333,9 +2561,22 @@ static void fail_readraw(void)
  Fake (read/write) sendfile. Returns -1 on read or write fail.
 ****************************************************************************/
 
-static ssize_t fake_sendfile(files_struct *fsp, SMB_OFF_T startpos, size_t nread, char *buf, size_t bufsize)
+static ssize_t fake_sendfile(files_struct *fsp, SMB_OFF_T startpos,
+                            size_t nread)
 {
+       size_t bufsize;
        size_t tosend = nread;
+       char *buf;
+
+       if (nread == 0) {
+               return 0;
+       }
+
+       bufsize = MIN(nread, 65536);
+
+       if (!(buf = SMB_MALLOC_ARRAY(char, bufsize))) {
+               return -1;
+       }
 
        while (tosend > 0) {
                ssize_t ret;
@@ -2348,6 +2589,7 @@ static ssize_t fake_sendfile(files_struct *fsp, SMB_OFF_T startpos, size_t nread
                }
                ret = read_file(fsp,buf,startpos,cur_read);
                if (ret == -1) {
+                       SAFE_FREE(buf);
                        return -1;
                }
 
@@ -2357,22 +2599,41 @@ static ssize_t fake_sendfile(files_struct *fsp, SMB_OFF_T startpos, size_t nread
                }
 
                if (write_data(smbd_server_fd(),buf,cur_read) != cur_read) {
+                       SAFE_FREE(buf);
                        return -1;
                }
                tosend -= cur_read;
                startpos += cur_read;
        }
 
+       SAFE_FREE(buf);
        return (ssize_t)nread;
 }
 
+/****************************************************************************
+ Return a readbraw error (4 bytes of zero).
+****************************************************************************/
+
+static void reply_readbraw_error(void)
+{
+       char header[4];
+       SIVAL(header,0,0);
+       if (write_data(smbd_server_fd(),header,4) != 4) {
+               fail_readraw();
+       }
+}
+
 /****************************************************************************
  Use sendfile in readbraw.
 ****************************************************************************/
 
-void send_file_readbraw(connection_struct *conn, files_struct *fsp, SMB_OFF_T startpos, size_t nread,
-               ssize_t mincount, char *outbuf, int out_buffsize)
+void send_file_readbraw(connection_struct *conn,
+                       files_struct *fsp,
+                       SMB_OFF_T startpos,
+                       size_t nread,
+                       ssize_t mincount)
 {
+       char *outbuf = NULL;
        ssize_t ret=0;
 
 #if defined(WITH_SENDFILE)
@@ -2385,15 +2646,16 @@ void send_file_readbraw(connection_struct *conn, files_struct *fsp, SMB_OFF_T st
 
        if ( (chain_size == 0) && (nread > 0) &&
            (fsp->wcp == NULL) && lp_use_sendfile(SNUM(conn)) ) {
-               DATA_BLOB header;
+               char header[4];
+               DATA_BLOB header_blob;
 
-               _smb_setlen(outbuf,nread);
-               header.data = (uint8 *)outbuf;
-               header.length = 4;
-               header.free = NULL;
+               _smb_setlen(header,nread);
+               header_blob = data_blob_const(header, 4);
 
-               if ( SMB_VFS_SENDFILE( smbd_server_fd(), fsp, fsp->fh->fd, &header, startpos, nread) == -1) {
-                       /* Returning ENOSYS means no data at all was sent. Do this as a normal read. */
+               if ( SMB_VFS_SENDFILE( smbd_server_fd(), fsp, fsp->fh->fd,
+                               &header_blob, startpos, nread) == -1) {
+                       /* Returning ENOSYS means no data at all was sent.
+                        * Do this as a normal read. */
                        if (errno == ENOSYS) {
                                goto normal_readbraw;
                        }
@@ -2408,7 +2670,7 @@ void send_file_readbraw(connection_struct *conn, files_struct *fsp, SMB_OFF_T st
                                set_use_sendfile(SNUM(conn), False);
                                DEBUG(0,("send_file_readbraw: sendfile not available. Faking..\n"));
 
-                               if (fake_sendfile(fsp, startpos, nread, outbuf + 4, out_buffsize - 4) == -1) {
+                               if (fake_sendfile(fsp, startpos, nread) == -1) {
                                        DEBUG(0,("send_file_readbraw: fake_sendfile failed for file %s (%s).\n",
                                                fsp->fsp_name, strerror(errno) ));
                                        exit_server_cleanly("send_file_readbraw fake_sendfile failed");
@@ -2427,6 +2689,14 @@ void send_file_readbraw(connection_struct *conn, files_struct *fsp, SMB_OFF_T st
 
 normal_readbraw:
 
+       outbuf = TALLOC_ARRAY(NULL, char, nread+4);
+       if (!outbuf) {
+               DEBUG(0,("send_file_readbraw: TALLOC_ARRAY failed for size %u.\n",
+                       (unsigned)(nread+4)));
+               reply_readbraw_error();
+               return;
+       }
+
        if (nread > 0) {
                ret = read_file(fsp,outbuf+4,startpos,nread);
 #if 0 /* mincount appears to be ignored in a W2K server. JRA. */
@@ -2441,23 +2711,35 @@ normal_readbraw:
        _smb_setlen(outbuf,ret);
        if (write_data(smbd_server_fd(),outbuf,4+ret) != 4+ret)
                fail_readraw();
+
+       TALLOC_FREE(outbuf);
 }
 
 /****************************************************************************
  Reply to a readbraw (core+ protocol).
 ****************************************************************************/
 
-int reply_readbraw(connection_struct *conn, char *inbuf, char *outbuf, int dum_size, int out_buffsize)
+void reply_readbraw(struct smb_request *req)
 {
+       connection_struct *conn = req->conn;
        ssize_t maxcount,mincount;
        size_t nread = 0;
        SMB_OFF_T startpos;
-       char *header = outbuf;
        files_struct *fsp;
+       SMB_STRUCT_STAT st;
+       SMB_OFF_T size = 0;
+
        START_PROFILE(SMBreadbraw);
 
-       if (srv_is_signing_active()) {
-               exit_server_cleanly("reply_readbraw: SMB signing is active - raw reads/writes are disallowed.");
+       if (srv_is_signing_active() || is_encrypted_packet(req->inbuf)) {
+               exit_server_cleanly("reply_readbraw: SMB signing/sealing is active - "
+                       "raw reads/writes are disallowed.");
+       }
+
+       if (req->wct < 8) {
+               reply_readbraw_error();
+               END_PROFILE(SMBreadbraw);
+               return;
        }
 
        /*
@@ -2466,32 +2748,49 @@ int reply_readbraw(connection_struct *conn, char *inbuf, char *outbuf, int dum_s
         * return a zero length response here.
         */
 
-       fsp = file_fsp(SVAL(inbuf,smb_vwv0));
+       fsp = file_fsp(SVAL(req->inbuf,smb_vwv0));
+
+       /*
+        * We have to do a check_fsp by hand here, as
+        * we must always return 4 zero bytes on error,
+        * not a NTSTATUS.
+        */
 
-       if (!FNUM_OK(fsp,conn) || !fsp->can_read) {
+       if (!fsp || !conn || conn != fsp->conn ||
+                       current_user.vuid != fsp->vuid ||
+                       fsp->is_directory || fsp->fh->fd == -1) {
                /*
                 * fsp could be NULL here so use the value from the packet. JRA.
                 */
-               DEBUG(3,("fnum %d not open in readbraw - cache prime?\n",(int)SVAL(inbuf,smb_vwv0)));
-               _smb_setlen(header,0);
-               if (write_data(smbd_server_fd(),header,4) != 4)
-                       fail_readraw();
+               DEBUG(3,("reply_readbraw: fnum %d not valid "
+                       "- cache prime?\n",
+                       (int)SVAL(req->inbuf,smb_vwv0)));
+               reply_readbraw_error();
                END_PROFILE(SMBreadbraw);
-               return(-1);
+               return;
        }
 
-       CHECK_FSP(fsp,conn);
+       /* Do a "by hand" version of CHECK_READ. */
+       if (!(fsp->can_read ||
+                       ((req->flags2 & FLAGS2_READ_PERMIT_EXECUTE) &&
+                               (fsp->access_mask & FILE_EXECUTE)))) {
+               DEBUG(3,("reply_readbraw: fnum %d not readable.\n",
+                               (int)SVAL(req->inbuf,smb_vwv0)));
+               reply_readbraw_error();
+               END_PROFILE(SMBreadbraw);
+               return;
+       }
 
        flush_write_cache(fsp, READRAW_FLUSH);
 
-       startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv1);
-       if(CVAL(inbuf,smb_wct) == 10) {
+       startpos = IVAL_TO_SMB_OFF_T(req->inbuf,smb_vwv1);
+       if(req->wct == 10) {
                /*
                 * This is a large offset (64 bit) read.
                 */
 #ifdef LARGE_SMB_OFF_T
 
-               startpos |= (((SMB_OFF_T)IVAL(inbuf,smb_vwv8)) << 32);
+               startpos |= (((SMB_OFF_T)IVAL(req->inbuf,smb_vwv8)) << 32);
 
 #else /* !LARGE_SMB_OFF_T */
 
@@ -2499,46 +2798,51 @@ int reply_readbraw(connection_struct *conn, char *inbuf, char *outbuf, int dum_s
                 * Ensure we haven't been sent a >32 bit offset.
                 */
 
-               if(IVAL(inbuf,smb_vwv8) != 0) {
-                       DEBUG(0,("readbraw - large offset (%x << 32) used and we don't support \
-64 bit offsets.\n", (unsigned int)IVAL(inbuf,smb_vwv8) ));
-                       _smb_setlen(header,0);
-                       if (write_data(smbd_server_fd(),header,4) != 4)
-                               fail_readraw();
+               if(IVAL(req->inbuf,smb_vwv8) != 0) {
+                       DEBUG(0,("reply_readbraw: large offset "
+                               "(%x << 32) used and we don't support "
+                               "64 bit offsets.\n",
+                       (unsigned int)IVAL(req->inbuf,smb_vwv8) ));
+                       reply_readbraw_error();
                        END_PROFILE(SMBreadbraw);
-                       return(-1);
+                       return;
                }
 
 #endif /* LARGE_SMB_OFF_T */
 
                if(startpos < 0) {
-                       DEBUG(0,("readbraw - negative 64 bit readraw offset (%.0f) !\n", (double)startpos ));
-                       _smb_setlen(header,0);
-                       if (write_data(smbd_server_fd(),header,4) != 4)
-                               fail_readraw();
+                       DEBUG(0,("reply_readbraw: negative 64 bit "
+                               "readraw offset (%.0f) !\n",
+                               (double)startpos ));
+                       reply_readbraw_error();
                        END_PROFILE(SMBreadbraw);
-                       return(-1);
+                       return;
                }      
        }
-       maxcount = (SVAL(inbuf,smb_vwv3) & 0xFFFF);
-       mincount = (SVAL(inbuf,smb_vwv4) & 0xFFFF);
+
+       maxcount = (SVAL(req->inbuf,smb_vwv3) & 0xFFFF);
+       mincount = (SVAL(req->inbuf,smb_vwv4) & 0xFFFF);
 
        /* ensure we don't overrun the packet size */
        maxcount = MIN(65535,maxcount);
 
-       if (!is_locked(fsp,(uint32)SVAL(inbuf,smb_pid),(SMB_BIG_UINT)maxcount,(SMB_BIG_UINT)startpos, READ_LOCK)) {
-               SMB_STRUCT_STAT st;
-               SMB_OFF_T size = 0;
-  
-               if (SMB_VFS_FSTAT(fsp,fsp->fh->fd,&st) == 0) {
-                       size = st.st_size;
-               }
+       if (is_locked(fsp,(uint32)req->smbpid,
+                       (SMB_BIG_UINT)maxcount,
+                       (SMB_BIG_UINT)startpos,
+                       READ_LOCK)) {
+               reply_readbraw_error();
+               END_PROFILE(SMBreadbraw);
+               return;
+       }
 
-               if (startpos >= size) {
-                       nread = 0;
-               } else {
-                       nread = MIN(maxcount,(size - startpos));          
-               }
+       if (SMB_VFS_FSTAT(fsp,fsp->fh->fd,&st) == 0) {
+               size = st.st_size;
+       }
+
+       if (startpos >= size) {
+               nread = 0;
+       } else {
+               nread = MIN(maxcount,(size - startpos));
        }
 
 #if 0 /* mincount appears to be ignored in a W2K server. JRA. */
@@ -2546,14 +2850,17 @@ int reply_readbraw(connection_struct *conn, char *inbuf, char *outbuf, int dum_s
                nread = 0;
 #endif
   
-       DEBUG( 3, ( "readbraw fnum=%d start=%.0f max=%lu min=%lu nread=%lu\n", fsp->fnum, (double)startpos,
-                               (unsigned long)maxcount, (unsigned long)mincount, (unsigned long)nread ) );
+       DEBUG( 3, ( "reply_readbraw: fnum=%d start=%.0f max=%lu "
+               "min=%lu nread=%lu\n",
+               fsp->fnum, (double)startpos,
+               (unsigned long)maxcount,
+               (unsigned long)mincount,
+               (unsigned long)nread ) );
   
-       send_file_readbraw(conn, fsp, startpos, nread, mincount, outbuf, out_buffsize);
+       send_file_readbraw(conn, fsp, startpos, nread, mincount);
 
-       DEBUG(5,("readbraw finished\n"));
+       DEBUG(5,("reply_readbraw finished\n"));
        END_PROFILE(SMBreadbraw);
-       return -1;
 }
 
 #undef DBGC_CLASS
@@ -2563,31 +2870,49 @@ int reply_readbraw(connection_struct *conn, char *inbuf, char *outbuf, int dum_s
  Reply to a lockread (core+ protocol).
 ****************************************************************************/
 
-int reply_lockread(connection_struct *conn, char *inbuf,char *outbuf, int length, int dum_buffsiz)
+void reply_lockread(struct smb_request *req)
 {
+       connection_struct *conn = req->conn;
        ssize_t nread = -1;
        char *data;
-       int outsize = 0;
        SMB_OFF_T startpos;
        size_t numtoread;
        NTSTATUS status;
-       files_struct *fsp = file_fsp(SVAL(inbuf,smb_vwv0));
+       files_struct *fsp;
        struct byte_range_lock *br_lck = NULL;
+       char *p = NULL;
+
        START_PROFILE(SMBlockread);
 
-       CHECK_FSP(fsp,conn);
-       if (!CHECK_READ(fsp,inbuf)) {
-               return(ERROR_DOS(ERRDOS,ERRbadaccess));
+       if (req->wct < 5) {
+               reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
+               END_PROFILE(SMBlockread);
+               return;
+       }
+
+       fsp = file_fsp(SVAL(req->inbuf,smb_vwv0));
+
+       if (!check_fsp(conn, req, fsp, &current_user)) {
+               END_PROFILE(SMBlockread);
+               return;
+       }
+
+       if (!CHECK_READ(fsp,req->inbuf)) {
+               reply_doserror(req, ERRDOS, ERRbadaccess);
+               END_PROFILE(SMBlockread);
+               return;
        }
 
        release_level_2_oplocks_on_change(fsp);
 
-       numtoread = SVAL(inbuf,smb_vwv1);
-       startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2);
-  
-       outsize = set_message(inbuf,outbuf,5,3,True);
-       numtoread = MIN(BUFFER_SIZE-outsize,numtoread);
-       data = smb_buf(outbuf) + 3;
+       numtoread = SVAL(req->inbuf,smb_vwv1);
+       startpos = IVAL_TO_SMB_OFF_T(req->inbuf,smb_vwv2);
+
+       numtoread = MIN(BUFFER_SIZE - (smb_size + 3*2 + 3), numtoread);
+
+       reply_outbuf(req, 5, numtoread + 3);
+
+       data = smb_buf(req->outbuf) + 3;
        
        /*
         * NB. Discovered by Menny Hamburger at Mainsoft. This is a core+
@@ -2599,7 +2924,7 @@ int reply_lockread(connection_struct *conn, char *inbuf,char *outbuf, int length
        
        br_lck = do_lock(smbd_messaging_context(),
                        fsp,
-                       (uint32)SVAL(inbuf,smb_pid), 
+                       req->smbpid,
                        (SMB_BIG_UINT)numtoread,
                        (SMB_BIG_UINT)startpos,
                        WRITE_LOCK,
@@ -2610,8 +2935,9 @@ int reply_lockread(connection_struct *conn, char *inbuf,char *outbuf, int length
        TALLOC_FREE(br_lck);
 
        if (NT_STATUS_V(status)) {
+               reply_nterror(req, status);
                END_PROFILE(SMBlockread);
-               return ERROR_NT(status);
+               return;
        }
 
        /*
@@ -2627,20 +2953,24 @@ Returning short read of maximum allowed for compatibility with Windows 2000.\n",
        nread = read_file(fsp,data,startpos,numtoread);
 
        if (nread < 0) {
+               reply_unixerror(req, ERRDOS, ERRnoaccess);
                END_PROFILE(SMBlockread);
-               return(UNIXERROR(ERRDOS,ERRnoaccess));
+               return;
        }
        
-       outsize += nread;
-       SSVAL(outbuf,smb_vwv0,nread);
-       SSVAL(outbuf,smb_vwv5,nread+3);
-       SSVAL(smb_buf(outbuf),1,nread);
+       srv_set_message((char *)req->outbuf, 5, nread+3, False);
+
+       SSVAL(req->outbuf,smb_vwv0,nread);
+       SSVAL(req->outbuf,smb_vwv5,nread+3);
+       p = smb_buf(req->outbuf);
+       SCVAL(p,0,0); /* pad byte. */
+       SSVAL(p,1,nread);
        
        DEBUG(3,("lockread fnum=%d num=%d nread=%d\n",
                 fsp->fnum, (int)numtoread, (int)nread));
 
        END_PROFILE(SMBlockread);
-       return(outsize);
+       return;
 }
 
 #undef DBGC_CLASS
@@ -2650,26 +2980,42 @@ Returning short read of maximum allowed for compatibility with Windows 2000.\n",
  Reply to a read.
 ****************************************************************************/
 
-int reply_read(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
+void reply_read(struct smb_request *req)
 {
+       connection_struct *conn = req->conn;
        size_t numtoread;
        ssize_t nread = 0;
        char *data;
        SMB_OFF_T startpos;
        int outsize = 0;
-       files_struct *fsp = file_fsp(SVAL(inbuf,smb_vwv0));
+       files_struct *fsp;
+
        START_PROFILE(SMBread);
 
-       CHECK_FSP(fsp,conn);
-       if (!CHECK_READ(fsp,inbuf)) {
-               return(ERROR_DOS(ERRDOS,ERRbadaccess));
+       if (req->wct < 3) {
+               reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
+               END_PROFILE(SMBread);
+               return;
+       }
+
+       fsp = file_fsp(SVAL(req->inbuf,smb_vwv0));
+
+       if (!check_fsp(conn, req, fsp, &current_user)) {
+               END_PROFILE(SMBread);
+               return;
+       }
+
+       if (!CHECK_READ(fsp,req->inbuf)) {
+               reply_doserror(req, ERRDOS, ERRbadaccess);
+               END_PROFILE(SMBread);
+               return;
        }
 
-       numtoread = SVAL(inbuf,smb_vwv1);
-       startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2);
+       numtoread = SVAL(req->inbuf,smb_vwv1);
+       startpos = IVAL_TO_SMB_OFF_T(req->inbuf,smb_vwv2);
 
-       outsize = set_message(inbuf,outbuf,5,3,True);
        numtoread = MIN(BUFFER_SIZE-outsize,numtoread);
+
        /*
         * The requested read size cannot be greater than max_recv. JRA.
         */
@@ -2680,50 +3026,60 @@ Returning short read of maximum allowed for compatibility with Windows 2000.\n",
                numtoread = MIN(numtoread,max_recv);
        }
 
-       data = smb_buf(outbuf) + 3;
+       reply_outbuf(req, 5, numtoread+3);
+
+       data = smb_buf(req->outbuf) + 3;
   
-       if (is_locked(fsp,(uint32)SVAL(inbuf,smb_pid),(SMB_BIG_UINT)numtoread,(SMB_BIG_UINT)startpos, READ_LOCK)) {
+       if (is_locked(fsp, (uint32)req->smbpid, (SMB_BIG_UINT)numtoread,
+                     (SMB_BIG_UINT)startpos, READ_LOCK)) {
+               reply_doserror(req, ERRDOS,ERRlock);
                END_PROFILE(SMBread);
-               return ERROR_DOS(ERRDOS,ERRlock);
+               return;
        }
 
        if (numtoread > 0)
                nread = read_file(fsp,data,startpos,numtoread);
 
        if (nread < 0) {
+               reply_unixerror(req, ERRDOS,ERRnoaccess);
                END_PROFILE(SMBread);
-               return(UNIXERROR(ERRDOS,ERRnoaccess));
+               return;
        }
-  
-       outsize += nread;
-       SSVAL(outbuf,smb_vwv0,nread);
-       SSVAL(outbuf,smb_vwv5,nread+3);
-       SCVAL(smb_buf(outbuf),0,1);
-       SSVAL(smb_buf(outbuf),1,nread);
+
+       srv_set_message((char *)req->outbuf, 5, nread+3, False);
+
+       SSVAL(req->outbuf,smb_vwv0,nread);
+       SSVAL(req->outbuf,smb_vwv5,nread+3);
+       SCVAL(smb_buf(req->outbuf),0,1);
+       SSVAL(smb_buf(req->outbuf),1,nread);
   
        DEBUG( 3, ( "read fnum=%d num=%d nread=%d\n",
                fsp->fnum, (int)numtoread, (int)nread ) );
 
        END_PROFILE(SMBread);
-       return(outsize);
+       return;
 }
 
 /****************************************************************************
  Setup readX header.
 ****************************************************************************/
 
-static int setup_readX_header(char *inbuf, char *outbuf, size_t smb_maxcnt)
+static int setup_readX_header(char *outbuf, size_t smb_maxcnt)
 {
        int outsize;
-       char *data = smb_buf(outbuf);
+       char *data;
 
-       SSVAL(outbuf,smb_vwv2,0xFFFF); /* Remaining - must be -1. */
-       SSVAL(outbuf,smb_vwv5,smb_maxcnt);
-       SSVAL(outbuf,smb_vwv6,smb_offset(data,outbuf));
+       outsize = srv_set_message(outbuf,12,smb_maxcnt,False);
+       data = smb_buf(outbuf);
+
+       memset(outbuf+smb_vwv0,'\0',24); /* valgrind init. */
+
+       SCVAL(outbuf,smb_vwv0,0xFF);
+       SSVAL(outbuf,smb_vwv2,0xFFFF); /* Remaining - must be -1. */
+       SSVAL(outbuf,smb_vwv5,smb_maxcnt);
+       SSVAL(outbuf,smb_vwv6,smb_offset(data,outbuf));
        SSVAL(outbuf,smb_vwv7,(smb_maxcnt >> 16));
        SSVAL(smb_buf(outbuf),-2,smb_maxcnt);
-       SCVAL(outbuf,smb_vwv0,0xFF);
-       outsize = set_message(inbuf, outbuf,12,smb_maxcnt,False);
        /* Reset the outgoing length, set_message truncates at 0x1FFFF. */
        _smb_setlen_large(outbuf,(smb_size + 12*2 + smb_maxcnt - 4));
        return outsize;
@@ -2733,16 +3089,16 @@ static int setup_readX_header(char *inbuf, char *outbuf, size_t smb_maxcnt)
  Reply to a read and X - possibly using sendfile.
 ****************************************************************************/
 
-int send_file_readX(connection_struct *conn, char *inbuf,char *outbuf,int length, int len_outbuf,
-               files_struct *fsp, SMB_OFF_T startpos, size_t smb_maxcnt)
+static void send_file_readX(connection_struct *conn, struct smb_request *req,
+                           files_struct *fsp, SMB_OFF_T startpos,
+                           size_t smb_maxcnt)
 {
        SMB_STRUCT_STAT sbuf;
-       int outsize = 0;
        ssize_t nread = -1;
-       char *data = smb_buf(outbuf);
 
        if(SMB_VFS_FSTAT(fsp,fsp->fh->fd, &sbuf) == -1) {
-               return(UNIXERROR(ERRDOS,ERRnoaccess));
+               reply_unixerror(req, ERRDOS, ERRnoaccess);
+               return;
        }
 
        if (startpos > sbuf.st_size) {
@@ -2757,26 +3113,27 @@ int send_file_readX(connection_struct *conn, char *inbuf,char *outbuf,int length
 
 #if defined(WITH_SENDFILE)
        /*
-        * We can only use sendfile on a non-chained packet 
+        * We can only use sendfile on a non-chained packet
         * but we can use on a non-oplocked file. tridge proved this
         * on a train in Germany :-). JRA.
         */
 
-       if ((chain_size == 0) && (CVAL(inbuf,smb_vwv0) == 0xFF) &&
+       if ((chain_size == 0) && (CVAL(req->inbuf,smb_vwv0) == 0xFF) &&
+           !is_encrypted_packet(req->inbuf) &&
            lp_use_sendfile(SNUM(conn)) && (fsp->wcp == NULL) ) {
+               uint8 headerbuf[smb_size + 12 * 2];
                DATA_BLOB header;
 
-               /* 
+               /*
                 * Set up the packet header before send. We
                 * assume here the sendfile will work (get the
                 * correct amount of data).
                 */
 
-               setup_readX_header(inbuf,outbuf,smb_maxcnt);
-               set_message(inbuf,outbuf,12,smb_maxcnt,False);
-               header.data = (uint8 *)outbuf;
-               header.length = data - outbuf;
-               header.free = NULL;
+               header = data_blob_const(headerbuf, sizeof(headerbuf));
+
+               construct_reply_common((char *)req->inbuf, (char *)headerbuf);
+               setup_readX_header((char *)headerbuf, smb_maxcnt);
 
                if ((nread = SMB_VFS_SENDFILE( smbd_server_fd(), fsp, fsp->fh->fd, &header, startpos, smb_maxcnt)) == -1) {
                        /* Returning ENOSYS means no data at all was sent. Do this as a normal read. */
@@ -2794,17 +3151,18 @@ int send_file_readX(connection_struct *conn, char *inbuf,char *outbuf,int length
                                /* Ensure we don't do this again. */
                                set_use_sendfile(SNUM(conn), False);
                                DEBUG(0,("send_file_readX: sendfile not available. Faking..\n"));
-
-                               if ((nread = fake_sendfile(fsp, startpos, smb_maxcnt, data,
-                                                       len_outbuf - (data-outbuf))) == -1) {
+                               nread = fake_sendfile(fsp, startpos,
+                                                     smb_maxcnt);
+                               if (nread == -1) {
                                        DEBUG(0,("send_file_readX: fake_sendfile failed for file %s (%s).\n",
                                                fsp->fsp_name, strerror(errno) ));
                                        exit_server_cleanly("send_file_readX: fake_sendfile failed");
                                }
                                DEBUG( 3, ( "send_file_readX: fake_sendfile fnum=%d max=%d nread=%d\n",
                                        fsp->fnum, (int)smb_maxcnt, (int)nread ) );
-                               /* Returning -1 here means successful sendfile. */
-                               return -1;
+                               /* No outbuf here means successful sendfile. */
+                               TALLOC_FREE(req->outbuf);
+                               return;
                        }
 
                        DEBUG(0,("send_file_readX: sendfile failed for file %s (%s). Terminating\n",
@@ -2814,43 +3172,53 @@ int send_file_readX(connection_struct *conn, char *inbuf,char *outbuf,int length
 
                DEBUG( 3, ( "send_file_readX: sendfile fnum=%d max=%d nread=%d\n",
                        fsp->fnum, (int)smb_maxcnt, (int)nread ) );
-               /* Returning -1 here means successful sendfile. */
-               return -1;
+               /* No outbuf here means successful sendfile. */
+               TALLOC_FREE(req->outbuf);
+               return;
        }
-
 #endif
 
 normal_read:
 
        if ((smb_maxcnt & 0xFF0000) > 0x10000) {
-               int sendlen = setup_readX_header(inbuf,outbuf,smb_maxcnt) - smb_maxcnt;
+               uint8 headerbuf[smb_size + 2*12];
+
+               construct_reply_common((char *)req->inbuf, (char *)headerbuf);
+               setup_readX_header((char *)headerbuf, smb_maxcnt);
+
                /* Send out the header. */
-               if (write_data(smbd_server_fd(),outbuf,sendlen) != sendlen) {
+               if (write_data(smbd_server_fd(), (char *)headerbuf,
+                              sizeof(headerbuf)) != sizeof(headerbuf)) {
                        DEBUG(0,("send_file_readX: write_data failed for file %s (%s). Terminating\n",
                                fsp->fsp_name, strerror(errno) ));
                        exit_server_cleanly("send_file_readX sendfile failed");
                }
-               if ((nread = fake_sendfile(fsp, startpos, smb_maxcnt, data,
-                                       len_outbuf - (data-outbuf))) == -1) {
+               nread = fake_sendfile(fsp, startpos, smb_maxcnt);
+               if (nread == -1) {
                        DEBUG(0,("send_file_readX: fake_sendfile failed for file %s (%s).\n",
                                fsp->fsp_name, strerror(errno) ));
                        exit_server_cleanly("send_file_readX: fake_sendfile failed");
                }
-               return -1;
+               TALLOC_FREE(req->outbuf);
+               return;
        } else {
-               nread = read_file(fsp,data,startpos,smb_maxcnt);
+               reply_outbuf(req, 12, smb_maxcnt);
 
+               nread = read_file(fsp, smb_buf(req->outbuf), startpos,
+                                 smb_maxcnt);
                if (nread < 0) {
-                       return(UNIXERROR(ERRDOS,ERRnoaccess));
+                       reply_unixerror(req, ERRDOS, ERRnoaccess);
+                       return;
                }
 
-               outsize = setup_readX_header(inbuf, outbuf,nread);
+               setup_readX_header((char *)req->outbuf, nread);
 
                DEBUG( 3, ( "send_file_readX fnum=%d max=%d nread=%d\n",
                        fsp->fnum, (int)smb_maxcnt, (int)nread ) );
 
-               /* Returning the number of bytes we want to send back - including header. */
-               return outsize;
+               chain_reply(req);
+
+               return;
        }
 }
 
@@ -2858,58 +3226,79 @@ normal_read:
  Reply to a read and X.
 ****************************************************************************/
 
-int reply_read_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
+void reply_read_and_X(struct smb_request *req)
 {
-       files_struct *fsp = file_fsp(SVAL(inbuf,smb_vwv2));
-       SMB_OFF_T startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv3);
-       ssize_t nread = -1;
-       size_t smb_maxcnt = SVAL(inbuf,smb_vwv5);
-       BOOL big_readX = False;
+       connection_struct *conn = req->conn;
+       files_struct *fsp;
+       SMB_OFF_T startpos;
+       size_t smb_maxcnt;
+       bool big_readX = False;
 #if 0
-       size_t smb_mincnt = SVAL(inbuf,smb_vwv6);
+       size_t smb_mincnt = SVAL(req->inbuf,smb_vwv6);
 #endif
 
        START_PROFILE(SMBreadX);
 
+       if ((req->wct != 10) && (req->wct != 12)) {
+               reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
+               return;
+       }
+
+       fsp = file_fsp(SVAL(req->inbuf,smb_vwv2));
+       startpos = IVAL_TO_SMB_OFF_T(req->inbuf,smb_vwv3);
+       smb_maxcnt = SVAL(req->inbuf,smb_vwv5);
+
        /* If it's an IPC, pass off the pipe handler. */
        if (IS_IPC(conn)) {
+               reply_pipe_read_and_X(req);
                END_PROFILE(SMBreadX);
-               return reply_pipe_read_and_X(inbuf,outbuf,length,bufsize);
+               return;
        }
 
-       CHECK_FSP(fsp,conn);
-       if (!CHECK_READ(fsp,inbuf)) {
-               return(ERROR_DOS(ERRDOS,ERRbadaccess));
+       if (!check_fsp(conn, req, fsp, &current_user)) {
+               END_PROFILE(SMBreadX);
+               return;
        }
 
-       set_message(inbuf,outbuf,12,0,True);
+       if (!CHECK_READ(fsp,req->inbuf)) {
+               reply_doserror(req, ERRDOS,ERRbadaccess);
+               END_PROFILE(SMBreadX);
+               return;
+       }
 
        if (global_client_caps & CAP_LARGE_READX) {
-               size_t upper_size = SVAL(inbuf,smb_vwv7);
+               size_t upper_size = SVAL(req->inbuf,smb_vwv7);
                smb_maxcnt |= (upper_size<<16);
                if (upper_size > 1) {
                        /* Can't do this on a chained packet. */
-                       if ((CVAL(inbuf,smb_vwv0) != 0xFF)) {
-                               return ERROR_NT(NT_STATUS_NOT_SUPPORTED);
+                       if ((CVAL(req->inbuf,smb_vwv0) != 0xFF)) {
+                               reply_nterror(req, NT_STATUS_NOT_SUPPORTED);
+                               END_PROFILE(SMBreadX);
+                               return;
                        }
                        /* We currently don't do this on signed or sealed data. */
-                       if (srv_is_signing_active() || srv_encryption_on()) {
-                               return ERROR_NT(NT_STATUS_NOT_SUPPORTED);
+                       if (srv_is_signing_active() || is_encrypted_packet(req->inbuf)) {
+                               reply_nterror(req, NT_STATUS_NOT_SUPPORTED);
+                               END_PROFILE(SMBreadX);
+                               return;
                        }
                        /* Is there room in the reply for this data ? */
                        if (smb_maxcnt > (0xFFFFFF - (smb_size -4 + 12*2)))  {
-                               return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
+                               reply_nterror(req,
+                                             NT_STATUS_INVALID_PARAMETER);
+                               END_PROFILE(SMBreadX);
+                               return;
                        }
                        big_readX = True;
                }
        }
 
-       if(CVAL(inbuf,smb_wct) == 12) {
+       if (req->wct == 12) {
 #ifdef LARGE_SMB_OFF_T
                /*
                 * This is a large offset (64 bit) read.
                 */
-               startpos |= (((SMB_OFF_T)IVAL(inbuf,smb_vwv10)) << 32);
+               startpos |= (((SMB_OFF_T)IVAL(req->inbuf,smb_vwv10)) << 32);
 
 #else /* !LARGE_SMB_OFF_T */
 
@@ -2917,184 +3306,277 @@ int reply_read_and_X(connection_struct *conn, char *inbuf,char *outbuf,int lengt
                 * Ensure we haven't been sent a >32 bit offset.
                 */
 
-               if(IVAL(inbuf,smb_vwv10) != 0) {
-                       DEBUG(0,("reply_read_and_X - large offset (%x << 32) used and we don't support \
-64 bit offsets.\n", (unsigned int)IVAL(inbuf,smb_vwv10) ));
+               if(IVAL(req->inbuf,smb_vwv10) != 0) {
+                       DEBUG(0,("reply_read_and_X - large offset (%x << 32) "
+                                "used and we don't support 64 bit offsets.\n",
+                                (unsigned int)IVAL(req->inbuf,smb_vwv10) ));
                        END_PROFILE(SMBreadX);
-                       return ERROR_DOS(ERRDOS,ERRbadaccess);
+                       reply_doserror(req, ERRDOS, ERRbadaccess);
+                       return;
                }
 
 #endif /* LARGE_SMB_OFF_T */
 
        }
 
-       if (is_locked(fsp,(uint32)SVAL(inbuf,smb_pid),(SMB_BIG_UINT)smb_maxcnt,(SMB_BIG_UINT)startpos, READ_LOCK)) {
+       if (is_locked(fsp, (uint32)req->smbpid, (SMB_BIG_UINT)smb_maxcnt,
+                     (SMB_BIG_UINT)startpos, READ_LOCK)) {
                END_PROFILE(SMBreadX);
-               return ERROR_DOS(ERRDOS,ERRlock);
+               reply_doserror(req, ERRDOS, ERRlock);
+               return;
        }
 
-       if (!big_readX && schedule_aio_read_and_X(conn, inbuf, outbuf, length, bufsize, fsp, startpos, smb_maxcnt)) {
+       if (!big_readX
+           && schedule_aio_read_and_X(conn, req, fsp, startpos, smb_maxcnt)) {
                END_PROFILE(SMBreadX);
-               return -1;
+               return;
        }
 
-       nread = send_file_readX(conn, inbuf, outbuf, length, bufsize, fsp, startpos, smb_maxcnt);
-       /* Only call chain_reply if not an error. */
-       if (nread != -1 && SVAL(outbuf,smb_rcls) == 0) {
-               nread = chain_reply(inbuf,&outbuf,length,bufsize);
-       }
+       send_file_readX(conn, req, fsp, startpos, smb_maxcnt);
 
        END_PROFILE(SMBreadX);
-       return nread;
+       return;
+}
+
+/****************************************************************************
+ Error replies to writebraw must have smb_wct == 1. Fix this up.
+****************************************************************************/
+
+void error_to_writebrawerr(struct smb_request *req)
+{
+       uint8 *old_outbuf = req->outbuf;
+
+       reply_outbuf(req, 1, 0);
+
+       memcpy(req->outbuf, old_outbuf, smb_size);
+       TALLOC_FREE(old_outbuf);
 }
 
 /****************************************************************************
  Reply to a writebraw (core+ or LANMAN1.0 protocol).
 ****************************************************************************/
 
-int reply_writebraw(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
+void reply_writebraw(struct smb_request *req)
 {
+       connection_struct *conn = req->conn;
+       int outsize = 0;
+       char *buf = NULL;
        ssize_t nwritten=0;
        ssize_t total_written=0;
        size_t numtowrite=0;
        size_t tcount;
        SMB_OFF_T startpos;
        char *data=NULL;
-       BOOL write_through;
-       files_struct *fsp = file_fsp(SVAL(inbuf,smb_vwv0));
-       int outsize = 0;
+       bool write_through;
+       files_struct *fsp;
        NTSTATUS status;
+
        START_PROFILE(SMBwritebraw);
 
+       /*
+        * If we ever reply with an error, it must have the SMB command
+        * type of SMBwritec, not SMBwriteBraw, as this tells the client
+        * we're finished.
+        */
+       SCVAL(req->inbuf,smb_com,SMBwritec);
+
        if (srv_is_signing_active()) {
-               exit_server_cleanly("reply_writebraw: SMB signing is active - raw reads/writes are disallowed.");
+               END_PROFILE(SMBwritebraw);
+               exit_server_cleanly("reply_writebraw: SMB signing is active - "
+                               "raw reads/writes are disallowed.");
+       }
+
+       if (req->wct < 12) {
+               reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
+               error_to_writebrawerr(req);
+               END_PROFILE(SMBwritebraw);
+               return;
+       }
+
+       fsp = file_fsp(SVAL(req->inbuf,smb_vwv0));
+       if (!check_fsp(conn, req, fsp, &current_user)) {
+               error_to_writebrawerr(req);
+               END_PROFILE(SMBwritebraw);
+               return;
        }
 
-       CHECK_FSP(fsp,conn);
        if (!CHECK_WRITE(fsp)) {
-               return(ERROR_DOS(ERRDOS,ERRbadaccess));
+               reply_doserror(req, ERRDOS, ERRbadaccess);
+               error_to_writebrawerr(req);
+               END_PROFILE(SMBwritebraw);
+               return;
        }
-  
-       tcount = IVAL(inbuf,smb_vwv1);
-       startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv3);
-       write_through = BITSETW(inbuf+smb_vwv7,0);
+
+       tcount = IVAL(req->inbuf,smb_vwv1);
+       startpos = IVAL_TO_SMB_OFF_T(req->inbuf,smb_vwv3);
+       write_through = BITSETW(req->inbuf+smb_vwv7,0);
 
        /* We have to deal with slightly different formats depending
                on whether we are using the core+ or lanman1.0 protocol */
 
        if(Protocol <= PROTOCOL_COREPLUS) {
-               numtowrite = SVAL(smb_buf(inbuf),-2);
-               data = smb_buf(inbuf);
+               numtowrite = SVAL(smb_buf(req->inbuf),-2);
+               data = smb_buf(req->inbuf);
        } else {
-               numtowrite = SVAL(inbuf,smb_vwv10);
-               data = smb_base(inbuf) + SVAL(inbuf, smb_vwv11);
+               numtowrite = SVAL(req->inbuf,smb_vwv10);
+               data = smb_base(req->inbuf) + SVAL(req->inbuf, smb_vwv11);
        }
 
-       /* force the error type */
-       SCVAL(inbuf,smb_com,SMBwritec);
-       SCVAL(outbuf,smb_com,SMBwritec);
+       /* Ensure we don't write bytes past the end of this packet. */
+       if (data + numtowrite > smb_base(req->inbuf) + smb_len(req->inbuf)) {
+               reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
+               error_to_writebrawerr(req);
+               END_PROFILE(SMBwritebraw);
+               return;
+       }
 
-       if (is_locked(fsp,(uint32)SVAL(inbuf,smb_pid),(SMB_BIG_UINT)tcount,(SMB_BIG_UINT)startpos, WRITE_LOCK)) {
+       if (is_locked(fsp,(uint32)req->smbpid,(SMB_BIG_UINT)tcount,
+                               (SMB_BIG_UINT)startpos, WRITE_LOCK)) {
+               reply_doserror(req, ERRDOS, ERRlock);
+               error_to_writebrawerr(req);
                END_PROFILE(SMBwritebraw);
-               return(ERROR_DOS(ERRDOS,ERRlock));
+               return;
        }
 
-       if (numtowrite>0)
-               nwritten = write_file(fsp,data,startpos,numtowrite);
-  
-       DEBUG(3,("writebraw1 fnum=%d start=%.0f num=%d wrote=%d sync=%d\n",
-               fsp->fnum, (double)startpos, (int)numtowrite, (int)nwritten, (int)write_through));
+       if (numtowrite>0) {
+               nwritten = write_file(req,fsp,data,startpos,numtowrite);
+       }
+
+       DEBUG(3,("reply_writebraw: initial write fnum=%d start=%.0f num=%d "
+                       "wrote=%d sync=%d\n",
+               fsp->fnum, (double)startpos, (int)numtowrite,
+               (int)nwritten, (int)write_through));
 
        if (nwritten < (ssize_t)numtowrite)  {
+               reply_unixerror(req, ERRHRD, ERRdiskfull);
+               error_to_writebrawerr(req);
                END_PROFILE(SMBwritebraw);
-               return(UNIXERROR(ERRHRD,ERRdiskfull));
+               return;
        }
 
        total_written = nwritten;
 
-       /* Return a message to the redirector to tell it to send more bytes */
-       SCVAL(outbuf,smb_com,SMBwritebraw);
-       SSVALS(outbuf,smb_vwv0,-1);
-       outsize = set_message(inbuf,outbuf,Protocol>PROTOCOL_COREPLUS?1:0,0,True);
-       show_msg(outbuf);
-       if (!send_smb(smbd_server_fd(),outbuf))
-               exit_server_cleanly("reply_writebraw: send_smb failed.");
-  
+       /* Allocate a buffer of 64k + length. */
+       buf = TALLOC_ARRAY(NULL, char, 65540);
+       if (!buf) {
+               reply_doserror(req, ERRDOS, ERRnomem);
+               error_to_writebrawerr(req);
+               END_PROFILE(SMBwritebraw);
+               return;
+       }
+
+       /* Return a SMBwritebraw message to the redirector to tell
+        * it to send more bytes */
+
+       memcpy(buf, req->inbuf, smb_size);
+       outsize = srv_set_message(buf,
+                       Protocol>PROTOCOL_COREPLUS?1:0,0,True);
+       SCVAL(buf,smb_com,SMBwritebraw);
+       SSVALS(buf,smb_vwv0,0xFFFF);
+       show_msg(buf);
+       if (!srv_send_smb(smbd_server_fd(),
+                       buf,
+                       IS_CONN_ENCRYPTED(conn))) {
+               exit_server_cleanly("reply_writebraw: srv_send_smb "
+                       "failed.");
+       }
+
        /* Now read the raw data into the buffer and write it */
-       if (read_smb_length(smbd_server_fd(),inbuf,SMB_SECONDARY_WAIT) == -1) {
+       if (read_smb_length(smbd_server_fd(),buf,
+                       SMB_SECONDARY_WAIT, get_srv_read_error()) == -1) {
                exit_server_cleanly("secondary writebraw failed");
        }
-  
-       /* Even though this is not an smb message, smb_len returns the generic length of an smb message */
-       numtowrite = smb_len(inbuf);
 
-       /* Set up outbuf to return the correct return */
-       outsize = set_message(inbuf,outbuf,1,0,True);
-       SCVAL(outbuf,smb_com,SMBwritec);
+       /*
+        * Even though this is not an smb message,
+        * smb_len returns the generic length of a packet.
+        */
+
+       numtowrite = smb_len(buf);
+
+       /* Set up outbuf to return the correct size */
+       reply_outbuf(req, 1, 0);
 
        if (numtowrite != 0) {
 
-               if (numtowrite > BUFFER_SIZE) {
-                       DEBUG(0,("reply_writebraw: Oversize secondary write raw requested (%u). Terminating\n",
+               if (numtowrite > 0xFFFF) {
+                       DEBUG(0,("reply_writebraw: Oversize secondary write "
+                               "raw requested (%u). Terminating\n",
                                (unsigned int)numtowrite ));
                        exit_server_cleanly("secondary writebraw failed");
                }
 
                if (tcount > nwritten+numtowrite) {
-                       DEBUG(3,("Client overestimated the write %d %d %d\n",
+                       DEBUG(3,("reply_writebraw: Client overestimated the "
+                               "write %d %d %d\n",
                                (int)tcount,(int)nwritten,(int)numtowrite));
                }
 
-               if (read_data( smbd_server_fd(), inbuf+4, numtowrite) != numtowrite ) {
-                       DEBUG(0,("reply_writebraw: Oversize secondary write raw read failed (%s). Terminating\n",
+               if (read_data(smbd_server_fd(), buf+4, numtowrite,get_srv_read_error())
+                                       != numtowrite ) {
+                       DEBUG(0,("reply_writebraw: Oversize secondary write "
+                               "raw read failed (%s). Terminating\n",
                                strerror(errno) ));
                        exit_server_cleanly("secondary writebraw failed");
                }
 
-               nwritten = write_file(fsp,inbuf+4,startpos+nwritten,numtowrite);
+               nwritten = write_file(req,fsp,buf+4,startpos+nwritten,numtowrite);
                if (nwritten == -1) {
+                       TALLOC_FREE(buf);
+                       reply_unixerror(req, ERRHRD, ERRdiskfull);
+                       error_to_writebrawerr(req);
                        END_PROFILE(SMBwritebraw);
-                       return(UNIXERROR(ERRHRD,ERRdiskfull));
+                       return;
                }
 
                if (nwritten < (ssize_t)numtowrite) {
-                       SCVAL(outbuf,smb_rcls,ERRHRD);
-                       SSVAL(outbuf,smb_err,ERRdiskfull);      
+                       SCVAL(req->outbuf,smb_rcls,ERRHRD);
+                       SSVAL(req->outbuf,smb_err,ERRdiskfull);
                }
 
-               if (nwritten > 0)
+               if (nwritten > 0) {
                        total_written += nwritten;
+               }
        }
-       SSVAL(outbuf,smb_vwv0,total_written);
+
+       TALLOC_FREE(buf);
+       SSVAL(req->outbuf,smb_vwv0,total_written);
 
        status = sync_file(conn, fsp, write_through);
        if (!NT_STATUS_IS_OK(status)) {
                DEBUG(5,("reply_writebraw: sync_file for %s returned %s\n",
                        fsp->fsp_name, nt_errstr(status) ));
+               reply_nterror(req, status);
+               error_to_writebrawerr(req);
                END_PROFILE(SMBwritebraw);
-               return ERROR_NT(status);
+               return;
        }
 
-       DEBUG(3,("writebraw2 fnum=%d start=%.0f num=%d wrote=%d\n",
-               fsp->fnum, (double)startpos, (int)numtowrite,(int)total_written));
+       DEBUG(3,("reply_writebraw: secondart write fnum=%d start=%.0f num=%d "
+               "wrote=%d\n",
+               fsp->fnum, (double)startpos, (int)numtowrite,
+               (int)total_written));
 
-       /* we won't return a status if write through is not selected - this follows what WfWg does */
+       /* We won't return a status if write through is not selected - this
+        * follows what WfWg does */
        END_PROFILE(SMBwritebraw);
+
        if (!write_through && total_written==tcount) {
 
 #if RABBIT_PELLET_FIX
                /*
                 * Fix for "rabbit pellet" mode, trigger an early TCP ack by
-                * sending a SMBkeepalive. Thanks to DaveCB at Sun for this. JRA.
+                * sending a SMBkeepalive. Thanks to DaveCB at Sun for this.
+                * JRA.
                 */
-               if (!send_keepalive(smbd_server_fd()))
-                       exit_server_cleanly("reply_writebraw: send of keepalive failed");
+               if (!send_keepalive(smbd_server_fd())) {
+                       exit_server_cleanly("reply_writebraw: send of "
+                               "keepalive failed");
+               }
 #endif
-               return(-1);
+               TALLOC_FREE(req->outbuf);
        }
-
-       return(outsize);
+       return;
 }
 
 #undef DBGC_CLASS
@@ -3104,30 +3586,47 @@ int reply_writebraw(connection_struct *conn, char *inbuf,char *outbuf, int size,
  Reply to a writeunlock (core+).
 ****************************************************************************/
 
-int reply_writeunlock(connection_struct *conn, char *inbuf,char *outbuf, 
-                     int size, int dum_buffsize)
+void reply_writeunlock(struct smb_request *req)
 {
+       connection_struct *conn = req->conn;
        ssize_t nwritten = -1;
        size_t numtowrite;
        SMB_OFF_T startpos;
        char *data;
        NTSTATUS status = NT_STATUS_OK;
-       files_struct *fsp = file_fsp(SVAL(inbuf,smb_vwv0));
-       int outsize = 0;
+       files_struct *fsp;
+
        START_PROFILE(SMBwriteunlock);
+
+       if (req->wct < 5) {
+               reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
+               END_PROFILE(SMBwriteunlock);
+               return;
+       }
        
-       CHECK_FSP(fsp,conn);
+       fsp = file_fsp(SVAL(req->inbuf,smb_vwv0));
+
+       if (!check_fsp(conn, req, fsp, &current_user)) {
+               END_PROFILE(SMBwriteunlock);
+               return;
+       }
+
        if (!CHECK_WRITE(fsp)) {
-               return(ERROR_DOS(ERRDOS,ERRbadaccess));
+               reply_doserror(req, ERRDOS,ERRbadaccess);
+               END_PROFILE(SMBwriteunlock);
+               return;
        }
 
-       numtowrite = SVAL(inbuf,smb_vwv1);
-       startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2);
-       data = smb_buf(inbuf) + 3;
+       numtowrite = SVAL(req->inbuf,smb_vwv1);
+       startpos = IVAL_TO_SMB_OFF_T(req->inbuf,smb_vwv2);
+       data = smb_buf(req->inbuf) + 3;
   
-       if (numtowrite && is_locked(fsp,(uint32)SVAL(inbuf,smb_pid),(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos, WRITE_LOCK)) {
+       if (numtowrite
+           && is_locked(fsp, (uint32)req->smbpid, (SMB_BIG_UINT)numtowrite,
+                        (SMB_BIG_UINT)startpos, WRITE_LOCK)) {
+               reply_doserror(req, ERRDOS, ERRlock);
                END_PROFILE(SMBwriteunlock);
-               return ERROR_DOS(ERRDOS,ERRlock);
+               return;
        }
 
        /* The special X/Open SMB protocol handling of
@@ -3136,45 +3635,48 @@ int reply_writeunlock(connection_struct *conn, char *inbuf,char *outbuf,
        if(numtowrite == 0) {
                nwritten = 0;
        } else {
-               nwritten = write_file(fsp,data,startpos,numtowrite);
+               nwritten = write_file(req,fsp,data,startpos,numtowrite);
        }
   
        status = sync_file(conn, fsp, False /* write through */);
        if (!NT_STATUS_IS_OK(status)) {
-               END_PROFILE(SMBwriteunlock);
                DEBUG(5,("reply_writeunlock: sync_file for %s returned %s\n",
                        fsp->fsp_name, nt_errstr(status) ));
-               return ERROR_NT(status);
+               reply_nterror(req, status);
+               END_PROFILE(SMBwriteunlock);
+               return;
        }
 
-       if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
+       if(((nwritten < numtowrite) && (numtowrite != 0))||(nwritten < 0)) {
+               reply_unixerror(req, ERRHRD, ERRdiskfull);
                END_PROFILE(SMBwriteunlock);
-               return(UNIXERROR(ERRHRD,ERRdiskfull));
+               return;
        }
 
        if (numtowrite) {
                status = do_unlock(smbd_messaging_context(),
                                fsp,
-                               (uint32)SVAL(inbuf,smb_pid),
+                               req->smbpid,
                                (SMB_BIG_UINT)numtowrite, 
                                (SMB_BIG_UINT)startpos,
                                WINDOWS_LOCK);
 
                if (NT_STATUS_V(status)) {
+                       reply_nterror(req, status);
                        END_PROFILE(SMBwriteunlock);
-                       return ERROR_NT(status);
+                       return;
                }
        }
+
+       reply_outbuf(req, 1, 0);
        
-       outsize = set_message(inbuf,outbuf,1,0,True);
-       
-       SSVAL(outbuf,smb_vwv0,nwritten);
+       SSVAL(req->outbuf,smb_vwv0,nwritten);
        
        DEBUG(3,("writeunlock fnum=%d num=%d wrote=%d\n",
                 fsp->fnum, (int)numtowrite, (int)nwritten));
        
        END_PROFILE(SMBwriteunlock);
-       return outsize;
+       return;
 }
 
 #undef DBGC_CLASS
@@ -3184,36 +3686,53 @@ int reply_writeunlock(connection_struct *conn, char *inbuf,char *outbuf,
  Reply to a write.
 ****************************************************************************/
 
-int reply_write(connection_struct *conn, char *inbuf,char *outbuf,int size,int dum_buffsize)
+void reply_write(struct smb_request *req)
 {
+       connection_struct *conn = req->conn;
        size_t numtowrite;
        ssize_t nwritten = -1;
        SMB_OFF_T startpos;
        char *data;
-       files_struct *fsp = file_fsp(SVAL(inbuf,smb_vwv0));
-       int outsize = 0;
+       files_struct *fsp;
        NTSTATUS status;
+
        START_PROFILE(SMBwrite);
 
+       if (req->wct < 5) {
+               END_PROFILE(SMBwrite);
+               reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
+               return;
+       }
+
        /* If it's an IPC, pass off the pipe handler. */
        if (IS_IPC(conn)) {
+               reply_pipe_write(req);
+               END_PROFILE(SMBwrite);
+               return;
+       }
+
+       fsp = file_fsp(SVAL(req->inbuf,smb_vwv0));
+
+       if (!check_fsp(conn, req, fsp, &current_user)) {
                END_PROFILE(SMBwrite);
-               return reply_pipe_write(inbuf,outbuf,size,dum_buffsize);
+               return;
        }
 
-       CHECK_FSP(fsp,conn);
        if (!CHECK_WRITE(fsp)) {
+               reply_doserror(req, ERRDOS, ERRbadaccess);
                END_PROFILE(SMBwrite);
-               return(ERROR_DOS(ERRDOS,ERRbadaccess));
+               return;
        }
 
-       numtowrite = SVAL(inbuf,smb_vwv1);
-       startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2);
-       data = smb_buf(inbuf) + 3;
+       numtowrite = SVAL(req->inbuf,smb_vwv1);
+       startpos = IVAL_TO_SMB_OFF_T(req->inbuf,smb_vwv2);
+       data = smb_buf(req->inbuf) + 3;
   
-       if (is_locked(fsp,(uint32)SVAL(inbuf,smb_pid),(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos, WRITE_LOCK)) {
+       if (is_locked(fsp, (uint32)req->smbpid, (SMB_BIG_UINT)numtowrite,
+                     (SMB_BIG_UINT)startpos, WRITE_LOCK)) {
+               reply_doserror(req, ERRDOS, ERRlock);
                END_PROFILE(SMBwrite);
-               return ERROR_DOS(ERRDOS,ERRlock);
+               return;
        }
 
        /*
@@ -3228,96 +3747,202 @@ int reply_write(connection_struct *conn, char *inbuf,char *outbuf,int size,int d
                 */
                nwritten = vfs_allocate_file_space(fsp, (SMB_OFF_T)startpos);
                if (nwritten < 0) {
+                       reply_nterror(req, NT_STATUS_DISK_FULL);
                        END_PROFILE(SMBwrite);
-                       return ERROR_NT(NT_STATUS_DISK_FULL);
+                       return;
                }
                nwritten = vfs_set_filelen(fsp, (SMB_OFF_T)startpos);
                if (nwritten < 0) {
+                       reply_nterror(req, NT_STATUS_DISK_FULL);
                        END_PROFILE(SMBwrite);
-                       return ERROR_NT(NT_STATUS_DISK_FULL);
+                       return;
                }
        } else
-               nwritten = write_file(fsp,data,startpos,numtowrite);
+               nwritten = write_file(req,fsp,data,startpos,numtowrite);
   
        status = sync_file(conn, fsp, False);
        if (!NT_STATUS_IS_OK(status)) {
-               END_PROFILE(SMBwrite);
                DEBUG(5,("reply_write: sync_file for %s returned %s\n",
                        fsp->fsp_name, nt_errstr(status) ));
-               return ERROR_NT(status);
+               reply_nterror(req, status);
+               END_PROFILE(SMBwrite);
+               return;
        }
 
        if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
+               reply_unixerror(req, ERRHRD, ERRdiskfull);
                END_PROFILE(SMBwrite);
-               return(UNIXERROR(ERRHRD,ERRdiskfull));
+               return;
        }
 
-       outsize = set_message(inbuf,outbuf,1,0,True);
+       reply_outbuf(req, 1, 0);
   
-       SSVAL(outbuf,smb_vwv0,nwritten);
+       SSVAL(req->outbuf,smb_vwv0,nwritten);
 
        if (nwritten < (ssize_t)numtowrite) {
-               SCVAL(outbuf,smb_rcls,ERRHRD);
-               SSVAL(outbuf,smb_err,ERRdiskfull);      
+               SCVAL(req->outbuf,smb_rcls,ERRHRD);
+               SSVAL(req->outbuf,smb_err,ERRdiskfull);
        }
   
        DEBUG(3,("write fnum=%d num=%d wrote=%d\n", fsp->fnum, (int)numtowrite, (int)nwritten));
 
        END_PROFILE(SMBwrite);
-       return(outsize);
+       return;
+}
+
+/****************************************************************************
+ Ensure a buffer is a valid writeX for recvfile purposes.
+****************************************************************************/
+
+#define STANDARD_WRITE_AND_X_HEADER_SIZE (smb_size - 4 + /* basic header */ \
+                                               (2*14) + /* word count (including bcc) */ \
+                                               1 /* pad byte */)
+
+bool is_valid_writeX_buffer(const uint8_t *inbuf)
+{
+       size_t numtowrite;
+       connection_struct *conn = NULL;
+       unsigned int doff = 0;
+       size_t len = smb_len_large(inbuf);
+
+       if (is_encrypted_packet(inbuf)) {
+               /* Can't do this on encrypted
+                * connections. */
+               return false;
+       }
+
+       if (CVAL(inbuf,smb_com) != SMBwriteX) {
+               return false;
+       }
+
+       if (CVAL(inbuf,smb_vwv0) != 0xFF ||
+                       CVAL(inbuf,smb_wct) != 14) {
+               DEBUG(10,("is_valid_writeX_buffer: chained or "
+                       "invalid word length.\n"));
+               return false;
+       }
+
+       conn = conn_find(SVAL(inbuf, smb_tid));
+       if (conn == NULL) {
+               DEBUG(10,("is_valid_writeX_buffer: bad tid\n"));
+               return false;
+       }
+       if (IS_IPC(conn)) {
+               DEBUG(10,("is_valid_writeX_buffer: IPC$ tid\n"));
+               return false;
+       }
+       doff = SVAL(inbuf,smb_vwv11);
+
+       numtowrite = SVAL(inbuf,smb_vwv10);
+
+       if (len > doff && len - doff > 0xFFFF) {
+               numtowrite |= (((size_t)SVAL(inbuf,smb_vwv9))<<16);
+       }
+
+       if (numtowrite == 0) {
+               DEBUG(10,("is_valid_writeX_buffer: zero write\n"));
+               return false;
+       }
+
+       /* Ensure the sizes match up. */
+       if (doff < STANDARD_WRITE_AND_X_HEADER_SIZE) {
+               /* no pad byte...old smbclient :-( */
+               DEBUG(10,("is_valid_writeX_buffer: small doff %u (min %u)\n",
+                       (unsigned int)doff,
+                       (unsigned int)STANDARD_WRITE_AND_X_HEADER_SIZE));
+               return false;
+       }
+
+       if (len - doff != numtowrite) {
+               DEBUG(10,("is_valid_writeX_buffer: doff mismatch "
+                       "len = %u, doff = %u, numtowrite = %u\n",
+                       (unsigned int)len,
+                       (unsigned int)doff,
+                       (unsigned int)numtowrite ));
+               return false;
+       }
+
+       DEBUG(10,("is_valid_writeX_buffer: true "
+               "len = %u, doff = %u, numtowrite = %u\n",
+               (unsigned int)len,
+               (unsigned int)doff,
+               (unsigned int)numtowrite ));
+
+       return true;
 }
 
 /****************************************************************************
  Reply to a write and X.
 ****************************************************************************/
 
-void reply_write_and_X(connection_struct *conn, struct smb_request *req)
+void reply_write_and_X(struct smb_request *req)
 {
+       connection_struct *conn = req->conn;
        files_struct *fsp;
        SMB_OFF_T startpos;
        size_t numtowrite;
-       BOOL write_through;
+       bool write_through;
        ssize_t nwritten;
        unsigned int smb_doff;
        unsigned int smblen;
        char *data;
-       BOOL large_writeX;
        NTSTATUS status;
 
-       char *inbuf, *outbuf;
-       int length, bufsize;
-
        START_PROFILE(SMBwriteX);
 
-       if (!reply_prep_legacy(req, &inbuf, &outbuf, &length, &bufsize)) {
-               reply_nterror(req, NT_STATUS_NO_MEMORY);
+       if ((req->wct != 12) && (req->wct != 14)) {
+               reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
                END_PROFILE(SMBwriteX);
                return;
        }
 
-       if ((CVAL(inbuf, smb_wct) != 12) && (CVAL(inbuf, smb_wct) != 14)) {
-               reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
-               END_PROFILE(SMBwriteX);
-               return;
+       numtowrite = SVAL(req->inbuf,smb_vwv10);
+       smb_doff = SVAL(req->inbuf,smb_vwv11);
+       smblen = smb_len(req->inbuf);
+
+       if (req->unread_bytes > 0xFFFF ||
+                       (smblen > smb_doff &&
+                               smblen - smb_doff > 0xFFFF)) {
+               numtowrite |= (((size_t)SVAL(req->inbuf,smb_vwv9))<<16);
        }
 
-       fsp = file_fsp(SVAL(inbuf,smb_vwv2));
-       startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv3);
-       numtowrite = SVAL(inbuf,smb_vwv10);
-       write_through = BITSETW(inbuf+smb_vwv7,0);
-       smb_doff = SVAL(inbuf,smb_vwv11);
-       smblen = smb_len(inbuf);
-       large_writeX = ((CVAL(inbuf,smb_wct) == 14) && (smblen > 0xFFFF));
+       if (req->unread_bytes) {
+               /* Can't do a recvfile write on IPC$ */
+               if (IS_IPC(conn)) {
+                       reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
+                       END_PROFILE(SMBwriteX);
+                       return;
+               }
+               if (numtowrite != req->unread_bytes) {
+                       reply_doserror(req, ERRDOS, ERRbadmem);
+                       END_PROFILE(SMBwriteX);
+                       return;
+               }
+       } else {
+               if (smb_doff > smblen || smb_doff + numtowrite < numtowrite ||
+                               smb_doff + numtowrite > smblen) {
+                       reply_doserror(req, ERRDOS, ERRbadmem);
+                       END_PROFILE(SMBwriteX);
+                       return;
+               }
+       }
 
        /* If it's an IPC, pass off the pipe handler. */
        if (IS_IPC(conn)) {
-               reply_post_legacy(
-                       req,
-                       reply_pipe_write_and_X(inbuf,outbuf,length,bufsize));
+               if (req->unread_bytes) {
+                       reply_doserror(req, ERRDOS, ERRbadmem);
+                       END_PROFILE(SMBwriteX);
+                       return;
+               }
+               reply_pipe_write_and_X(req);
                END_PROFILE(SMBwriteX);
                return;
        }
 
+       fsp = file_fsp(SVAL(req->inbuf,smb_vwv2));
+       startpos = IVAL_TO_SMB_OFF_T(req->inbuf,smb_vwv3);
+       write_through = BITSETW(req->inbuf+smb_vwv7,0);
+
        if (!check_fsp(conn, req, fsp, &current_user)) {
                END_PROFILE(SMBwriteX);
                return;
@@ -3329,27 +3954,14 @@ void reply_write_and_X(connection_struct *conn, struct smb_request *req)
                return;
        }
 
-       set_message(inbuf, outbuf, 6, 0, True);
-  
-       /* Deal with possible LARGE_WRITEX */
-       if (large_writeX) {
-               numtowrite |= ((((size_t)SVAL(inbuf,smb_vwv9)) & 1 )<<16);
-       }
-
-       if(smb_doff > smblen || (smb_doff + numtowrite > smblen)) {
-               reply_doserror(req, ERRDOS, ERRbadmem);
-               END_PROFILE(SMBwriteX);
-               return;
-       }
-
-       data = smb_base(inbuf) + smb_doff;
+       data = smb_base(req->inbuf) + smb_doff;
 
-       if(CVAL(inbuf,smb_wct) == 14) {
+       if(req->wct == 14) {
 #ifdef LARGE_SMB_OFF_T
                /*
                 * This is a large offset (64 bit) write.
                 */
-               startpos |= (((SMB_OFF_T)IVAL(inbuf,smb_vwv12)) << 32);
+               startpos |= (((SMB_OFF_T)IVAL(req->inbuf,smb_vwv12)) << 32);
 
 #else /* !LARGE_SMB_OFF_T */
 
@@ -3357,10 +3969,10 @@ void reply_write_and_X(connection_struct *conn, struct smb_request *req)
                 * Ensure we haven't been sent a >32 bit offset.
                 */
 
-               if(IVAL(inbuf,smb_vwv12) != 0) {
+               if(IVAL(req->inbuf,smb_vwv12) != 0) {
                        DEBUG(0,("reply_write_and_X - large offset (%x << 32) "
                                 "used and we don't support 64 bit offsets.\n",
-                                (unsigned int)IVAL(inbuf,smb_vwv12) ));
+                                (unsigned int)IVAL(req->inbuf,smb_vwv12) ));
                        reply_doserror(req, ERRDOS, ERRbadaccess);
                        END_PROFILE(SMBwriteX);
                        return;
@@ -3369,7 +3981,7 @@ void reply_write_and_X(connection_struct *conn, struct smb_request *req)
 #endif /* LARGE_SMB_OFF_T */
        }
 
-       if (is_locked(fsp,(uint32)SVAL(inbuf,smb_pid),
+       if (is_locked(fsp,(uint32)req->smbpid,
                      (SMB_BIG_UINT)numtowrite,
                      (SMB_BIG_UINT)startpos, WRITE_LOCK)) {
                reply_doserror(req, ERRDOS, ERRlock);
@@ -3386,29 +3998,29 @@ void reply_write_and_X(connection_struct *conn, struct smb_request *req)
                nwritten = 0;
        } else {
 
-               if (schedule_aio_write_and_X(conn, inbuf, outbuf, length, bufsize,
-                                       fsp,data,startpos,numtowrite)) {
-                       reply_post_legacy(req, -1);
+               if (req->unread_bytes == 0 &&
+                               schedule_aio_write_and_X(conn, req, fsp, data,
+                                                       startpos, numtowrite)) {
                        END_PROFILE(SMBwriteX);
                        return;
                }
 
-               nwritten = write_file(fsp,data,startpos,numtowrite);
+               nwritten = write_file(req,fsp,data,startpos,numtowrite);
        }
-  
+
        if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
                reply_unixerror(req, ERRHRD, ERRdiskfull);
                END_PROFILE(SMBwriteX);
                return;
        }
 
-       SSVAL(outbuf,smb_vwv2,nwritten);
-       if (large_writeX)
-               SSVAL(outbuf,smb_vwv4,(nwritten>>16)&1);
+       reply_outbuf(req, 6, 0);
+       SSVAL(req->outbuf,smb_vwv2,nwritten);
+       SSVAL(req->outbuf,smb_vwv4,nwritten>>16);
 
        if (nwritten < (ssize_t)numtowrite) {
-               SCVAL(outbuf,smb_rcls,ERRHRD);
-               SSVAL(outbuf,smb_err,ERRdiskfull);      
+               SCVAL(req->outbuf,smb_rcls,ERRHRD);
+               SSVAL(req->outbuf,smb_err,ERRdiskfull);
        }
 
        DEBUG(3,("writeX fnum=%d num=%d wrote=%d\n",
@@ -3423,10 +4035,8 @@ void reply_write_and_X(connection_struct *conn, struct smb_request *req)
                return;
        }
 
-       reply_post_legacy(req, smb_len(req->outbuf));
-
        END_PROFILE(SMBwriteX);
-       chain_reply_new(req);
+       chain_reply(req);
        return;
 }
 
@@ -3434,22 +4044,33 @@ void reply_write_and_X(connection_struct *conn, struct smb_request *req)
  Reply to a lseek.
 ****************************************************************************/
 
-int reply_lseek(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
+void reply_lseek(struct smb_request *req)
 {
+       connection_struct *conn = req->conn;
        SMB_OFF_T startpos;
        SMB_OFF_T res= -1;
        int mode,umode;
-       int outsize = 0;
-       files_struct *fsp = file_fsp(SVAL(inbuf,smb_vwv0));
+       files_struct *fsp;
+
        START_PROFILE(SMBlseek);
 
-       CHECK_FSP(fsp,conn);
+       if (req->wct < 4) {
+               reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
+               END_PROFILE(SMBlseek);
+               return;
+       }
+
+       fsp = file_fsp(SVAL(req->inbuf,smb_vwv0));
+
+       if (!check_fsp(conn, req, fsp, &current_user)) {
+               return;
+       }
 
        flush_write_cache(fsp, SEEK_FLUSH);
 
-       mode = SVAL(inbuf,smb_vwv1) & 3;
+       mode = SVAL(req->inbuf,smb_vwv1) & 3;
        /* NB. This doesn't use IVAL_TO_SMB_OFF_T as startpos can be signed in this case. */
-       startpos = (SMB_OFF_T)IVALS(inbuf,smb_vwv2);
+       startpos = (SMB_OFF_T)IVALS(req->inbuf,smb_vwv2);
 
        switch (mode) {
                case 0:
@@ -3470,46 +4091,50 @@ int reply_lseek(connection_struct *conn, char *inbuf,char *outbuf, int size, int
        }
 
        if (umode == SEEK_END) {
-               if((res = SMB_VFS_LSEEK(fsp,fsp->fh->fd,startpos,umode)) == -1) {
+               if((res = SMB_VFS_LSEEK(fsp,startpos,umode)) == -1) {
                        if(errno == EINVAL) {
                                SMB_OFF_T current_pos = startpos;
                                SMB_STRUCT_STAT sbuf;
 
                                if(SMB_VFS_FSTAT(fsp,fsp->fh->fd, &sbuf) == -1) {
+                                       reply_unixerror(req, ERRDOS,
+                                                       ERRnoaccess);
                                        END_PROFILE(SMBlseek);
-                                       return(UNIXERROR(ERRDOS,ERRnoaccess));
+                                       return;
                                }
 
                                current_pos += sbuf.st_size;
                                if(current_pos < 0)
-                                       res = SMB_VFS_LSEEK(fsp,fsp->fh->fd,0,SEEK_SET);
+                                       res = SMB_VFS_LSEEK(fsp,0,SEEK_SET);
                        }
                }
 
                if(res == -1) {
+                       reply_unixerror(req, ERRDOS, ERRnoaccess);
                        END_PROFILE(SMBlseek);
-                       return(UNIXERROR(ERRDOS,ERRnoaccess));
+                       return;
                }
        }
 
        fsp->fh->pos = res;
-  
-       outsize = set_message(inbuf,outbuf,2,0,True);
-       SIVAL(outbuf,smb_vwv0,res);
+
+       reply_outbuf(req, 2, 0);
+       SIVAL(req->outbuf,smb_vwv0,res);
   
        DEBUG(3,("lseek fnum=%d ofs=%.0f newpos = %.0f mode=%d\n",
                fsp->fnum, (double)startpos, (double)res, mode));
 
        END_PROFILE(SMBlseek);
-       return(outsize);
+       return;
 }
 
 /****************************************************************************
  Reply to a flush.
 ****************************************************************************/
 
-void reply_flush(connection_struct *conn, struct smb_request *req)
+void reply_flush(struct smb_request *req)
 {
+       connection_struct *conn = req->conn;
        uint16 fnum;
        files_struct *fsp;
 
@@ -3552,7 +4177,7 @@ void reply_flush(connection_struct *conn, struct smb_request *req)
  conn POINTER CAN BE NULL HERE !
 ****************************************************************************/
 
-void reply_exit(connection_struct *conn, struct smb_request *req)
+void reply_exit(struct smb_request *req)
 {
        START_PROFILE(SMBexit);
 
@@ -3570,8 +4195,9 @@ void reply_exit(connection_struct *conn, struct smb_request *req)
  Reply to a close - has to deal with closing a directory opened by NT SMB's.
 ****************************************************************************/
 
-void reply_close(connection_struct *conn, struct smb_request *req)
+void reply_close(struct smb_request *req)
 {
+       connection_struct *conn = req->conn;
        NTSTATUS status = NT_STATUS_OK;
        files_struct *fsp = NULL;
        START_PROFILE(SMBclose);
@@ -3648,35 +4274,52 @@ void reply_close(connection_struct *conn, struct smb_request *req)
  Reply to a writeclose (Core+ protocol).
 ****************************************************************************/
 
-int reply_writeclose(connection_struct *conn,
-                    char *inbuf,char *outbuf, int size, int dum_buffsize)
+void reply_writeclose(struct smb_request *req)
 {
+       connection_struct *conn = req->conn;
        size_t numtowrite;
        ssize_t nwritten = -1;
-       int outsize = 0;
        NTSTATUS close_status = NT_STATUS_OK;
        SMB_OFF_T startpos;
        char *data;
        struct timespec mtime;
-       files_struct *fsp = file_fsp(SVAL(inbuf,smb_vwv0));
+       files_struct *fsp;
+
        START_PROFILE(SMBwriteclose);
 
-       CHECK_FSP(fsp,conn);
+       if (req->wct < 6) {
+               reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
+               END_PROFILE(SMBwriteclose);
+               return;
+       }
+
+       fsp = file_fsp(SVAL(req->inbuf,smb_vwv0));
+
+       if (!check_fsp(conn, req, fsp, &current_user)) {
+               END_PROFILE(SMBwriteclose);
+               return;
+       }
        if (!CHECK_WRITE(fsp)) {
-               return(ERROR_DOS(ERRDOS,ERRbadaccess));
+               reply_doserror(req, ERRDOS,ERRbadaccess);
+               END_PROFILE(SMBwriteclose);
+               return;
        }
 
-       numtowrite = SVAL(inbuf,smb_vwv1);
-       startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2);
-       mtime = convert_time_t_to_timespec(srv_make_unix_date3(inbuf+smb_vwv4));
-       data = smb_buf(inbuf) + 1;
+       numtowrite = SVAL(req->inbuf,smb_vwv1);
+       startpos = IVAL_TO_SMB_OFF_T(req->inbuf,smb_vwv2);
+       mtime = convert_time_t_to_timespec(srv_make_unix_date3(
+                                                  req->inbuf+smb_vwv4));
+       data = smb_buf(req->inbuf) + 1;
   
-       if (numtowrite && is_locked(fsp,(uint32)SVAL(inbuf,smb_pid),(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos, WRITE_LOCK)) {
+       if (numtowrite
+           && is_locked(fsp, (uint32)req->smbpid, (SMB_BIG_UINT)numtowrite,
+                        (SMB_BIG_UINT)startpos, WRITE_LOCK)) {
+               reply_doserror(req, ERRDOS,ERRlock);
                END_PROFILE(SMBwriteclose);
-               return ERROR_DOS(ERRDOS,ERRlock);
+               return;
        }
   
-       nwritten = write_file(fsp,data,startpos,numtowrite);
+       nwritten = write_file(req,fsp,data,startpos,numtowrite);
 
        set_filetime(conn, fsp->fsp_name, mtime);
   
@@ -3696,20 +4339,22 @@ int reply_writeclose(connection_struct *conn,
                 conn->num_files_open));
   
        if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
+               reply_doserror(req, ERRHRD, ERRdiskfull);
                END_PROFILE(SMBwriteclose);
-               return(UNIXERROR(ERRHRD,ERRdiskfull));
+               return;
        }
  
        if(!NT_STATUS_IS_OK(close_status)) {
+               reply_nterror(req, close_status);
                END_PROFILE(SMBwriteclose);
-               return ERROR_NT(close_status);
+               return;
        }
-       outsize = set_message(inbuf,outbuf,1,0,True);
+
+       reply_outbuf(req, 1, 0);
   
-       SSVAL(outbuf,smb_vwv0,nwritten);
+       SSVAL(req->outbuf,smb_vwv0,nwritten);
        END_PROFILE(SMBwriteclose);
-       return(outsize);
+       return;
 }
 
 #undef DBGC_CLASS
@@ -3719,30 +4364,40 @@ int reply_writeclose(connection_struct *conn,
  Reply to a lock.
 ****************************************************************************/
 
-int reply_lock(connection_struct *conn,
-              char *inbuf,char *outbuf, int length, int dum_buffsize)
+void reply_lock(struct smb_request *req)
 {
-       int outsize = set_message(inbuf,outbuf,0,0,False);
+       connection_struct *conn = req->conn;
        SMB_BIG_UINT count,offset;
        NTSTATUS status;
-       files_struct *fsp = file_fsp(SVAL(inbuf,smb_vwv0));
+       files_struct *fsp;
        struct byte_range_lock *br_lck = NULL;
 
        START_PROFILE(SMBlock);
 
-       CHECK_FSP(fsp,conn);
+       if (req->wct < 5) {
+               reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
+               END_PROFILE(SMBlock);
+               return;
+       }
+
+       fsp = file_fsp(SVAL(req->inbuf,smb_vwv0));
+
+       if (!check_fsp(conn, req, fsp, &current_user)) {
+               END_PROFILE(SMBlock);
+               return;
+       }
 
        release_level_2_oplocks_on_change(fsp);
 
-       count = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv1);
-       offset = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv3);
+       count = (SMB_BIG_UINT)IVAL(req->inbuf,smb_vwv1);
+       offset = (SMB_BIG_UINT)IVAL(req->inbuf,smb_vwv3);
 
        DEBUG(3,("lock fd=%d fnum=%d offset=%.0f count=%.0f\n",
                 fsp->fh->fd, fsp->fnum, (double)offset, (double)count));
 
        br_lck = do_lock(smbd_messaging_context(),
                        fsp,
-                       (uint32)SVAL(inbuf,smb_pid),
+                       req->smbpid,
                        count,
                        offset,
                        WRITE_LOCK,
@@ -3754,49 +4409,66 @@ int reply_lock(connection_struct *conn,
        TALLOC_FREE(br_lck);
 
        if (NT_STATUS_V(status)) {
+               reply_nterror(req, status);
                END_PROFILE(SMBlock);
-               return ERROR_NT(status);
+               return;
        }
 
+       reply_outbuf(req, 0, 0);
+
        END_PROFILE(SMBlock);
-       return(outsize);
+       return;
 }
 
 /****************************************************************************
  Reply to a unlock.
 ****************************************************************************/
 
-int reply_unlock(connection_struct *conn, char *inbuf,char *outbuf, int size, 
-                int dum_buffsize)
+void reply_unlock(struct smb_request *req)
 {
-       int outsize = set_message(inbuf,outbuf,0,0,False);
+       connection_struct *conn = req->conn;
        SMB_BIG_UINT count,offset;
        NTSTATUS status;
-       files_struct *fsp = file_fsp(SVAL(inbuf,smb_vwv0));
+       files_struct *fsp;
+
        START_PROFILE(SMBunlock);
 
-       CHECK_FSP(fsp,conn);
+       if (req->wct < 5) {
+               reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
+               END_PROFILE(SMBunlock);
+               return;
+       }
+
+       fsp = file_fsp(SVAL(req->inbuf,smb_vwv0));
+
+       if (!check_fsp(conn, req, fsp, &current_user)) {
+               END_PROFILE(SMBunlock);
+               return;
+       }
        
-       count = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv1);
-       offset = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv3);
+       count = (SMB_BIG_UINT)IVAL(req->inbuf,smb_vwv1);
+       offset = (SMB_BIG_UINT)IVAL(req->inbuf,smb_vwv3);
        
        status = do_unlock(smbd_messaging_context(),
                        fsp,
-                       (uint32)SVAL(inbuf,smb_pid),
+                       req->smbpid,
                        count,
                        offset,
                        WINDOWS_LOCK);
 
        if (NT_STATUS_V(status)) {
+               reply_nterror(req, status);
                END_PROFILE(SMBunlock);
-               return ERROR_NT(status);
+               return;
        }
 
        DEBUG( 3, ( "unlock fd=%d fnum=%d offset=%.0f count=%.0f\n",
                    fsp->fh->fd, fsp->fnum, (double)offset, (double)count ) );
-       
+
+       reply_outbuf(req, 0, 0);
+
        END_PROFILE(SMBunlock);
-       return(outsize);
+       return;
 }
 
 #undef DBGC_CLASS
@@ -3807,8 +4479,9 @@ int reply_unlock(connection_struct *conn, char *inbuf,char *outbuf, int size,
  conn POINTER CAN BE NULL HERE !
 ****************************************************************************/
 
-void reply_tdis(connection_struct *conn, struct smb_request *req)
+void reply_tdis(struct smb_request *req)
 {
+       connection_struct *conn = req->conn;
        START_PROFILE(SMBtdis);
 
        if (!conn) {
@@ -3821,6 +4494,7 @@ void reply_tdis(connection_struct *conn, struct smb_request *req)
        conn->used = False;
 
        close_cnum(conn,req->vuid);
+       req->conn = NULL;
 
        reply_outbuf(req, 0, 0);
        END_PROFILE(SMBtdis);
@@ -3832,8 +4506,9 @@ void reply_tdis(connection_struct *conn, struct smb_request *req)
  conn POINTER CAN BE NULL HERE !
 ****************************************************************************/
 
-void reply_echo(connection_struct *conn, struct smb_request *req)
+void reply_echo(struct smb_request *req)
 {
+       connection_struct *conn = req->conn;
        int smb_reverb;
        int seq_num;
        unsigned int data_len = smb_buflen(req->inbuf);
@@ -3871,8 +4546,10 @@ void reply_echo(connection_struct *conn, struct smb_request *req)
                SSVAL(req->outbuf,smb_vwv0,seq_num);
 
                show_msg((char *)req->outbuf);
-               if (!send_smb(smbd_server_fd(),(char *)req->outbuf))
-                       exit_server_cleanly("reply_echo: send_smb failed.");
+               if (!srv_send_smb(smbd_server_fd(),
+                               (char *)req->outbuf,
+                               IS_CONN_ENCRYPTED(conn)||req->encrypted))
+                       exit_server_cleanly("reply_echo: srv_send_smb failed.");
        }
 
        DEBUG(3,("echo %d times\n", smb_reverb));
@@ -3889,55 +4566,74 @@ void reply_echo(connection_struct *conn, struct smb_request *req)
  Reply to a printopen.
 ****************************************************************************/
 
-int reply_printopen(connection_struct *conn, 
-                   char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
+void reply_printopen(struct smb_request *req)
 {
-       int outsize = 0;
+       connection_struct *conn = req->conn;
        files_struct *fsp;
        NTSTATUS status;
        
        START_PROFILE(SMBsplopen);
-       
+
+       if (req->wct < 2) {
+               reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
+               END_PROFILE(SMBsplopen);
+               return;
+       }
+
        if (!CAN_PRINT(conn)) {
+               reply_doserror(req, ERRDOS, ERRnoaccess);
                END_PROFILE(SMBsplopen);
-               return ERROR_DOS(ERRDOS,ERRnoaccess);
+               return;
        }
 
        /* Open for exclusive use, write only. */
        status = print_fsp_open(conn, NULL, &fsp);
 
        if (!NT_STATUS_IS_OK(status)) {
+               reply_nterror(req, status);
                END_PROFILE(SMBsplopen);
-               return(ERROR_NT(status));
+               return;
        }
 
-       outsize = set_message(inbuf,outbuf,1,0,True);
-       SSVAL(outbuf,smb_vwv0,fsp->fnum);
+       reply_outbuf(req, 1, 0);
+       SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
   
        DEBUG(3,("openprint fd=%d fnum=%d\n",
                 fsp->fh->fd, fsp->fnum));
 
        END_PROFILE(SMBsplopen);
-       return(outsize);
+       return;
 }
 
 /****************************************************************************
  Reply to a printclose.
 ****************************************************************************/
 
-int reply_printclose(connection_struct *conn,
-                    char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
+void reply_printclose(struct smb_request *req)
 {
-       int outsize = set_message(inbuf,outbuf,0,0,False);
-       files_struct *fsp = file_fsp(SVAL(inbuf,smb_vwv0));
+       connection_struct *conn = req->conn;
+       files_struct *fsp;
        NTSTATUS status;
+
        START_PROFILE(SMBsplclose);
 
-       CHECK_FSP(fsp,conn);
+       if (req->wct < 3) {
+               reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
+               END_PROFILE(SMBsplclose);
+               return;
+       }
+
+       fsp = file_fsp(SVAL(req->inbuf,smb_vwv0));
+
+       if (!check_fsp(conn, req, fsp, &current_user)) {
+               END_PROFILE(SMBsplclose);
+                return;
+        }
 
        if (!CAN_PRINT(conn)) {
+               reply_nterror(req, NT_STATUS_DOS(ERRSRV, ERRerror));
                END_PROFILE(SMBsplclose);
-               return ERROR_NT(NT_STATUS_DOS(ERRSRV, ERRerror));
+               return;
        }
   
        DEBUG(3,("printclose fd=%d fnum=%d\n",
@@ -3946,39 +4642,51 @@ int reply_printclose(connection_struct *conn,
        status = close_file(fsp,NORMAL_CLOSE);
 
        if(!NT_STATUS_IS_OK(status)) {
+               reply_nterror(req, status);
                END_PROFILE(SMBsplclose);
-               return ERROR_NT(status);
+               return;
        }
 
        END_PROFILE(SMBsplclose);
-       return(outsize);
+       return;
 }
 
 /****************************************************************************
  Reply to a printqueue.
 ****************************************************************************/
 
-int reply_printqueue(connection_struct *conn,
-                    char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
+void reply_printqueue(struct smb_request *req)
 {
-       int outsize = set_message(inbuf,outbuf,2,3,True);
-       int max_count = SVAL(inbuf,smb_vwv0);
-       int start_index = SVAL(inbuf,smb_vwv1);
+       connection_struct *conn = req->conn;
+       int max_count;
+       int start_index;
+
        START_PROFILE(SMBsplretq);
 
+       if (req->wct < 2) {
+               reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
+               END_PROFILE(SMBsplretq);
+               return;
+       }
+
+       max_count = SVAL(req->inbuf,smb_vwv0);
+       start_index = SVAL(req->inbuf,smb_vwv1);
+
        /* we used to allow the client to get the cnum wrong, but that
           is really quite gross and only worked when there was only
           one printer - I think we should now only accept it if they
           get it right (tridge) */
        if (!CAN_PRINT(conn)) {
+               reply_doserror(req, ERRDOS, ERRnoaccess);
                END_PROFILE(SMBsplretq);
-               return ERROR_DOS(ERRDOS,ERRnoaccess);
+               return;
        }
 
-       SSVAL(outbuf,smb_vwv0,0);
-       SSVAL(outbuf,smb_vwv1,0);
-       SCVAL(smb_buf(outbuf),0,1);
-       SSVAL(smb_buf(outbuf),1,0);
+       reply_outbuf(req, 2, 3);
+       SSVAL(req->outbuf,smb_vwv0,0);
+       SSVAL(req->outbuf,smb_vwv1,0);
+       SCVAL(smb_buf(req->outbuf),0,1);
+       SSVAL(smb_buf(req->outbuf),1,0);
   
        DEBUG(3,("printqueue start_index=%d max_count=%d\n",
                 start_index, max_count));
@@ -3986,7 +4694,6 @@ int reply_printqueue(connection_struct *conn,
        {
                print_queue_struct *queue = NULL;
                print_status_struct status;
-               char *p = smb_buf(outbuf) + 3;
                int count = print_queue_status(SNUM(conn), &queue, &status);
                int num_to_get = ABS(max_count);
                int first = (max_count>0?start_index:start_index+max_count+1);
@@ -3999,22 +4706,33 @@ int reply_printqueue(connection_struct *conn,
     
 
                for (i=first;i<first+num_to_get;i++) {
+                       char blob[28];
+                       char *p = blob;
+
                        srv_put_dos_date2(p,0,queue[i].time);
                        SCVAL(p,4,(queue[i].status==LPQ_PRINTING?2:3));
                        SSVAL(p,5, queue[i].job);
                        SIVAL(p,7,queue[i].size);
                        SCVAL(p,11,0);
-                       srvstr_push(outbuf, SVAL(outbuf, smb_flg2), p+12,
+                       srvstr_push(blob, req->flags2, p+12,
                                    queue[i].fs_user, 16, STR_ASCII);
-                       p += 28;
+
+                       if (message_push_blob(
+                                   &req->outbuf,
+                                   data_blob_const(
+                                           blob, sizeof(blob))) == -1) {
+                               reply_nterror(req, NT_STATUS_NO_MEMORY);
+                               END_PROFILE(SMBsplretq);
+                               return;
+                       }
                }
 
                if (count > 0) {
-                       outsize = set_message(inbuf,outbuf,2,28*count+3,False); 
-                       SSVAL(outbuf,smb_vwv0,count);
-                       SSVAL(outbuf,smb_vwv1,(max_count>0?first+count:first-1));
-                       SCVAL(smb_buf(outbuf),0,1);
-                       SSVAL(smb_buf(outbuf),1,28*count);
+                       SSVAL(req->outbuf,smb_vwv0,count);
+                       SSVAL(req->outbuf,smb_vwv1,
+                             (max_count>0?first+count:first-1));
+                       SCVAL(smb_buf(req->outbuf),0,1);
+                       SSVAL(smb_buf(req->outbuf),1,28*count);
                }
 
                SAFE_FREE(queue);
@@ -4023,60 +4741,85 @@ int reply_printqueue(connection_struct *conn,
        }
   
        END_PROFILE(SMBsplretq);
-       return(outsize);
+       return;
 }
 
 /****************************************************************************
  Reply to a printwrite.
 ****************************************************************************/
 
-int reply_printwrite(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
+void reply_printwrite(struct smb_request *req)
 {
+       connection_struct *conn = req->conn;
        int numtowrite;
-       int outsize = set_message(inbuf,outbuf,0,0,False);
        char *data;
-       files_struct *fsp = file_fsp(SVAL(inbuf,smb_vwv0));
+       files_struct *fsp;
 
        START_PROFILE(SMBsplwr);
+
+       if (req->wct < 1) {
+               reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
+               END_PROFILE(SMBsplwr);
+               return;
+       }
   
+       fsp = file_fsp(SVAL(req->inbuf,smb_vwv0));
+
+       if (!check_fsp(conn, req, fsp, &current_user)) {
+               END_PROFILE(SMBsplwr);
+                return;
+        }
+
        if (!CAN_PRINT(conn)) {
+               reply_doserror(req, ERRDOS, ERRnoaccess);
                END_PROFILE(SMBsplwr);
-               return ERROR_DOS(ERRDOS,ERRnoaccess);
+               return;
        }
 
-       CHECK_FSP(fsp,conn);
        if (!CHECK_WRITE(fsp)) {
-               return(ERROR_DOS(ERRDOS,ERRbadaccess));
+               reply_doserror(req, ERRDOS, ERRbadaccess);
+               END_PROFILE(SMBsplwr);
+               return;
        }
 
-       numtowrite = SVAL(smb_buf(inbuf),1);
-       data = smb_buf(inbuf) + 3;
-  
-       if (write_file(fsp,data,-1,numtowrite) != numtowrite) {
+       numtowrite = SVAL(smb_buf(req->inbuf),1);
+
+       if (smb_buflen(req->inbuf) < numtowrite + 3) {
+               reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
+               END_PROFILE(SMBsplwr);
+               return;
+       }
+
+       data = smb_buf(req->inbuf) + 3;
+
+       if (write_file(req,fsp,data,-1,numtowrite) != numtowrite) {
+               reply_unixerror(req, ERRHRD, ERRdiskfull);
                END_PROFILE(SMBsplwr);
-               return(UNIXERROR(ERRHRD,ERRdiskfull));
+               return;
        }
 
        DEBUG( 3, ( "printwrite fnum=%d num=%d\n", fsp->fnum, numtowrite ) );
-  
+
        END_PROFILE(SMBsplwr);
-       return(outsize);
+       return;
 }
 
 /****************************************************************************
  Reply to a mkdir.
 ****************************************************************************/
 
-void reply_mkdir(connection_struct *conn, struct smb_request *req)
+void reply_mkdir(struct smb_request *req)
 {
-       pstring directory;
+       connection_struct *conn = req->conn;
+       char *directory = NULL;
        NTSTATUS status;
        SMB_STRUCT_STAT sbuf;
+       TALLOC_CTX *ctx = talloc_tos();
 
        START_PROFILE(SMBmkdir);
-       srvstr_get_path((char *)req->inbuf, req->flags2, directory,
-                       smb_buf(req->inbuf) + 1, sizeof(directory), 0,
+
+       srvstr_get_path(ctx, (char *)req->inbuf, req->flags2, &directory,
+                       smb_buf(req->inbuf) + 1, 0,
                        STR_TERMINATE, &status);
        if (!NT_STATUS_IS_OK(status)) {
                reply_nterror(req, status);
@@ -4084,9 +4827,10 @@ void reply_mkdir(connection_struct *conn, struct smb_request *req)
                return;
        }
 
-       status = resolve_dfspath(conn,
+       status = resolve_dfspath(ctx, conn,
                                 req->flags2 & FLAGS2_DFS_PATHNAMES,
-                                directory);
+                                directory,
+                                &directory);
        if (!NT_STATUS_IS_OK(status)) {
                if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
                        reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
@@ -4099,7 +4843,7 @@ void reply_mkdir(connection_struct *conn, struct smb_request *req)
                return;
        }
 
-       status = unix_convert(conn, directory, False, NULL, &sbuf);
+       status = unix_convert(ctx, conn, directory, False, &directory, NULL, &sbuf);
        if (!NT_STATUS_IS_OK(status)) {
                reply_nterror(req, status);
                END_PROFILE(SMBmkdir);
@@ -4112,8 +4856,8 @@ void reply_mkdir(connection_struct *conn, struct smb_request *req)
                END_PROFILE(SMBmkdir);
                return;
        }
-  
-       status = create_directory(conn, directory);
+
+       status = create_directory(conn, req, directory);
 
        DEBUG(5, ("create_directory returned %s\n", nt_errstr(status)));
 
@@ -4148,10 +4892,12 @@ void reply_mkdir(connection_struct *conn, struct smb_request *req)
  tree recursively. Return True on ok, False on fail.
 ****************************************************************************/
 
-static BOOL recursive_rmdir(connection_struct *conn, char *directory)
+static bool recursive_rmdir(TALLOC_CTX *ctx,
+                       connection_struct *conn,
+                       char *directory)
 {
        const char *dname = NULL;
-       BOOL ret = True;
+       bool ret = True;
        long offset = 0;
        struct smb_Dir *dir_hnd = OpenDir(conn, directory, NULL, 0);
 
@@ -4159,33 +4905,35 @@ static BOOL recursive_rmdir(connection_struct *conn, char *directory)
                return False;
 
        while((dname = ReadDirName(dir_hnd, &offset))) {
-               pstring fullname;
+               char *fullname = NULL;
                SMB_STRUCT_STAT st;
 
-               if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0))
+               if (ISDOT(dname) || ISDOTDOT(dname)) {
                        continue;
+               }
 
-               if (!is_visible_file(conn, directory, dname, &st, False))
+               if (!is_visible_file(conn, directory, dname, &st, False)) {
                        continue;
+               }
 
                /* Construct the full name. */
-               if(strlen(directory) + strlen(dname) + 1 >= sizeof(fullname)) {
+               fullname = talloc_asprintf(ctx,
+                               "%s/%s",
+                               directory,
+                               dname);
+               if (!fullname) {
                        errno = ENOMEM;
                        ret = False;
                        break;
                }
 
-               pstrcpy(fullname, directory);
-               pstrcat(fullname, "/");
-               pstrcat(fullname, dname);
-
                if(SMB_VFS_LSTAT(conn,fullname, &st) != 0) {
                        ret = False;
                        break;
                }
 
                if(st.st_mode & S_IFDIR) {
-                       if(!recursive_rmdir(conn, fullname)) {
+                       if(!recursive_rmdir(ctx, conn, fullname)) {
                                ret = False;
                                break;
                        }
@@ -4197,6 +4945,7 @@ static BOOL recursive_rmdir(connection_struct *conn, char *directory)
                        ret = False;
                        break;
                }
+               TALLOC_FREE(fullname);
        }
        CloseDir(dir_hnd);
        return ret;
@@ -4206,7 +4955,9 @@ static BOOL recursive_rmdir(connection_struct *conn, char *directory)
  The internals of the rmdir code - called elsewhere.
 ****************************************************************************/
 
-NTSTATUS rmdir_internals(connection_struct *conn, const char *directory)
+NTSTATUS rmdir_internals(TALLOC_CTX *ctx,
+                       connection_struct *conn,
+                       const char *directory)
 {
        int ret;
        SMB_STRUCT_STAT st;
@@ -4236,7 +4987,7 @@ NTSTATUS rmdir_internals(connection_struct *conn, const char *directory)
        }
 
        if(((errno == ENOTEMPTY)||(errno == EEXIST)) && lp_veto_files(SNUM(conn))) {
-               /* 
+               /*
                 * Check to see if the only thing in this directory are
                 * vetoed files/directories. If so then delete them and
                 * retry. If we fail to delete any of them (and we *don't*
@@ -4267,34 +5018,40 @@ NTSTATUS rmdir_internals(connection_struct *conn, const char *directory)
 
                RewindDir(dir_hnd,&dirpos);
                while ((dname = ReadDirName(dir_hnd,&dirpos))) {
-                       pstring fullname;
+                       char *fullname = NULL;
 
-                       if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0))
+                       if (ISDOT(dname) || ISDOTDOT(dname)) {
                                continue;
-                       if (!is_visible_file(conn, directory, dname, &st, False))
+                       }
+                       if (!is_visible_file(conn, directory, dname, &st, False)) {
                                continue;
+                       }
+
+                       fullname = talloc_asprintf(ctx,
+                                       "%s/%s",
+                                       directory,
+                                       dname);
 
-                       /* Construct the full name. */
-                       if(strlen(directory) + strlen(dname) + 1 >= sizeof(fullname)) {
+                       if(!fullname) {
                                errno = ENOMEM;
                                break;
                        }
 
-                       pstrcpy(fullname, directory);
-                       pstrcat(fullname, "/");
-                       pstrcat(fullname, dname);
-                   
-                       if(SMB_VFS_LSTAT(conn,fullname, &st) != 0)
+                       if(SMB_VFS_LSTAT(conn,fullname, &st) != 0) {
                                break;
+                       }
                        if(st.st_mode & S_IFDIR) {
                                if(lp_recursive_veto_delete(SNUM(conn))) {
-                                       if(!recursive_rmdir(conn, fullname))
+                                       if(!recursive_rmdir(ctx, conn, fullname))
                                                break;
                                }
-                               if(SMB_VFS_RMDIR(conn,fullname) != 0)
+                               if(SMB_VFS_RMDIR(conn,fullname) != 0) {
                                        break;
-                       } else if(SMB_VFS_UNLINK(conn,fullname) != 0)
+                               }
+                       } else if(SMB_VFS_UNLINK(conn,fullname) != 0) {
                                break;
+                       }
+                       TALLOC_FREE(fullname);
                }
                CloseDir(dir_hnd);
                /* Retry the rmdir */
@@ -4320,15 +5077,18 @@ NTSTATUS rmdir_internals(connection_struct *conn, const char *directory)
  Reply to a rmdir.
 ****************************************************************************/
 
-void reply_rmdir(connection_struct *conn, struct smb_request *req)
+void reply_rmdir(struct smb_request *req)
 {
-       pstring directory;
+       connection_struct *conn = req->conn;
+       char *directory = NULL;
        SMB_STRUCT_STAT sbuf;
        NTSTATUS status;
+       TALLOC_CTX *ctx = talloc_tos();
+
        START_PROFILE(SMBrmdir);
 
-       srvstr_get_path((char *)req->inbuf, req->flags2, directory,
-                       smb_buf(req->inbuf) + 1, sizeof(directory), 0,
+       srvstr_get_path(ctx, (char *)req->inbuf, req->flags2, &directory,
+                       smb_buf(req->inbuf) + 1, 0,
                        STR_TERMINATE, &status);
        if (!NT_STATUS_IS_OK(status)) {
                reply_nterror(req, status);
@@ -4336,9 +5096,10 @@ void reply_rmdir(connection_struct *conn, struct smb_request *req)
                return;
        }
 
-       status = resolve_dfspath(conn,
+       status = resolve_dfspath(ctx, conn,
                                 req->flags2 & FLAGS2_DFS_PATHNAMES,
-                                directory);
+                                directory,
+                                &directory);
        if (!NT_STATUS_IS_OK(status)) {
                if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
                        reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
@@ -4351,13 +5112,14 @@ void reply_rmdir(connection_struct *conn, struct smb_request *req)
                return;
        }
 
-       status = unix_convert(conn, directory, False, NULL, &sbuf);
+       status = unix_convert(ctx, conn, directory, False, &directory,
+                       NULL, &sbuf);
        if (!NT_STATUS_IS_OK(status)) {
                reply_nterror(req, status);
                END_PROFILE(SMBrmdir);
                return;
        }
-  
+
        status = check_name(conn, directory);
        if (!NT_STATUS_IS_OK(status)) {
                reply_nterror(req, status);
@@ -4366,104 +5128,146 @@ void reply_rmdir(connection_struct *conn, struct smb_request *req)
        }
 
        dptr_closepath(directory, req->smbpid);
-       status = rmdir_internals(conn, directory);
+       status = rmdir_internals(ctx, conn, directory);
        if (!NT_STATUS_IS_OK(status)) {
                reply_nterror(req, status);
                END_PROFILE(SMBrmdir);
                return;
        }
+
        reply_outbuf(req, 0, 0);
-  
+
        DEBUG( 3, ( "rmdir %s\n", directory ) );
-  
+
        END_PROFILE(SMBrmdir);
        return;
 }
 
 /*******************************************************************
  Resolve wildcards in a filename rename.
- Note that name is in UNIX charset and thus potentially can be more
- than fstring buffer (255 bytes) especially in default UTF-8 case.
- Therefore, we use pstring inside and all calls should ensure that
- name2 is at least pstring-long (they do already)
 ********************************************************************/
 
-static BOOL resolve_wildcards(const char *name1, char *name2)
+static bool resolve_wildcards(TALLOC_CTX *ctx,
+                               const char *name1,
+                               const char *name2,
+                               char **pp_newname)
 {
-       pstring root1,root2;
-       pstring ext1,ext2;
+       char *name2_copy = NULL;
+       char *root1 = NULL;
+       char *root2 = NULL;
+       char *ext1 = NULL;
+       char *ext2 = NULL;
        char *p,*p2, *pname1, *pname2;
-       int available_space, actual_space;
        
+       name2_copy = talloc_strdup(ctx, name2);
+       if (!name2_copy) {
+               return False;
+       }
+
        pname1 = strrchr_m(name1,'/');
-       pname2 = strrchr_m(name2,'/');
+       pname2 = strrchr_m(name2_copy,'/');
 
-       if (!pname1 || !pname2)
-               return(False);
+       if (!pname1 || !pname2) {
+               return False;
+       }
   
-       pstrcpy(root1,pname1);
-       pstrcpy(root2,pname2);
+       /* Truncate the copy of name2 at the last '/' */
+       *pname2 = '\0';
+
+       /* Now go past the '/' */
+       pname1++;
+       pname2++;
+
+       root1 = talloc_strdup(ctx, pname1);
+       root2 = talloc_strdup(ctx, pname2);
+
+       if (!root1 || !root2) {
+               return False;
+       }
+
        p = strrchr_m(root1,'.');
        if (p) {
                *p = 0;
-               pstrcpy(ext1,p+1);
+               ext1 = talloc_strdup(ctx, p+1);
        } else {
-               pstrcpy(ext1,"");    
+               ext1 = talloc_strdup(ctx, "");
        }
        p = strrchr_m(root2,'.');
        if (p) {
                *p = 0;
-               pstrcpy(ext2,p+1);
+               ext2 = talloc_strdup(ctx, p+1);
        } else {
-               pstrcpy(ext2,"");    
+               ext2 = talloc_strdup(ctx, "");
+       }
+
+       if (!ext1 || !ext2) {
+               return False;
        }
 
        p = root1;
        p2 = root2;
        while (*p2) {
                if (*p2 == '?') {
+                       /* Hmmm. Should this be mb-aware ? */
                        *p2 = *p;
                        p2++;
                } else if (*p2 == '*') {
-                       pstrcpy(p2, p);
+                       *p2 = '\0';
+                       root2 = talloc_asprintf(ctx, "%s%s",
+                                               root2,
+                                               p);
+                       if (!root2) {
+                               return False;
+                       }
                        break;
                } else {
                        p2++;
                }
-               if (*p)
+               if (*p) {
                        p++;
+               }
        }
 
        p = ext1;
        p2 = ext2;
        while (*p2) {
                if (*p2 == '?') {
+                       /* Hmmm. Should this be mb-aware ? */
                        *p2 = *p;
                        p2++;
                } else if (*p2 == '*') {
-                       pstrcpy(p2, p);
+                       *p2 = '\0';
+                       ext2 = talloc_asprintf(ctx, "%s%s",
+                                               ext2,
+                                               p);
+                       if (!ext2) {
+                               return False;
+                       }
                        break;
                } else {
                        p2++;
                }
-               if (*p)
+               if (*p) {
                        p++;
+               }
        }
 
-       available_space = sizeof(pstring) - PTR_DIFF(pname2, name2);
-       
-       if (ext2[0]) {
-               actual_space = snprintf(pname2, available_space - 1, "%s.%s", root2, ext2);
-               if (actual_space >= available_space - 1) {
-                       DEBUG(1,("resolve_wildcards: can't fit resolved name into specified buffer (overrun by %d bytes)\n",
-                               actual_space - available_space));
-               }
+       if (*ext2) {
+               *pp_newname = talloc_asprintf(ctx, "%s/%s.%s",
+                               name2_copy,
+                               root2,
+                               ext2);
        } else {
-               pstrcpy_base(pname2, root2, name2);
+               *pp_newname = talloc_asprintf(ctx, "%s/%s",
+                               name2_copy,
+                               root2);
+       }
+
+       if (!*pp_newname) {
+               return False;
        }
 
-       return(True);
+       return True;
 }
 
 /****************************************************************************
@@ -4476,7 +5280,7 @@ static void rename_open_files(connection_struct *conn,
                              const char *newname)
 {
        files_struct *fsp;
-       BOOL did_rename = False;
+       bool did_rename = False;
 
        for(fsp = file_find_di_first(lck->id); fsp;
            fsp = file_find_di_next(fsp)) {
@@ -4488,7 +5292,7 @@ static void rename_open_files(connection_struct *conn,
                        continue;
                }
                DEBUG(10,("rename_open_files: renaming file fnum %d (file_id %s) from %s -> %s\n",
-                         fsp->fnum, file_id_static_string(&fsp->file_id),
+                         fsp->fnum, file_id_string_tos(&fsp->file_id),
                        fsp->fsp_name, newname ));
                string_set(&fsp->fsp_name, newname);
                did_rename = True;
@@ -4496,7 +5300,7 @@ static void rename_open_files(connection_struct *conn,
 
        if (!did_rename) {
                DEBUG(10,("rename_open_files: no open files on file_id %s for %s\n",
-                         file_id_static_string(&lck->id), newname ));
+                         file_id_string_tos(&lck->id), newname ));
        }
 
        /* Send messages to all smbd's (not ourself) that the name has changed. */
@@ -4515,7 +5319,7 @@ static void rename_open_files(connection_struct *conn,
  report from <AndyLiebman@aol.com>.
 ****************************************************************************/
 
-static BOOL rename_path_prefix_equal(const char *src, const char *dest)
+static bool rename_path_prefix_equal(const char *src, const char *dest)
 {
        const char *psrc = src;
        const char *pdst = dest;
@@ -4537,7 +5341,7 @@ static BOOL rename_path_prefix_equal(const char *src, const char *dest)
  * Do the notify calls from a rename
  */
 
-static void notify_rename(connection_struct *conn, BOOL is_dir,
+static void notify_rename(connection_struct *conn, bool is_dir,
                          const char *oldpath, const char *newpath)
 {
        char *olddir, *newdir;
@@ -4579,36 +5383,34 @@ static void notify_rename(connection_struct *conn, BOOL is_dir,
  Rename an open file - given an fsp.
 ****************************************************************************/
 
-NTSTATUS rename_internals_fsp(connection_struct *conn, files_struct *fsp, pstring newname, uint32 attrs, BOOL replace_if_exists)
+NTSTATUS rename_internals_fsp(connection_struct *conn,
+                       files_struct *fsp,
+                       char *newname,
+                       const char *newname_last_component,
+                       uint32 attrs,
+                       bool replace_if_exists)
 {
+       TALLOC_CTX *ctx = talloc_tos();
        SMB_STRUCT_STAT sbuf, sbuf1;
-       pstring newname_last_component;
        NTSTATUS status = NT_STATUS_OK;
        struct share_mode_lock *lck = NULL;
-       BOOL dst_exists;
+       bool dst_exists;
 
        ZERO_STRUCT(sbuf);
 
-       status = unix_convert(conn, newname, False, 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;
-       }
-
        status = check_name(conn, newname);
        if (!NT_STATUS_IS_OK(status)) {
                return status;
        }
-  
+
        /* Ensure newname contains a '/' */
        if(strrchr_m(newname,'/') == 0) {
-               pstring tmpstr;
-               
-               pstrcpy(tmpstr, "./");
-               pstrcat(tmpstr, newname);
-               pstrcpy(newname, tmpstr);
+               newname = talloc_asprintf(ctx,
+                                       "./%s",
+                                       newname);
+               if (!newname) {
+                       return NT_STATUS_NO_MEMORY;
+               }
        }
 
        /*
@@ -4622,7 +5424,7 @@ NTSTATUS rename_internals_fsp(connection_struct *conn, files_struct *fsp, pstrin
        if((conn->case_sensitive == False) && (conn->case_preserve == True) &&
                        strequal(newname, fsp->fsp_name)) {
                char *p;
-               pstring newname_modified_last_component;
+               char *newname_modified_last_component = NULL;
 
                /*
                 * Get the last component of the modified name.
@@ -4630,15 +5432,23 @@ NTSTATUS rename_internals_fsp(connection_struct *conn, files_struct *fsp, pstrin
                 * character above.
                 */
                p = strrchr_m(newname,'/');
-               pstrcpy(newname_modified_last_component,p+1);
-                       
-               if(strcsequal(newname_modified_last_component, 
+               newname_modified_last_component = talloc_strdup(ctx,
+                                               p+1);
+               if (!newname_modified_last_component) {
+                       return NT_STATUS_NO_MEMORY;
+               }
+
+               if(strcsequal(newname_modified_last_component,
                              newname_last_component) == False) {
                        /*
                         * Replace the modified last component with
                         * the original.
                         */
-                       pstrcpy(p+1, newname_last_component);
+                       *p = '\0'; /* Truncate at the '/' */
+                       newname = talloc_asprintf(ctx,
+                                       "%s/%s",
+                                       newname,
+                                       newname_last_component);
                }
        }
 
@@ -4738,7 +5548,7 @@ NTSTATUS rename_internals_fsp(connection_struct *conn, files_struct *fsp, pstrin
                        }
                }
                TALLOC_FREE(lck);
-               return NT_STATUS_OK;    
+               return NT_STATUS_OK;
        }
 
        TALLOC_FREE(lck);
@@ -4748,7 +5558,7 @@ NTSTATUS rename_internals_fsp(connection_struct *conn, files_struct *fsp, pstrin
        } else {
                status = map_nt_error_from_unix(errno);
        }
-               
+
        DEBUG(3,("rename_internals_fsp: Error %s rename %s -> %s\n",
                nt_errstr(status), fsp->fsp_name,newname));
 
@@ -4757,21 +5567,25 @@ NTSTATUS rename_internals_fsp(connection_struct *conn, files_struct *fsp, pstrin
 
 /****************************************************************************
  The guts of the rename command, split out so it may be called by the NT SMB
- code. 
+ code.
 ****************************************************************************/
 
-NTSTATUS rename_internals(connection_struct *conn, struct smb_request *req,
-                               pstring name,
-                               pstring newname,
-                               uint32 attrs,
-                               BOOL replace_if_exists,
-                               BOOL src_has_wild,
-                               BOOL dest_has_wild)
+NTSTATUS rename_internals(TALLOC_CTX *ctx,
+                       connection_struct *conn,
+                       struct smb_request *req,
+                       const char *name_in,
+                       const char *newname_in,
+                       uint32 attrs,
+                       bool replace_if_exists,
+                       bool src_has_wild,
+                       bool dest_has_wild)
 {
-       pstring directory;
-       pstring mask;
-       pstring last_component_src;
-       pstring last_component_dest;
+       char *directory = NULL;
+       char *mask = NULL;
+       char *last_component_src = NULL;
+       char *last_component_dest = NULL;
+       char *name = NULL;
+       char *newname = NULL;
        char *p;
        int count=0;
        NTSTATUS status = NT_STATUS_OK;
@@ -4779,27 +5593,26 @@ NTSTATUS rename_internals(connection_struct *conn, struct smb_request *req,
        struct smb_Dir *dir_hnd = NULL;
        const char *dname;
        long offset = 0;
-       pstring destname;
-
-       *directory = *mask = 0;
 
        ZERO_STRUCT(sbuf1);
        ZERO_STRUCT(sbuf2);
 
-       status = unix_convert(conn, name, src_has_wild, last_component_src, &sbuf1);
+       status = unix_convert(ctx, conn, name_in, src_has_wild, &name,
+                       &last_component_src, &sbuf1);
        if (!NT_STATUS_IS_OK(status)) {
                return status;
        }
 
-       status = unix_convert(conn, newname, dest_has_wild, last_component_dest, &sbuf2);
+       status = unix_convert(ctx, conn, newname_in, dest_has_wild, &newname,
+                       &last_component_dest, &sbuf2);
        if (!NT_STATUS_IS_OK(status)) {
                return status;
        }
 
        /*
         * Split the old name into directory and last component
-        * strings. Note that unix_convert may have stripped off a 
-        * leading ./ from both name and newname if the rename is 
+        * strings. Note that unix_convert may have stripped off a
+        * leading ./ from both name and newname if the rename is
         * at the root of the share. We need to make sure either both
         * name and newname contain a / character or neither of them do
         * as this is checked in resolve_wildcards().
@@ -4807,12 +5620,18 @@ NTSTATUS rename_internals(connection_struct *conn, struct smb_request *req,
 
        p = strrchr_m(name,'/');
        if (!p) {
-               pstrcpy(directory,".");
-               pstrcpy(mask,name);
+               directory = talloc_strdup(ctx, ".");
+               if (!directory) {
+                       return NT_STATUS_NO_MEMORY;
+               }
+               mask = name;
        } else {
                *p = 0;
-               pstrcpy(directory,name);
-               pstrcpy(mask,p+1);
+               directory = talloc_strdup(ctx, name);
+               if (!directory) {
+                       return NT_STATUS_NO_MEMORY;
+               }
+               mask = p+1;
                *p = '/'; /* Replace needed for exceptional test below. */
        }
 
@@ -4826,7 +5645,14 @@ NTSTATUS rename_internals(connection_struct *conn, struct smb_request *req,
         */
 
        if (!VALID_STAT(sbuf1) && mangle_is_mangled(mask, conn->params)) {
-               mangle_check_cache( mask, sizeof(pstring)-1, conn->params );
+               char *new_mask = NULL;
+               mangle_lookup_name_from_8_3(ctx,
+                                       mask,
+                                       &new_mask,
+                                       conn->params );
+               if (new_mask) {
+                       mask = new_mask;
+               }
        }
 
        if (!src_has_wild) {
@@ -4835,38 +5661,48 @@ NTSTATUS rename_internals(connection_struct *conn, struct smb_request *req,
                /*
                 * No wildcards - just process the one file.
                 */
-               BOOL is_short_name = mangle_is_8_3(name, True, conn->params);
+               bool is_short_name = mangle_is_8_3(name, True, conn->params);
 
                /* Add a terminating '/' to the directory name. */
-               pstrcat(directory,"/");
-               pstrcat(directory,mask);
-               
+               directory = talloc_asprintf_append(directory,
+                               "/%s",
+                               mask);
+               if (!directory) {
+                       return NT_STATUS_NO_MEMORY;
+               }
+
                /* Ensure newname contains a '/' also */
                if(strrchr_m(newname,'/') == 0) {
-                       pstring tmpstr;
-                       
-                       pstrcpy(tmpstr, "./");
-                       pstrcat(tmpstr, newname);
-                       pstrcpy(newname, tmpstr);
+                       newname = talloc_asprintf(ctx,
+                                               "./%s",
+                                               newname);
+                       if (!newname) {
+                               return NT_STATUS_NO_MEMORY;
+                       }
                }
-               
+
                DEBUG(3, ("rename_internals: case_sensitive = %d, "
                          "case_preserve = %d, short case preserve = %d, "
                          "directory = %s, newname = %s, "
-                         "last_component_dest = %s, is_8_3 = %d\n", 
+                         "last_component_dest = %s, is_8_3 = %d\n",
                          conn->case_sensitive, conn->case_preserve,
-                         conn->short_case_preserve, directory, 
+                         conn->short_case_preserve, directory,
                          newname, last_component_dest, is_short_name));
 
                /* The dest name still may have wildcards. */
                if (dest_has_wild) {
-                       if (!resolve_wildcards(directory,newname)) {
-                               DEBUG(6, ("rename_internals: resolve_wildcards %s %s failed\n", 
-                                         directory,newname));
+                       char *mod_newname = NULL;
+                       if (!resolve_wildcards(ctx,
+                                       directory,newname,&mod_newname)) {
+                               DEBUG(6, ("rename_internals: resolve_wildcards "
+                                       "%s %s failed\n",
+                                       directory,
+                                       newname));
                                return NT_STATUS_NO_MEMORY;
                        }
+                       newname = mod_newname;
                }
-                               
+
                ZERO_STRUCT(sbuf1);
                SMB_VFS_STAT(conn, directory, &sbuf1);
 
@@ -4888,8 +5724,9 @@ NTSTATUS rename_internals(connection_struct *conn, struct smb_request *req,
                        return status;
                }
 
-               status = rename_internals_fsp(conn, fsp, newname, attrs,
-                                             replace_if_exists);
+               status = rename_internals_fsp(conn, fsp, newname,
+                                             last_component_dest,
+                                             attrs, replace_if_exists);
 
                close_file(fsp, NORMAL_CLOSE);
 
@@ -4903,40 +5740,38 @@ NTSTATUS rename_internals(connection_struct *conn, struct smb_request *req,
         * Wildcards - process each file that matches.
         */
        if (strequal(mask,"????????.???")) {
-               pstrcpy(mask,"*");
+               mask[0] = '*';
+               mask[1] = '\0';
        }
-                       
+
        status = check_name(conn, directory);
        if (!NT_STATUS_IS_OK(status)) {
                return status;
        }
-       
+
        dir_hnd = OpenDir(conn, directory, mask, attrs);
        if (dir_hnd == NULL) {
                return map_nt_error_from_unix(errno);
        }
-               
+
        status = NT_STATUS_NO_SUCH_FILE;
        /*
         * Was status = NT_STATUS_OBJECT_NAME_NOT_FOUND;
         * - gentest fix. JRA
         */
-                       
+
        while ((dname = ReadDirName(dir_hnd, &offset))) {
-               files_struct *fsp;
-               pstring fname;
-               BOOL sysdir_entry = False;
+               files_struct *fsp = NULL;
+               char *fname = NULL;
+               char *destname = NULL;
+               bool sysdir_entry = False;
 
-               pstrcpy(fname,dname);
-                               
                /* Quick check for "." and ".." */
-               if (fname[0] == '.') {
-                       if (!fname[1] || (fname[1] == '.' && !fname[2])) {
-                               if (attrs & aDIR) {
-                                       sysdir_entry = True;
-                               } else {
-                                       continue;
-                               }
+               if (ISDOT(dname) || ISDOTDOT(dname)) {
+                       if (attrs & aDIR) {
+                               sysdir_entry = True;
+                       } else {
+                               continue;
                        }
                }
 
@@ -4944,25 +5779,34 @@ NTSTATUS rename_internals(connection_struct *conn, struct smb_request *req,
                        continue;
                }
 
-               if(!mask_match(fname, mask, conn->case_sensitive)) {
+               if(!mask_match(dname, mask, conn->case_sensitive)) {
                        continue;
                }
-                               
+
                if (sysdir_entry) {
                        status = NT_STATUS_OBJECT_NAME_INVALID;
                        break;
                }
 
-               slprintf(fname, sizeof(fname)-1, "%s/%s", directory, dname);
+               fname = talloc_asprintf(ctx,
+                               "%s/%s",
+                               directory,
+                               dname);
+               if (!fname) {
+                       return NT_STATUS_NO_MEMORY;
+               }
 
-               pstrcpy(destname,newname);
-                       
-               if (!resolve_wildcards(fname,destname)) {
-                       DEBUG(6, ("resolve_wildcards %s %s failed\n", 
+               if (!resolve_wildcards(ctx,
+                               fname,newname,&destname)) {
+                       DEBUG(6, ("resolve_wildcards %s %s failed\n",
                                  fname, destname));
+                       TALLOC_FREE(fname);
                        continue;
                }
-                               
+               if (!destname) {
+                       return NT_STATUS_NO_MEMORY;
+               }
+
                ZERO_STRUCT(sbuf1);
                SMB_VFS_STAT(conn, fname, &sbuf1);
 
@@ -4985,8 +5829,8 @@ NTSTATUS rename_internals(connection_struct *conn, struct smb_request *req,
                        break;
                }
 
-               status = rename_internals_fsp(conn, fsp, destname, attrs,
-                                             replace_if_exists);
+               status = rename_internals_fsp(conn, fsp, destname, dname,
+                                             attrs, replace_if_exists);
 
                close_file(fsp, NORMAL_CLOSE);
 
@@ -5001,13 +5845,16 @@ NTSTATUS rename_internals(connection_struct *conn, struct smb_request *req,
 
                DEBUG(3,("rename_internals: doing rename on %s -> "
                         "%s\n",fname,destname));
+
+               TALLOC_FREE(fname);
+               TALLOC_FREE(destname);
        }
        CloseDir(dir_hnd);
 
        if (count == 0 && NT_STATUS_IS_OK(status)) {
                status = map_nt_error_from_unix(errno);
        }
-       
+
        return status;
 }
 
@@ -5015,75 +5862,100 @@ NTSTATUS rename_internals(connection_struct *conn, struct smb_request *req,
  Reply to a mv.
 ****************************************************************************/
 
-int reply_mv(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, 
-            int dum_buffsize)
+void reply_mv(struct smb_request *req)
 {
-       int outsize = 0;
-       pstring name;
-       pstring newname;
+       connection_struct *conn = req->conn;
+       char *name = NULL;
+       char *newname = NULL;
        char *p;
-       uint32 attrs = SVAL(inbuf,smb_vwv0);
+       uint32 attrs;
        NTSTATUS status;
-       BOOL src_has_wcard = False;
-       BOOL dest_has_wcard = False;
-       struct smb_request req;
+       bool src_has_wcard = False;
+       bool dest_has_wcard = False;
+       TALLOC_CTX *ctx = talloc_tos();
 
        START_PROFILE(SMBmv);
 
-       init_smb_request(&req, (uint8 *)inbuf);
+       if (req->wct < 1) {
+               reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
+               END_PROFILE(SMBmv);
+               return;
+       }
+
+       attrs = SVAL(req->inbuf,smb_vwv0);
 
-       p = smb_buf(inbuf) + 1;
-       p += srvstr_get_path_wcard(inbuf, SVAL(inbuf,smb_flg2), name, p,
-                                  sizeof(name), 0, STR_TERMINATE, &status,
+       p = smb_buf(req->inbuf) + 1;
+       p += srvstr_get_path_wcard(ctx, (char *)req->inbuf, req->flags2, &name, p,
+                                  0, STR_TERMINATE, &status,
                                   &src_has_wcard);
        if (!NT_STATUS_IS_OK(status)) {
+               reply_nterror(req, status);
                END_PROFILE(SMBmv);
-               return ERROR_NT(status);
+               return;
        }
        p++;
-       p += srvstr_get_path_wcard(inbuf, SVAL(inbuf,smb_flg2), newname, p,
-                                  sizeof(newname), 0, STR_TERMINATE, &status,
+       p += srvstr_get_path_wcard(ctx, (char *)req->inbuf, req->flags2, &newname, p,
+                                  0, STR_TERMINATE, &status,
                                   &dest_has_wcard);
        if (!NT_STATUS_IS_OK(status)) {
+               reply_nterror(req, status);
                END_PROFILE(SMBmv);
-               return ERROR_NT(status);
+               return;
        }
-       
-       status = resolve_dfspath_wcard(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, name, &src_has_wcard);
+
+       status = resolve_dfspath_wcard(ctx, conn,
+                                      req->flags2 & FLAGS2_DFS_PATHNAMES,
+                                      name,
+                                      &name,
+                                      &src_has_wcard);
        if (!NT_STATUS_IS_OK(status)) {
-               END_PROFILE(SMBmv);
                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);
+                       END_PROFILE(SMBmv);
+                       return;
                }
-               return ERROR_NT(status);
+               reply_nterror(req, status);
+               END_PROFILE(SMBmv);
+               return;
        }
 
-       status = resolve_dfspath_wcard(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, newname, &dest_has_wcard);
+       status = resolve_dfspath_wcard(ctx, conn,
+                                      req->flags2 & FLAGS2_DFS_PATHNAMES,
+                                      newname,
+                                      &newname,
+                                      &dest_has_wcard);
        if (!NT_STATUS_IS_OK(status)) {
-               END_PROFILE(SMBmv);
                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);
+                       END_PROFILE(SMBmv);
+                       return;
                }
-               return ERROR_NT(status);
+               reply_nterror(req, status);
+               END_PROFILE(SMBmv);
+               return;
        }
-       
+
        DEBUG(3,("reply_mv : %s -> %s\n",name,newname));
-       
-       status = rename_internals(conn, &req, name, newname, attrs, False,
+
+       status = rename_internals(ctx, conn, req, name, newname, attrs, False,
                                  src_has_wcard, dest_has_wcard);
        if (!NT_STATUS_IS_OK(status)) {
-               END_PROFILE(SMBmv);
-               if (open_was_deferred(SVAL(inbuf,smb_mid))) {
+               if (open_was_deferred(req->mid)) {
                        /* We have re-scheduled this call. */
-                       return -1;
+                       END_PROFILE(SMBmv);
+                       return;
                }
-               return ERROR_NT(status);
+               reply_nterror(req, status);
+               END_PROFILE(SMBmv);
+               return;
        }
 
-       outsize = set_message(inbuf,outbuf,0,0,False);
-  
+       reply_outbuf(req, 0, 0);
+
        END_PROFILE(SMBmv);
-       return(outsize);
+       return;
 }
 
 /*******************************************************************
@@ -5094,34 +5966,43 @@ int reply_mv(connection_struct *conn, char *inbuf,char *outbuf, int dum_size,
  * TODO: check error codes on all callers
  */
 
-NTSTATUS copy_file(connection_struct *conn,
-                       char *src,
-                       char *dest1,
+NTSTATUS copy_file(TALLOC_CTX *ctx,
+                       connection_struct *conn,
+                       const char *src,
+                       const char *dest1,
                        int ofun,
                        int count,
-                       BOOL target_is_directory)
+                       bool target_is_directory)
 {
        SMB_STRUCT_STAT src_sbuf, sbuf2;
        SMB_OFF_T ret=-1;
        files_struct *fsp1,*fsp2;
-       pstring dest;
+       char *dest = NULL;
        uint32 dosattrs;
        uint32 new_create_disposition;
        NTSTATUS status;
-       pstrcpy(dest,dest1);
+
+       dest = talloc_strdup(ctx, dest1);
+       if (!dest) {
+               return NT_STATUS_NO_MEMORY;
+       }
        if (target_is_directory) {
-               char *p = strrchr_m(src,'/');
+               const char *p = strrchr_m(src,'/');
                if (p) {
                        p++;
                } else {
                        p = src;
                }
-               pstrcat(dest,"/");
-               pstrcat(dest,p);
+               dest = talloc_asprintf_append(dest,
+                               "/%s",
+                               p);
+               if (!dest) {
+                       return NT_STATUS_NO_MEMORY;
+               }
        }
 
        if (!vfs_file_exist(conn,src,&src_sbuf)) {
+               TALLOC_FREE(dest);
                return NT_STATUS_OBJECT_NAME_NOT_FOUND;
        }
 
@@ -5130,6 +6011,7 @@ NTSTATUS copy_file(connection_struct *conn,
        } else {
                if (!map_open_params_to_ntcreate(dest1,0,ofun,
                                NULL, NULL, &new_create_disposition, NULL)) {
+                       TALLOC_FREE(dest);
                        return NT_STATUS_INVALID_PARAMETER;
                }
        }
@@ -5144,6 +6026,7 @@ NTSTATUS copy_file(connection_struct *conn,
                        NULL, &fsp1);
 
        if (!NT_STATUS_IS_OK(status)) {
+               TALLOC_FREE(dest);
                return status;
        }
 
@@ -5161,13 +6044,15 @@ NTSTATUS copy_file(connection_struct *conn,
                        INTERNAL_OPEN_ONLY,
                        NULL, &fsp2);
 
+       TALLOC_FREE(dest);
+
        if (!NT_STATUS_IS_OK(status)) {
                close_file(fsp1,ERROR_CLOSE);
                return status;
        }
 
        if ((ofun&3) == 1) {
-               if(SMB_VFS_LSEEK(fsp2,fsp2->fh->fd,0,SEEK_END) == -1) {
+               if(SMB_VFS_LSEEK(fsp2,0,SEEK_END) == -1) {
                        DEBUG(0,("copy_file: error - vfs lseek returned error %s\n", strerror(errno) ));
                        /*
                         * Stop the copy from occurring.
@@ -5176,7 +6061,7 @@ NTSTATUS copy_file(connection_struct *conn,
                        src_sbuf.st_size = 0;
                }
        }
-  
+
        if (src_sbuf.st_size) {
                ret = vfs_transfer_file(fsp1, fsp2, src_sbuf.st_size);
        }
@@ -5209,110 +6094,157 @@ NTSTATUS copy_file(connection_struct *conn,
  Reply to a file copy.
 ****************************************************************************/
 
-int reply_copy(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
+void reply_copy(struct smb_request *req)
 {
-       int outsize = 0;
-       pstring name;
-       pstring directory;
-       pstring mask,newname;
+       connection_struct *conn = req->conn;
+       char *name = NULL;
+       char *newname = NULL;
+       char *directory = NULL;
+       char *mask = NULL;
        char *p;
        int count=0;
        int error = ERRnoaccess;
        int err = 0;
-       int tid2 = SVAL(inbuf,smb_vwv0);
-       int ofun = SVAL(inbuf,smb_vwv1);
-       int flags = SVAL(inbuf,smb_vwv2);
-       BOOL target_is_directory=False;
-       BOOL source_has_wild = False;
-       BOOL dest_has_wild = False;
+       int tid2;
+       int ofun;
+       int flags;
+       bool target_is_directory=False;
+       bool source_has_wild = False;
+       bool dest_has_wild = False;
        SMB_STRUCT_STAT sbuf1, sbuf2;
        NTSTATUS status;
+       TALLOC_CTX *ctx = talloc_tos();
+
        START_PROFILE(SMBcopy);
 
-       *directory = *mask = 0;
+       if (req->wct < 3) {
+               reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
+               END_PROFILE(SMBcopy);
+               return;
+       }
+
+       tid2 = SVAL(req->inbuf,smb_vwv0);
+       ofun = SVAL(req->inbuf,smb_vwv1);
+       flags = SVAL(req->inbuf,smb_vwv2);
 
-       p = smb_buf(inbuf);
-       p += srvstr_get_path_wcard(inbuf, SVAL(inbuf,smb_flg2), name, p,
-                                  sizeof(name), 0, STR_TERMINATE, &status,
+       p = smb_buf(req->inbuf);
+       p += srvstr_get_path_wcard(ctx, (char *)req->inbuf, req->flags2, &name, p,
+                                  0, STR_TERMINATE, &status,
                                   &source_has_wild);
        if (!NT_STATUS_IS_OK(status)) {
+               reply_nterror(req, status);
                END_PROFILE(SMBcopy);
-               return ERROR_NT(status);
+               return;
        }
-       p += srvstr_get_path_wcard(inbuf, SVAL(inbuf,smb_flg2), newname, p,
-                                  sizeof(newname), 0, STR_TERMINATE, &status,
+       p += srvstr_get_path_wcard(ctx, (char *)req->inbuf, req->flags2, &newname, p,
+                                  0, STR_TERMINATE, &status,
                                   &dest_has_wild);
        if (!NT_STATUS_IS_OK(status)) {
+               reply_nterror(req, status);
                END_PROFILE(SMBcopy);
-               return ERROR_NT(status);
+               return;
        }
-   
+
        DEBUG(3,("reply_copy : %s -> %s\n",name,newname));
-   
+
        if (tid2 != conn->cnum) {
                /* can't currently handle inter share copies XXXX */
                DEBUG(3,("Rejecting inter-share copy\n"));
+               reply_doserror(req, ERRSRV, ERRinvdevice);
                END_PROFILE(SMBcopy);
-               return ERROR_DOS(ERRSRV,ERRinvdevice);
+               return;
        }
 
-       status = resolve_dfspath_wcard(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, name, &source_has_wild);
+       status = resolve_dfspath_wcard(ctx, conn,
+                                      req->flags2 & FLAGS2_DFS_PATHNAMES,
+                                      name,
+                                      &name,
+                                      &source_has_wild);
        if (!NT_STATUS_IS_OK(status)) {
-               END_PROFILE(SMBcopy);
                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);
+                       END_PROFILE(SMBcopy);
+                       return;
                }
-               return ERROR_NT(status);
+               reply_nterror(req, status);
+               END_PROFILE(SMBcopy);
+               return;
        }
 
-       status = resolve_dfspath_wcard(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, newname, &dest_has_wild);
+       status = resolve_dfspath_wcard(ctx, conn,
+                                      req->flags2 & FLAGS2_DFS_PATHNAMES,
+                                      newname,
+                                      &newname,
+                                      &dest_has_wild);
        if (!NT_STATUS_IS_OK(status)) {
-               END_PROFILE(SMBcopy);
                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);
+                       END_PROFILE(SMBcopy);
+                       return;
                }
-               return ERROR_NT(status);
+               reply_nterror(req, status);
+               END_PROFILE(SMBcopy);
+               return;
        }
 
-       status = unix_convert(conn, name, source_has_wild, NULL, &sbuf1);
+       status = unix_convert(ctx, conn, name, source_has_wild,
+                       &name, NULL, &sbuf1);
        if (!NT_STATUS_IS_OK(status)) {
+               reply_nterror(req, status);
                END_PROFILE(SMBcopy);
-               return ERROR_NT(status);
+               return;
        }
 
-       status = unix_convert(conn, newname, dest_has_wild, NULL, &sbuf2);
+       status = unix_convert(ctx, conn, newname, dest_has_wild,
+                       &newname, NULL, &sbuf2);
        if (!NT_STATUS_IS_OK(status)) {
+               reply_nterror(req, status);
                END_PROFILE(SMBcopy);
-               return ERROR_NT(status);
+               return;
        }
 
        target_is_directory = VALID_STAT_OF_DIR(sbuf2);
 
        if ((flags&1) && target_is_directory) {
+               reply_doserror(req, ERRDOS, ERRbadfile);
                END_PROFILE(SMBcopy);
-               return ERROR_DOS(ERRDOS,ERRbadfile);
+               return;
        }
 
        if ((flags&2) && !target_is_directory) {
+               reply_doserror(req, ERRDOS, ERRbadpath);
                END_PROFILE(SMBcopy);
-               return ERROR_DOS(ERRDOS,ERRbadpath);
+               return;
        }
 
        if ((flags&(1<<5)) && VALID_STAT_OF_DIR(sbuf1)) {
                /* wants a tree copy! XXXX */
                DEBUG(3,("Rejecting tree copy\n"));
+               reply_doserror(req, ERRSRV, ERRerror);
                END_PROFILE(SMBcopy);
-               return ERROR_DOS(ERRSRV,ERRerror);
+               return;
        }
 
        p = strrchr_m(name,'/');
        if (!p) {
-               pstrcpy(directory,"./");
-               pstrcpy(mask,name);
+               directory = talloc_strdup(ctx, "./");
+               if (!directory) {
+                       reply_nterror(req, NT_STATUS_NO_MEMORY);
+                       END_PROFILE(SMBcopy);
+                       return;
+               }
+               mask = name;
        } else {
                *p = 0;
-               pstrcpy(directory,name);
-               pstrcpy(mask,p+1);
+               directory = talloc_strdup(ctx, name);
+               if (!directory) {
+                       reply_nterror(req, NT_STATUS_NO_MEMORY);
+                       END_PROFILE(SMBcopy);
+                       return;
+               }
+               mask = p+1;
        }
 
        /*
@@ -5325,170 +6257,165 @@ int reply_copy(connection_struct *conn, char *inbuf,char *outbuf, int dum_size,
         */
 
        if (!VALID_STAT(sbuf1) && mangle_is_mangled(mask, conn->params)) {
-               mangle_check_cache( mask, sizeof(pstring)-1, conn->params );
+               char *new_mask = NULL;
+               mangle_lookup_name_from_8_3(ctx,
+                                       mask,
+                                       &new_mask,
+                                       conn->params );
+               if (new_mask) {
+                       mask = new_mask;
+               }
        }
 
        if (!source_has_wild) {
-               pstrcat(directory,"/");
-               pstrcat(directory,mask);
+               directory = talloc_asprintf_append(directory,
+                               "/%s",
+                               mask);
                if (dest_has_wild) {
-                       if (!resolve_wildcards(directory,newname)) {
+                       char *mod_newname = NULL;
+                       if (!resolve_wildcards(ctx,
+                                       directory,newname,&mod_newname)) {
+                               reply_nterror(req, NT_STATUS_NO_MEMORY);
                                END_PROFILE(SMBcopy);
-                               return ERROR_NT(NT_STATUS_NO_MEMORY);
+                               return;
                        }
+                       newname = mod_newname;
                }
 
                status = check_name(conn, directory);
                if (!NT_STATUS_IS_OK(status)) {
-                       return ERROR_NT(status);
+                       reply_nterror(req, status);
+                       END_PROFILE(SMBcopy);
+                       return;
                }
-               
+
                status = check_name(conn, newname);
                if (!NT_STATUS_IS_OK(status)) {
-                       return ERROR_NT(status);
+                       reply_nterror(req, status);
+                       END_PROFILE(SMBcopy);
+                       return;
                }
-               
-               status = copy_file(conn,directory,newname,ofun,
-                                       count,target_is_directory);
+
+               status = copy_file(ctx,conn,directory,newname,ofun,
+                               count,target_is_directory);
 
                if(!NT_STATUS_IS_OK(status)) {
+                       reply_nterror(req, status);
                        END_PROFILE(SMBcopy);
-                       return ERROR_NT(status);
+                       return;
                } else {
                        count++;
                }
        } else {
                struct smb_Dir *dir_hnd = NULL;
-               const char *dname;
+               const char *dname = NULL;
                long offset = 0;
-               pstring destname;
 
-               if (strequal(mask,"????????.???"))
-                       pstrcpy(mask,"*");
+               if (strequal(mask,"????????.???")) {
+                       mask[0] = '*';
+                       mask[1] = '\0';
+               }
 
                status = check_name(conn, directory);
                if (!NT_STATUS_IS_OK(status)) {
-                       return ERROR_NT(status);
+                       reply_nterror(req, status);
+                       END_PROFILE(SMBcopy);
+                       return;
                }
-               
+
                dir_hnd = OpenDir(conn, directory, mask, 0);
                if (dir_hnd == NULL) {
                        status = map_nt_error_from_unix(errno);
-                       return ERROR_NT(status);
+                       reply_nterror(req, status);
+                       END_PROFILE(SMBcopy);
+                       return;
                }
 
                error = ERRbadfile;
 
                while ((dname = ReadDirName(dir_hnd, &offset))) {
-                       pstring fname;
-                       pstrcpy(fname,dname);
-    
+                       char *destname = NULL;
+                       char *fname = NULL;
+
+                       if (ISDOT(dname) || ISDOTDOT(dname)) {
+                               continue;
+                       }
+
                        if (!is_visible_file(conn, directory, dname, &sbuf1, False)) {
                                continue;
                        }
 
-                       if(!mask_match(fname, mask, conn->case_sensitive)) {
+                       if(!mask_match(dname, mask, conn->case_sensitive)) {
                                continue;
                        }
 
                        error = ERRnoaccess;
-                       slprintf(fname,sizeof(fname)-1, "%s/%s",directory,dname);
-                       pstrcpy(destname,newname);
-                       if (!resolve_wildcards(fname,destname)) {
+                       fname = talloc_asprintf(ctx,
+                                       "%s/%s",
+                                       directory,
+                                       dname);
+                       if (!fname) {
+                               reply_nterror(req, NT_STATUS_NO_MEMORY);
+                               END_PROFILE(SMBcopy);
+                               return;
+                       }
+
+                       if (!resolve_wildcards(ctx,
+                                       fname,newname,&destname)) {
                                continue;
                        }
+                       if (!destname) {
+                               reply_nterror(req, NT_STATUS_NO_MEMORY);
+                               END_PROFILE(SMBcopy);
+                               return;
+                       }
 
                        status = check_name(conn, fname);
                        if (!NT_STATUS_IS_OK(status)) {
-                               return ERROR_NT(status);
+                               reply_nterror(req, status);
+                               END_PROFILE(SMBcopy);
+                               return;
                        }
-               
+
                        status = check_name(conn, destname);
                        if (!NT_STATUS_IS_OK(status)) {
-                               return ERROR_NT(status);
+                               reply_nterror(req, status);
+                               END_PROFILE(SMBcopy);
+                               return;
                        }
-               
+
                        DEBUG(3,("reply_copy : doing copy on %s -> %s\n",fname, destname));
 
-                       status = copy_file(conn,fname,destname,ofun,
+                       status = copy_file(ctx,conn,fname,destname,ofun,
                                        count,target_is_directory);
                        if (NT_STATUS_IS_OK(status)) {
                                count++;
                        }
+                       TALLOC_FREE(fname);
+                       TALLOC_FREE(destname);
                }
                CloseDir(dir_hnd);
        }
-  
+
        if (count == 0) {
                if(err) {
                        /* Error on close... */
                        errno = err;
+                       reply_unixerror(req, ERRHRD, ERRgeneral);
                        END_PROFILE(SMBcopy);
-                       return(UNIXERROR(ERRHRD,ERRgeneral));
+                       return;
                }
 
+               reply_doserror(req, ERRDOS, error);
                END_PROFILE(SMBcopy);
-               return ERROR_DOS(ERRDOS,error);
-       }
-  
-       outsize = set_message(inbuf,outbuf,1,0,True);
-       SSVAL(outbuf,smb_vwv0,count);
-
-       END_PROFILE(SMBcopy);
-       return(outsize);
-}
-
-/****************************************************************************
- Reply to a setdir.
-****************************************************************************/
-
-int reply_setdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
-{
-       int snum;
-       int outsize = 0;
-       pstring newdir;
-       NTSTATUS status;
-
-       START_PROFILE(pathworks_setdir);
-  
-       snum = SNUM(conn);
-       if (!CAN_SETDIR(snum)) {
-               END_PROFILE(pathworks_setdir);
-               return ERROR_DOS(ERRDOS,ERRnoaccess);
-       }
-
-       srvstr_get_path(inbuf, SVAL(inbuf,smb_flg2), newdir,
-                       smb_buf(inbuf) + 1, sizeof(newdir), 0, STR_TERMINATE,
-                       &status);
-       if (!NT_STATUS_IS_OK(status)) {
-               END_PROFILE(pathworks_setdir);
-               return ERROR_NT(status);
-       }
-  
-       status = resolve_dfspath(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, newdir);
-       if (!NT_STATUS_IS_OK(status)) {
-               END_PROFILE(pathworks_setdir);
-               if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
-                       return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath);
-               }
-               return ERROR_NT(status);
+               return;
        }
 
-       if (strlen(newdir) != 0) {
-               if (!vfs_directory_exist(conn,newdir,NULL)) {
-                       END_PROFILE(pathworks_setdir);
-                       return ERROR_DOS(ERRDOS,ERRbadpath);
-               }
-               set_conn_connectpath(conn,newdir);
-       }
-  
-       outsize = set_message(inbuf,outbuf,0,0,False);
-       SCVAL(outbuf,smb_reh,CVAL(inbuf,smb_reh));
-  
-       DEBUG(3,("setdir %s\n", newdir));
+       reply_outbuf(req, 1, 0);
+       SSVAL(req->outbuf,smb_vwv0,count);
 
-       END_PROFILE(pathworks_setdir);
-       return(outsize);
+       END_PROFILE(SMBcopy);
+       return;
 }
 
 #undef DBGC_CLASS
@@ -5498,7 +6425,7 @@ int reply_setdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size
  Get a lock pid, dealing with large count requests.
 ****************************************************************************/
 
-uint32 get_lock_pid( char *data, int data_offset, BOOL large_file_format)
+uint32 get_lock_pid( char *data, int data_offset, bool large_file_format)
 {
        if(!large_file_format)
                return (uint32)SVAL(data,SMB_LPID_OFFSET(data_offset));
@@ -5510,7 +6437,7 @@ uint32 get_lock_pid( char *data, int data_offset, BOOL large_file_format)
  Get a lock count, dealing with large count requests.
 ****************************************************************************/
 
-SMB_BIG_UINT get_lock_count( char *data, int data_offset, BOOL large_file_format)
+SMB_BIG_UINT get_lock_count( char *data, int data_offset, bool large_file_format)
 {
        SMB_BIG_UINT count = 0;
 
@@ -5582,7 +6509,7 @@ static uint32 map_lock_offset(uint32 high, uint32 low)
  Get a lock offset, dealing with large offset requests.
 ****************************************************************************/
 
-SMB_BIG_UINT get_lock_offset( char *data, int data_offset, BOOL large_file_format, BOOL *err)
+SMB_BIG_UINT get_lock_offset( char *data, int data_offset, bool large_file_format, bool *err)
 {
        SMB_BIG_UINT offset = 0;
 
@@ -5631,35 +6558,53 @@ SMB_BIG_UINT get_lock_offset( char *data, int data_offset, BOOL large_file_forma
  Reply to a lockingX request.
 ****************************************************************************/
 
-int reply_lockingX(connection_struct *conn, char *inbuf, char *outbuf,
-                  int length, int bufsize)
+void reply_lockingX(struct smb_request *req)
 {
-       files_struct *fsp = file_fsp(SVAL(inbuf,smb_vwv2));
-       unsigned char locktype = CVAL(inbuf,smb_vwv3);
-       unsigned char oplocklevel = CVAL(inbuf,smb_vwv3+1);
-       uint16 num_ulocks = SVAL(inbuf,smb_vwv6);
-       uint16 num_locks = SVAL(inbuf,smb_vwv7);
+       connection_struct *conn = req->conn;
+       files_struct *fsp;
+       unsigned char locktype;
+       unsigned char oplocklevel;
+       uint16 num_ulocks;
+       uint16 num_locks;
        SMB_BIG_UINT count = 0, offset = 0;
        uint32 lock_pid;
-       int32 lock_timeout = IVAL(inbuf,smb_vwv4);
+       int32 lock_timeout;
        int i;
        char *data;
-       BOOL large_file_format =
-               (locktype & LOCKING_ANDX_LARGE_FILES)?True:False;
-       BOOL err;
+       bool large_file_format;
+       bool err;
        NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
 
        START_PROFILE(SMBlockingX);
+
+       if (req->wct < 8) {
+               reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
+               END_PROFILE(SMBlockingX);
+               return;
+       }
        
-       CHECK_FSP(fsp,conn);
+       fsp = file_fsp(SVAL(req->inbuf,smb_vwv2));
+       locktype = CVAL(req->inbuf,smb_vwv3);
+       oplocklevel = CVAL(req->inbuf,smb_vwv3+1);
+       num_ulocks = SVAL(req->inbuf,smb_vwv6);
+       num_locks = SVAL(req->inbuf,smb_vwv7);
+       lock_timeout = IVAL(req->inbuf,smb_vwv4);
+       large_file_format = (locktype & LOCKING_ANDX_LARGE_FILES)?True:False;
+
+       if (!check_fsp(conn, req, fsp, &current_user)) {
+               END_PROFILE(SMBlockingX);
+               return;
+       }
        
-       data = smb_buf(inbuf);
+       data = smb_buf(req->inbuf);
 
        if (locktype & LOCKING_ANDX_CHANGE_LOCKTYPE) {
                /* we don't support these - and CANCEL_LOCK makes w2k
                   and XP reboot so I don't really want to be
                   compatible! (tridge) */
-               return ERROR_NT(NT_STATUS_DOS(ERRDOS, ERRnoatomiclocks));
+               reply_nterror(req, NT_STATUS_DOS(ERRDOS, ERRnoatomiclocks));
+               END_PROFILE(SMBlockingX);
+               return;
        }
        
        /* Check if this is an oplock break on a file
@@ -5667,8 +6612,8 @@ int reply_lockingX(connection_struct *conn, char *inbuf, char *outbuf,
        */
        if ((locktype & LOCKING_ANDX_OPLOCK_RELEASE)) {
                /* Client can insist on breaking to none. */
-               BOOL break_to_none = (oplocklevel == 0);
-               BOOL result;
+               bool break_to_none = (oplocklevel == 0);
+               bool result;
 
                DEBUG(5,("reply_lockingX: oplock break reply (%u) from client "
                         "for fnum = %d\n", (unsigned int)oplocklevel,
@@ -5696,10 +6641,11 @@ int reply_lockingX(connection_struct *conn, char *inbuf, char *outbuf,
                         * send a reply */
                        if (num_locks == 0 && num_ulocks == 0) {
                                END_PROFILE(SMBlockingX);
-                               return -1;
+                               return;
                        } else {
                                END_PROFILE(SMBlockingX);
-                               return ERROR_DOS(ERRDOS,ERRlock);
+                               reply_doserror(req, ERRDOS, ERRlock);
+                               return;
                        }
                }
 
@@ -5724,12 +6670,13 @@ int reply_lockingX(connection_struct *conn, char *inbuf, char *outbuf,
                if (num_locks == 0 && num_ulocks == 0) {
                        /* Sanity check - ensure a pure oplock break is not a
                           chained request. */
-                       if(CVAL(inbuf,smb_vwv0) != 0xff)
+                       if(CVAL(req->inbuf,smb_vwv0) != 0xff)
                                DEBUG(0,("reply_lockingX: Error : pure oplock "
                                         "break is a chained %d request !\n",
-                                        (unsigned int)CVAL(inbuf,smb_vwv0) ));
+                                        (unsigned int)CVAL(req->inbuf,
+                                                           smb_vwv0) ));
                        END_PROFILE(SMBlockingX);
-                       return -1;
+                       return;
                }
        }
 
@@ -5739,6 +6686,13 @@ int reply_lockingX(connection_struct *conn, char *inbuf, char *outbuf,
         */
        
        release_level_2_oplocks_on_change(fsp);
+
+       if (smb_buflen(req->inbuf) <
+           (num_ulocks + num_locks) * (large_file_format ? 20 : 10)) {
+               reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
+               END_PROFILE(SMBlockingX);
+               return;
+       }
        
        /* Data now points at the beginning of the list
           of smb_unlkrng structs */
@@ -5752,7 +6706,8 @@ int reply_lockingX(connection_struct *conn, char *inbuf, char *outbuf,
                 */
                if(err) {
                        END_PROFILE(SMBlockingX);
-                       return ERROR_DOS(ERRDOS,ERRnoaccess);
+                       reply_doserror(req, ERRDOS, ERRnoaccess);
+                       return;
                }
 
                DEBUG(10,("reply_lockingX: unlock start=%.0f, len=%.0f for "
@@ -5768,7 +6723,8 @@ int reply_lockingX(connection_struct *conn, char *inbuf, char *outbuf,
 
                if (NT_STATUS_V(status)) {
                        END_PROFILE(SMBlockingX);
-                       return ERROR_NT(status);
+                       reply_nterror(req, status);
+                       return;
                }
        }
 
@@ -5796,7 +6752,8 @@ int reply_lockingX(connection_struct *conn, char *inbuf, char *outbuf,
                 */
                if(err) {
                        END_PROFILE(SMBlockingX);
-                       return ERROR_DOS(ERRDOS,ERRnoaccess);
+                       reply_doserror(req, ERRDOS, ERRnoaccess);
+                       return;
                }
                
                DEBUG(10,("reply_lockingX: lock start=%.0f, len=%.0f for pid "
@@ -5819,7 +6776,12 @@ int reply_lockingX(connection_struct *conn, char *inbuf, char *outbuf,
                                                locktype,
                                                NT_STATUS_FILE_LOCK_CONFLICT)) {
                                        END_PROFILE(SMBlockingX);
-                                       return ERROR_NT(NT_STATUS_DOS(ERRDOS, ERRcancelviolation));
+                                       reply_nterror(
+                                               req,
+                                               NT_STATUS_DOS(
+                                                       ERRDOS,
+                                                       ERRcancelviolation));
+                                       return;
                                }
                        }
                        /* Remove a matching pending lock. */
@@ -5829,8 +6791,8 @@ int reply_lockingX(connection_struct *conn, char *inbuf, char *outbuf,
                                                offset,
                                                WINDOWS_LOCK);
                } else {
-                       BOOL blocking_lock = lock_timeout ? True : False;
-                       BOOL defer_lock = False;
+                       bool blocking_lock = lock_timeout ? True : False;
+                       bool defer_lock = False;
                        struct byte_range_lock *br_lck;
                        uint32 block_smbpid;
 
@@ -5872,7 +6834,7 @@ int reply_lockingX(connection_struct *conn, char *inbuf, char *outbuf,
                                 * onto the blocking lock queue.
                                 */
                                if(push_blocking_lock_request(br_lck,
-                                                       inbuf, length,
+                                                       req,
                                                        fsp,
                                                        lock_timeout,
                                                        i,
@@ -5884,7 +6846,7 @@ int reply_lockingX(connection_struct *conn, char *inbuf, char *outbuf,
                                                        block_smbpid)) {
                                        TALLOC_FREE(br_lck);
                                        END_PROFILE(SMBlockingX);
-                                       return -1;
+                                       return;
                                }
                        }
 
@@ -5893,7 +6855,8 @@ int reply_lockingX(connection_struct *conn, char *inbuf, char *outbuf,
 
                if (NT_STATUS_V(status)) {
                        END_PROFILE(SMBlockingX);
-                       return ERROR_NT(status);
+                       reply_nterror(req, status);
+                       return;
                }
        }
        
@@ -5920,7 +6883,8 @@ int reply_lockingX(connection_struct *conn, char *inbuf, char *outbuf,
                         */
                        if(err) {
                                END_PROFILE(SMBlockingX);
-                               return ERROR_DOS(ERRDOS,ERRnoaccess);
+                               reply_doserror(req, ERRDOS, ERRnoaccess);
+                               return;
                        }
                        
                        do_unlock(smbd_messaging_context(),
@@ -5931,16 +6895,17 @@ int reply_lockingX(connection_struct *conn, char *inbuf, char *outbuf,
                                WINDOWS_LOCK);
                }
                END_PROFILE(SMBlockingX);
-               return ERROR_NT(status);
+               reply_nterror(req, status);
+               return;
        }
 
-       set_message(inbuf,outbuf,2,0,True);
+       reply_outbuf(req, 2, 0);
        
        DEBUG(3, ("lockingX fnum=%d type=%d num_locks=%d num_ulocks=%d\n",
                  fsp->fnum, (unsigned int)locktype, num_locks, num_ulocks));
        
        END_PROFILE(SMBlockingX);
-       return chain_reply(inbuf,&outbuf,length,bufsize);
+       chain_reply(req);
 }
 
 #undef DBGC_CLASS
@@ -5948,108 +6913,71 @@ int reply_lockingX(connection_struct *conn, char *inbuf, char *outbuf,
 
 /****************************************************************************
  Reply to a SMBreadbmpx (read block multiplex) request.
+ Always reply with an error, if someone has a platform really needs this,
+ please contact vl@samba.org
 ****************************************************************************/
 
-int reply_readbmpx(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
+void reply_readbmpx(struct smb_request *req)
 {
-       ssize_t nread = -1;
-       ssize_t total_read;
-       char *data;
-       SMB_OFF_T startpos;
-       int outsize;
-       size_t maxcount;
-       int max_per_packet;
-       size_t tcount;
-       int pad;
-       files_struct *fsp = file_fsp(SVAL(inbuf,smb_vwv0));
        START_PROFILE(SMBreadBmpx);
+       reply_doserror(req, ERRSRV, ERRuseSTD);
+       END_PROFILE(SMBreadBmpx);
+       return;
+}
 
-       /* this function doesn't seem to work - disable by default */
-       if (!lp_readbmpx()) {
-               END_PROFILE(SMBreadBmpx);
-               return ERROR_DOS(ERRSRV,ERRuseSTD);
-       }
-
-       outsize = set_message(inbuf,outbuf,8,0,True);
-
-       CHECK_FSP(fsp,conn);
-       if (!CHECK_READ(fsp,inbuf)) {
-               return(ERROR_DOS(ERRDOS,ERRbadaccess));
-       }
-
-       startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv1);
-       maxcount = SVAL(inbuf,smb_vwv3);
-
-       data = smb_buf(outbuf);
-       pad = ((long)data)%4;
-       if (pad)
-               pad = 4 - pad;
-       data += pad;
-
-       max_per_packet = bufsize-(outsize+pad);
-       tcount = maxcount;
-       total_read = 0;
-
-       if (is_locked(fsp,(uint32)SVAL(inbuf,smb_pid),(SMB_BIG_UINT)maxcount,(SMB_BIG_UINT)startpos, READ_LOCK)) {
-               END_PROFILE(SMBreadBmpx);
-               return ERROR_DOS(ERRDOS,ERRlock);
-       }
-
-       do {
-               size_t N = MIN(max_per_packet,tcount-total_read);
-  
-               nread = read_file(fsp,data,startpos,N);
-
-               if (nread <= 0)
-                       nread = 0;
-
-               if (nread < (ssize_t)N)
-                       tcount = total_read + nread;
-
-               set_message(inbuf,outbuf,8,nread+pad,False);
-               SIVAL(outbuf,smb_vwv0,startpos);
-               SSVAL(outbuf,smb_vwv2,tcount);
-               SSVAL(outbuf,smb_vwv6,nread);
-               SSVAL(outbuf,smb_vwv7,smb_offset(data,outbuf));
-
-               show_msg(outbuf);
-               if (!send_smb(smbd_server_fd(),outbuf))
-                       exit_server_cleanly("reply_readbmpx: send_smb failed.");
-
-               total_read += nread;
-               startpos += nread;
-       } while (total_read < (ssize_t)tcount);
+/****************************************************************************
+ Reply to a SMBreadbs (read block multiplex secondary) request.
+ Always reply with an error, if someone has a platform really needs this,
+ please contact vl@samba.org
+****************************************************************************/
 
-       END_PROFILE(SMBreadBmpx);
-       return(-1);
+void reply_readbs(struct smb_request *req)
+{
+       START_PROFILE(SMBreadBs);
+       reply_doserror(req, ERRSRV, ERRuseSTD);
+       END_PROFILE(SMBreadBs);
+       return;
 }
 
 /****************************************************************************
  Reply to a SMBsetattrE.
 ****************************************************************************/
 
-int reply_setattrE(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
+void reply_setattrE(struct smb_request *req)
 {
+       connection_struct *conn = req->conn;
        struct timespec ts[2];
-       int outsize = 0;
-       files_struct *fsp = file_fsp(SVAL(inbuf,smb_vwv0));
+       files_struct *fsp;
+
        START_PROFILE(SMBsetattrE);
 
-       outsize = set_message(inbuf,outbuf,0,0,False);
+       if (req->wct < 7) {
+               reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
+               END_PROFILE(SMBsetattrE);
+               return;
+       }
+
+       fsp = file_fsp(SVAL(req->inbuf,smb_vwv0));
 
        if(!fsp || (fsp->conn != conn)) {
+               reply_doserror(req, ERRDOS, ERRbadfid);
                END_PROFILE(SMBsetattrE);
-               return ERROR_DOS(ERRDOS,ERRbadfid);
+               return;
        }
 
+
        /*
         * Convert the DOS times into unix times. Ignore create
         * time as UNIX can't set this.
         */
 
-       ts[0] = convert_time_t_to_timespec(srv_make_unix_date2(inbuf+smb_vwv3)); /* atime. */
-       ts[1] = convert_time_t_to_timespec(srv_make_unix_date2(inbuf+smb_vwv5)); /* mtime. */
+       ts[0] = convert_time_t_to_timespec(
+               srv_make_unix_date2(req->inbuf+smb_vwv3)); /* atime. */
+       ts[1] = convert_time_t_to_timespec(
+               srv_make_unix_date2(req->inbuf+smb_vwv5)); /* mtime. */
   
+       reply_outbuf(req, 0, 0);
+
        /* 
         * Patch from Ray Frush <frush@engr.colostate.edu>
         * Sometimes times are sent as zero - ignore them.
@@ -6062,7 +6990,7 @@ int reply_setattrE(connection_struct *conn, char *inbuf,char *outbuf, int size,
                        dbgtext( "ignoring zero request - not setting timestamps of 0\n" );
                }
                END_PROFILE(SMBsetattrE);
-               return(outsize);
+               return;
        } else if (!null_timespec(ts[0]) && null_timespec(ts[1])) {
                /* set modify time = to access time if modify time was unset */
                ts[1] = ts[0];
@@ -6071,8 +6999,9 @@ int reply_setattrE(connection_struct *conn, char *inbuf,char *outbuf, int size,
        /* Set the date on this file */
        /* Should we set pending modtime here ? JRA */
        if(file_ntimes(conn, fsp->fsp_name, ts)) {
+               reply_doserror(req, ERRDOS, ERRnoaccess);
                END_PROFILE(SMBsetattrE);
-               return ERROR_DOS(ERRDOS,ERRnoaccess);
+               return;
        }
   
        DEBUG( 3, ( "reply_setattrE fnum=%d actime=%u modtime=%u\n",
@@ -6081,7 +7010,7 @@ int reply_setattrE(connection_struct *conn, char *inbuf,char *outbuf, int size,
                (unsigned int)ts[1].tv_sec));
 
        END_PROFILE(SMBsetattrE);
-       return(outsize);
+       return;
 }
 
 
@@ -6089,233 +7018,64 @@ int reply_setattrE(connection_struct *conn, char *inbuf,char *outbuf, int size,
 
 /****************************************************************************
  Reply to a SMBwritebmpx (write block multiplex primary) request.
+ Always reply with an error, if someone has a platform really needs this,
+ please contact vl@samba.org
 ****************************************************************************/
 
-int reply_writebmpx(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
+void reply_writebmpx(struct smb_request *req)
 {
-       size_t numtowrite;
-       ssize_t nwritten = -1;
-       int outsize = 0;
-       SMB_OFF_T startpos;
-       size_t tcount;
-       BOOL write_through;
-       int smb_doff;
-       char *data;
-       files_struct *fsp = file_fsp(SVAL(inbuf,smb_vwv0));
-       NTSTATUS status;
        START_PROFILE(SMBwriteBmpx);
-
-       CHECK_FSP(fsp,conn);
-       if (!CHECK_WRITE(fsp)) {
-               return(ERROR_DOS(ERRDOS,ERRbadaccess));
-       }
-       if (HAS_CACHED_ERROR(fsp)) {
-               return(CACHED_ERROR(fsp));
-       }
-
-       tcount = SVAL(inbuf,smb_vwv1);
-       startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv3);
-       write_through = BITSETW(inbuf+smb_vwv7,0);
-       numtowrite = SVAL(inbuf,smb_vwv10);
-       smb_doff = SVAL(inbuf,smb_vwv11);
-
-       data = smb_base(inbuf) + smb_doff;
-
-       /* If this fails we need to send an SMBwriteC response,
-               not an SMBwritebmpx - set this up now so we don't forget */
-       SCVAL(outbuf,smb_com,SMBwritec);
-
-       if (is_locked(fsp,(uint32)SVAL(inbuf,smb_pid),(SMB_BIG_UINT)tcount,(SMB_BIG_UINT)startpos,WRITE_LOCK)) {
-               END_PROFILE(SMBwriteBmpx);
-               return(ERROR_DOS(ERRDOS,ERRlock));
-       }
-
-       nwritten = write_file(fsp,data,startpos,numtowrite);
-
-       status = sync_file(conn, fsp, write_through);
-       if (!NT_STATUS_IS_OK(status)) {
-               END_PROFILE(SMBwriteBmpx);
-               DEBUG(5,("reply_writebmpx: sync_file for %s returned %s\n",
-                       fsp->fsp_name, nt_errstr(status) ));
-               return ERROR_NT(status);
-       }
-  
-       if(nwritten < (ssize_t)numtowrite) {
-               END_PROFILE(SMBwriteBmpx);
-               return(UNIXERROR(ERRHRD,ERRdiskfull));
-       }
-
-       /* If the maximum to be written to this file
-               is greater than what we just wrote then set
-               up a secondary struct to be attached to this
-               fd, we will use this to cache error messages etc. */
-
-       if((ssize_t)tcount > nwritten) {
-               write_bmpx_struct *wbms;
-               if(fsp->wbmpx_ptr != NULL)
-                       wbms = fsp->wbmpx_ptr; /* Use an existing struct */
-               else
-                       wbms = SMB_MALLOC_P(write_bmpx_struct);
-               if(!wbms) {
-                       DEBUG(0,("Out of memory in reply_readmpx\n"));
-                       END_PROFILE(SMBwriteBmpx);
-                       return(ERROR_DOS(ERRSRV,ERRnoresource));
-               }
-               wbms->wr_mode = write_through;
-               wbms->wr_discard = False; /* No errors yet */
-               wbms->wr_total_written = nwritten;
-               wbms->wr_errclass = 0;
-               wbms->wr_error = 0;
-               fsp->wbmpx_ptr = wbms;
-       }
-
-       /* We are returning successfully, set the message type back to
-               SMBwritebmpx */
-       SCVAL(outbuf,smb_com,SMBwriteBmpx);
-  
-       outsize = set_message(inbuf,outbuf,1,0,True);
-  
-       SSVALS(outbuf,smb_vwv0,-1); /* We don't support smb_remaining */
-  
-       DEBUG( 3, ( "writebmpx fnum=%d num=%d wrote=%d\n",
-                       fsp->fnum, (int)numtowrite, (int)nwritten ) );
-
-       if (write_through && tcount==nwritten) {
-               /* We need to send both a primary and a secondary response */
-               smb_setlen(inbuf,outbuf,outsize - 4);
-               show_msg(outbuf);
-               if (!send_smb(smbd_server_fd(),outbuf))
-                       exit_server_cleanly("reply_writebmpx: send_smb failed.");
-
-               /* Now the secondary */
-               outsize = set_message(inbuf,outbuf,1,0,True);
-               SCVAL(outbuf,smb_com,SMBwritec);
-               SSVAL(outbuf,smb_vwv0,nwritten);
-       }
-
+       reply_doserror(req, ERRSRV, ERRuseSTD);
        END_PROFILE(SMBwriteBmpx);
-       return(outsize);
+       return;
 }
 
 /****************************************************************************
  Reply to a SMBwritebs (write block multiplex secondary) request.
+ Always reply with an error, if someone has a platform really needs this,
+ please contact vl@samba.org
 ****************************************************************************/
 
-int reply_writebs(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
+void reply_writebs(struct smb_request *req)
 {
-       size_t numtowrite;
-       ssize_t nwritten = -1;
-       int outsize = 0;
-       SMB_OFF_T startpos;
-       size_t tcount;
-       BOOL write_through;
-       int smb_doff;
-       char *data;
-       write_bmpx_struct *wbms;
-       BOOL send_response = False; 
-       files_struct *fsp = file_fsp(SVAL(inbuf,smb_vwv0));
-       NTSTATUS status;
        START_PROFILE(SMBwriteBs);
-
-       CHECK_FSP(fsp,conn);
-       if (!CHECK_WRITE(fsp)) {
-               return(ERROR_DOS(ERRDOS,ERRbadaccess));
-       }
-
-       tcount = SVAL(inbuf,smb_vwv1);
-       startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2);
-       numtowrite = SVAL(inbuf,smb_vwv6);
-       smb_doff = SVAL(inbuf,smb_vwv7);
-
-       data = smb_base(inbuf) + smb_doff;
-
-       /* We need to send an SMBwriteC response, not an SMBwritebs */
-       SCVAL(outbuf,smb_com,SMBwritec);
-
-       /* This fd should have an auxiliary struct attached,
-               check that it does */
-       wbms = fsp->wbmpx_ptr;
-       if(!wbms) {
-               END_PROFILE(SMBwriteBs);
-               return(-1);
-       }
-
-       /* If write through is set we can return errors, else we must cache them */
-       write_through = wbms->wr_mode;
-
-       /* Check for an earlier error */
-       if(wbms->wr_discard) {
-               END_PROFILE(SMBwriteBs);
-               return -1; /* Just discard the packet */
-       }
-
-       nwritten = write_file(fsp,data,startpos,numtowrite);
-
-       status = sync_file(conn, fsp, write_through);
-  
-       if (nwritten < (ssize_t)numtowrite || !NT_STATUS_IS_OK(status)) {
-               if(write_through) {
-                       /* We are returning an error - we can delete the aux struct */
-                       if (wbms)
-                               free((char *)wbms);
-                       fsp->wbmpx_ptr = NULL;
-                       END_PROFILE(SMBwriteBs);
-                       return(ERROR_DOS(ERRHRD,ERRdiskfull));
-               }
-               wbms->wr_errclass = ERRHRD;
-               wbms->wr_error = ERRdiskfull;
-               wbms->wr_status = NT_STATUS_DISK_FULL;
-               wbms->wr_discard = True;
-               END_PROFILE(SMBwriteBs);
-               return -1;
-       }
-
-       /* Increment the total written, if this matches tcount
-               we can discard the auxiliary struct (hurrah !) and return a writeC */
-       wbms->wr_total_written += nwritten;
-       if(wbms->wr_total_written >= tcount) {
-               if (write_through) {
-                       outsize = set_message(inbuf,outbuf,1,0,True);
-                       SSVAL(outbuf,smb_vwv0,wbms->wr_total_written);    
-                       send_response = True;
-               }
-
-               free((char *)wbms);
-               fsp->wbmpx_ptr = NULL;
-       }
-
-       if(send_response) {
-               END_PROFILE(SMBwriteBs);
-               return(outsize);
-       }
-
+       reply_doserror(req, ERRSRV, ERRuseSTD);
        END_PROFILE(SMBwriteBs);
-       return(-1);
+       return;
 }
 
 /****************************************************************************
  Reply to a SMBgetattrE.
 ****************************************************************************/
 
-int reply_getattrE(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
+void reply_getattrE(struct smb_request *req)
 {
+       connection_struct *conn = req->conn;
        SMB_STRUCT_STAT sbuf;
-       int outsize = 0;
        int mode;
-       files_struct *fsp = file_fsp(SVAL(inbuf,smb_vwv0));
+       files_struct *fsp;
+
        START_PROFILE(SMBgetattrE);
 
-       outsize = set_message(inbuf,outbuf,11,0,True);
+       if (req->wct < 1) {
+               reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
+               END_PROFILE(SMBgetattrE);
+               return;
+       }
+
+       fsp = file_fsp(SVAL(req->inbuf,smb_vwv0));
 
        if(!fsp || (fsp->conn != conn)) {
+               reply_doserror(req, ERRDOS, ERRbadfid);
                END_PROFILE(SMBgetattrE);
-               return ERROR_DOS(ERRDOS,ERRbadfid);
+               return;
        }
 
        /* Do an fstat on this file */
        if(fsp_stat(fsp, &sbuf)) {
+               reply_unixerror(req, ERRDOS, ERRnoaccess);
                END_PROFILE(SMBgetattrE);
-               return(UNIXERROR(ERRDOS,ERRnoaccess));
+               return;
        }
   
        mode = dos_mode(conn,fsp->fsp_name,&sbuf);
@@ -6326,23 +7086,27 @@ int reply_getattrE(connection_struct *conn, char *inbuf,char *outbuf, int size,
         * this.
         */
 
-       srv_put_dos_date2(outbuf,smb_vwv0,get_create_time(&sbuf,lp_fake_dir_create_times(SNUM(conn))));
-       srv_put_dos_date2(outbuf,smb_vwv2,sbuf.st_atime);
+       reply_outbuf(req, 11, 0);
+
+       srv_put_dos_date2((char *)req->outbuf, smb_vwv0,
+                         get_create_time(&sbuf,
+                                         lp_fake_dir_create_times(SNUM(conn))));
+       srv_put_dos_date2((char *)req->outbuf, smb_vwv2, sbuf.st_atime);
        /* Should we check pending modtime here ? JRA */
-       srv_put_dos_date2(outbuf,smb_vwv4,sbuf.st_mtime);
+       srv_put_dos_date2((char *)req->outbuf, smb_vwv4, sbuf.st_mtime);
 
        if (mode & aDIR) {
-               SIVAL(outbuf,smb_vwv6,0);
-               SIVAL(outbuf,smb_vwv8,0);
+               SIVAL(req->outbuf, smb_vwv6, 0);
+               SIVAL(req->outbuf, smb_vwv8, 0);
        } else {
                uint32 allocation_size = get_allocation_size(conn,fsp, &sbuf);
-               SIVAL(outbuf,smb_vwv6,(uint32)sbuf.st_size);
-               SIVAL(outbuf,smb_vwv8,allocation_size);
+               SIVAL(req->outbuf, smb_vwv6, (uint32)sbuf.st_size);
+               SIVAL(req->outbuf, smb_vwv8, allocation_size);
        }
-       SSVAL(outbuf,smb_vwv10, mode);
+       SSVAL(req->outbuf,smb_vwv10, mode);
   
        DEBUG( 3, ( "reply_getattrE fnum=%d\n", fsp->fnum));
   
        END_PROFILE(SMBgetattrE);
-       return(outsize);
+       return;
 }