r3054: use talloc_zero_array_p() in a couple of places
[bbaumbach/samba-autobuild/.git] / source4 / smb_server / trans2.c
index e416b63bd401b54d6ba643ef9cf3a4dbab84449a..ed58791fbeabc56bb2f983a54cddd85f18327302 100644 (file)
 /* grow the data allocation size of a trans2 reply - this guarantees
    that requests to grow the data size later will not change the
    pointer */
-static void trans2_grow_data_allocation(struct request_context *req, 
+static void trans2_grow_data_allocation(struct smbsrv_request *req, 
                                        struct smb_trans2 *trans,
                                        uint16_t new_size)
 {
        if (new_size <= trans->out.data.length) {
                return;
        }
-       trans->out.data.data = talloc_realloc(req->mem_ctx, trans->out.data.data, new_size);
+       trans->out.data.data = talloc_realloc(req, trans->out.data.data, new_size);
 }
 
 
 /* grow the data size of a trans2 reply */
-static void trans2_grow_data(struct request_context *req, 
+static void trans2_grow_data(struct smbsrv_request *req, 
                             struct smb_trans2 *trans,
                             uint16_t new_size)
 {
@@ -53,7 +53,7 @@ static void trans2_grow_data(struct request_context *req,
 }
 
 /* grow the data, zero filling any new bytes */
-static void trans2_grow_data_fill(struct request_context *req, 
+static void trans2_grow_data_fill(struct smbsrv_request *req, 
                                  struct smb_trans2 *trans,
                                  uint16_t new_size)
 {
@@ -66,24 +66,24 @@ static void trans2_grow_data_fill(struct request_context *req,
 
 
 /* setup a trans2 reply, given the data and params sizes */
-static void trans2_setup_reply(struct request_context *req, 
+static void trans2_setup_reply(struct smbsrv_request *req, 
                               struct smb_trans2 *trans,
                               uint16_t param_size, uint16_t data_size,
                               uint16_t setup_count)
 {
        trans->out.setup_count = setup_count;
        if (setup_count != 0) {
-               trans->out.setup = talloc_zero(req->mem_ctx, sizeof(uint16_t) * setup_count);
+               trans->out.setup = talloc_zero_array_p(req, uint16_t, setup_count);
        }
-       trans->out.params = data_blob_talloc(req->mem_ctx, NULL, param_size);
-       trans->out.data = data_blob_talloc(req->mem_ctx, NULL, data_size);
+       trans->out.params = data_blob_talloc(req, NULL, param_size);
+       trans->out.data = data_blob_talloc(req, NULL, data_size);
 }
 
 
 /*
   pull a string from a blob in a trans2 request
 */
-static size_t trans2_pull_blob_string(struct request_context *req, 
+static size_t trans2_pull_blob_string(struct smbsrv_request *req, 
                                      const DATA_BLOB *blob,
                                      uint16_t offset,
                                      const char **str,
@@ -107,7 +107,7 @@ static size_t trans2_pull_blob_string(struct request_context *req,
   push a string into the data section of a trans2 request
   return the number of bytes consumed in the output
 */
-static size_t trans2_push_data_string(struct request_context *req, 
+static size_t trans2_push_data_string(struct smbsrv_request *req, 
                                      struct smb_trans2 *trans,
                                      uint16_t len_offset,
                                      uint16_t offset,
@@ -143,10 +143,10 @@ static size_t trans2_push_data_string(struct request_context *req,
                alignment = 1;
                if (dest_len > 0) {
                        SCVAL(trans->out.data.data + offset, 0, 0);
-                       ret = push_string(NULL, trans->out.data.data + offset + 1, str->s, dest_len-1, flags);
+                       ret = push_string(trans->out.data.data + offset + 1, str->s, dest_len-1, flags);
                }
        } else {
-               ret = push_string(NULL, trans->out.data.data + offset, str->s, dest_len, flags);
+               ret = push_string(trans->out.data.data + offset, str->s, dest_len, flags);
        }
 
        /* sometimes the string needs to be terminated, but the length
@@ -176,7 +176,7 @@ static size_t trans2_push_data_string(struct request_context *req,
   len_offset points to the place in the packet where the length field
   should go
 */
-static void trans2_append_data_string(struct request_context *req, 
+static void trans2_append_data_string(struct smbsrv_request *req, 
                                        struct smb_trans2 *trans,
                                        const WIRE_STRING *str,
                                        uint_t len_offset,
@@ -192,11 +192,23 @@ static void trans2_append_data_string(struct request_context *req,
        trans2_grow_data(req, trans, offset + ret);
 }
 
+/*
+  align the end of the data section of a trans reply on an even boundary
+*/
+static void trans2_align_data(struct smbsrv_request *req, struct smb_trans2 *trans)
+{
+       if ((trans->out.data.length & 1) == 0) {
+               return;
+       }
+       trans2_grow_data(req, trans, trans->out.data.length+1);
+       SCVAL(trans->out.data.data, trans->out.data.length-1, 0);
+}
+
 
 /*
   trans2 qfsinfo implementation
 */
-static NTSTATUS trans2_qfsinfo(struct request_context *req, struct smb_trans2 *trans)
+static NTSTATUS trans2_qfsinfo(struct smbsrv_request *req, struct smb_trans2 *trans)
 {
        union smb_fsinfo fsinfo;
        NTSTATUS status;
@@ -215,7 +227,7 @@ static NTSTATUS trans2_qfsinfo(struct request_context *req, struct smb_trans2 *t
        case SMB_QFS_ALLOCATION:
                fsinfo.allocation.level = RAW_QFS_ALLOCATION;
 
-               status = req->conn->ntvfs_ops->fsinfo(req, &fsinfo);
+               status = ntvfs_fsinfo(req, &fsinfo);
                if (!NT_STATUS_IS_OK(status)) {
                        return status;
                }
@@ -233,7 +245,7 @@ static NTSTATUS trans2_qfsinfo(struct request_context *req, struct smb_trans2 *t
        case SMB_QFS_VOLUME:
                fsinfo.volume.level = RAW_QFS_VOLUME;
 
-               status = req->conn->ntvfs_ops->fsinfo(req, &fsinfo);
+               status = ntvfs_fsinfo(req, &fsinfo);
                if (!NT_STATUS_IS_OK(status)) {
                        return status;
                }
@@ -253,7 +265,7 @@ static NTSTATUS trans2_qfsinfo(struct request_context *req, struct smb_trans2 *t
        case SMB_QFS_VOLUME_INFORMATION:
                fsinfo.volume_info.level = RAW_QFS_VOLUME_INFO;
 
-               status = req->conn->ntvfs_ops->fsinfo(req, &fsinfo);
+               status = ntvfs_fsinfo(req, &fsinfo);
                if (!NT_STATUS_IS_OK(status)) {
                        return status;
                }
@@ -262,6 +274,7 @@ static NTSTATUS trans2_qfsinfo(struct request_context *req, struct smb_trans2 *t
 
                push_nttime(trans->out.data.data, 0, fsinfo.volume_info.out.create_time);
                SIVAL(trans->out.data.data,       8, fsinfo.volume_info.out.serial_number);
+               SSVAL(trans->out.data.data,      16, 0); /* padding */
                trans2_append_data_string(req, trans, 
                                          &fsinfo.volume_info.out.volume_name, 
                                          12, STR_UNICODE);
@@ -272,7 +285,7 @@ static NTSTATUS trans2_qfsinfo(struct request_context *req, struct smb_trans2 *t
        case SMB_QFS_SIZE_INFORMATION:
                fsinfo.size_info.level = RAW_QFS_SIZE_INFO;
 
-               status = req->conn->ntvfs_ops->fsinfo(req, &fsinfo);
+               status = ntvfs_fsinfo(req, &fsinfo);
                if (!NT_STATUS_IS_OK(status)) {
                        return status;
                }
@@ -290,7 +303,7 @@ static NTSTATUS trans2_qfsinfo(struct request_context *req, struct smb_trans2 *t
        case SMB_QFS_DEVICE_INFORMATION:
                fsinfo.device_info.level = RAW_QFS_DEVICE_INFO;
 
-               status = req->conn->ntvfs_ops->fsinfo(req, &fsinfo);
+               status = ntvfs_fsinfo(req, &fsinfo);
                if (!NT_STATUS_IS_OK(status)) {
                        return status;
                }
@@ -304,7 +317,7 @@ static NTSTATUS trans2_qfsinfo(struct request_context *req, struct smb_trans2 *t
        case SMB_QFS_ATTRIBUTE_INFORMATION:
                fsinfo.attribute_info.level = RAW_QFS_ATTRIBUTE_INFO;
 
-               status = req->conn->ntvfs_ops->fsinfo(req, &fsinfo);
+               status = ntvfs_fsinfo(req, &fsinfo);
                if (!NT_STATUS_IS_OK(status)) {
                        return status;
                }
@@ -325,7 +338,7 @@ static NTSTATUS trans2_qfsinfo(struct request_context *req, struct smb_trans2 *t
        case SMB_QFS_QUOTA_INFORMATION:
                fsinfo.quota_information.level = RAW_QFS_QUOTA_INFORMATION;
 
-               status = req->conn->ntvfs_ops->fsinfo(req, &fsinfo);
+               status = ntvfs_fsinfo(req, &fsinfo);
                if (!NT_STATUS_IS_OK(status)) {
                        return status;
                }
@@ -345,7 +358,7 @@ static NTSTATUS trans2_qfsinfo(struct request_context *req, struct smb_trans2 *t
        case SMB_QFS_FULL_SIZE_INFORMATION:
                fsinfo.full_size_information.level = RAW_QFS_FULL_SIZE_INFORMATION;
 
-               status = req->conn->ntvfs_ops->fsinfo(req, &fsinfo);
+               status = ntvfs_fsinfo(req, &fsinfo);
                if (!NT_STATUS_IS_OK(status)) {
                        return status;
                }
@@ -363,14 +376,14 @@ static NTSTATUS trans2_qfsinfo(struct request_context *req, struct smb_trans2 *t
        case SMB_QFS_OBJECTID_INFORMATION:
                fsinfo.objectid_information.level = RAW_QFS_OBJECTID_INFORMATION;
 
-               status = req->conn->ntvfs_ops->fsinfo(req, &fsinfo);
+               status = ntvfs_fsinfo(req, &fsinfo);
                if (!NT_STATUS_IS_OK(status)) {
                        return status;
                }
 
                trans2_setup_reply(req, trans, 0, 64, 0);
 
-               status = ndr_push_struct_blob(&guid_blob, req->mem_ctx
+               status = ndr_push_struct_blob(&guid_blob, req, 
                                              &fsinfo.objectid_information.out.guid,
                                              (ndr_push_flags_fn_t)ndr_push_GUID);
                if (!NT_STATUS_IS_OK(status)) {
@@ -391,7 +404,7 @@ static NTSTATUS trans2_qfsinfo(struct request_context *req, struct smb_trans2 *t
 /*
   fill in the reply from a qpathinfo or qfileinfo call
 */
-static NTSTATUS trans2_fileinfo_fill(struct request_context *req, struct smb_trans2 *trans,
+static NTSTATUS trans2_fileinfo_fill(struct smbsrv_request *req, struct smb_trans2 *trans,
                                     union smb_fileinfo *st)
 {
        uint_t i;
@@ -420,9 +433,9 @@ static NTSTATUS trans2_fileinfo_fill(struct request_context *req, struct smb_tra
                trans2_setup_reply(req, trans, 2, 22, 0);
 
                SSVAL(trans->out.params.data, 0, 0);
-               srv_push_dos_date2(req->smb, trans->out.data.data, 0, st->standard.out.create_time);
-               srv_push_dos_date2(req->smb, trans->out.data.data, 4, st->standard.out.access_time);
-               srv_push_dos_date2(req->smb, trans->out.data.data, 8, st->standard.out.write_time);
+               srv_push_dos_date2(req->smb_conn, trans->out.data.data, 0, st->standard.out.create_time);
+               srv_push_dos_date2(req->smb_conn, trans->out.data.data, 4, st->standard.out.access_time);
+               srv_push_dos_date2(req->smb_conn, trans->out.data.data, 8, st->standard.out.write_time);
                SIVAL(trans->out.data.data,        12, st->standard.out.size);
                SIVAL(trans->out.data.data,        16, st->standard.out.alloc_size);
                SSVAL(trans->out.data.data,        20, st->standard.out.attrib);
@@ -432,9 +445,9 @@ static NTSTATUS trans2_fileinfo_fill(struct request_context *req, struct smb_tra
                trans2_setup_reply(req, trans, 2, 26, 0);
 
                SSVAL(trans->out.params.data, 0, 0);
-               srv_push_dos_date2(req->smb, trans->out.data.data, 0, st->ea_size.out.create_time);
-               srv_push_dos_date2(req->smb, trans->out.data.data, 4, st->ea_size.out.access_time);
-               srv_push_dos_date2(req->smb, trans->out.data.data, 8, st->ea_size.out.write_time);
+               srv_push_dos_date2(req->smb_conn, trans->out.data.data, 0, st->ea_size.out.create_time);
+               srv_push_dos_date2(req->smb_conn, trans->out.data.data, 4, st->ea_size.out.access_time);
+               srv_push_dos_date2(req->smb_conn, trans->out.data.data, 8, st->ea_size.out.write_time);
                SIVAL(trans->out.data.data,        12, st->ea_size.out.size);
                SIVAL(trans->out.data.data,        16, st->ea_size.out.alloc_size);
                SSVAL(trans->out.data.data,        20, st->ea_size.out.attrib);
@@ -555,6 +568,7 @@ static NTSTATUS trans2_fileinfo_fill(struct request_context *req, struct smb_tra
                push_nttime(trans->out.data.data, 16, st->all_info.out.write_time);
                push_nttime(trans->out.data.data, 24, st->all_info.out.change_time);
                SIVAL(trans->out.data.data,       32, st->all_info.out.attrib);
+               SIVAL(trans->out.data.data,       36, 0);
                SBVAL(trans->out.data.data,       40, st->all_info.out.alloc_size);
                SBVAL(trans->out.data.data,       48, st->all_info.out.size);
                SIVAL(trans->out.data.data,       56, st->all_info.out.nlink);
@@ -614,14 +628,14 @@ static NTSTATUS trans2_fileinfo_fill(struct request_context *req, struct smb_tra
 /*
   trans2 qpathinfo implementation
 */
-static NTSTATUS trans2_qpathinfo(struct request_context *req, struct smb_trans2 *trans)
+static NTSTATUS trans2_qpathinfo(struct smbsrv_request *req, struct smb_trans2 *trans)
 {
        union smb_fileinfo st;
        NTSTATUS status;
        uint16_t level;
 
        /* make sure we got enough parameters */
-       if (trans->in.params.length < 8) {
+       if (trans->in.params.length < 2) {
                return NT_STATUS_FOOBAR;
        }
 
@@ -633,13 +647,13 @@ static NTSTATUS trans2_qpathinfo(struct request_context *req, struct smb_trans2
        }
 
        /* work out the backend level - we make it 1-1 in the header */
-       st.generic.level = (enum fileinfo_level)level;
+       st.generic.level = (enum smb_fileinfo_level)level;
        if (st.generic.level >= RAW_FILEINFO_GENERIC) {
                return NT_STATUS_INVALID_LEVEL;
        }
 
        /* call the backend */
-       status = req->conn->ntvfs_ops->qpathinfo(req, &st);
+       status = ntvfs_qpathinfo(req, &st);
        if (!NT_STATUS_IS_OK(status)) {
                return status;
        }
@@ -654,7 +668,7 @@ static NTSTATUS trans2_qpathinfo(struct request_context *req, struct smb_trans2
 /*
   trans2 qpathinfo implementation
 */
-static NTSTATUS trans2_qfileinfo(struct request_context *req, struct smb_trans2 *trans)
+static NTSTATUS trans2_qfileinfo(struct smbsrv_request *req, struct smb_trans2 *trans)
 {
        union smb_fileinfo st;
        NTSTATUS status;
@@ -669,13 +683,13 @@ static NTSTATUS trans2_qfileinfo(struct request_context *req, struct smb_trans2
        level = SVAL(trans->in.params.data, 2);
 
        /* work out the backend level - we make it 1-1 in the header */
-       st.generic.level = (enum fileinfo_level)level;
+       st.generic.level = (enum smb_fileinfo_level)level;
        if (st.generic.level >= RAW_FILEINFO_GENERIC) {
                return NT_STATUS_INVALID_LEVEL;
        }
 
        /* call the backend */
-       status = req->conn->ntvfs_ops->qfileinfo(req, &st);
+       status = ntvfs_qfileinfo(req, &st);
        if (!NT_STATUS_IS_OK(status)) {
                return status;
        }
@@ -690,7 +704,7 @@ static NTSTATUS trans2_qfileinfo(struct request_context *req, struct smb_trans2
 /*
   parse a trans2 setfileinfo/setpathinfo data blob
 */
-static NTSTATUS trans2_parse_sfileinfo(struct request_context *req,
+static NTSTATUS trans2_parse_sfileinfo(struct smbsrv_request *req,
                                       union smb_setfileinfo *st,
                                       const DATA_BLOB *blob)
 {
@@ -705,9 +719,9 @@ static NTSTATUS trans2_parse_sfileinfo(struct request_context *req,
 
        case RAW_SFILEINFO_STANDARD:
                CHECK_MIN_BLOB_SIZE(blob, 12);
-               st->standard.in.create_time = srv_pull_dos_date2(req->smb, blob->data + 0);
-               st->standard.in.access_time = srv_pull_dos_date2(req->smb, blob->data + 4);
-               st->standard.in.write_time  = srv_pull_dos_date2(req->smb, blob->data + 8);
+               st->standard.in.create_time = srv_pull_dos_date2(req->smb_conn, blob->data + 0);
+               st->standard.in.access_time = srv_pull_dos_date2(req->smb_conn, blob->data + 4);
+               st->standard.in.write_time  = srv_pull_dos_date2(req->smb_conn, blob->data + 8);
                return NT_STATUS_OK;
 
        case RAW_SFILEINFO_EA_SET:
@@ -720,7 +734,7 @@ static NTSTATUS trans2_parse_sfileinfo(struct request_context *req,
                        DATA_BLOB blob2;
                        blob2.data = blob->data+4;
                        blob2.length = len-4;
-                       len = ea_pull_struct(&blob2, req->mem_ctx, &st->ea_set.in.ea);
+                       len = ea_pull_struct(&blob2, req, &st->ea_set.in.ea);
                }
                if (len == 0) {
                        return NT_STATUS_INVALID_PARAMETER;
@@ -786,7 +800,7 @@ static NTSTATUS trans2_parse_sfileinfo(struct request_context *req,
 /*
   trans2 setfileinfo implementation
 */
-static NTSTATUS trans2_setfileinfo(struct request_context *req, struct smb_trans2 *trans)
+static NTSTATUS trans2_setfileinfo(struct smbsrv_request *req, struct smb_trans2 *trans)
 {
        union smb_setfileinfo st;
        NTSTATUS status;
@@ -804,14 +818,14 @@ static NTSTATUS trans2_setfileinfo(struct request_context *req, struct smb_trans
        blob = &trans->in.data;
 
        st.generic.file.fnum = fnum;
-       st.generic.level = (enum setfileinfo_level)level;
+       st.generic.level = (enum smb_setfileinfo_level)level;
 
        status = trans2_parse_sfileinfo(req, &st, blob);
        if (!NT_STATUS_IS_OK(status)) {
                return status;
        }
 
-       status = req->conn->ntvfs_ops->setfileinfo(req, &st);
+       status = ntvfs_setfileinfo(req, &st);
        if (!NT_STATUS_IS_OK(status)) {
                return status;
        }
@@ -824,7 +838,7 @@ static NTSTATUS trans2_setfileinfo(struct request_context *req, struct smb_trans
 /*
   trans2 setpathinfo implementation
 */
-static NTSTATUS trans2_setpathinfo(struct request_context *req, struct smb_trans2 *trans)
+static NTSTATUS trans2_setpathinfo(struct smbsrv_request *req, struct smb_trans2 *trans)
 {
        union smb_setfileinfo st;
        NTSTATUS status;
@@ -838,9 +852,9 @@ static NTSTATUS trans2_setpathinfo(struct request_context *req, struct smb_trans
 
        level = SVAL(trans->in.params.data, 0);
        blob = &trans->in.data;
-       st.generic.level = (enum setfileinfo_level)level;
+       st.generic.level = (enum smb_setfileinfo_level)level;
 
-       trans2_pull_blob_string(req, &trans->in.params, 4, &st.generic.file.fname, 0);
+       trans2_pull_blob_string(req, &trans->in.params, 6, &st.generic.file.fname, 0);
        if (st.generic.file.fname == NULL) {
                return NT_STATUS_FOOBAR;
        }
@@ -850,7 +864,7 @@ static NTSTATUS trans2_setpathinfo(struct request_context *req, struct smb_trans
                return status;
        }
 
-       status = req->conn->ntvfs_ops->setpathinfo(req, &st);
+       status = ntvfs_setpathinfo(req, &st);
        if (!NT_STATUS_IS_OK(status)) {
                return status;
        }
@@ -863,9 +877,9 @@ static NTSTATUS trans2_setpathinfo(struct request_context *req, struct smb_trans
 
 /* a structure to encapsulate the state information about an in-progress ffirst/fnext operation */
 struct find_state {
-       struct request_context *req;
+       struct smbsrv_request *req;
        struct smb_trans2 *trans;
-       enum search_level level;
+       enum smb_search_level level;
        uint16_t last_entry_offset;
        uint16_t flags;
 };
@@ -873,7 +887,7 @@ struct find_state {
 /*
   fill a single entry in a trans2 find reply 
 */
-static void find_fill_info(struct request_context *req,
+static void find_fill_info(struct smbsrv_request *req,
                           struct smb_trans2 *trans, 
                           struct find_state *state,
                           union smb_search_data *file)
@@ -883,6 +897,8 @@ static void find_fill_info(struct request_context *req,
 
        switch (state->level) {
        case RAW_SEARCH_SEARCH:
+       case RAW_SEARCH_FFIRST:
+       case RAW_SEARCH_FUNIQUE:
        case RAW_SEARCH_GENERIC:
                /* handled elsewhere */
                break;
@@ -896,9 +912,9 @@ static void find_fill_info(struct request_context *req,
                        trans2_grow_data(req, trans, ofs + 23);
                }
                data = trans->out.data.data + ofs;
-               srv_push_dos_date2(req->smb, data, 0, file->standard.create_time);
-               srv_push_dos_date2(req->smb, data, 4, file->standard.access_time);
-               srv_push_dos_date2(req->smb, data, 8, file->standard.write_time);
+               srv_push_dos_date2(req->smb_conn, data, 0, file->standard.create_time);
+               srv_push_dos_date2(req->smb_conn, data, 4, file->standard.access_time);
+               srv_push_dos_date2(req->smb_conn, data, 8, file->standard.write_time);
                SIVAL(data, 12, file->standard.size);
                SIVAL(data, 16, file->standard.alloc_size);
                SSVAL(data, 20, file->standard.attrib);
@@ -915,15 +931,17 @@ static void find_fill_info(struct request_context *req,
                        trans2_grow_data(req, trans, ofs + 27);
                }
                data = trans->out.data.data + ofs;
-               srv_push_dos_date2(req->smb, data, 0, file->ea_size.create_time);
-               srv_push_dos_date2(req->smb, data, 4, file->ea_size.access_time);
-               srv_push_dos_date2(req->smb, data, 8, file->ea_size.write_time);
+               srv_push_dos_date2(req->smb_conn, data, 0, file->ea_size.create_time);
+               srv_push_dos_date2(req->smb_conn, data, 4, file->ea_size.access_time);
+               srv_push_dos_date2(req->smb_conn, data, 8, file->ea_size.write_time);
                SIVAL(data, 12, file->ea_size.size);
                SIVAL(data, 16, file->ea_size.alloc_size);
                SSVAL(data, 20, file->ea_size.attrib);
                SIVAL(data, 22, file->ea_size.ea_size);
                trans2_append_data_string(req, trans, &file->ea_size.name, 
-                                         ofs + 26, STR_LEN8BIT | STR_TERMINATE | STR_NOALIGN);
+                                         ofs + 26, STR_LEN8BIT | STR_NOALIGN);
+               trans2_grow_data(req, trans, trans->out.data.length + 1);
+               trans->out.data.data[trans->out.data.length-1] = 0;
                break;
 
        case RAW_SEARCH_DIRECTORY_INFO:
@@ -991,6 +1009,7 @@ static void find_fill_info(struct request_context *req,
                                        24, STR_UNICODE | STR_LEN8BIT);
                trans2_append_data_string(req, trans, &file->both_directory_info.name, 
                                          ofs + 60, STR_TERMINATE_ASCII);
+               trans2_align_data(req, trans);
                data = trans->out.data.data + ofs;
                SIVAL(data,          0, trans->out.data.length - ofs);
                break;
@@ -1028,13 +1047,12 @@ static void find_fill_info(struct request_context *req,
                SIVAL(data,         56, file->id_both_directory_info.attrib);
                SIVAL(data,         64, file->id_both_directory_info.ea_size);
                SCVAL(data,         69, 0); /* reserved */
-               memset(data+70,0,24);
+               memset(data+70,0,26);
                trans2_push_data_string(req, trans, 
                                        68 + ofs, 70 + ofs, 
                                        &file->id_both_directory_info.short_name, 
                                        24, STR_UNICODE | STR_LEN8BIT);
-               SBVAL(data,         94, file->id_both_directory_info.file_id);
-               SSVAL(data,        102, 0); /* reserved? */
+               SBVAL(data,         96, file->id_both_directory_info.file_id);
                trans2_append_data_string(req, trans, &file->id_both_directory_info.name, 
                                          ofs + 60, STR_TERMINATE_ASCII);
                data = trans->out.data.data + ofs;
@@ -1069,7 +1087,7 @@ static BOOL find_callback(void *private, union smb_search_data *file)
 /*
   trans2 findfirst implementation
 */
-static NTSTATUS trans2_findfirst(struct request_context *req, struct smb_trans2 *trans)
+static NTSTATUS trans2_findfirst(struct smbsrv_request *req, struct smb_trans2 *trans)
 {
        union smb_search_first search;
        NTSTATUS status;
@@ -1093,7 +1111,7 @@ static NTSTATUS trans2_findfirst(struct request_context *req, struct smb_trans2
                return NT_STATUS_FOOBAR;
        }
 
-       search.t2ffirst.level = (enum search_level)level;
+       search.t2ffirst.level = (enum smb_search_level)level;
        if (search.t2ffirst.level >= RAW_SEARCH_GENERIC) {
                return NT_STATUS_INVALID_LEVEL;
        }
@@ -1109,8 +1127,9 @@ static NTSTATUS trans2_findfirst(struct request_context *req, struct smb_trans2
        trans2_setup_reply(req, trans, 10, 0, 0);
 
        /* call the backend */
-       status = req->conn->ntvfs_ops->search_first(req, &search, &state, find_callback);
+       status = ntvfs_search_first(req, &search, &state, find_callback);
        if (!NT_STATUS_IS_OK(status)) {
+               trans2_setup_reply(req, trans, 0, 0, 0);
                return status;
        }
 
@@ -1121,7 +1140,7 @@ static NTSTATUS trans2_findfirst(struct request_context *req, struct smb_trans2
        SSVAL(param, VWV(2), search.t2ffirst.out.end_of_search);
        SSVAL(param, VWV(3), 0);
        SSVAL(param, VWV(4), state.last_entry_offset);
-       
+
        return NT_STATUS_OK;
 }
 
@@ -1129,7 +1148,7 @@ static NTSTATUS trans2_findfirst(struct request_context *req, struct smb_trans2
 /*
   trans2 findnext implementation
 */
-static NTSTATUS trans2_findnext(struct request_context *req, struct smb_trans2 *trans)
+static NTSTATUS trans2_findnext(struct smbsrv_request *req, struct smb_trans2 *trans)
 {
        union smb_search_next search;
        NTSTATUS status;
@@ -1153,7 +1172,7 @@ static NTSTATUS trans2_findnext(struct request_context *req, struct smb_trans2 *
                return NT_STATUS_FOOBAR;
        }
 
-       search.t2fnext.level = (enum search_level)level;
+       search.t2fnext.level = (enum smb_search_level)level;
        if (search.t2fnext.level >= RAW_SEARCH_GENERIC) {
                return NT_STATUS_INVALID_LEVEL;
        }
@@ -1169,7 +1188,7 @@ static NTSTATUS trans2_findnext(struct request_context *req, struct smb_trans2 *
        trans2_setup_reply(req, trans, 8, 0, 0);
 
        /* call the backend */
-       status = req->conn->ntvfs_ops->search_next(req, &search, &state, find_callback);
+       status = ntvfs_search_next(req, &search, &state, find_callback);
        if (!NT_STATUS_IS_OK(status)) {
                return status;
        }
@@ -1188,11 +1207,14 @@ static NTSTATUS trans2_findnext(struct request_context *req, struct smb_trans2 *
 /*
   backend for trans2 requests
 */
-static NTSTATUS trans2_backend(struct request_context *req, struct smb_trans2 *trans)
+static NTSTATUS trans2_backend(struct smbsrv_request *req, struct smb_trans2 *trans)
 {
-       if (req->conn->ntvfs_ops->trans2 != NULL) {
-               /* direct trans2 pass thru */
-               return req->conn->ntvfs_ops->trans2(req, trans);
+       NTSTATUS status;
+
+       /* direct trans2 pass thru */
+       status = ntvfs_trans2(req, trans);
+       if (!NT_STATUS_EQUAL(NT_STATUS_NOT_IMPLEMENTED, status)) {
+               return status;
        }
 
        /* must have at least one setup word */
@@ -1222,23 +1244,10 @@ static NTSTATUS trans2_backend(struct request_context *req, struct smb_trans2 *t
        return NT_STATUS_FOOBAR;
 }
 
-
-/*
-  backend for trans requests
-*/
-static NTSTATUS trans_backend(struct request_context *req, struct smb_trans2 *trans)
-{
-       if (!req->conn->ntvfs_ops->trans) {
-               return NT_STATUS_NOT_IMPLEMENTED;
-       }
-       return req->conn->ntvfs_ops->trans(req, trans);
-}
-
-
 /****************************************************************************
  Reply to an SMBtrans or SMBtrans2 request
 ****************************************************************************/
-void reply_trans_generic(struct request_context *req, uint8 command)
+void reply_trans_generic(struct smbsrv_request *req, uint8_t command)
 {
        struct smb_trans2 trans;
        int i;
@@ -1274,8 +1283,8 @@ void reply_trans_generic(struct request_context *req, uint8 command)
        }
 
        /* parse out the setup words */
-       trans.in.setup = talloc(req->mem_ctx, trans.in.setup_count * sizeof(uint16_t));
-       if (!trans.in.setup) {
+       trans.in.setup = talloc(req, trans.in.setup_count * sizeof(uint16_t));
+       if (trans.in.setup_count && !trans.in.setup) {
                req_reply_error(req, NT_STATUS_NO_MEMORY);
                return;
        }
@@ -1302,12 +1311,12 @@ void reply_trans_generic(struct request_context *req, uint8 command)
 
        /* its a full request, give it to the backend */
        if (command == SMBtrans) {
-               status = trans_backend(req, &trans);
+               status = ntvfs_trans(req, &trans);
        } else {
                status = trans2_backend(req, &trans);
        }
 
-       if (!NT_STATUS_IS_OK(status)) {
+       if (NT_STATUS_IS_ERR(status)) {
                req_reply_error(req, status);
                return;
        }
@@ -1317,8 +1326,6 @@ void reply_trans_generic(struct request_context *req, uint8 command)
        params      = trans.out.params.data;
        data        = trans.out.data.data;
 
-       req->control_flags |= REQ_CONTROL_PROTECTED;
-
        /* we need to divide up the reply into chunks that fit into
           the negotiated buffer size */
        do {
@@ -1326,6 +1333,10 @@ void reply_trans_generic(struct request_context *req, uint8 command)
                uint_t align1 = 1, align2 = (params_left ? 2 : 0);
 
                req_setup_reply(req, 10 + trans.out.setup_count, 0);
+
+               if (!NT_STATUS_IS_OK(status)) {
+                       req_setup_error(req, status);
+               }
        
                max_bytes = req_max_data(req) - (align1 + align2);
 
@@ -1374,9 +1385,9 @@ void reply_trans_generic(struct request_context *req, uint8 command)
                params += this_param;
                data += this_data;
 
-               /* if this is the last chunk then the request can be destroyed */
-               if (params_left == 0 && data_left == 0) {
-                       req->control_flags &= ~REQ_CONTROL_PROTECTED;
+               /* don't destroy unless this is the last chunk */
+               if (params_left != 0 || data_left != 0) {
+                       talloc_increase_ref_count(req);
                }
 
                req_send_reply(req);
@@ -1387,7 +1398,7 @@ void reply_trans_generic(struct request_context *req, uint8 command)
 /****************************************************************************
  Reply to an SMBtrans2
 ****************************************************************************/
-void reply_trans2(struct request_context *req)
+void reply_trans2(struct smbsrv_request *req)
 {
        reply_trans_generic(req, SMBtrans2);
 }
@@ -1395,7 +1406,7 @@ void reply_trans2(struct request_context *req)
 /****************************************************************************
  Reply to an SMBtrans
 ****************************************************************************/
-void reply_trans(struct request_context *req)
+void reply_trans(struct smbsrv_request *req)
 {
        reply_trans_generic(req, SMBtrans);
 }
@@ -1403,7 +1414,7 @@ void reply_trans(struct request_context *req)
 /****************************************************************************
  Reply to an SMBtranss2 request
 ****************************************************************************/
-void reply_transs2(struct request_context *req)
+void reply_transs2(struct smbsrv_request *req)
 {
        req_reply_error(req, NT_STATUS_FOOBAR);
 }