r4069: better error code for SMBwriteBMPX
[samba.git] / source4 / smb_server / reply.c
index 298b2443d33c8b4c202dfdc048d8c2b9879c0329..d81b2bfeefb84479bb0197813efd2fb51073eefd 100644 (file)
@@ -24,6 +24,8 @@
 */
 
 #include "includes.h"
+#include "smb_server/smb_server.h"
+
 
 /* useful way of catching wct errors with file and line number */
 #define REQ_CHECK_WCT(req, wcount) do { \
                return; \
        }} while (0)
 
-/* check req->async.status and if not OK then send an error reply */
+/* check req->async_states->status and if not OK then send an error reply */
 #define CHECK_ASYNC_STATUS do { \
-       if (!NT_STATUS_IS_OK(req->async.status)) { \
-               req_reply_error(req, req->async.status); \
+       if (!NT_STATUS_IS_OK(req->async_states->status)) { \
+               req_reply_error(req, req->async_states->status); \
                return; \
        }} while (0)
        
 /* useful wrapper for talloc with NO_MEMORY reply */
 #define REQ_TALLOC(ptr, size) do { \
-       ptr = talloc(req->mem_ctx, size); \
+       ptr = talloc(req, size); \
        if (!ptr) { \
                req_reply_error(req, NT_STATUS_NO_MEMORY); \
                return; \
    immediately
 */
 #define REQ_ASYNC_TAIL do { \
-       if (!(req->control_flags & REQ_CONTROL_ASYNC)) { \
-               req->async.send_fn(req); \
+       if (!(req->async_states->state & NTVFS_ASYNC_STATE_ASYNC)) { \
+               req->async_states->send_fn(req); \
        }} while (0)
 
 /* zero out some reserved fields in a reply */
 #define REQ_VWV_RESERVED(start, count) memset(req->out.vwv + VWV(start), 0, (count)*2)
 
-/*
-  put a NTTIME into a packet
-*/
-void push_nttime(void *base, uint16 offset, NTTIME *t)
-{
-       SIVAL(base, offset,   t->low);
-       SIVAL(base, offset+4, t->high);
-}
-
-/*
-  pull a NTTIME from a packet
-*/
-NTTIME pull_nttime(void *base, uint16 offset)
-{
-       NTTIME ret;
-       ret.low = IVAL(base, offset);
-       ret.high = IVAL(base, offset+4);
-       return ret;
-}
-
-
 /****************************************************************************
  Reply to a simple request (async send)
 ****************************************************************************/
-static void reply_simple_send(struct request_context *req)
+static void reply_simple_send(struct smbsrv_request *req)
 {
        CHECK_ASYNC_STATUS;
 
@@ -98,11 +79,11 @@ static void reply_simple_send(struct request_context *req)
 /****************************************************************************
  Reply to a tcon.
 ****************************************************************************/
-void reply_tcon(struct request_context *req)
+void reply_tcon(struct smbsrv_request *req)
 {
        union smb_tcon con;
        NTSTATUS status;
-       char *p;
+       uint8_t *p;
        
        /* parse request */
        REQ_CHECK_WCT(req, 0);
@@ -132,7 +113,7 @@ void reply_tcon(struct request_context *req)
 
        SSVAL(req->out.vwv, VWV(0), con.tcon.out.max_xmit);
        SSVAL(req->out.vwv, VWV(1), con.tcon.out.cnum);
-       SSVAL(req->out.hdr, HDR_TID, req->conn->cnum);
+       SSVAL(req->out.hdr, HDR_TID, req->tcon->cnum);
   
        req_send_reply(req);
 }
@@ -141,12 +122,12 @@ void reply_tcon(struct request_context *req)
 /****************************************************************************
  Reply to a tcon and X.
 ****************************************************************************/
-void reply_tcon_and_X(struct request_context *req)
+void reply_tcon_and_X(struct smbsrv_request *req)
 {
        NTSTATUS status;
        union smb_tcon con;
-       char *p;
-       uint16 passlen;
+       uint8_t *p;
+       uint16_t passlen;
 
        con.tconx.level = RAW_TCON_TCONX;
 
@@ -180,8 +161,8 @@ void reply_tcon_and_X(struct request_context *req)
                return;
        }
 
-       /* construct reply - two varients */
-       if (req->smb->negotiate.protocol < PROTOCOL_NT1) {
+       /* construct reply - two variants */
+       if (req->smb_conn->negotiate.protocol < PROTOCOL_NT1) {
                req_setup_reply(req, 2, 0);
 
                SSVAL(req->out.vwv, VWV(0), SMB_CHAIN_NONE);
@@ -210,7 +191,7 @@ void reply_tcon_and_X(struct request_context *req)
 /****************************************************************************
  Reply to an unknown request
 ****************************************************************************/
-void reply_unknown(struct request_context *req)
+void reply_unknown(struct smbsrv_request *req)
 {
        int type;
 
@@ -225,9 +206,9 @@ void reply_unknown(struct request_context *req)
 /****************************************************************************
  Reply to an ioctl (async reply)
 ****************************************************************************/
-static void reply_ioctl_send(struct request_context *req)
+static void reply_ioctl_send(struct smbsrv_request *req)
 {
-       union smb_ioctl *io = req->async.private;
+       union smb_ioctl *io = req->async_states->private_data;
 
        CHECK_ASYNC_STATUS;
 
@@ -245,7 +226,7 @@ static void reply_ioctl_send(struct request_context *req)
 /****************************************************************************
  Reply to an ioctl.
 ****************************************************************************/
-void reply_ioctl(struct request_context *req)
+void reply_ioctl(struct smbsrv_request *req)
 {
        union smb_ioctl *io;
 
@@ -257,11 +238,12 @@ void reply_ioctl(struct request_context *req)
        io->ioctl.in.fnum     = req_fnum(req, req->in.vwv, VWV(0));
        io->ioctl.in.request  = IVAL(req->in.vwv, VWV(1));
 
-       req->async.send_fn = reply_ioctl_send;
-       req->async.private = io;
+       req->async_states->state |= NTVFS_ASYNC_STATE_MAY_ASYNC;
+       req->async_states->send_fn = reply_ioctl_send;
+       req->async_states->private_data = io;
 
        /* call backend */
-       req->async.status = req->conn->ntvfs_ops->ioctl(req, io);
+       req->async_states->status = ntvfs_ioctl(req, io);
 
        REQ_ASYNC_TAIL;
 }
@@ -270,7 +252,7 @@ void reply_ioctl(struct request_context *req)
 /****************************************************************************
  Reply to a chkpth.
 ****************************************************************************/
-void reply_chkpth(struct request_context *req)
+void reply_chkpth(struct smbsrv_request *req)
 {
        struct smb_chkpath *io;
 
@@ -278,9 +260,10 @@ void reply_chkpth(struct request_context *req)
 
        req_pull_ascii4(req, &io->in.path, req->in.data, STR_TERMINATE);
 
-       req->async.send_fn = reply_simple_send;
+       req->async_states->state |= NTVFS_ASYNC_STATE_MAY_ASYNC;
+       req->async_states->send_fn = reply_simple_send;
 
-       req->async.status = req->conn->ntvfs_ops->chkpath(req, io);
+       req->async_states->status = ntvfs_chkpath(req, io);
 
        REQ_ASYNC_TAIL;
 }
@@ -288,9 +271,9 @@ void reply_chkpth(struct request_context *req)
 /****************************************************************************
  Reply to a getatr (async reply)
 ****************************************************************************/
-static void reply_getatr_send(struct request_context *req)
+static void reply_getatr_send(struct smbsrv_request *req)
 {
-       union smb_fileinfo *st = req->async.private;
+       union smb_fileinfo *st = req->async_states->private_data;
 
        CHECK_ASYNC_STATUS;
        
@@ -298,7 +281,7 @@ static void reply_getatr_send(struct request_context *req)
        req_setup_reply(req, 10, 0);
 
        SSVAL(req->out.vwv,         VWV(0), st->getattr.out.attrib);
-       put_dos_date3(req->out.vwv, VWV(1), st->getattr.out.write_time);
+       srv_push_dos_date3(req->smb_conn, req->out.vwv, VWV(1), st->getattr.out.write_time);
        SIVAL(req->out.vwv,         VWV(3), st->getattr.out.size);
 
        REQ_VWV_RESERVED(5, 5);
@@ -310,7 +293,7 @@ static void reply_getatr_send(struct request_context *req)
 /****************************************************************************
  Reply to a getatr.
 ****************************************************************************/
-void reply_getatr(struct request_context *req)
+void reply_getatr(struct smbsrv_request *req)
 {
        union smb_fileinfo *st;
 
@@ -325,11 +308,12 @@ void reply_getatr(struct request_context *req)
                return;
        }
 
-       req->async.send_fn = reply_getatr_send;
-       req->async.private = st;
+       req->async_states->state |= NTVFS_ASYNC_STATE_MAY_ASYNC;
+       req->async_states->send_fn = reply_getatr_send;
+       req->async_states->private_data = st;
 
        /* call backend */
-       req->async.status = req->conn->ntvfs_ops->qpathinfo(req, st);
+       req->async_states->status = ntvfs_qpathinfo(req, st);
 
        REQ_ASYNC_TAIL;
 }
@@ -338,7 +322,7 @@ void reply_getatr(struct request_context *req)
 /****************************************************************************
  Reply to a setatr.
 ****************************************************************************/
-void reply_setatr(struct request_context *req)
+void reply_setatr(struct smbsrv_request *req)
 {
        union smb_setfileinfo *st;
 
@@ -348,7 +332,7 @@ void reply_setatr(struct request_context *req)
 
        st->setattr.level = RAW_SFILEINFO_SETATTR;
        st->setattr.in.attrib     = SVAL(req->in.vwv, VWV(0));
-       st->setattr.in.write_time = make_unix_date3(req->in.vwv + VWV(1));
+       st->setattr.in.write_time = srv_pull_dos_date3(req->smb_conn, req->in.vwv + VWV(1));
        
        req_pull_ascii4(req, &st->setattr.file.fname, req->in.data, STR_TERMINATE);
 
@@ -357,10 +341,11 @@ void reply_setatr(struct request_context *req)
                return;
        }
        
-       req->async.send_fn = reply_simple_send;
+       req->async_states->state |= NTVFS_ASYNC_STATE_MAY_ASYNC;
+       req->async_states->send_fn = reply_simple_send;
 
        /* call backend */
-       req->async.status = req->conn->ntvfs_ops->setpathinfo(req, st);
+       req->async_states->status = ntvfs_setpathinfo(req, st);
 
        REQ_ASYNC_TAIL;
 }
@@ -369,9 +354,9 @@ void reply_setatr(struct request_context *req)
 /****************************************************************************
  Reply to a dskattr (async reply)
 ****************************************************************************/
-static void reply_dskattr_send(struct request_context *req)
+static void reply_dskattr_send(struct smbsrv_request *req)
 {
-       union smb_fsinfo *fs = req->async.private;
+       union smb_fsinfo *fs = req->async_states->private_data;
 
        CHECK_ASYNC_STATUS;
        
@@ -392,7 +377,7 @@ static void reply_dskattr_send(struct request_context *req)
 /****************************************************************************
  Reply to a dskattr.
 ****************************************************************************/
-void reply_dskattr(struct request_context *req)
+void reply_dskattr(struct smbsrv_request *req)
 {
        union smb_fsinfo *fs;
 
@@ -400,11 +385,12 @@ void reply_dskattr(struct request_context *req)
        
        fs->dskattr.level = RAW_QFS_DSKATTR;
 
-       req->async.send_fn = reply_dskattr_send;
-       req->async.private = fs;
+       req->async_states->state |= NTVFS_ASYNC_STATE_MAY_ASYNC;
+       req->async_states->send_fn = reply_dskattr_send;
+       req->async_states->private_data = fs;
 
        /* call backend */
-       req->async.status = req->conn->ntvfs_ops->fsinfo(req, fs);
+       req->async_states->status = ntvfs_fsinfo(req, fs);
 
        REQ_ASYNC_TAIL;
 }
@@ -414,20 +400,20 @@ void reply_dskattr(struct request_context *req)
 /****************************************************************************
  Reply to an open (async reply)
 ****************************************************************************/
-static void reply_open_send(struct request_context *req)
+static void reply_open_send(struct smbsrv_request *req)
 {
-       union smb_open *oi = req->async.private;
+       union smb_open *oi = req->async_states->private_data;
 
        CHECK_ASYNC_STATUS;
 
        /* construct reply */
        req_setup_reply(req, 7, 0);
 
-       SSVAL(req->out.vwv, VWV(0), oi->open.out.fnum);
-       SSVAL(req->out.vwv, VWV(1), oi->open.out.attrib);
-       put_dos_date3(req->out.vwv, VWV(2), oi->open.out.write_time);
-       SIVAL(req->out.vwv, VWV(4), oi->open.out.size);
-       SSVAL(req->out.vwv, VWV(6), oi->open.out.rmode);
+       SSVAL(req->out.vwv, VWV(0), oi->openold.out.fnum);
+       SSVAL(req->out.vwv, VWV(1), oi->openold.out.attrib);
+       srv_push_dos_date3(req->smb_conn, req->out.vwv, VWV(2), oi->openold.out.write_time);
+       SIVAL(req->out.vwv, VWV(4), oi->openold.out.size);
+       SSVAL(req->out.vwv, VWV(6), oi->openold.out.rmode);
 
        req_send_reply(req);
 }
@@ -435,7 +421,7 @@ static void reply_open_send(struct request_context *req)
 /****************************************************************************
  Reply to an open.
 ****************************************************************************/
-void reply_open(struct request_context *req)
+void reply_open(struct smbsrv_request *req)
 {
        union smb_open *oi;
 
@@ -443,22 +429,23 @@ void reply_open(struct request_context *req)
        REQ_CHECK_WCT(req, 2);
        REQ_TALLOC(oi, sizeof(*oi));
 
-       oi->open.level = RAW_OPEN_OPEN;
-       oi->open.in.flags = SVAL(req->in.vwv, VWV(0));
-       oi->open.in.search_attrs = SVAL(req->in.vwv, VWV(1));
+       oi->openold.level = RAW_OPEN_OPEN;
+       oi->openold.in.flags = SVAL(req->in.vwv, VWV(0));
+       oi->openold.in.search_attrs = SVAL(req->in.vwv, VWV(1));
 
-       req_pull_ascii4(req, &oi->open.in.fname, req->in.data, STR_TERMINATE);
+       req_pull_ascii4(req, &oi->openold.in.fname, req->in.data, STR_TERMINATE);
 
-       if (!oi->open.in.fname) {
+       if (!oi->openold.in.fname) {
                req_reply_error(req, NT_STATUS_OBJECT_NAME_NOT_FOUND);
                return;
        }
 
-       req->async.send_fn = reply_open_send;
-       req->async.private = oi;
+       req->async_states->state |= NTVFS_ASYNC_STATE_MAY_ASYNC;
+       req->async_states->send_fn = reply_open_send;
+       req->async_states->private_data = oi;
        
        /* call backend */
-       req->async.status = req->conn->ntvfs_ops->open(req, oi);
+       req->async_states->status = ntvfs_openfile(req, oi);
 
        REQ_ASYNC_TAIL;
 }
@@ -467,9 +454,9 @@ void reply_open(struct request_context *req)
 /****************************************************************************
  Reply to an open and X (async reply)
 ****************************************************************************/
-static void reply_open_and_X_send(struct request_context *req)
+static void reply_open_and_X_send(struct smbsrv_request *req)
 {
-       union smb_open *oi = req->async.private;
+       union smb_open *oi = req->async_states->private_data;
 
        CHECK_ASYNC_STATUS;
 
@@ -484,7 +471,7 @@ static void reply_open_and_X_send(struct request_context *req)
        SSVAL(req->out.vwv, VWV(1), 0);
        SSVAL(req->out.vwv, VWV(2), oi->openx.out.fnum);
        SSVAL(req->out.vwv, VWV(3), oi->openx.out.attrib);
-       put_dos_date3(req->out.vwv, VWV(4), oi->openx.out.write_time);
+       srv_push_dos_date3(req->smb_conn, req->out.vwv, VWV(4), oi->openx.out.write_time);
        SIVAL(req->out.vwv, VWV(6), oi->openx.out.size);
        SSVAL(req->out.vwv, VWV(8), oi->openx.out.access);
        SSVAL(req->out.vwv, VWV(9), oi->openx.out.ftype);
@@ -504,7 +491,7 @@ static void reply_open_and_X_send(struct request_context *req)
 /****************************************************************************
  Reply to an open and X.
 ****************************************************************************/
-void reply_open_and_X(struct request_context *req)
+void reply_open_and_X(struct smbsrv_request *req)
 {
        union smb_open *oi;
 
@@ -517,7 +504,7 @@ void reply_open_and_X(struct request_context *req)
        oi->openx.in.open_mode    = SVAL(req->in.vwv, VWV(3));
        oi->openx.in.search_attrs = SVAL(req->in.vwv, VWV(4));
        oi->openx.in.file_attrs   = SVAL(req->in.vwv, VWV(5));
-       oi->openx.in.write_time   = make_unix_date3(req->in.vwv + VWV(6));
+       oi->openx.in.write_time   = srv_pull_dos_date3(req->smb_conn, req->in.vwv + VWV(6));
        oi->openx.in.open_func    = SVAL(req->in.vwv, VWV(8));
        oi->openx.in.size         = IVAL(req->in.vwv, VWV(9));
        oi->openx.in.timeout      = IVAL(req->in.vwv, VWV(11));
@@ -529,11 +516,12 @@ void reply_open_and_X(struct request_context *req)
                return;
        }
 
-       req->async.send_fn = reply_open_and_X_send;
-       req->async.private = oi;
+       req->async_states->state |= NTVFS_ASYNC_STATE_MAY_ASYNC;
+       req->async_states->send_fn = reply_open_and_X_send;
+       req->async_states->private_data = oi;
 
        /* call the backend */
-       req->async.status = req->conn->ntvfs_ops->open(req, oi);
+       req->async_states->status = ntvfs_openfile(req, oi);
 
        REQ_ASYNC_TAIL;
 }
@@ -542,9 +530,9 @@ void reply_open_and_X(struct request_context *req)
 /****************************************************************************
  Reply to a mknew or a create.
 ****************************************************************************/
-static void reply_mknew_send(struct request_context *req)
+static void reply_mknew_send(struct smbsrv_request *req)
 {
-       union smb_open *oi = req->async.private;
+       union smb_open *oi = req->async_states->private_data;
 
        CHECK_ASYNC_STATUS;
 
@@ -560,7 +548,7 @@ static void reply_mknew_send(struct request_context *req)
 /****************************************************************************
  Reply to a mknew or a create.
 ****************************************************************************/
-void reply_mknew(struct request_context *req)
+void reply_mknew(struct smbsrv_request *req)
 {
        union smb_open *oi;
 
@@ -568,9 +556,13 @@ void reply_mknew(struct request_context *req)
        REQ_CHECK_WCT(req, 3);
        REQ_TALLOC(oi, sizeof(*oi));
 
-       oi->mknew.level = RAW_OPEN_MKNEW;
+       if (CVAL(req->in.hdr, HDR_COM) == SMBmknew) {
+               oi->mknew.level = RAW_OPEN_MKNEW;
+       } else {
+               oi->mknew.level = RAW_OPEN_CREATE;
+       }
        oi->mknew.in.attrib  = SVAL(req->in.vwv, VWV(0));
-       oi->mknew.in.write_time  = make_unix_date3(req->in.vwv + VWV(1));
+       oi->mknew.in.write_time  = srv_pull_dos_date3(req->smb_conn, req->in.vwv + VWV(1));
 
        req_pull_ascii4(req, &oi->mknew.in.fname, req->in.data, STR_TERMINATE);
 
@@ -579,11 +571,12 @@ void reply_mknew(struct request_context *req)
                return;
        }
 
-       req->async.send_fn = reply_mknew_send;
-       req->async.private = oi;
+       req->async_states->state |= NTVFS_ASYNC_STATE_MAY_ASYNC;
+       req->async_states->send_fn = reply_mknew_send;
+       req->async_states->private_data = oi;
 
        /* call the backend */
-       req->async.status = req->conn->ntvfs_ops->open(req, oi);
+       req->async_states->status = ntvfs_openfile(req, oi);
 
        REQ_ASYNC_TAIL;
 }
@@ -591,9 +584,9 @@ void reply_mknew(struct request_context *req)
 /****************************************************************************
  Reply to a create temporary file (async reply)
 ****************************************************************************/
-static void reply_ctemp_send(struct request_context *req)
+static void reply_ctemp_send(struct smbsrv_request *req)
 {
-       union smb_open *oi = req->async.private;
+       union smb_open *oi = req->async_states->private_data;
 
        CHECK_ASYNC_STATUS;
 
@@ -603,7 +596,7 @@ static void reply_ctemp_send(struct request_context *req)
        SSVAL(req->out.vwv, VWV(0), oi->ctemp.out.fnum);
 
        /* the returned filename is relative to the directory */
-       req_push_str(req, NULL, oi->ctemp.out.name, -1, STR_TERMINATE);
+       req_push_str(req, NULL, oi->ctemp.out.name, -1, STR_TERMINATE | STR_ASCII);
 
        req_send_reply(req);
 }
@@ -611,7 +604,7 @@ static void reply_ctemp_send(struct request_context *req)
 /****************************************************************************
  Reply to a create temporary file.
 ****************************************************************************/
-void reply_ctemp(struct request_context *req)
+void reply_ctemp(struct smbsrv_request *req)
 {
        union smb_open *oi;
 
@@ -621,7 +614,7 @@ void reply_ctemp(struct request_context *req)
 
        oi->ctemp.level = RAW_OPEN_CTEMP;
        oi->ctemp.in.attrib = SVAL(req->in.vwv, VWV(0));
-       oi->ctemp.in.write_time = make_unix_date3(req->in.vwv + VWV(1));
+       oi->ctemp.in.write_time = srv_pull_dos_date3(req->smb_conn, req->in.vwv + VWV(1));
 
        /* the filename is actually a directory name, the server provides a filename
           in that directory */
@@ -632,11 +625,12 @@ void reply_ctemp(struct request_context *req)
                return;
        }
 
-       req->async.send_fn = reply_ctemp_send;
-       req->async.private = oi;
+       req->async_states->state |= NTVFS_ASYNC_STATE_MAY_ASYNC;
+       req->async_states->send_fn = reply_ctemp_send;
+       req->async_states->private_data = oi;
 
        /* call the backend */
-       req->async.status = req->conn->ntvfs_ops->open(req, oi);
+       req->async_states->status = ntvfs_openfile(req, oi);
 
        REQ_ASYNC_TAIL;
 }
@@ -645,7 +639,7 @@ void reply_ctemp(struct request_context *req)
 /****************************************************************************
  Reply to a unlink
 ****************************************************************************/
-void reply_unlink(struct request_context *req)
+void reply_unlink(struct smbsrv_request *req)
 {
        struct smb_unlink *unl;
 
@@ -657,10 +651,11 @@ void reply_unlink(struct request_context *req)
 
        req_pull_ascii4(req, &unl->in.pattern, req->in.data, STR_TERMINATE);
        
-       req->async.send_fn = reply_simple_send;
+       req->async_states->state |= NTVFS_ASYNC_STATE_MAY_ASYNC;
+       req->async_states->send_fn = reply_simple_send;
 
        /* call backend */
-       req->async.status = req->conn->ntvfs_ops->unlink(req, unl);
+       req->async_states->status = ntvfs_unlink(req, unl);
 
        REQ_ASYNC_TAIL;
 }
@@ -672,40 +667,34 @@ void reply_unlink(struct request_context *req)
  only the 4 byte NBT header
  This command must be replied to synchronously
 ****************************************************************************/
-void reply_readbraw(struct request_context *req)
+void reply_readbraw(struct smbsrv_request *req)
 {
        NTSTATUS status;
        union smb_read io;
 
        io.readbraw.level = RAW_READ_READBRAW;
 
-       /* there are two varients, one with 10 and one with 8 command words */
-       if (req->in.wct != 10) {
-               REQ_CHECK_WCT(req, 8);
+       /* there are two variants, one with 10 and one with 8 command words */
+       if (req->in.wct < 8) {
+               goto failed;
        }
 
        io.readbraw.in.fnum    = req_fnum(req, req->in.vwv, VWV(0));
        io.readbraw.in.offset  = IVAL(req->in.vwv, VWV(1));
-       io.readbraw.in.mincnt  = SVAL(req->in.vwv, VWV(3));
-       io.readbraw.in.maxcnt  = SVAL(req->in.vwv, VWV(4));
+       io.readbraw.in.maxcnt  = SVAL(req->in.vwv, VWV(3));
+       io.readbraw.in.mincnt  = SVAL(req->in.vwv, VWV(4));
        io.readbraw.in.timeout = IVAL(req->in.vwv, VWV(5));
 
-       /* the 64 bit varient */
+       /* the 64 bit variant */
        if (req->in.wct == 10) {
-               uint32 offset_high = IVAL(req->in.vwv, VWV(8));
-#ifdef LARGE_SMB_OFF_T
-               io.readbraw.in.offset |= (((SMB_OFF_T)offset_high) << 32);
-#else
-               if (offset_high != 0) {
-                       goto failed;
-               }
-#endif
+               uint32_t offset_high = IVAL(req->in.vwv, VWV(8));
+               io.readbraw.in.offset |= (((off_t)offset_high) << 32);
        }
 
        /* before calling the backend we setup the raw buffer. This
         * saves a copy later */
        req->out.size = io.readbraw.in.maxcnt + NBT_HDR_SIZE;
-       req->out.buffer = talloc(req->mem_ctx, req->out.size);
+       req->out.buffer = talloc(req, req->out.size);
        if (req->out.buffer == NULL) {
                goto failed;
        }
@@ -715,7 +704,7 @@ void reply_readbraw(struct request_context *req)
        io.readbraw.out.data = req->out.buffer + NBT_HDR_SIZE;
 
        /* call the backend */
-       status = req->conn->ntvfs_ops->read(req, &io);
+       status = ntvfs_read(req, &io);
 
        if (!NT_STATUS_IS_OK(status)) {
                goto failed;
@@ -723,24 +712,25 @@ void reply_readbraw(struct request_context *req)
 
        req->out.size = io.readbraw.out.nread + NBT_HDR_SIZE;
 
-       req_send_reply(req);
+       req_send_reply_nosign(req);
        return;
 
 failed:
        /* any failure in readbraw is equivalent to reading zero bytes */
        req->out.size = 4;
-       req->out.buffer = talloc(req->mem_ctx, req->out.size);
+       req->out.buffer = talloc(req, req->out.size);
        SIVAL(req->out.buffer, 0, 0); /* init NBT header */
-       req_send_reply(req);
+
+       req_send_reply_nosign(req);
 }
 
 
 /****************************************************************************
  Reply to a lockread (async reply)
 ****************************************************************************/
-static void reply_lockread_send(struct request_context *req)
+static void reply_lockread_send(struct smbsrv_request *req)
 {
-       union smb_read *io = req->async.private;
+       union smb_read *io = req->async_states->private_data;
 
        CHECK_ASYNC_STATUS;
 
@@ -764,7 +754,7 @@ static void reply_lockread_send(struct request_context *req)
  Reply to a lockread (core+ protocol).
  note that the lock is a write lock, not a read lock!
 ****************************************************************************/
-void reply_lockread(struct request_context *req)
+void reply_lockread(struct smbsrv_request *req)
 {
        union smb_read *io;
        
@@ -784,11 +774,12 @@ void reply_lockread(struct request_context *req)
        /* tell the backend where to put the data */
        io->lockread.out.data = req->out.data + 3;
 
-       req->async.send_fn = reply_lockread_send;
-       req->async.private = io;
+       req->async_states->state |= NTVFS_ASYNC_STATE_MAY_ASYNC;
+       req->async_states->send_fn = reply_lockread_send;
+       req->async_states->private_data = io;
 
        /* call backend */
-       req->async.status = req->conn->ntvfs_ops->read(req, io);
+       req->async_states->status = ntvfs_read(req, io);
 
        REQ_ASYNC_TAIL;
 }
@@ -798,9 +789,9 @@ void reply_lockread(struct request_context *req)
 /****************************************************************************
  Reply to a read (async reply)
 ****************************************************************************/
-static void reply_read_send(struct request_context *req)
+static void reply_read_send(struct smbsrv_request *req)
 {
-       union smb_read *io = req->async.private;
+       union smb_read *io = req->async_states->private_data;
 
        CHECK_ASYNC_STATUS;
 
@@ -822,7 +813,7 @@ static void reply_read_send(struct request_context *req)
 /****************************************************************************
  Reply to a read.
 ****************************************************************************/
-void reply_read(struct request_context *req)
+void reply_read(struct smbsrv_request *req)
 {
        union smb_read *io;
 
@@ -842,11 +833,12 @@ void reply_read(struct request_context *req)
        /* tell the backend where to put the data */
        io->read.out.data = req->out.data + 3;
 
-       req->async.send_fn = reply_read_send;
-       req->async.private = io;
+       req->async_states->state |= NTVFS_ASYNC_STATE_MAY_ASYNC;
+       req->async_states->send_fn = reply_read_send;
+       req->async_states->private_data = io;
 
        /* call backend */
-       req->async.status = req->conn->ntvfs_ops->read(req, io);
+       req->async_states->status = ntvfs_read(req, io);
 
        REQ_ASYNC_TAIL;
 }
@@ -856,15 +848,21 @@ void reply_read(struct request_context *req)
 /****************************************************************************
  Reply to a read and X (async reply)
 ****************************************************************************/
-static void reply_read_and_X_send(struct request_context *req)
+static void reply_read_and_X_send(struct smbsrv_request *req)
 {
-       union smb_read *io = req->async.private;
+       union smb_read *io = req->async_states->private_data;
 
        CHECK_ASYNC_STATUS;
 
        /* readx reply packets can be over-sized */
        req->control_flags |= REQ_CONTROL_LARGE;
-       req_grow_data(req, 1 + io->readx.out.nread);
+       if (io->readx.in.maxcnt != 0xFFFF &&
+           io->readx.in.mincnt != 0xFFFF) {
+               req_grow_data(req, 1 + io->readx.out.nread);
+               SCVAL(req->out.data, 0, 0); /* padding */
+       } else {
+               req_grow_data(req, io->readx.out.nread);
+       }
 
        /* construct reply */
        SSVAL(req->out.vwv, VWV(0), SMB_CHAIN_NONE);
@@ -874,7 +872,6 @@ static void reply_read_and_X_send(struct request_context *req)
        REQ_VWV_RESERVED(4, 1);
        SSVAL(req->out.vwv, VWV(5), io->readx.out.nread);
        SSVAL(req->out.vwv, VWV(6), PTR_DIFF(io->readx.out.data, req->out.hdr));
-       SCVAL(req->out.data, 0, 0); /* padding */
        REQ_VWV_RESERVED(7, 5);
 
        chain_reply(req);
@@ -883,7 +880,7 @@ static void reply_read_and_X_send(struct request_context *req)
 /****************************************************************************
  Reply to a read and X.
 ****************************************************************************/
-void reply_read_and_X(struct request_context *req)
+void reply_read_and_X(struct smbsrv_request *req)
 {
        union smb_read *io;
 
@@ -900,31 +897,37 @@ void reply_read_and_X(struct request_context *req)
        io->readx.in.maxcnt        = SVAL(req->in.vwv, VWV(5));
        io->readx.in.mincnt        = SVAL(req->in.vwv, VWV(6));
        io->readx.in.remaining     = SVAL(req->in.vwv, VWV(9));
+
+       if (req->smb_conn->negotiate.client_caps & CAP_LARGE_READX) {
+               uint32_t high_part = IVAL(req->in.vwv, VWV(7));
+               if (high_part == 1) {
+                       io->readx.in.maxcnt |= high_part << 16;
+               }
+       }
        
-       /* the 64 bit varient */
+       /* the 64 bit variant */
        if (req->in.wct == 12) {
-               uint32 offset_high = IVAL(req->in.vwv, VWV(10));
-#ifdef LARGE_SMB_OFF_T
-               io->readx.in.offset |= (((SMB_OFF_T)offset_high) << 32);
-#else
-               if (offset_high != 0) {
-                       req_reply_error(req, NT_STATUS_FOOBAR);
-                       return;
-               }
-#endif
+               uint32_t offset_high = IVAL(req->in.vwv, VWV(10));
+               io->readx.in.offset |= (((uint64_t)offset_high) << 32);
        }
 
        /* setup the reply packet assuming the maximum possible read */
        req_setup_reply(req, 12, 1 + io->readx.in.maxcnt);
 
        /* tell the backend where to put the data. Notice the pad byte. */
-       io->readx.out.data = req->out.data + 1;
+       if (io->readx.in.maxcnt != 0xFFFF &&
+           io->readx.in.mincnt != 0xFFFF) {
+               io->readx.out.data = req->out.data + 1;
+       } else {
+               io->readx.out.data = req->out.data;
+       }
 
-       req->async.send_fn = reply_read_and_X_send;
-       req->async.private = io;
+       req->async_states->state |= NTVFS_ASYNC_STATE_MAY_ASYNC;
+       req->async_states->send_fn = reply_read_and_X_send;
+       req->async_states->private_data = io;
 
        /* call backend */
-       req->async.status = req->conn->ntvfs_ops->read(req, io);
+       req->async_states->status = ntvfs_read(req, io);
 
        REQ_ASYNC_TAIL;
 }
@@ -933,7 +936,7 @@ void reply_read_and_X(struct request_context *req)
 /****************************************************************************
  Reply to a writebraw (core+ or LANMAN1.0 protocol).
 ****************************************************************************/
-void reply_writebraw(struct request_context *req)
+void reply_writebraw(struct smbsrv_request *req)
 {
        /* this one is damn complex - put it off for now */
        req_reply_error(req, NT_STATUS_FOOBAR);
@@ -943,9 +946,9 @@ void reply_writebraw(struct request_context *req)
 /****************************************************************************
  Reply to a writeunlock (async reply)
 ****************************************************************************/
-static void reply_writeunlock_send(struct request_context *req)
+static void reply_writeunlock_send(struct smbsrv_request *req)
 {
-       union smb_write *io = req->async.private;
+       union smb_write *io = req->async_states->private_data;
 
        CHECK_ASYNC_STATUS;
 
@@ -960,7 +963,7 @@ static void reply_writeunlock_send(struct request_context *req)
 /****************************************************************************
  Reply to a writeunlock (core+).
 ****************************************************************************/
-void reply_writeunlock(struct request_context *req)
+void reply_writeunlock(struct smbsrv_request *req)
 {
        union smb_write *io;
 
@@ -986,11 +989,12 @@ void reply_writeunlock(struct request_context *req)
                return;
        }
 
-       req->async.send_fn = reply_writeunlock_send;
-       req->async.private = io;
+       req->async_states->state |= NTVFS_ASYNC_STATE_MAY_ASYNC;
+       req->async_states->send_fn = reply_writeunlock_send;
+       req->async_states->private_data = io;
 
        /* call backend */
-       req->async.status = req->conn->ntvfs_ops->write(req, io);
+       req->async_states->status = ntvfs_write(req, io);
 
        REQ_ASYNC_TAIL;
 }
@@ -1000,9 +1004,9 @@ void reply_writeunlock(struct request_context *req)
 /****************************************************************************
  Reply to a write (async reply)
 ****************************************************************************/
-static void reply_write_send(struct request_context *req)
+static void reply_write_send(struct smbsrv_request *req)
 {
-       union smb_write *io = req->async.private;
+       union smb_write *io = req->async_states->private_data;
        
        CHECK_ASYNC_STATUS;
 
@@ -1017,7 +1021,7 @@ static void reply_write_send(struct request_context *req)
 /****************************************************************************
  Reply to a write
 ****************************************************************************/
-void reply_write(struct request_context *req)
+void reply_write(struct smbsrv_request *req)
 {
        union smb_write *io;
 
@@ -1043,11 +1047,12 @@ void reply_write(struct request_context *req)
                return;
        }
 
-       req->async.send_fn = reply_write_send;
-       req->async.private = io;
+       req->async_states->state |= NTVFS_ASYNC_STATE_MAY_ASYNC;
+       req->async_states->send_fn = reply_write_send;
+       req->async_states->private_data = io;
 
        /* call backend */
-       req->async.status = req->conn->ntvfs_ops->write(req, io);
+       req->async_states->status = ntvfs_write(req, io);
 
        REQ_ASYNC_TAIL;
 }
@@ -1056,9 +1061,9 @@ void reply_write(struct request_context *req)
 /****************************************************************************
  Reply to a write and X (async reply)
 ****************************************************************************/
-static void reply_write_and_X_send(struct request_context *req)
+static void reply_write_and_X_send(struct smbsrv_request *req)
 {
-       union smb_write *io = req->async.private;
+       union smb_write *io = req->async_states->private_data;
 
        CHECK_ASYNC_STATUS;
 
@@ -1078,7 +1083,7 @@ static void reply_write_and_X_send(struct request_context *req)
 /****************************************************************************
  Reply to a write and X.
 ****************************************************************************/
-void reply_write_and_X(struct request_context *req)
+void reply_write_and_X(struct smbsrv_request *req)
 {
        union smb_write *io;
        
@@ -1097,17 +1102,10 @@ void reply_write_and_X(struct request_context *req)
        io->writex.in.data      = req->in.hdr + SVAL(req->in.vwv, VWV(11));
 
        if (req->in.wct == 14) {
-               uint32 offset_high = IVAL(req->in.vwv, VWV(12));
-               uint16 count_high = SVAL(req->in.vwv, VWV(9));
-#ifdef LARGE_SMB_OFF_T
-               io->writex.in.offset |= (((SMB_OFF_T)offset_high) << 32);
-#else
-               if (offset_high != 0) {
-                       req_reply_error(req, NT_STATUS_FOOBAR);
-                       return;
-               }
-#endif
-               io->writex.in.count |= ((uint32)count_high) << 16;
+               uint32_t offset_high = IVAL(req->in.vwv, VWV(12));
+               uint16_t count_high = SVAL(req->in.vwv, VWV(9));
+               io->writex.in.offset |= (((uint64_t)offset_high) << 32);
+               io->writex.in.count |= ((uint32_t)count_high) << 16;
        }
 
        /* make sure the data is in bounds */
@@ -1116,11 +1114,12 @@ void reply_write_and_X(struct request_context *req)
                return;
        } 
 
-       req->async.send_fn = reply_write_and_X_send;
-       req->async.private = io;
+       req->async_states->state |= NTVFS_ASYNC_STATE_MAY_ASYNC;
+       req->async_states->send_fn = reply_write_and_X_send;
+       req->async_states->private_data = io;
 
        /* call backend */
-       req->async.status = req->conn->ntvfs_ops->write(req, io);
+       req->async_states->status = ntvfs_write(req, io);
 
        REQ_ASYNC_TAIL;
 }
@@ -1129,9 +1128,9 @@ void reply_write_and_X(struct request_context *req)
 /****************************************************************************
  Reply to a lseek (async reply)
 ****************************************************************************/
-static void reply_lseek_send(struct request_context *req)
+static void reply_lseek_send(struct smbsrv_request *req)
 {
-       struct smb_seek *io = req->async.private;
+       struct smb_seek *io = req->async_states->private_data;
 
        CHECK_ASYNC_STATUS;
 
@@ -1146,7 +1145,7 @@ static void reply_lseek_send(struct request_context *req)
 /****************************************************************************
  Reply to a lseek.
 ****************************************************************************/
-void reply_lseek(struct request_context *req)
+void reply_lseek(struct smbsrv_request *req)
 {
        struct smb_seek *io;
 
@@ -1157,11 +1156,12 @@ void reply_lseek(struct request_context *req)
        io->in.mode   = SVAL(req->in.vwv,  VWV(1));
        io->in.offset = IVALS(req->in.vwv, VWV(2));
 
-       req->async.send_fn = reply_lseek_send;
-       req->async.private = io;
+       req->async_states->state |= NTVFS_ASYNC_STATE_MAY_ASYNC;
+       req->async_states->send_fn = reply_lseek_send;
+       req->async_states->private_data = io;
        
        /* call backend */
-       req->async.status = req->conn->ntvfs_ops->seek(req, io);
+       req->async_states->status = ntvfs_seek(req, io);
 
        REQ_ASYNC_TAIL;
 }
@@ -1169,7 +1169,7 @@ void reply_lseek(struct request_context *req)
 /****************************************************************************
  Reply to a flush.
 ****************************************************************************/
-void reply_flush(struct request_context *req)
+void reply_flush(struct smbsrv_request *req)
 {
        struct smb_flush *io;
 
@@ -1179,33 +1179,37 @@ void reply_flush(struct request_context *req)
 
        io->in.fnum   = req_fnum(req, req->in.vwv,  VWV(0));
        
-       req->async.send_fn = reply_simple_send;
+       req->async_states->state |= NTVFS_ASYNC_STATE_MAY_ASYNC;
+       req->async_states->send_fn = reply_simple_send;
 
        /* call backend */
-       req->async.status = req->conn->ntvfs_ops->flush(req, io);
+       req->async_states->status = ntvfs_flush(req, io);
        
        REQ_ASYNC_TAIL;
 }
 
 
 /****************************************************************************
- Reply to a exit.
+ Reply to a exit. This closes all files open by a smbpid
 ****************************************************************************/
-void reply_exit(struct request_context *req)
+void reply_exit(struct smbsrv_request *req)
 {
+       NTSTATUS status;
+       struct smbsrv_tcon *tcon;
        REQ_CHECK_WCT(req, 0);
 
-       req->async.send_fn = reply_simple_send;
-
-       if (!req->conn) {
-               req_reply_error(req, NT_STATUS_INVALID_HANDLE);
-               return;
+       for (tcon=req->smb_conn->tree.tcons;tcon;tcon=tcon->next) {
+               req->tcon = tcon;
+               status = ntvfs_exit(req);
+               req->tcon = NULL;
+               if (!NT_STATUS_IS_OK(status)) {
+                       req_reply_error(req, status);
+                       return;
+               }
        }
 
-       /* call backend */
-       req->async.status = req->conn->ntvfs_ops->exit(req);
-       
-       REQ_ASYNC_TAIL;
+       req_setup_reply(req, 0, 0);
+       req_send_reply(req);
 }
 
 
@@ -1214,7 +1218,7 @@ void reply_exit(struct request_context *req)
 
  Note that this has to deal with closing a directory opened by NT SMB's.
 ****************************************************************************/
-void reply_close(struct request_context *req)
+void reply_close(struct smbsrv_request *req)
 {
        union smb_close *io;
 
@@ -1224,12 +1228,13 @@ void reply_close(struct request_context *req)
 
        io->close.level = RAW_CLOSE_CLOSE;
        io->close.in.fnum  = req_fnum(req, req->in.vwv,  VWV(0));
-       io->close.in.write_time = make_unix_date3(req->in.vwv + VWV(1));
+       io->close.in.write_time = srv_pull_dos_date3(req->smb_conn, req->in.vwv + VWV(1));
 
-       req->async.send_fn = reply_simple_send;
+       req->async_states->state |= NTVFS_ASYNC_STATE_MAY_ASYNC;
+       req->async_states->send_fn = reply_simple_send;
 
        /* call backend */
-       req->async.status = req->conn->ntvfs_ops->close(req, io);
+       req->async_states->status = ntvfs_close(req, io);
 
        REQ_ASYNC_TAIL;
 }
@@ -1239,9 +1244,9 @@ void reply_close(struct request_context *req)
 /****************************************************************************
  Reply to a writeclose (async reply)
 ****************************************************************************/
-static void reply_writeclose_send(struct request_context *req)
+static void reply_writeclose_send(struct smbsrv_request *req)
 {
-       union smb_write *io = req->async.private;
+       union smb_write *io = req->async_states->private_data;
 
        CHECK_ASYNC_STATUS;
 
@@ -1256,7 +1261,7 @@ static void reply_writeclose_send(struct request_context *req)
 /****************************************************************************
  Reply to a writeclose (Core+ protocol).
 ****************************************************************************/
-void reply_writeclose(struct request_context *req)
+void reply_writeclose(struct smbsrv_request *req)
 {
        union smb_write *io;
 
@@ -1271,7 +1276,7 @@ void reply_writeclose(struct request_context *req)
        io->writeclose.in.fnum   = req_fnum(req, req->in.vwv, VWV(0));
        io->writeclose.in.count  = SVAL(req->in.vwv, VWV(1));
        io->writeclose.in.offset = IVAL(req->in.vwv, VWV(2));
-       io->writeclose.in.mtime  = make_unix_date3(req->in.vwv + VWV(4));
+       io->writeclose.in.mtime  = srv_pull_dos_date3(req->smb_conn, req->in.vwv + VWV(4));
        io->writeclose.in.data   = req->in.data + 1;
 
        /* make sure they gave us the data they promised */
@@ -1280,11 +1285,12 @@ void reply_writeclose(struct request_context *req)
                return;
        }
 
-       req->async.send_fn = reply_writeclose_send;
-       req->async.private = io;
+       req->async_states->state |= NTVFS_ASYNC_STATE_MAY_ASYNC;
+       req->async_states->send_fn = reply_writeclose_send;
+       req->async_states->private_data = io;
 
        /* call backend */
-       req->async.status = req->conn->ntvfs_ops->write(req, io);
+       req->async_states->status = ntvfs_write(req, io);
 
        REQ_ASYNC_TAIL;
 }
@@ -1292,7 +1298,7 @@ void reply_writeclose(struct request_context *req)
 /****************************************************************************
  Reply to a lock.
 ****************************************************************************/
-void reply_lock(struct request_context *req)
+void reply_lock(struct smbsrv_request *req)
 {
        union smb_lock *lck;
 
@@ -1305,10 +1311,11 @@ void reply_lock(struct request_context *req)
        lck->lock.in.count  = IVAL(req->in.vwv, VWV(1));
        lck->lock.in.offset = IVAL(req->in.vwv, VWV(3));
 
-       req->async.send_fn = reply_simple_send;
+       req->async_states->state |= NTVFS_ASYNC_STATE_MAY_ASYNC;
+       req->async_states->send_fn = reply_simple_send;
 
        /* call backend */
-       req->async.status = req->conn->ntvfs_ops->lock(req, lck);
+       req->async_states->status = ntvfs_lock(req, lck);
 
        REQ_ASYNC_TAIL;
 }
@@ -1317,7 +1324,7 @@ void reply_lock(struct request_context *req)
 /****************************************************************************
  Reply to a unlock.
 ****************************************************************************/
-void reply_unlock(struct request_context *req)
+void reply_unlock(struct smbsrv_request *req)
 {
        union smb_lock *lck;
 
@@ -1330,10 +1337,11 @@ void reply_unlock(struct request_context *req)
        lck->unlock.in.count  = IVAL(req->in.vwv, VWV(1));
        lck->unlock.in.offset = IVAL(req->in.vwv, VWV(3));
 
-       req->async.send_fn = reply_simple_send;
+       req->async_states->state |= NTVFS_ASYNC_STATE_MAY_ASYNC;
+       req->async_states->send_fn = reply_simple_send;
 
        /* call backend */
-       req->async.status = req->conn->ntvfs_ops->lock(req, lck);
+       req->async_states->status = ntvfs_lock(req, lck);
 
        REQ_ASYNC_TAIL;
 }
@@ -1342,11 +1350,11 @@ void reply_unlock(struct request_context *req)
 /****************************************************************************
  Reply to a tdis.
 ****************************************************************************/
-void reply_tdis(struct request_context *req)
+void reply_tdis(struct smbsrv_request *req)
 {
        REQ_CHECK_WCT(req, 0);
 
-       close_cnum(req->conn);
+       close_cnum(req->tcon);
 
        /* construct reply */
        req_setup_reply(req, 0, 0);
@@ -1359,9 +1367,9 @@ void reply_tdis(struct request_context *req)
  Reply to a echo. This is one of the few calls that is handled directly (the
  backends don't see it at all)
 ****************************************************************************/
-void reply_echo(struct request_context *req)
+void reply_echo(struct smbsrv_request *req)
 {
-       uint16 count;
+       uint16_t count;
        int i;
 
        REQ_CHECK_WCT(req, 0);
@@ -1372,17 +1380,17 @@ void reply_echo(struct request_context *req)
 
        memcpy(req->out.data, req->in.data, req->in.data_size);
 
-       /* we need to make sure the request isn't destroyed till the
-        * last packet */
-       req->control_flags |= REQ_CONTROL_PROTECTED;
-
        for (i=1; i <= count;i++) {
-               if (i == count) {
-                       req->control_flags &= ~REQ_CONTROL_PROTECTED;
+               struct smbsrv_request *this_req;
+               
+               if (i != count) {
+                       this_req = req_setup_secondary(req);
+               } else {
+                       this_req = req;
                }
 
-               SSVAL(req->out.vwv, VWV(0), i);
-               req_send_reply(req);
+               SSVAL(this_req->out.vwv, VWV(0), i);
+               req_send_reply(this_req);
        }
 }
 
@@ -1391,16 +1399,16 @@ void reply_echo(struct request_context *req)
 /****************************************************************************
  Reply to a printopen (async reply)
 ****************************************************************************/
-static void reply_printopen_send(struct request_context *req)
+static void reply_printopen_send(struct smbsrv_request *req)
 {
-       union smb_open *oi = req->async.private;
+       union smb_open *oi = req->async_states->private_data;
 
        CHECK_ASYNC_STATUS;
 
        /* construct reply */
        req_setup_reply(req, 1, 0);
 
-       SSVAL(req->out.vwv, VWV(0), oi->open.out.fnum);
+       SSVAL(req->out.vwv, VWV(0), oi->openold.out.fnum);
 
        req_send_reply(req);
 }
@@ -1408,7 +1416,7 @@ static void reply_printopen_send(struct request_context *req)
 /****************************************************************************
  Reply to a printopen.
 ****************************************************************************/
-void reply_printopen(struct request_context *req)
+void reply_printopen(struct smbsrv_request *req)
 {
        union smb_open *oi;
 
@@ -1422,11 +1430,12 @@ void reply_printopen(struct request_context *req)
 
        req_pull_ascii4(req, &oi->splopen.in.ident, req->in.data, STR_TERMINATE);
 
-       req->async.send_fn = reply_printopen_send;
-       req->async.private = oi;
+       req->async_states->state |= NTVFS_ASYNC_STATE_MAY_ASYNC;
+       req->async_states->send_fn = reply_printopen_send;
+       req->async_states->private_data = oi;
 
        /* call backend */
-       req->async.status = req->conn->ntvfs_ops->open(req, oi);
+       req->async_states->status = ntvfs_openfile(req, oi);
 
        REQ_ASYNC_TAIL;
 }
@@ -1434,7 +1443,7 @@ void reply_printopen(struct request_context *req)
 /****************************************************************************
  Reply to a printclose.
 ****************************************************************************/
-void reply_printclose(struct request_context *req)
+void reply_printclose(struct smbsrv_request *req)
 {
        union smb_close *io;
 
@@ -1445,10 +1454,11 @@ void reply_printclose(struct request_context *req)
        io->splclose.level = RAW_CLOSE_SPLCLOSE;
        io->splclose.in.fnum = req_fnum(req, req->in.vwv,  VWV(0));
 
-       req->async.send_fn = reply_simple_send;
+       req->async_states->state |= NTVFS_ASYNC_STATE_MAY_ASYNC;
+       req->async_states->send_fn = reply_simple_send;
 
        /* call backend */
-       req->async.status = req->conn->ntvfs_ops->close(req, io);
+       req->async_states->status = ntvfs_close(req, io);
 
        REQ_ASYNC_TAIL;
 }
@@ -1456,9 +1466,9 @@ void reply_printclose(struct request_context *req)
 /****************************************************************************
  Reply to a printqueue.
 ****************************************************************************/
-void reply_printqueue_send(struct request_context *req)
+void reply_printqueue_send(struct smbsrv_request *req)
 {
-       union smb_lpq *lpq = req->async.private;
+       union smb_lpq *lpq = req->async_states->private_data;
        int i, maxcount;
        const uint_t el_size = 28;      
 
@@ -1486,7 +1496,7 @@ void reply_printqueue_send(struct request_context *req)
        req->out.ptr = req->out.data + 3;
 
        for (i=0;i<lpq->retq.out.count;i++) {
-               put_dos_date2(req->out.ptr, 0 , lpq->retq.out.queue[i].time);
+               srv_push_dos_date2(req->smb_conn, req->out.ptr, 0 , lpq->retq.out.queue[i].time);
                SCVAL(req->out.ptr,  4, lpq->retq.out.queue[i].status);
                SSVAL(req->out.ptr,  5, lpq->retq.out.queue[i].job);
                SIVAL(req->out.ptr,  7, lpq->retq.out.queue[i].size);
@@ -1501,7 +1511,7 @@ void reply_printqueue_send(struct request_context *req)
 /****************************************************************************
  Reply to a printqueue.
 ****************************************************************************/
-void reply_printqueue(struct request_context *req)
+void reply_printqueue(struct smbsrv_request *req)
 {
        union smb_lpq *lpq;
 
@@ -1513,11 +1523,12 @@ void reply_printqueue(struct request_context *req)
        lpq->retq.in.maxcount = SVAL(req->in.vwv,  VWV(0));
        lpq->retq.in.startidx = SVAL(req->in.vwv,  VWV(1));
 
-       req->async.send_fn = reply_printqueue_send;
-       req->async.private = lpq;
+       req->async_states->state |= NTVFS_ASYNC_STATE_MAY_ASYNC;
+       req->async_states->send_fn = reply_printqueue_send;
+       req->async_states->private_data = lpq;
 
        /* call backend */
-       req->async.status = req->conn->ntvfs_ops->lpq(req, lpq);
+       req->async_states->status = ntvfs_lpq(req, lpq);
 
        REQ_ASYNC_TAIL;
 }
@@ -1526,7 +1537,7 @@ void reply_printqueue(struct request_context *req)
 /****************************************************************************
  Reply to a printwrite.
 ****************************************************************************/
-void reply_printwrite(struct request_context *req)
+void reply_printwrite(struct smbsrv_request *req)
 {
        union smb_write *io;
 
@@ -1551,10 +1562,11 @@ void reply_printwrite(struct request_context *req)
                return;
        }
 
-       req->async.send_fn = reply_simple_send;
+       req->async_states->state |= NTVFS_ASYNC_STATE_MAY_ASYNC;
+       req->async_states->send_fn = reply_simple_send;
 
        /* call backend */
-       req->async.status = req->conn->ntvfs_ops->write(req, io);
+       req->async_states->status = ntvfs_write(req, io);
 
        REQ_ASYNC_TAIL;
 }
@@ -1563,7 +1575,7 @@ void reply_printwrite(struct request_context *req)
 /****************************************************************************
  Reply to a mkdir.
 ****************************************************************************/
-void reply_mkdir(struct request_context *req)
+void reply_mkdir(struct smbsrv_request *req)
 {
        union smb_mkdir *io;
 
@@ -1574,10 +1586,11 @@ void reply_mkdir(struct request_context *req)
        io->generic.level = RAW_MKDIR_MKDIR;
        req_pull_ascii4(req, &io->mkdir.in.path, req->in.data, STR_TERMINATE);
 
-       req->async.send_fn = reply_simple_send;
+       req->async_states->state |= NTVFS_ASYNC_STATE_MAY_ASYNC;
+       req->async_states->send_fn = reply_simple_send;
 
        /* call backend */
-       req->async.status = req->conn->ntvfs_ops->mkdir(req, io);
+       req->async_states->status = ntvfs_mkdir(req, io);
 
        REQ_ASYNC_TAIL;
 }
@@ -1586,7 +1599,7 @@ void reply_mkdir(struct request_context *req)
 /****************************************************************************
  Reply to a rmdir.
 ****************************************************************************/
-void reply_rmdir(struct request_context *req)
+void reply_rmdir(struct smbsrv_request *req)
 {
        struct smb_rmdir *io;
  
@@ -1596,10 +1609,11 @@ void reply_rmdir(struct request_context *req)
 
        req_pull_ascii4(req, &io->in.path, req->in.data, STR_TERMINATE);
 
-       req->async.send_fn = reply_simple_send;
+       req->async_states->state |= NTVFS_ASYNC_STATE_MAY_ASYNC;
+       req->async_states->send_fn = reply_simple_send;
 
        /* call backend */
-       req->async.status = req->conn->ntvfs_ops->rmdir(req, io);
+       req->async_states->status = ntvfs_rmdir(req, io);
 
        REQ_ASYNC_TAIL;
 }
@@ -1608,10 +1622,10 @@ void reply_rmdir(struct request_context *req)
 /****************************************************************************
  Reply to a mv.
 ****************************************************************************/
-void reply_mv(struct request_context *req)
+void reply_mv(struct smbsrv_request *req)
 {
        union smb_rename *io;
-       char *p;
+       uint8_t *p;
  
        /* parse the request */
        REQ_CHECK_WCT(req, 1);
@@ -1629,10 +1643,11 @@ void reply_mv(struct request_context *req)
                return;
        }
 
-       req->async.send_fn = reply_simple_send;
+       req->async_states->state |= NTVFS_ASYNC_STATE_MAY_ASYNC;
+       req->async_states->send_fn = reply_simple_send;
 
        /* call backend */
-       req->async.status = req->conn->ntvfs_ops->rename(req, io);
+       req->async_states->status = ntvfs_rename(req, io);
 
        REQ_ASYNC_TAIL;
 }
@@ -1641,10 +1656,10 @@ void reply_mv(struct request_context *req)
 /****************************************************************************
  Reply to an NT rename.
 ****************************************************************************/
-void reply_ntrename(struct request_context *req)
+void reply_ntrename(struct smbsrv_request *req)
 {
        union smb_rename *io;
-       char *p;
+       uint8_t *p;
  
        /* parse the request */
        REQ_CHECK_WCT(req, 4);
@@ -1664,10 +1679,11 @@ void reply_ntrename(struct request_context *req)
                return;
        }
 
-       req->async.send_fn = reply_simple_send;
+       req->async_states->state |= NTVFS_ASYNC_STATE_MAY_ASYNC;
+       req->async_states->send_fn = reply_simple_send;
 
        /* call backend */
-       req->async.status = req->conn->ntvfs_ops->rename(req, io);
+       req->async_states->status = ntvfs_rename(req, io);
 
        REQ_ASYNC_TAIL;
 }
@@ -1675,9 +1691,9 @@ void reply_ntrename(struct request_context *req)
 /****************************************************************************
  Reply to a file copy (async reply)
 ****************************************************************************/
-static void reply_copy_send(struct request_context *req)
+static void reply_copy_send(struct smbsrv_request *req)
 {
-       struct smb_copy *cp = req->async.private;
+       struct smb_copy *cp = req->async_states->private_data;
 
        CHECK_ASYNC_STATUS;
 
@@ -1692,10 +1708,10 @@ static void reply_copy_send(struct request_context *req)
 /****************************************************************************
  Reply to a file copy.
 ****************************************************************************/
-void reply_copy(struct request_context *req)
+void reply_copy(struct smbsrv_request *req)
 {
        struct smb_copy *cp;
-       char *p;
+       uint8_t *p;
 
        /* parse request */
        REQ_CHECK_WCT(req, 3);
@@ -1714,11 +1730,12 @@ void reply_copy(struct request_context *req)
                return;
        }
 
-       req->async.send_fn = reply_copy_send;
-       req->async.private = cp;
+       req->async_states->state |= NTVFS_ASYNC_STATE_MAY_ASYNC;
+       req->async_states->send_fn = reply_copy_send;
+       req->async_states->private_data = cp;
 
        /* call backend */
-       req->async.status = req->conn->ntvfs_ops->copy(req, cp);
+       req->async_states->status = ntvfs_copy(req, cp);
 
        REQ_ASYNC_TAIL;
 }
@@ -1726,9 +1743,9 @@ void reply_copy(struct request_context *req)
 /****************************************************************************
  Reply to a lockingX request (async send)
 ****************************************************************************/
-static void reply_lockingX_send(struct request_context *req)
+static void reply_lockingX_send(struct smbsrv_request *req)
 {
-       union smb_lock *lck = req->async.private;
+       union smb_lock *lck = req->async_states->private_data;
 
        CHECK_ASYNC_STATUS;
 
@@ -1752,12 +1769,12 @@ static void reply_lockingX_send(struct request_context *req)
 /****************************************************************************
  Reply to a lockingX request.
 ****************************************************************************/
-void reply_lockingX(struct request_context *req)
+void reply_lockingX(struct smbsrv_request *req)
 {
        union smb_lock *lck;
        uint_t total_locks, i;
        uint_t lck_size;
-       char *p;
+       uint8_t *p;
 
        /* parse request */
        REQ_CHECK_WCT(req, 8);
@@ -1772,7 +1789,7 @@ void reply_lockingX(struct request_context *req)
 
        total_locks = lck->lockx.in.ulock_cnt + lck->lockx.in.lock_cnt;
 
-       /* there are two varients, one with 64 bit offsets and counts */
+       /* there are two variants, one with 64 bit offsets and counts */
        if (lck->lockx.in.mode & LOCKING_ANDX_LARGE_FILES) {
                lck_size = 20;
        } else {
@@ -1794,7 +1811,7 @@ void reply_lockingX(struct request_context *req)
 
        /* construct the locks array */
        for (i=0;i<total_locks;i++) {
-               uint32 ofs_high=0, count_high=0;
+               uint32_t ofs_high=0, count_high=0;
 
                lck->lockx.in.locks[i].pid = SVAL(p, 0);
 
@@ -1808,22 +1825,18 @@ void reply_lockingX(struct request_context *req)
                        lck->lockx.in.locks[i].count  = IVAL(p, 6);
                }
                if (ofs_high != 0 || count_high != 0) {
-#ifdef LARGE_SMB_OFF_T
-                       lck->lockx.in.locks[i].count  |= ((SMB_OFF_T)count_high) << 32;
-                       lck->lockx.in.locks[i].offset |= ((SMB_OFF_T)ofs_high) << 32;
-#else
-                       req_reply_error(req, NT_STATUS_FOOBAR);
-                       return;
-#endif
+                       lck->lockx.in.locks[i].count  |= ((uint64_t)count_high) << 32;
+                       lck->lockx.in.locks[i].offset |= ((uint64_t)ofs_high) << 32;
                }
                p += lck_size;
        }
 
-       req->async.send_fn = reply_lockingX_send;
-       req->async.private = lck;
+       req->async_states->state |= NTVFS_ASYNC_STATE_MAY_ASYNC;
+       req->async_states->send_fn = reply_lockingX_send;
+       req->async_states->private_data = lck;
 
        /* call backend */
-       req->async.status = req->conn->ntvfs_ops->lock(req, lck);
+       req->async_states->status = ntvfs_lock(req, lck);
 
        REQ_ASYNC_TAIL;
 }
@@ -1831,7 +1844,7 @@ void reply_lockingX(struct request_context *req)
 /****************************************************************************
  Reply to a SMBreadbmpx (read block multiplex) request.
 ****************************************************************************/
-void reply_readbmpx(struct request_context *req)
+void reply_readbmpx(struct smbsrv_request *req)
 {
        /* tell the client to not use a multiplexed read - its too broken to use */
        req_reply_dos_error(req, ERRSRV, ERRuseSTD);
@@ -1841,7 +1854,7 @@ void reply_readbmpx(struct request_context *req)
 /****************************************************************************
  Reply to a SMBsetattrE.
 ****************************************************************************/
-void reply_setattrE(struct request_context *req)
+void reply_setattrE(struct smbsrv_request *req)
 {
        union smb_setfileinfo *info;
 
@@ -1851,14 +1864,15 @@ void reply_setattrE(struct request_context *req)
 
        info->setattre.level = RAW_SFILEINFO_SETATTRE;
        info->setattre.file.fnum =      req_fnum(req, req->in.vwv,    VWV(0));
-       info->setattre.in.create_time = make_unix_date2(req->in.vwv + VWV(1));
-       info->setattre.in.access_time = make_unix_date2(req->in.vwv + VWV(3));
-       info->setattre.in.write_time  = make_unix_date2(req->in.vwv + VWV(5));
+       info->setattre.in.create_time = srv_pull_dos_date2(req->smb_conn, req->in.vwv + VWV(1));
+       info->setattre.in.access_time = srv_pull_dos_date2(req->smb_conn, req->in.vwv + VWV(3));
+       info->setattre.in.write_time  = srv_pull_dos_date2(req->smb_conn, req->in.vwv + VWV(5));
 
-       req->async.send_fn = reply_simple_send;
+       req->async_states->state |= NTVFS_ASYNC_STATE_MAY_ASYNC;
+       req->async_states->send_fn = reply_simple_send;
 
        /* call backend */
-       req->async.status = req->conn->ntvfs_ops->setfileinfo(req, info);
+       req->async_states->status = ntvfs_setfileinfo(req, info);
 
        REQ_ASYNC_TAIL;
 }
@@ -1867,20 +1881,18 @@ void reply_setattrE(struct request_context *req)
 /****************************************************************************
  Reply to a SMBwritebmpx (write block multiplex primary) request.
 ****************************************************************************/
-void reply_writebmpx(struct request_context *req)
+void reply_writebmpx(struct smbsrv_request *req)
 {
-       /* we will need to implement this one for OS/2, but right now I can't be bothered */
-       req_reply_error(req, NT_STATUS_FOOBAR);
+       req_reply_dos_error(req, ERRSRV, ERRuseSTD);
 }
 
 
 /****************************************************************************
  Reply to a SMBwritebs (write block multiplex secondary) request.
 ****************************************************************************/
-void reply_writebs(struct request_context *req)
+void reply_writebs(struct smbsrv_request *req)
 {
-       /* see reply_writebmpx */
-       req_reply_error(req, NT_STATUS_FOOBAR);
+       req_reply_dos_error(req, ERRSRV, ERRuseSTD);
 }
 
 
@@ -1888,18 +1900,18 @@ void reply_writebs(struct request_context *req)
 /****************************************************************************
  Reply to a SMBgetattrE (async reply)
 ****************************************************************************/
-static void reply_getattrE_send(struct request_context *req)
+static void reply_getattrE_send(struct smbsrv_request *req)
 {
-       union smb_fileinfo *info = req->async.private;
+       union smb_fileinfo *info = req->async_states->private_data;
 
        CHECK_ASYNC_STATUS;
 
        /* setup reply */
        req_setup_reply(req, 11, 0);
 
-       put_dos_date2(req->out.vwv, VWV(0), info->getattre.out.create_time);
-       put_dos_date2(req->out.vwv, VWV(2), info->getattre.out.access_time);
-       put_dos_date2(req->out.vwv, VWV(4), info->getattre.out.write_time);
+       srv_push_dos_date2(req->smb_conn, req->out.vwv, VWV(0), info->getattre.out.create_time);
+       srv_push_dos_date2(req->smb_conn, req->out.vwv, VWV(2), info->getattre.out.access_time);
+       srv_push_dos_date2(req->smb_conn, req->out.vwv, VWV(4), info->getattre.out.write_time);
        SIVAL(req->out.vwv,         VWV(6), info->getattre.out.size);
        SIVAL(req->out.vwv,         VWV(8), info->getattre.out.alloc_size);
        SSVAL(req->out.vwv,        VWV(10), info->getattre.out.attrib);
@@ -1910,7 +1922,7 @@ static void reply_getattrE_send(struct request_context *req)
 /****************************************************************************
  Reply to a SMBgetattrE.
 ****************************************************************************/
-void reply_getattrE(struct request_context *req)
+void reply_getattrE(struct smbsrv_request *req)
 {
        union smb_fileinfo *info;
 
@@ -1921,11 +1933,12 @@ void reply_getattrE(struct request_context *req)
        info->getattr.level = RAW_FILEINFO_GETATTRE;
        info->getattr.in.fnum = req_fnum(req, req->in.vwv, VWV(0));
 
-       req->async.send_fn = reply_getattrE_send;
-       req->async.private = info;
+       req->async_states->state |= NTVFS_ASYNC_STATE_MAY_ASYNC;
+       req->async_states->send_fn = reply_getattrE_send;
+       req->async_states->private_data = info;
 
        /* call backend */
-       req->async.status = req->conn->ntvfs_ops->qfileinfo(req, info);
+       req->async_states->status = ntvfs_qfileinfo(req, info);
 
        REQ_ASYNC_TAIL;
 }
@@ -1934,12 +1947,12 @@ void reply_getattrE(struct request_context *req)
 /****************************************************************************
 reply to an old style session setup command
 ****************************************************************************/
-static void reply_sesssetup_old(struct request_context *req)
+static void reply_sesssetup_old(struct smbsrv_request *req)
 {
        NTSTATUS status;
        union smb_sesssetup sess;
-       char *p;
-       uint16 passlen;
+       uint8_t *p;
+       uint16_t passlen;
 
        sess.old.level = RAW_SESSSETUP_OLD;
 
@@ -1992,12 +2005,12 @@ static void reply_sesssetup_old(struct request_context *req)
 /****************************************************************************
 reply to an NT1 style session setup command
 ****************************************************************************/
-static void reply_sesssetup_nt1(struct request_context *req)
+static void reply_sesssetup_nt1(struct smbsrv_request *req)
 {
        NTSTATUS status;
        union smb_sesssetup sess;
-       char *p;
-       uint16 passlen1, passlen2;
+       uint8_t *p;
+       uint16_t passlen1, passlen2;
 
        sess.nt1.level = RAW_SESSSETUP_NT1;
 
@@ -2062,12 +2075,12 @@ static void reply_sesssetup_nt1(struct request_context *req)
 /****************************************************************************
 reply to an SPNEGO style session setup command
 ****************************************************************************/
-static void reply_sesssetup_spnego(struct request_context *req)
+static void reply_sesssetup_spnego(struct smbsrv_request *req)
 {
        NTSTATUS status;
        union smb_sesssetup sess;
-       char *p;
-       uint16 blob_len;
+       uint8_t *p;
+       uint16_t blob_len;
 
        sess.spnego.level = RAW_SESSSETUP_SPNEGO;
 
@@ -2093,7 +2106,8 @@ static void reply_sesssetup_spnego(struct request_context *req)
        /* call the generic handler */
        status = sesssetup_backend(req, &sess);
 
-       if (!NT_STATUS_IS_OK(status)) {
+       if (!NT_STATUS_IS_OK(status) && 
+           !NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
                req_reply_error(req, status);
                return;
        }
@@ -2101,6 +2115,10 @@ static void reply_sesssetup_spnego(struct request_context *req)
        /* construct reply */
        req_setup_reply(req, 4, sess.spnego.out.secblob.length);
 
+       if (NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
+               req_setup_error(req, status);
+       }
+
        SSVAL(req->out.vwv, VWV(0), SMB_CHAIN_NONE);
        SSVAL(req->out.vwv, VWV(1), 0);
        SSVAL(req->out.vwv, VWV(2), sess.spnego.out.action);
@@ -2111,6 +2129,7 @@ static void reply_sesssetup_spnego(struct request_context *req)
        memcpy(req->out.data, sess.spnego.out.secblob.data, sess.spnego.out.secblob.length);
        req_push_str(req, NULL, sess.spnego.out.os, -1, STR_TERMINATE);
        req_push_str(req, NULL, sess.spnego.out.lanman, -1, STR_TERMINATE);
+       req_push_str(req, NULL, sess.spnego.out.domain, -1, STR_TERMINATE);
 
        chain_reply(req);
 }
@@ -2119,7 +2138,7 @@ static void reply_sesssetup_spnego(struct request_context *req)
 /****************************************************************************
 reply to a session setup command
 ****************************************************************************/
-void reply_sesssetup(struct request_context *req)
+void reply_sesssetup(struct smbsrv_request *req)
 {
        switch (req->in.wct) {
        case 10:
@@ -2136,27 +2155,36 @@ void reply_sesssetup(struct request_context *req)
                return;
        }
 
-       /* unsupported varient */
+       /* unsupported variant */
        req_reply_error(req, NT_STATUS_FOOBAR);
 }
 
-
 /****************************************************************************
  Reply to a SMBulogoffX.
 ****************************************************************************/
-void reply_ulogoffX(struct request_context *req)
+void reply_ulogoffX(struct smbsrv_request *req)
 {
-       uint16 vuid;
+       struct smbsrv_tcon *tcon;
+       uint16_t vuid;
+       NTSTATUS status;
 
        vuid = SVAL(req->in.hdr, HDR_UID);
-       
+
        /* in user level security we are supposed to close any files
-          open by this user */
+          open by this user on all open tree connects */
        if ((vuid != 0) && (lp_security() != SEC_SHARE)) {
-               DEBUG(0,("REWRITE: not closing user files\n"));
+               for (tcon=req->smb_conn->tree.tcons;tcon;tcon=tcon->next) {
+                       req->tcon = tcon;
+                       status = ntvfs_logoff(req);
+                       req->tcon = NULL;
+                       if (!NT_STATUS_IS_OK(status)) {
+                               req_reply_error(req, status);
+                               return;
+                       }
+               }
        }
 
-       invalidate_vuid(req->smb, vuid);
+       smbsrv_invalidate_vuid(req->smb_conn, vuid);
 
        req_setup_reply(req, 2, 0);
 
@@ -2170,12 +2198,12 @@ void reply_ulogoffX(struct request_context *req)
 /****************************************************************************
  Reply to an SMBfindclose request
 ****************************************************************************/
-void reply_findclose(struct request_context *req)
+void reply_findclose(struct smbsrv_request *req)
 {
        NTSTATUS status;
        union smb_search_close io;
 
-       io.findclose.level = RAW_FINDCLOSE_CLOSE;
+       io.findclose.level = RAW_FINDCLOSE_FINDCLOSE;
 
        /* parse request */
        REQ_CHECK_WCT(req, 1);
@@ -2183,7 +2211,7 @@ void reply_findclose(struct request_context *req)
        io.findclose.in.handle  = SVAL(req->in.vwv, VWV(0));
        
        /* call backend */
-       status = req->conn->ntvfs_ops->search_close(req, &io);
+       status = ntvfs_search_close(req, &io);
 
        if (!NT_STATUS_IS_OK(status)) {
                req_reply_error(req, status);
@@ -2199,7 +2227,7 @@ void reply_findclose(struct request_context *req)
 /****************************************************************************
  Reply to an SMBfindnclose request
 ****************************************************************************/
-void reply_findnclose(struct request_context *req)
+void reply_findnclose(struct smbsrv_request *req)
 {
        req_reply_error(req, NT_STATUS_FOOBAR);
 }
@@ -2208,9 +2236,9 @@ void reply_findnclose(struct request_context *req)
 /****************************************************************************
  Reply to an SMBntcreateX request (async send)
 ****************************************************************************/
-static void reply_ntcreate_and_X_send(struct request_context *req)
+static void reply_ntcreate_and_X_send(struct smbsrv_request *req)
 {
-       union smb_open *io = req->async.private;
+       union smb_open *io = req->async_states->private_data;
 
        CHECK_ASYNC_STATUS;
 
@@ -2224,10 +2252,10 @@ static void reply_ntcreate_and_X_send(struct request_context *req)
        /* the rest of the parameters are not aligned! */
        SSVAL(req->out.vwv,        5, io->ntcreatex.out.fnum);
        SIVAL(req->out.vwv,        7, io->ntcreatex.out.create_action);
-       push_nttime(req->out.vwv, 11, &io->ntcreatex.out.create_time);
-       push_nttime(req->out.vwv, 19, &io->ntcreatex.out.access_time);
-       push_nttime(req->out.vwv, 27, &io->ntcreatex.out.write_time);
-       push_nttime(req->out.vwv, 35, &io->ntcreatex.out.change_time);
+       push_nttime(req->out.vwv, 11, io->ntcreatex.out.create_time);
+       push_nttime(req->out.vwv, 19, io->ntcreatex.out.access_time);
+       push_nttime(req->out.vwv, 27, io->ntcreatex.out.write_time);
+       push_nttime(req->out.vwv, 35, io->ntcreatex.out.change_time);
        SIVAL(req->out.vwv,       43, io->ntcreatex.out.attrib);
        SBVAL(req->out.vwv,       47, io->ntcreatex.out.alloc_size);
        SBVAL(req->out.vwv,       55, io->ntcreatex.out.size);
@@ -2241,10 +2269,10 @@ static void reply_ntcreate_and_X_send(struct request_context *req)
 /****************************************************************************
  Reply to an SMBntcreateX request
 ****************************************************************************/
-void reply_ntcreate_and_X(struct request_context *req)
+void reply_ntcreate_and_X(struct smbsrv_request *req)
 {
        union smb_open *io;
-       uint16 fname_len;
+       uint16_t fname_len;
 
        /* parse the request */
        REQ_CHECK_WCT(req, 24);
@@ -2264,6 +2292,8 @@ void reply_ntcreate_and_X(struct request_context *req)
        io->ntcreatex.in.create_options =   IVAL(req->in.vwv, 39);
        io->ntcreatex.in.impersonation =    IVAL(req->in.vwv, 43);
        io->ntcreatex.in.security_flags =   CVAL(req->in.vwv, 47);
+       io->ntcreatex.in.ea_list          = NULL;
+       io->ntcreatex.in.sec_desc         = NULL;
 
        /* we need a neater way to handle this alignment */
        if ((req->flags2 & FLAGS2_UNICODE_STRINGS) && 
@@ -2277,11 +2307,12 @@ void reply_ntcreate_and_X(struct request_context *req)
                return;
        }
 
-       req->async.send_fn = reply_ntcreate_and_X_send;
-       req->async.private = io;
+       req->async_states->state |= NTVFS_ASYNC_STATE_MAY_ASYNC;
+       req->async_states->send_fn = reply_ntcreate_and_X_send;
+       req->async_states->private_data = io;
 
        /* call the backend */
-       req->async.status = req->conn->ntvfs_ops->open(req, io);
+       req->async_states->status = ntvfs_openfile(req, io);
 
        REQ_ASYNC_TAIL;
 }
@@ -2290,15 +2321,18 @@ void reply_ntcreate_and_X(struct request_context *req)
 /****************************************************************************
  Reply to an SMBntcancel request
 ****************************************************************************/
-void reply_ntcancel(struct request_context *req)
+void reply_ntcancel(struct smbsrv_request *req)
 {
-       req_reply_error(req, NT_STATUS_FOOBAR);
+       /* NOTE: this request does not generate a reply */
+       req_signing_no_reply(req);
+       ntvfs_cancel(req);
+       req_destroy(req);
 }
 
 /****************************************************************************
  Reply to an SMBsends request
 ****************************************************************************/
-void reply_sends(struct request_context *req)
+void reply_sends(struct smbsrv_request *req)
 {
        req_reply_error(req, NT_STATUS_FOOBAR);
 }
@@ -2306,7 +2340,7 @@ void reply_sends(struct request_context *req)
 /****************************************************************************
  Reply to an SMBsendstrt request
 ****************************************************************************/
-void reply_sendstrt(struct request_context *req)
+void reply_sendstrt(struct smbsrv_request *req)
 {
        req_reply_error(req, NT_STATUS_FOOBAR);
 }
@@ -2314,7 +2348,7 @@ void reply_sendstrt(struct request_context *req)
 /****************************************************************************
  Reply to an SMBsendend request
 ****************************************************************************/
-void reply_sendend(struct request_context *req)
+void reply_sendend(struct smbsrv_request *req)
 {
        req_reply_error(req, NT_STATUS_FOOBAR);
 }
@@ -2322,7 +2356,7 @@ void reply_sendend(struct request_context *req)
 /****************************************************************************
  Reply to an SMBsendtxt request
 ****************************************************************************/
-void reply_sendtxt(struct request_context *req)
+void reply_sendtxt(struct smbsrv_request *req)
 {
        req_reply_error(req, NT_STATUS_FOOBAR);
 }
@@ -2332,10 +2366,10 @@ void reply_sendtxt(struct request_context *req)
 /****************************************************************************
  Reply to a special message - a SMB packet with non zero NBT message type
 ****************************************************************************/
-void reply_special(struct request_context *req)
+void reply_special(struct smbsrv_request *req)
 {
-       uint8 msg_type;
-       char buf[4];
+       uint8_t msg_type;
+       uint8_t *buf = talloc_zero_array_p(req, uint8_t, 4);
        
        msg_type = CVAL(req->in.buffer,0);
 
@@ -2343,20 +2377,21 @@ void reply_special(struct request_context *req)
        
        switch (msg_type) {
        case 0x81: /* session request */
-               if (req->smb->negotiate.done_nbt_session) {
-                       exit_server(req->smb, "multiple session request not permitted");
+               if (req->smb_conn->negotiate.done_nbt_session) {
+                       smbsrv_terminate_connection(req->smb_conn, "multiple session request not permitted");
                }
                
                SCVAL(buf,0,0x82);
                SCVAL(buf,3,0);
                
                DEBUG(0,("REWRITE: not parsing netbios names in NBT session request!\n"));
-               
-               req->smb->negotiate.done_nbt_session = True;
+               /* TODO: store the name for the session setup 'remote machine' code, as well as smbstatus */
+
+               req->smb_conn->negotiate.done_nbt_session = True;
                
                req->out.buffer = buf;
                req->out.size = 4;
-               req_send_reply(req);
+               req_send_reply_nosign(req);
                return;
                
        case 0x89: /* session keepalive request 
@@ -2365,7 +2400,7 @@ void reply_special(struct request_context *req)
                SCVAL(buf, 3, 0);
                req->out.buffer = buf;
                req->out.size = 4;
-               req_send_reply(req);
+               req_send_reply_nosign(req);
                return;
                
        case SMBkeepalive: