Change uint_t to unsigned int in source4
[garming/samba-autobuild/.git] / source4 / smb_server / smb / trans2.c
index ecc516527423165a00c5c03bc6174cf374ec3794..36dc3175e8d25c56b7fd40c1dbf1836a6d8d4c4c 100644 (file)
@@ -5,7 +5,7 @@
 
    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
-   the Free Software Foundation; either version 2 of the License, or
+   the Free Software Foundation; either version 3 of the License, or
    (at your option) any later version.
    
    This program is distributed in the hope that it will be useful,
    GNU General Public License for more details.
    
    You should have received a copy of the GNU General Public License
-   along with this program; if not, write to the Free Software
-   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
 /*
    This file handles the parsing of transact2 requests
 */
 
 #include "includes.h"
-#include "dlinklist.h"
 #include "smb_server/smb_server.h"
-#include "librpc/gen_ndr/ndr_misc.h"
 #include "ntvfs/ntvfs.h"
 #include "libcli/raw/libcliraw.h"
+#include "libcli/raw/raw_proto.h"
 
 #define TRANS2_CHECK_ASYNC_STATUS_SIMPLE do { \
        if (!NT_STATUS_IS_OK(req->ntvfs->async_states->status)) { \
@@ -61,37 +59,10 @@ struct trans_op {
                return NT_STATUS_INFO_LENGTH_MISMATCH; \
        }} while (0)
 
-/* grow the data size of a trans2 reply */
-static NTSTATUS trans2_grow_data(TALLOC_CTX *mem_ctx,
-                                DATA_BLOB *blob,
-                                uint32_t new_size)
-{
-       if (new_size > blob->length) {
-               blob->data = talloc_realloc(mem_ctx, blob->data, uint8_t, new_size);
-               NT_STATUS_HAVE_NO_MEMORY(blob->data);
-       }
-       blob->length = new_size;
-       return NT_STATUS_OK;
-}
-
-/* grow the data, zero filling any new bytes */
-static NTSTATUS trans2_grow_data_fill(TALLOC_CTX *mem_ctx,
-                                     DATA_BLOB *blob,
-                                     uint32_t new_size)
-{
-       uint32_t old_size = blob->length;
-       TRANS2_CHECK(trans2_grow_data(mem_ctx, blob, new_size));
-       if (new_size > old_size) {
-               memset(blob->data + old_size, 0, new_size - old_size);
-       }
-       return NT_STATUS_OK;
-}
-
-
 /* setup a trans2 reply, given the data and params sizes */
 static NTSTATUS trans2_setup_reply(struct smb_trans2 *trans,
                                   uint16_t param_size, uint16_t data_size,
-                                  uint16_t setup_count)
+                                  uint8_t setup_count)
 {
        trans->out.setup_count = setup_count;
        if (setup_count > 0) {
@@ -107,147 +78,17 @@ static NTSTATUS trans2_setup_reply(struct smb_trans2 *trans,
        return NT_STATUS_OK;
 }
 
-
-/*
-  pull a string from a blob in a trans2 request
-*/
-static size_t trans2_pull_blob_string(struct smbsrv_request *req, 
-                                     const DATA_BLOB *blob,
-                                     uint16_t offset,
-                                     const char **str,
-                                     int flags)
-{
-       /* we use STR_NO_RANGE_CHECK because the params are allocated
-          separately in a DATA_BLOB, so we need to do our own range
-          checking */
-       if (offset >= blob->length) {
-               *str = NULL;
-               return 0;
-       }
-       
-       return req_pull_string(req, str, 
-                              blob->data + offset, 
-                              blob->length - offset,
-                              STR_NO_RANGE_CHECK | flags);
-}
-
-/*
-  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 smbsrv_request *req,
-                                     TALLOC_CTX *mem_ctx,
-                                     DATA_BLOB *blob,
-                                     uint32_t len_offset,
-                                     uint32_t offset,
-                                     const struct smb_wire_string *str,
-                                     int dest_len,
-                                     int flags)
-{
-       int alignment = 0, ret = 0, pkt_len;
-
-       /* we use STR_NO_RANGE_CHECK because the params are allocated
-          separately in a DATA_BLOB, so we need to do our own range
-          checking */
-       if (!str->s || offset >= blob->length) {
-               if (flags & STR_LEN8BIT) {
-                       SCVAL(blob->data, len_offset, 0);
-               } else {
-                       SIVAL(blob->data, len_offset, 0);
-               }
-               return 0;
-       }
-
-       flags |= STR_NO_RANGE_CHECK;
-
-       if (dest_len == -1 || (dest_len > blob->length - offset)) {
-               dest_len = blob->length - offset;
-       }
-
-       if (!(flags & (STR_ASCII|STR_UNICODE))) {
-               flags |= (req->flags2 & FLAGS2_UNICODE_STRINGS) ? STR_UNICODE : STR_ASCII;
-       }
-
-       if ((offset&1) && (flags & STR_UNICODE) && !(flags & STR_NOALIGN)) {
-               alignment = 1;
-               if (dest_len > 0) {
-                       SCVAL(blob->data + offset, 0, 0);
-                       ret = push_string(blob->data + offset + 1, str->s, dest_len-1, flags);
-               }
-       } else {
-               ret = push_string(blob->data + offset, str->s, dest_len, flags);
-       }
-
-       /* sometimes the string needs to be terminated, but the length
-          on the wire must not include the termination! */
-       pkt_len = ret;
-
-       if ((flags & STR_LEN_NOTERM) && (flags & STR_TERMINATE)) {
-               if ((flags & STR_UNICODE) && ret >= 2) {
-                       pkt_len = ret-2;
-               }
-               if ((flags & STR_ASCII) && ret >= 1) {
-                       pkt_len = ret-1;
-               }
-       }
-
-       if (flags & STR_LEN8BIT) {
-               SCVAL(blob->data, len_offset, pkt_len);
-       } else {
-               SIVAL(blob->data, len_offset, pkt_len);
-       }
-
-       return ret + alignment;
-}
-
-/*
-  append a string to the data section of a trans2 reply
-  len_offset points to the place in the packet where the length field
-  should go
-*/
-static NTSTATUS trans2_append_data_string(struct smbsrv_request *req, 
-                                         TALLOC_CTX *mem_ctx,
-                                         DATA_BLOB *blob,
-                                         const struct smb_wire_string *str,
-                                         uint_t len_offset,
-                                         int flags)
-{
-       size_t ret;
-       uint32_t offset;
-       const int max_bytes_per_char = 3;
-
-       offset = blob->length;
-       TRANS2_CHECK(trans2_grow_data(mem_ctx, blob, offset + (2+strlen_m(str->s))*max_bytes_per_char));
-       ret = trans2_push_data_string(req, mem_ctx, blob, len_offset, offset, str, -1, flags);
-       if (ret < 0) {
-               return NT_STATUS_FOOBAR;
-       }
-       TRANS2_CHECK(trans2_grow_data(mem_ctx, blob, offset + ret));
-       return NT_STATUS_OK;
-}
-
-/*
-  align the end of the data section of a trans reply on an even boundary
-*/
-static NTSTATUS trans2_align_data(struct smb_trans2 *trans)
-{
-       if (trans->out.data.length & 1) {
-               TRANS2_CHECK(trans2_grow_data_fill(trans, &trans->out.data, trans->out.data.length+1));
-       }
-       return NT_STATUS_OK;
-}
-
-static NTSTATUS trans2_push_fsinfo(struct smbsrv_request *req,
-                                  union smb_fsinfo *fsinfo,
+static NTSTATUS trans2_push_fsinfo(struct smbsrv_connection *smb_conn,
                                   TALLOC_CTX *mem_ctx,
-                                  DATA_BLOB *blob)
+                                  DATA_BLOB *blob,
+                                  union smb_fsinfo *fsinfo,
+                                  int default_str_flags)
 {
-       uint_t i;
-       DATA_BLOB guid_blob;
+       enum smb_fsinfo_level passthru_level;
 
        switch (fsinfo->generic.level) {
-       case SMB_QFS_ALLOCATION:
-               TRANS2_CHECK(trans2_grow_data(mem_ctx, blob, 18));
+       case RAW_QFS_ALLOCATION:
+               TRANS2_CHECK(smbsrv_blob_grow_data(mem_ctx, blob, 18));
 
                SIVAL(blob->data,  0, fsinfo->allocation.out.fs_id);
                SIVAL(blob->data,  4, fsinfo->allocation.out.sectors_per_unit);
@@ -257,106 +98,43 @@ static NTSTATUS trans2_push_fsinfo(struct smbsrv_request *req,
 
                return NT_STATUS_OK;
 
-       case SMB_QFS_VOLUME:
-               TRANS2_CHECK(trans2_grow_data(mem_ctx, blob, 5));
+       case RAW_QFS_VOLUME:
+               TRANS2_CHECK(smbsrv_blob_grow_data(mem_ctx, blob, 5));
 
                SIVAL(blob->data,       0, fsinfo->volume.out.serial_number);
                /* w2k3 implements this incorrectly for unicode - it
                 * leaves the last byte off the string */
-               TRANS2_CHECK(trans2_append_data_string(req, mem_ctx, blob,
-                                                      &fsinfo->volume.out.volume_name, 
-                                                      4, STR_LEN8BIT|STR_NOALIGN));
-
-               return NT_STATUS_OK;
-
-       case SMB_QFS_VOLUME_INFO:
-       case SMB_QFS_VOLUME_INFORMATION:
-               TRANS2_CHECK(trans2_grow_data(mem_ctx, blob, 18));
-
-               push_nttime(blob->data, 0, fsinfo->volume_info.out.create_time);
-               SIVAL(blob->data,       8, fsinfo->volume_info.out.serial_number);
-               SSVAL(blob->data,      16, 0); /* padding */
-               TRANS2_CHECK(trans2_append_data_string(req, mem_ctx, blob,
-                                                      &fsinfo->volume_info.out.volume_name, 
-                                                      12, STR_UNICODE));
-
-               return NT_STATUS_OK;
-
-       case SMB_QFS_SIZE_INFO:
-       case SMB_QFS_SIZE_INFORMATION:
-               TRANS2_CHECK(trans2_grow_data(mem_ctx, blob, 24));
-
-               SBVAL(blob->data,  0, fsinfo->size_info.out.total_alloc_units);
-               SBVAL(blob->data,  8, fsinfo->size_info.out.avail_alloc_units);
-               SIVAL(blob->data, 16, fsinfo->size_info.out.sectors_per_unit);
-               SIVAL(blob->data, 20, fsinfo->size_info.out.bytes_per_sector);
-
-               return NT_STATUS_OK;
-
-       case SMB_QFS_DEVICE_INFO:
-       case SMB_QFS_DEVICE_INFORMATION:
-               TRANS2_CHECK(trans2_grow_data(mem_ctx, blob, 8));
-
-               SIVAL(blob->data,      0, fsinfo->device_info.out.device_type);
-               SIVAL(blob->data,      4, fsinfo->device_info.out.characteristics);
+               TRANS2_CHECK(smbsrv_blob_append_string(mem_ctx, blob,
+                                                      fsinfo->volume.out.volume_name.s,
+                                                      4, default_str_flags,
+                                                      STR_LEN8BIT|STR_NOALIGN));
 
                return NT_STATUS_OK;
 
-       case SMB_QFS_ATTRIBUTE_INFO:
-       case SMB_QFS_ATTRIBUTE_INFORMATION:
-               TRANS2_CHECK(trans2_grow_data(mem_ctx, blob, 12));
-
-               SIVAL(blob->data, 0, fsinfo->attribute_info.out.fs_attr);
-               SIVAL(blob->data, 4, fsinfo->attribute_info.out.max_file_component_length);
-               /* this must not be null terminated or win98 gets
-                  confused!  also note that w2k3 returns this as
-                  unicode even when ascii is negotiated */
-               TRANS2_CHECK(trans2_append_data_string(req, mem_ctx, blob,
-                                                      &fsinfo->attribute_info.out.fs_type,
-                                                      8, STR_UNICODE));
-               return NT_STATUS_OK;
-
-
-       case SMB_QFS_QUOTA_INFORMATION:
-               TRANS2_CHECK(trans2_grow_data(mem_ctx, blob, 48));
-
-               SBVAL(blob->data,   0, fsinfo->quota_information.out.unknown[0]);
-               SBVAL(blob->data,   8, fsinfo->quota_information.out.unknown[1]);
-               SBVAL(blob->data,  16, fsinfo->quota_information.out.unknown[2]);
-               SBVAL(blob->data,  24, fsinfo->quota_information.out.quota_soft);
-               SBVAL(blob->data,  32, fsinfo->quota_information.out.quota_hard);
-               SBVAL(blob->data,  40, fsinfo->quota_information.out.quota_flags);
-
-               return NT_STATUS_OK;
-
-
-       case SMB_QFS_FULL_SIZE_INFORMATION:
-               TRANS2_CHECK(trans2_grow_data(mem_ctx, blob, 32));
-
-               SBVAL(blob->data,  0, fsinfo->full_size_information.out.total_alloc_units);
-               SBVAL(blob->data,  8, fsinfo->full_size_information.out.call_avail_alloc_units);
-               SBVAL(blob->data, 16, fsinfo->full_size_information.out.actual_avail_alloc_units);
-               SIVAL(blob->data, 24, fsinfo->full_size_information.out.sectors_per_unit);
-               SIVAL(blob->data, 28, fsinfo->full_size_information.out.bytes_per_sector);
-
-               return NT_STATUS_OK;
+       case RAW_QFS_VOLUME_INFO:
+               passthru_level = RAW_QFS_VOLUME_INFORMATION;
+               break;
 
-       case SMB_QFS_OBJECTID_INFORMATION:
-               TRANS2_CHECK(trans2_grow_data(mem_ctx, blob, 64));
+       case RAW_QFS_SIZE_INFO:
+               passthru_level = RAW_QFS_SIZE_INFORMATION;
+               break;
 
-               TRANS2_CHECK(ndr_push_struct_blob(&guid_blob, mem_ctx, 
-                                                 &fsinfo->objectid_information.out.guid,
-                                                 (ndr_push_flags_fn_t)ndr_push_GUID));
-               memcpy(blob->data, guid_blob.data, guid_blob.length);
+       case RAW_QFS_DEVICE_INFO:
+               passthru_level = RAW_QFS_DEVICE_INFORMATION;
+               break;
 
-               for (i=0;i<6;i++) {
-                       SBVAL(blob->data, 16 + 8*i, fsinfo->objectid_information.out.unknown[i]);
-               }
+       case RAW_QFS_ATTRIBUTE_INFO:
+               passthru_level = RAW_QFS_ATTRIBUTE_INFORMATION;
+               break;
 
-               return NT_STATUS_OK;
+       default:
+               passthru_level = fsinfo->generic.level;
+               break;
        }
 
-       return NT_STATUS_INVALID_LEVEL;
+       return smbsrv_push_passthru_fsinfo(mem_ctx, blob,
+                                          passthru_level, fsinfo,
+                                          default_str_flags);
 }
 
 /*
@@ -372,7 +150,9 @@ static NTSTATUS trans2_qfsinfo_send(struct trans_op *op)
 
        TRANS2_CHECK(trans2_setup_reply(trans, 0, 0, 0));
 
-       TRANS2_CHECK(trans2_push_fsinfo(req, fsinfo, trans, &trans->out.data));
+       TRANS2_CHECK(trans2_push_fsinfo(req->smb_conn, trans,
+                                       &trans->out.data, fsinfo,
+                                       SMBSRV_REQ_DEFAULT_STR_FLAGS(req)));
 
        return NT_STATUS_OK;
 }
@@ -394,54 +174,18 @@ static NTSTATUS trans2_qfsinfo(struct smbsrv_request *req, struct trans_op *op)
        fsinfo = talloc(op, union smb_fsinfo);
        NT_STATUS_HAVE_NO_MEMORY(fsinfo);
 
-       op->op_info = fsinfo;
-       op->send_fn = trans2_qfsinfo_send;
-
        level = SVAL(trans->in.params.data, 0);
 
-       switch (level) {
-       case SMB_QFS_ALLOCATION:
-               fsinfo->allocation.level = RAW_QFS_ALLOCATION;
-               return ntvfs_fsinfo(req->ntvfs, fsinfo);
-
-       case SMB_QFS_VOLUME:
-               fsinfo->volume.level = RAW_QFS_VOLUME;
-               return ntvfs_fsinfo(req->ntvfs, fsinfo);
-
-       case SMB_QFS_VOLUME_INFO:
-       case SMB_QFS_VOLUME_INFORMATION:
-               fsinfo->volume_info.level = RAW_QFS_VOLUME_INFO;
-               return ntvfs_fsinfo(req->ntvfs, fsinfo);
-
-       case SMB_QFS_SIZE_INFO:
-       case SMB_QFS_SIZE_INFORMATION:
-               fsinfo->size_info.level = RAW_QFS_SIZE_INFO;
-               return ntvfs_fsinfo(req->ntvfs, fsinfo);
-
-       case SMB_QFS_DEVICE_INFO:
-       case SMB_QFS_DEVICE_INFORMATION:
-               fsinfo->device_info.level = RAW_QFS_DEVICE_INFO;
-               return ntvfs_fsinfo(req->ntvfs, fsinfo);
-
-       case SMB_QFS_ATTRIBUTE_INFO:
-       case SMB_QFS_ATTRIBUTE_INFORMATION:
-               fsinfo->attribute_info.level = RAW_QFS_ATTRIBUTE_INFO;
-               return ntvfs_fsinfo(req->ntvfs, fsinfo);
-
-       case SMB_QFS_QUOTA_INFORMATION:
-               fsinfo->quota_information.level = RAW_QFS_QUOTA_INFORMATION;
-               return ntvfs_fsinfo(req->ntvfs, fsinfo);
-
-       case SMB_QFS_FULL_SIZE_INFORMATION:
-               fsinfo->full_size_information.level = RAW_QFS_FULL_SIZE_INFORMATION;
-               return ntvfs_fsinfo(req->ntvfs, fsinfo);
-
-       case SMB_QFS_OBJECTID_INFORMATION:
-               fsinfo->objectid_information.level = RAW_QFS_OBJECTID_INFORMATION;
-               return ntvfs_fsinfo(req->ntvfs, fsinfo);
+       /* work out the backend level - we make it 1-1 in the header */
+       fsinfo->generic.level = (enum smb_fsinfo_level)level;
+       if (fsinfo->generic.level >= RAW_QFS_GENERIC) {
+               return NT_STATUS_INVALID_LEVEL;
        }
 
-       return NT_STATUS_INVALID_LEVEL;
+       op->op_info = fsinfo;
+       op->send_fn = trans2_qfsinfo_send;
+
+       return ntvfs_fsinfo(req->ntvfs, fsinfo);
 }
 
 
@@ -456,7 +200,7 @@ static NTSTATUS trans2_open_send(struct trans_op *op)
 
        TRANS2_CHECK_ASYNC_STATUS(io, union smb_open);
 
-       trans2_setup_reply(trans, 30, 0, 0);
+       TRANS2_CHECK(trans2_setup_reply(trans, 30, 0, 0));
 
        smbsrv_push_fnum(trans->out.params.data, VWV(0), io->t2open.out.file.ntvfs);
        SSVAL(trans->out.params.data, VWV(1), io->t2open.out.attrib);
@@ -481,7 +225,6 @@ static NTSTATUS trans2_open(struct smbsrv_request *req, struct trans_op *op)
 {
        struct smb_trans2 *trans = op->trans;
        union smb_open *io;
-       NTSTATUS status;
 
        /* make sure we got enough parameters */
        if (trans->in.params.length < 29) {
@@ -497,17 +240,19 @@ static NTSTATUS trans2_open(struct smbsrv_request *req, struct trans_op *op)
        io->t2open.in.search_attrs = SVAL(trans->in.params.data, VWV(2));
        io->t2open.in.file_attrs   = SVAL(trans->in.params.data, VWV(3));
        io->t2open.in.write_time   = srv_pull_dos_date(req->smb_conn, 
-                                                   trans->in.params.data + VWV(4));;
+                                                   trans->in.params.data + VWV(4));
        io->t2open.in.open_func    = SVAL(trans->in.params.data, VWV(6));
        io->t2open.in.size         = IVAL(trans->in.params.data, VWV(7));
        io->t2open.in.timeout      = IVAL(trans->in.params.data, VWV(9));
        io->t2open.in.num_eas      = 0;
        io->t2open.in.eas          = NULL;
 
-       trans2_pull_blob_string(req, &trans->in.params, 28, &io->t2open.in.fname, 0);
+       smbsrv_blob_pull_string(&req->in.bufinfo, &trans->in.params, 28, &io->t2open.in.fname, 0);
+       if (io->t2open.in.fname == NULL) {
+               return NT_STATUS_FOOBAR;
+       }
 
-       status = ea_pull_list(&trans->in.data, io, &io->t2open.in.num_eas, &io->t2open.in.eas);
-       NT_STATUS_NOT_OK_RETURN(status);
+       TRANS2_CHECK(ea_pull_list(&trans->in.data, io, &io->t2open.in.num_eas, &io->t2open.in.eas));
 
        op->op_info = io;
        op->send_fn = trans2_open_send;
@@ -526,7 +271,7 @@ static NTSTATUS trans2_simple_send(struct trans_op *op)
 
        TRANS2_CHECK_ASYNC_STATUS_SIMPLE;
 
-       trans2_setup_reply(trans, 2, 0, 0);
+       TRANS2_CHECK(trans2_setup_reply(trans, 2, 0, 0));
 
        SSVAL(trans->out.params.data, VWV(0), 0);
 
@@ -540,7 +285,6 @@ static NTSTATUS trans2_mkdir(struct smbsrv_request *req, struct trans_op *op)
 {
        struct smb_trans2 *trans = op->trans;
        union smb_mkdir *io;
-       NTSTATUS status;
 
        /* make sure we got enough parameters */
        if (trans->in.params.length < 5) {
@@ -551,12 +295,14 @@ static NTSTATUS trans2_mkdir(struct smbsrv_request *req, struct trans_op *op)
        NT_STATUS_HAVE_NO_MEMORY(io);
 
        io->t2mkdir.level = RAW_MKDIR_T2MKDIR;
-       trans2_pull_blob_string(req, &trans->in.params, 4, &io->t2mkdir.in.path, 0);
+       smbsrv_blob_pull_string(&req->in.bufinfo, &trans->in.params, 4, &io->t2mkdir.in.path, 0);
+       if (io->t2mkdir.in.path == NULL) {
+               return NT_STATUS_FOOBAR;
+       }
 
-       status = ea_pull_list(&trans->in.data, io, 
-                             &io->t2mkdir.in.num_eas, 
-                             &io->t2mkdir.in.eas);
-       NT_STATUS_NOT_OK_RETURN(status);
+       TRANS2_CHECK(ea_pull_list(&trans->in.data, io, 
+                                 &io->t2mkdir.in.num_eas, 
+                                 &io->t2mkdir.in.eas));
 
        op->op_info = io;
        op->send_fn = trans2_simple_send;
@@ -564,113 +310,57 @@ static NTSTATUS trans2_mkdir(struct smbsrv_request *req, struct trans_op *op)
        return ntvfs_mkdir(req->ntvfs, io);
 }
 
-static NTSTATUS trans2_push_fileinfo(struct smbsrv_request *req,
-                                    union smb_fileinfo *st,
+static NTSTATUS trans2_push_fileinfo(struct smbsrv_connection *smb_conn,
                                     TALLOC_CTX *mem_ctx,
-                                    DATA_BLOB *blob)
+                                    DATA_BLOB *blob,
+                                    union smb_fileinfo *st,
+                                    int default_str_flags)
 {
-       uint_t i;
        uint32_t list_size;
+       enum smb_fileinfo_level passthru_level;
 
        switch (st->generic.level) {
        case RAW_FILEINFO_GENERIC:
        case RAW_FILEINFO_GETATTR:
        case RAW_FILEINFO_GETATTRE:
        case RAW_FILEINFO_SEC_DESC:
+       case RAW_FILEINFO_SMB2_ALL_EAS:
+       case RAW_FILEINFO_SMB2_ALL_INFORMATION:
                /* handled elsewhere */
                return NT_STATUS_INVALID_LEVEL;
 
-       case RAW_FILEINFO_BASIC_INFO:
-       case RAW_FILEINFO_BASIC_INFORMATION:
-               TRANS2_CHECK(trans2_grow_data(mem_ctx, blob, 40));
-
-               push_nttime(blob->data,  0, st->basic_info.out.create_time);
-               push_nttime(blob->data,  8, st->basic_info.out.access_time);
-               push_nttime(blob->data, 16, st->basic_info.out.write_time);
-               push_nttime(blob->data, 24, st->basic_info.out.change_time);
-               SIVAL(blob->data,       32, st->basic_info.out.attrib);
-               SIVAL(blob->data,       36, 0); /* padding */
-               return NT_STATUS_OK;
+       case RAW_FILEINFO_UNIX_BASIC:
+       case RAW_FILEINFO_UNIX_LINK:
+               /* not implemented yet */
+               return NT_STATUS_INVALID_LEVEL;
 
        case RAW_FILEINFO_STANDARD:
-               TRANS2_CHECK(trans2_grow_data(mem_ctx, blob, 22));
+               TRANS2_CHECK(smbsrv_blob_grow_data(mem_ctx, blob, 22));
 
-               srv_push_dos_date2(req->smb_conn, blob->data, 0, st->standard.out.create_time);
-               srv_push_dos_date2(req->smb_conn, blob->data, 4, st->standard.out.access_time);
-               srv_push_dos_date2(req->smb_conn, blob->data, 8, st->standard.out.write_time);
+               srv_push_dos_date2(smb_conn, blob->data, 0, st->standard.out.create_time);
+               srv_push_dos_date2(smb_conn, blob->data, 4, st->standard.out.access_time);
+               srv_push_dos_date2(smb_conn, blob->data, 8, st->standard.out.write_time);
                SIVAL(blob->data,        12, st->standard.out.size);
                SIVAL(blob->data,        16, st->standard.out.alloc_size);
                SSVAL(blob->data,        20, st->standard.out.attrib);
                return NT_STATUS_OK;
 
        case RAW_FILEINFO_EA_SIZE:
-               TRANS2_CHECK(trans2_grow_data(mem_ctx, blob, 26));
+               TRANS2_CHECK(smbsrv_blob_grow_data(mem_ctx, blob, 26));
 
-               srv_push_dos_date2(req->smb_conn, blob->data, 0, st->ea_size.out.create_time);
-               srv_push_dos_date2(req->smb_conn, blob->data, 4, st->ea_size.out.access_time);
-               srv_push_dos_date2(req->smb_conn, blob->data, 8, st->ea_size.out.write_time);
+               srv_push_dos_date2(smb_conn, blob->data, 0, st->ea_size.out.create_time);
+               srv_push_dos_date2(smb_conn, blob->data, 4, st->ea_size.out.access_time);
+               srv_push_dos_date2(smb_conn, blob->data, 8, st->ea_size.out.write_time);
                SIVAL(blob->data,        12, st->ea_size.out.size);
                SIVAL(blob->data,        16, st->ea_size.out.alloc_size);
                SSVAL(blob->data,        20, st->ea_size.out.attrib);
                SIVAL(blob->data,        22, st->ea_size.out.ea_size);
                return NT_STATUS_OK;
 
-       case RAW_FILEINFO_NETWORK_OPEN_INFORMATION:
-               TRANS2_CHECK(trans2_grow_data(mem_ctx, blob, 56));
-
-               push_nttime(blob->data,  0, st->network_open_information.out.create_time);
-               push_nttime(blob->data,  8, st->network_open_information.out.access_time);
-               push_nttime(blob->data, 16, st->network_open_information.out.write_time);
-               push_nttime(blob->data, 24, st->network_open_information.out.change_time);
-               SBVAL(blob->data,       32, st->network_open_information.out.alloc_size);
-               SBVAL(blob->data,       40, st->network_open_information.out.size);
-               SIVAL(blob->data,       48, st->network_open_information.out.attrib);
-               SIVAL(blob->data,       52, 0); /* padding */
-               return NT_STATUS_OK;
-
-       case RAW_FILEINFO_STANDARD_INFO:
-       case RAW_FILEINFO_STANDARD_INFORMATION:
-               TRANS2_CHECK(trans2_grow_data(mem_ctx, blob, 24));
-
-               SBVAL(blob->data,  0, st->standard_info.out.alloc_size);
-               SBVAL(blob->data,  8, st->standard_info.out.size);
-               SIVAL(blob->data, 16, st->standard_info.out.nlink);
-               SCVAL(blob->data, 20, st->standard_info.out.delete_pending);
-               SCVAL(blob->data, 21, st->standard_info.out.directory);
-               SSVAL(blob->data, 22, 0); /* padding */
-               return NT_STATUS_OK;
-
-       case RAW_FILEINFO_ATTRIBUTE_TAG_INFORMATION:
-               TRANS2_CHECK(trans2_grow_data(mem_ctx, blob, 8));
-
-               SIVAL(blob->data,  0, st->attribute_tag_information.out.attrib);
-               SIVAL(blob->data,  4, st->attribute_tag_information.out.reparse_tag);
-               return NT_STATUS_OK;
-
-       case RAW_FILEINFO_EA_INFO:
-       case RAW_FILEINFO_EA_INFORMATION:
-               TRANS2_CHECK(trans2_grow_data(mem_ctx, blob, 4));
-
-               SIVAL(blob->data,  0, st->ea_info.out.ea_size);
-               return NT_STATUS_OK;
-
-       case RAW_FILEINFO_MODE_INFORMATION:
-               TRANS2_CHECK(trans2_grow_data(mem_ctx, blob, 4));
-
-               SIVAL(blob->data,  0, st->mode_information.out.mode);
-               return NT_STATUS_OK;
-
-       case RAW_FILEINFO_ALIGNMENT_INFORMATION:
-               TRANS2_CHECK(trans2_grow_data(mem_ctx, blob, 4));
-
-               SIVAL(blob->data,  0, 
-                     st->alignment_information.out.alignment_requirement);
-               return NT_STATUS_OK;
-
        case RAW_FILEINFO_EA_LIST:
                list_size = ea_list_size(st->ea_list.out.num_eas,
                                         st->ea_list.out.eas);
-               TRANS2_CHECK(trans2_grow_data(mem_ctx, blob, list_size));
+               TRANS2_CHECK(smbsrv_blob_grow_data(mem_ctx, blob, list_size));
 
                ea_put_list(blob->data, 
                            st->ea_list.out.num_eas, st->ea_list.out.eas);
@@ -679,119 +369,55 @@ static NTSTATUS trans2_push_fileinfo(struct smbsrv_request *req,
        case RAW_FILEINFO_ALL_EAS:
                list_size = ea_list_size(st->all_eas.out.num_eas,
                                                  st->all_eas.out.eas);
-               TRANS2_CHECK(trans2_grow_data(mem_ctx, blob, list_size));
+               TRANS2_CHECK(smbsrv_blob_grow_data(mem_ctx, blob, list_size));
 
                ea_put_list(blob->data, 
                            st->all_eas.out.num_eas, st->all_eas.out.eas);
                return NT_STATUS_OK;
 
-       case RAW_FILEINFO_ACCESS_INFORMATION:
-               TRANS2_CHECK(trans2_grow_data(mem_ctx, blob, 4));
-
-               SIVAL(blob->data,  0, st->access_information.out.access_flags);
-               return NT_STATUS_OK;
-
-       case RAW_FILEINFO_POSITION_INFORMATION:
-               TRANS2_CHECK(trans2_grow_data(mem_ctx, blob, 8));
-
-               SBVAL(blob->data,  0, st->position_information.out.position);
+       case RAW_FILEINFO_IS_NAME_VALID:
                return NT_STATUS_OK;
 
-       case RAW_FILEINFO_COMPRESSION_INFO:
-       case RAW_FILEINFO_COMPRESSION_INFORMATION:
-               TRANS2_CHECK(trans2_grow_data(mem_ctx, blob, 16));
-
-               SBVAL(blob->data,  0, st->compression_info.out.compressed_size);
-               SSVAL(blob->data,  8, st->compression_info.out.format);
-               SCVAL(blob->data, 10, st->compression_info.out.unit_shift);
-               SCVAL(blob->data, 11, st->compression_info.out.chunk_shift);
-               SCVAL(blob->data, 12, st->compression_info.out.cluster_shift);
-               SSVAL(blob->data, 13, 0); /* 3 bytes padding */
-               SCVAL(blob->data, 15, 0);
-               return NT_STATUS_OK;
+       case RAW_FILEINFO_BASIC_INFO:
+               passthru_level = RAW_FILEINFO_BASIC_INFORMATION;
+               break;
 
-       case RAW_FILEINFO_IS_NAME_VALID:
-               return NT_STATUS_OK;
+       case RAW_FILEINFO_STANDARD_INFO:
+               passthru_level = RAW_FILEINFO_STANDARD_INFORMATION;
+               break;
 
-       case RAW_FILEINFO_INTERNAL_INFORMATION:
-               TRANS2_CHECK(trans2_grow_data(mem_ctx, blob, 8));
+       case RAW_FILEINFO_EA_INFO:
+               passthru_level = RAW_FILEINFO_EA_INFORMATION;
+               break;
 
-               SBVAL(blob->data,  0, st->internal_information.out.file_id);
-               return NT_STATUS_OK;
+       case RAW_FILEINFO_COMPRESSION_INFO:
+               passthru_level = RAW_FILEINFO_COMPRESSION_INFORMATION;
+               break;
 
        case RAW_FILEINFO_ALL_INFO:
-       case RAW_FILEINFO_ALL_INFORMATION:
-               TRANS2_CHECK(trans2_grow_data(mem_ctx, blob, 72));
-
-               push_nttime(blob->data,  0, st->all_info.out.create_time);
-               push_nttime(blob->data,  8, st->all_info.out.access_time);
-               push_nttime(blob->data, 16, st->all_info.out.write_time);
-               push_nttime(blob->data, 24, st->all_info.out.change_time);
-               SIVAL(blob->data,       32, st->all_info.out.attrib);
-               SIVAL(blob->data,       36, 0);
-               SBVAL(blob->data,       40, st->all_info.out.alloc_size);
-               SBVAL(blob->data,       48, st->all_info.out.size);
-               SIVAL(blob->data,       56, st->all_info.out.nlink);
-               SCVAL(blob->data,       60, st->all_info.out.delete_pending);
-               SCVAL(blob->data,       61, st->all_info.out.directory);
-               SSVAL(blob->data,       62, 0); /* padding */
-               SIVAL(blob->data,       64, st->all_info.out.ea_size);
-               TRANS2_CHECK(trans2_append_data_string(req, mem_ctx, blob,
-                                                      &st->all_info.out.fname,
-                                                      68, STR_UNICODE));
-               return NT_STATUS_OK;
+               passthru_level = RAW_FILEINFO_ALL_INFORMATION;
+               break;
 
        case RAW_FILEINFO_NAME_INFO:
-       case RAW_FILEINFO_NAME_INFORMATION:
-               TRANS2_CHECK(trans2_grow_data(mem_ctx, blob, 4));
-
-               TRANS2_CHECK(trans2_append_data_string(req, mem_ctx, blob,
-                                                      &st->name_info.out.fname,
-                                                      0, STR_UNICODE));
-               return NT_STATUS_OK;
+               passthru_level = RAW_FILEINFO_NAME_INFORMATION;
+               break;
 
        case RAW_FILEINFO_ALT_NAME_INFO:
-       case RAW_FILEINFO_ALT_NAME_INFORMATION:
-               TRANS2_CHECK(trans2_grow_data(mem_ctx, blob, 4));
-
-               TRANS2_CHECK(trans2_append_data_string(req, mem_ctx, blob, 
-                                                      &st->alt_name_info.out.fname,
-                                                      0, STR_UNICODE));
-               return NT_STATUS_OK;
+               passthru_level = RAW_FILEINFO_ALT_NAME_INFORMATION;
+               break;
 
        case RAW_FILEINFO_STREAM_INFO:
-       case RAW_FILEINFO_STREAM_INFORMATION:
-               for (i=0;i<st->stream_info.out.num_streams;i++) {
-                       uint32_t data_size = blob->length;
-                       uint8_t *data;
-
-                       TRANS2_CHECK(trans2_grow_data(mem_ctx, blob, data_size + 24));
-                       data = blob->data + data_size;
-                       SBVAL(data,  8, st->stream_info.out.streams[i].size);
-                       SBVAL(data, 16, st->stream_info.out.streams[i].alloc_size);
-                       TRANS2_CHECK(trans2_append_data_string(req, mem_ctx, blob,
-                                                              &st->stream_info.out.streams[i].stream_name,
-                                                              data_size + 4, STR_UNICODE));
-                       if (i == st->stream_info.out.num_streams - 1) {
-                               SIVAL(blob->data, data_size, 0);
-                       } else {
-                               TRANS2_CHECK(trans2_grow_data_fill(mem_ctx, blob, (blob->length+7)&~7));
-                               SIVAL(blob->data, data_size, 
-                                     blob->length - data_size);
-                       }
-               }
-               return NT_STATUS_OK;
-               
-       case RAW_FILEINFO_UNIX_BASIC:
-       case RAW_FILEINFO_UNIX_LINK:
-               return NT_STATUS_INVALID_LEVEL;
+               passthru_level = RAW_FILEINFO_STREAM_INFORMATION;
+               break;
 
-       case RAW_FILEINFO_SMB2_ALL_EAS:
-       case RAW_FILEINFO_SMB2_ALL_INFORMATION:
-               return NT_STATUS_INVALID_LEVEL;
+       default:
+               passthru_level = st->generic.level;
+               break;
        }
 
-       return NT_STATUS_INVALID_LEVEL;
+       return smbsrv_push_passthru_fileinfo(mem_ctx, blob,
+                                            passthru_level, st,
+                                            default_str_flags);
 }
 
 /*
@@ -808,7 +434,9 @@ static NTSTATUS trans2_fileinfo_send(struct trans_op *op)
        TRANS2_CHECK(trans2_setup_reply(trans, 2, 0, 0));
        SSVAL(trans->out.params.data, 0, 0);
 
-       TRANS2_CHECK(trans2_push_fileinfo(req, st, trans, &trans->out.data));
+       TRANS2_CHECK(trans2_push_fileinfo(req->smb_conn, trans,
+                                         &trans->out.data, st,
+                                         SMBSRV_REQ_DEFAULT_STR_FLAGS(req)));
 
        return NT_STATUS_OK;
 }
@@ -820,7 +448,6 @@ static NTSTATUS trans2_qpathinfo(struct smbsrv_request *req, struct trans_op *op
 {
        struct smb_trans2 *trans = op->trans;
        union smb_fileinfo *st;
-       NTSTATUS status;
        uint16_t level;
 
        /* make sure we got enough parameters */
@@ -833,7 +460,7 @@ static NTSTATUS trans2_qpathinfo(struct smbsrv_request *req, struct trans_op *op
 
        level = SVAL(trans->in.params.data, 0);
 
-       trans2_pull_blob_string(req, &trans->in.params, 6, &st->generic.in.file.path, 0);
+       smbsrv_blob_pull_string(&req->in.bufinfo, &trans->in.params, 6, &st->generic.in.file.path, 0);
        if (st->generic.in.file.path == NULL) {
                return NT_STATUS_FOOBAR;
        }
@@ -845,10 +472,9 @@ static NTSTATUS trans2_qpathinfo(struct smbsrv_request *req, struct trans_op *op
        }
 
        if (st->generic.level == RAW_FILEINFO_EA_LIST) {
-               status = ea_pull_name_list(&trans->in.data, req, 
-                                          &st->ea_list.in.num_names,
-                                          &st->ea_list.in.ea_names);
-               NT_STATUS_NOT_OK_RETURN(status);
+               TRANS2_CHECK(ea_pull_name_list(&trans->in.data, req, 
+                                              &st->ea_list.in.num_names,
+                                              &st->ea_list.in.ea_names));
        }
 
        op->op_info = st;
@@ -865,7 +491,6 @@ static NTSTATUS trans2_qfileinfo(struct smbsrv_request *req, struct trans_op *op
 {
        struct smb_trans2 *trans = op->trans;
        union smb_fileinfo *st;
-       NTSTATUS status;
        uint16_t level;
        struct ntvfs_handle *h;
 
@@ -888,10 +513,9 @@ static NTSTATUS trans2_qfileinfo(struct smbsrv_request *req, struct trans_op *op
        }
 
        if (st->generic.level == RAW_FILEINFO_EA_LIST) {
-               status = ea_pull_name_list(&trans->in.data, req, 
-                                          &st->ea_list.in.num_names,
-                                          &st->ea_list.in.ea_names);
-               NT_STATUS_NOT_OK_RETURN(status);
+               TRANS2_CHECK(ea_pull_name_list(&trans->in.data, req, 
+                                              &st->ea_list.in.num_names,
+                                              &st->ea_list.in.ea_names));
        }
 
        op->op_info = st;
@@ -909,7 +533,7 @@ static NTSTATUS trans2_parse_sfileinfo(struct smbsrv_request *req,
                                       union smb_setfileinfo *st,
                                       const DATA_BLOB *blob)
 {
-       uint32_t len;
+       enum smb_setfileinfo_level passthru_level;
 
        switch (st->generic.level) {
        case RAW_SFILEINFO_GENERIC:
@@ -921,9 +545,11 @@ static NTSTATUS trans2_parse_sfileinfo(struct smbsrv_request *req,
 
        case RAW_SFILEINFO_STANDARD:
                CHECK_MIN_BLOB_SIZE(blob, 12);
+
                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:
@@ -933,69 +559,57 @@ static NTSTATUS trans2_parse_sfileinfo(struct smbsrv_request *req,
 
        case SMB_SFILEINFO_BASIC_INFO:
        case SMB_SFILEINFO_BASIC_INFORMATION:
-               CHECK_MIN_BLOB_SIZE(blob, 36);
-               st->basic_info.in.create_time = pull_nttime(blob->data,  0);
-               st->basic_info.in.access_time = pull_nttime(blob->data,  8);
-               st->basic_info.in.write_time =  pull_nttime(blob->data, 16);
-               st->basic_info.in.change_time = pull_nttime(blob->data, 24);
-               st->basic_info.in.attrib =      IVAL(blob->data,        32);
-               return NT_STATUS_OK;
+               passthru_level = SMB_SFILEINFO_BASIC_INFORMATION;
+               break;
 
        case SMB_SFILEINFO_DISPOSITION_INFO:
        case SMB_SFILEINFO_DISPOSITION_INFORMATION:
-               CHECK_MIN_BLOB_SIZE(blob, 1);
-               st->disposition_info.in.delete_on_close = CVAL(blob->data, 0);
-               return NT_STATUS_OK;
+               passthru_level = SMB_SFILEINFO_DISPOSITION_INFORMATION;
+               break;
 
        case SMB_SFILEINFO_ALLOCATION_INFO:
        case SMB_SFILEINFO_ALLOCATION_INFORMATION:
-               CHECK_MIN_BLOB_SIZE(blob, 8);
-               st->allocation_info.in.alloc_size = BVAL(blob->data, 0);
-               return NT_STATUS_OK;                            
+               passthru_level = SMB_SFILEINFO_ALLOCATION_INFORMATION;
+               break;
 
        case RAW_SFILEINFO_END_OF_FILE_INFO:
        case RAW_SFILEINFO_END_OF_FILE_INFORMATION:
-               CHECK_MIN_BLOB_SIZE(blob, 8);
-               st->end_of_file_info.in.size = BVAL(blob->data, 0);
-               return NT_STATUS_OK;
-
-       case RAW_SFILEINFO_RENAME_INFORMATION: {
-               DATA_BLOB blob2;
-
-               CHECK_MIN_BLOB_SIZE(blob, 12);
-               st->rename_information.in.overwrite = CVAL(blob->data, 0);
-               st->rename_information.in.root_fid  = IVAL(blob->data, 4);
-               len                                 = IVAL(blob->data, 8);
-               blob2.data = blob->data+12;
-               blob2.length = MIN(blob->length, len);
-               trans2_pull_blob_string(req, &blob2, 0, 
-                                       &st->rename_information.in.new_name, STR_UNICODE);
-               return NT_STATUS_OK;
-       }
+               passthru_level = RAW_SFILEINFO_END_OF_FILE_INFORMATION;
+               break;
 
+       case RAW_SFILEINFO_RENAME_INFORMATION:
        case RAW_SFILEINFO_POSITION_INFORMATION:
-               CHECK_MIN_BLOB_SIZE(blob, 8);
-               st->position_information.in.position = BVAL(blob->data, 0);
-               return NT_STATUS_OK;
-
        case RAW_SFILEINFO_MODE_INFORMATION:
-               CHECK_MIN_BLOB_SIZE(blob, 4);
-               st->mode_information.in.mode = IVAL(blob->data, 0);
-               return NT_STATUS_OK;
+               passthru_level = st->generic.level;
+               break;
 
        case RAW_SFILEINFO_UNIX_BASIC:
        case RAW_SFILEINFO_UNIX_LINK:
        case RAW_SFILEINFO_UNIX_HLINK:
-       case RAW_SFILEINFO_1023:
+       case RAW_SFILEINFO_PIPE_INFORMATION:
+       case RAW_SFILEINFO_VALID_DATA_INFORMATION:
+       case RAW_SFILEINFO_SHORT_NAME_INFORMATION:
        case RAW_SFILEINFO_1025:
+       case RAW_SFILEINFO_1027:
        case RAW_SFILEINFO_1029:
+       case RAW_SFILEINFO_1030:
+       case RAW_SFILEINFO_1031:
        case RAW_SFILEINFO_1032:
-       case RAW_SFILEINFO_1039:
-       case RAW_SFILEINFO_1040:
+       case RAW_SFILEINFO_1036:
+       case RAW_SFILEINFO_1041:
+       case RAW_SFILEINFO_1042:
+       case RAW_SFILEINFO_1043:
+       case RAW_SFILEINFO_1044:
+               return NT_STATUS_INVALID_LEVEL;
+
+       default:
+               /* we need a default here to cope with invalid values on the wire */
                return NT_STATUS_INVALID_LEVEL;
        }
 
-       return NT_STATUS_INVALID_LEVEL;
+       return smbsrv_pull_passthru_sfileinfo(st, passthru_level, st,
+                                             blob, SMBSRV_REQ_DEFAULT_STR_FLAGS(req),
+                                             &req->in.bufinfo);
 }
 
 /*
@@ -1005,7 +619,6 @@ static NTSTATUS trans2_setfileinfo(struct smbsrv_request *req, struct trans_op *
 {
        struct smb_trans2 *trans = op->trans;
        union smb_setfileinfo *st;
-       NTSTATUS status;
        uint16_t level;
        struct ntvfs_handle *h;
 
@@ -1027,8 +640,7 @@ static NTSTATUS trans2_setfileinfo(struct smbsrv_request *req, struct trans_op *
                return NT_STATUS_INVALID_LEVEL;
        }
 
-       status = trans2_parse_sfileinfo(req, st, &trans->in.data);
-       NT_STATUS_NOT_OK_RETURN(status);
+       TRANS2_CHECK(trans2_parse_sfileinfo(req, st, &trans->in.data));
 
        op->op_info = st;
        op->send_fn = trans2_simple_send;
@@ -1044,7 +656,6 @@ static NTSTATUS trans2_setpathinfo(struct smbsrv_request *req, struct trans_op *
 {
        struct smb_trans2 *trans = op->trans;
        union smb_setfileinfo *st;
-       NTSTATUS status;
        uint16_t level;
 
        /* make sure we got enough parameters */
@@ -1057,7 +668,7 @@ static NTSTATUS trans2_setpathinfo(struct smbsrv_request *req, struct trans_op *
 
        level = SVAL(trans->in.params.data, 0);
 
-       trans2_pull_blob_string(req, &trans->in.params, 6, &st->generic.in.file.path, 0);
+       smbsrv_blob_pull_string(&req->in.bufinfo, &trans->in.params, 6, &st->generic.in.file.path, 0);
        if (st->generic.in.file.path == NULL) {
                return NT_STATUS_FOOBAR;
        }
@@ -1068,8 +679,7 @@ static NTSTATUS trans2_setpathinfo(struct smbsrv_request *req, struct trans_op *
                return NT_STATUS_INVALID_LEVEL;
        }
 
-       status = trans2_parse_sfileinfo(req, st, &trans->in.data);
-       NT_STATUS_NOT_OK_RETURN(status);
+       TRANS2_CHECK(trans2_parse_sfileinfo(req, st, &trans->in.data));
 
        op->op_info = st;
        op->send_fn = trans2_simple_send;
@@ -1082,7 +692,7 @@ static NTSTATUS trans2_setpathinfo(struct smbsrv_request *req, struct trans_op *
 struct find_state {
        struct trans_op *op;
        void *search;
-       enum smb_search_level level;
+       enum smb_search_data_level data_level;
        uint16_t last_entry_offset;
        uint16_t flags;
 };
@@ -1090,31 +700,28 @@ struct find_state {
 /*
   fill a single entry in a trans2 find reply 
 */
-static BOOL find_fill_info(struct find_state *state,
-                          union smb_search_data *file)
+static NTSTATUS find_fill_info(struct find_state *state,
+                              const union smb_search_data *file)
 {
        struct smbsrv_request *req = state->op->req;
        struct smb_trans2 *trans = state->op->trans;
        uint8_t *data;
-       uint_t ofs = trans->out.data.length;
+       unsigned int ofs = trans->out.data.length;
        uint32_t ea_size;
 
-       switch (state->level) {
-       case RAW_SEARCH_SEARCH:
-       case RAW_SEARCH_FFIRST:
-       case RAW_SEARCH_FUNIQUE:
-       case RAW_SEARCH_GENERIC:
-       case RAW_SEARCH_SMB2:
+       switch (state->data_level) {
+       case RAW_SEARCH_DATA_GENERIC:
+       case RAW_SEARCH_DATA_SEARCH:
                /* handled elsewhere */
-               return False;
+               return NT_STATUS_INVALID_LEVEL;
 
-       case RAW_SEARCH_STANDARD:
+       case RAW_SEARCH_DATA_STANDARD:
                if (state->flags & FLAG_TRANS2_FIND_REQUIRE_RESUME) {
-                       trans2_grow_data(trans, &trans->out.data, ofs + 27);
+                       TRANS2_CHECK(smbsrv_blob_grow_data(trans, &trans->out.data, ofs + 27));
                        SIVAL(trans->out.data.data, ofs, file->standard.resume_key);
                        ofs += 4;
                } else {
-                       trans2_grow_data(trans, &trans->out.data, ofs + 23);
+                       TRANS2_CHECK(smbsrv_blob_grow_data(trans, &trans->out.data, ofs + 23));
                }
                data = trans->out.data.data + ofs;
                srv_push_dos_date2(req->smb_conn, data, 0, file->standard.create_time);
@@ -1123,17 +730,18 @@ static BOOL find_fill_info(struct find_state *state,
                SIVAL(data, 12, file->standard.size);
                SIVAL(data, 16, file->standard.alloc_size);
                SSVAL(data, 20, file->standard.attrib);
-               trans2_append_data_string(req, trans, &trans->out.data, &file->standard.name, 
-                                         ofs + 22, STR_LEN8BIT | STR_TERMINATE | STR_LEN_NOTERM);
+               TRANS2_CHECK(smbsrv_blob_append_string(trans, &trans->out.data, file->standard.name.s, 
+                                                      ofs + 22, SMBSRV_REQ_DEFAULT_STR_FLAGS(req),
+                                                      STR_LEN8BIT | STR_TERMINATE | STR_LEN_NOTERM));
                break;
 
-       case RAW_SEARCH_EA_SIZE:
+       case RAW_SEARCH_DATA_EA_SIZE:
                if (state->flags & FLAG_TRANS2_FIND_REQUIRE_RESUME) {
-                       trans2_grow_data(trans, &trans->out.data, ofs + 31);
+                       TRANS2_CHECK(smbsrv_blob_grow_data(trans, &trans->out.data, ofs + 31));
                        SIVAL(trans->out.data.data, ofs, file->ea_size.resume_key);
                        ofs += 4;
                } else {
-                       trans2_grow_data(trans, &trans->out.data, ofs + 27);
+                       TRANS2_CHECK(smbsrv_blob_grow_data(trans, &trans->out.data, ofs + 27));
                }
                data = trans->out.data.data + ofs;
                srv_push_dos_date2(req->smb_conn, data, 0, file->ea_size.create_time);
@@ -1143,24 +751,20 @@ static BOOL find_fill_info(struct find_state *state,
                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, &trans->out.data, &file->ea_size.name
-                                         ofs + 26, STR_LEN8BIT | STR_NOALIGN);
-               trans2_grow_data(trans, &trans->out.data, trans->out.data.length + 1);
-               trans->out.data.data[trans->out.data.length-1] = 0;
+               TRANS2_CHECK(smbsrv_blob_append_string(trans, &trans->out.data, file->ea_size.name.s
+                                                      ofs + 26, SMBSRV_REQ_DEFAULT_STR_FLAGS(req),
+                                                      STR_LEN8BIT | STR_NOALIGN));
+               TRANS2_CHECK(smbsrv_blob_fill_data(trans, &trans->out.data, trans->out.data.length + 1));
                break;
 
-       case RAW_SEARCH_EA_LIST:
+       case RAW_SEARCH_DATA_EA_LIST:
                ea_size = ea_list_size(file->ea_list.eas.num_eas, file->ea_list.eas.eas);
                if (state->flags & FLAG_TRANS2_FIND_REQUIRE_RESUME) {
-                       if (!NT_STATUS_IS_OK(trans2_grow_data(trans, &trans->out.data, ofs + 27 + ea_size))) {
-                               return False;
-                       }
+                       TRANS2_CHECK(smbsrv_blob_grow_data(trans, &trans->out.data, ofs + 27 + ea_size));
                        SIVAL(trans->out.data.data, ofs, file->ea_list.resume_key);
                        ofs += 4;
                } else {
-                       if (!NT_STATUS_IS_OK(trans2_grow_data(trans, &trans->out.data, ofs + 23 + ea_size))) {
-                               return False;
-                       }
+                       TRANS2_CHECK(smbsrv_blob_grow_data(trans, &trans->out.data, ofs + 23 + ea_size));
                }
                data = trans->out.data.data + ofs;
                srv_push_dos_date2(req->smb_conn, data, 0, file->ea_list.create_time);
@@ -1170,149 +774,47 @@ static BOOL find_fill_info(struct find_state *state,
                SIVAL(data, 16, file->ea_list.alloc_size);
                SSVAL(data, 20, file->ea_list.attrib);
                ea_put_list(data+22, file->ea_list.eas.num_eas, file->ea_list.eas.eas);
-               trans2_append_data_string(req, trans, &trans->out.data, &file->ea_list.name, 
-                                         ofs + 22 + ea_size, STR_LEN8BIT | STR_NOALIGN);
-               trans2_grow_data(trans, &trans->out.data, trans->out.data.length + 1);
-               trans->out.data.data[trans->out.data.length-1] = 0;
-               break;
-
-       case RAW_SEARCH_DIRECTORY_INFO:
-               trans2_grow_data(trans, &trans->out.data, ofs + 64);
-               data = trans->out.data.data + ofs;
-               SIVAL(data,          4, file->directory_info.file_index);
-               push_nttime(data,    8, file->directory_info.create_time);
-               push_nttime(data,   16, file->directory_info.access_time);
-               push_nttime(data,   24, file->directory_info.write_time);
-               push_nttime(data,   32, file->directory_info.change_time);
-               SBVAL(data,         40, file->directory_info.size);
-               SBVAL(data,         48, file->directory_info.alloc_size);
-               SIVAL(data,         56, file->directory_info.attrib);
-               trans2_append_data_string(req, trans, &trans->out.data, &file->directory_info.name, 
-                                         ofs + 60, STR_TERMINATE_ASCII);
-               data = trans->out.data.data + ofs;
-               SIVAL(data,          0, trans->out.data.length - ofs);
-               break;
-
-       case RAW_SEARCH_FULL_DIRECTORY_INFO:
-               trans2_grow_data(trans, &trans->out.data, ofs + 68);
-               data = trans->out.data.data + ofs;
-               SIVAL(data,          4, file->full_directory_info.file_index);
-               push_nttime(data,    8, file->full_directory_info.create_time);
-               push_nttime(data,   16, file->full_directory_info.access_time);
-               push_nttime(data,   24, file->full_directory_info.write_time);
-               push_nttime(data,   32, file->full_directory_info.change_time);
-               SBVAL(data,         40, file->full_directory_info.size);
-               SBVAL(data,         48, file->full_directory_info.alloc_size);
-               SIVAL(data,         56, file->full_directory_info.attrib);
-               SIVAL(data,         64, file->full_directory_info.ea_size);
-               trans2_append_data_string(req, trans, &trans->out.data, &file->full_directory_info.name, 
-                                         ofs + 60, STR_TERMINATE_ASCII);
-               data = trans->out.data.data + ofs;
-               SIVAL(data,          0, trans->out.data.length - ofs);
-               break;
-
-       case RAW_SEARCH_NAME_INFO:
-               trans2_grow_data(trans, &trans->out.data, ofs + 12);
-               data = trans->out.data.data + ofs;
-               SIVAL(data,          4, file->name_info.file_index);
-               trans2_append_data_string(req, trans, &trans->out.data, &file->name_info.name, 
-                                         ofs + 8, STR_TERMINATE_ASCII);
-               data = trans->out.data.data + ofs;
-               SIVAL(data,          0, trans->out.data.length - ofs);
-               break;
-
-       case RAW_SEARCH_BOTH_DIRECTORY_INFO:
-               trans2_grow_data(trans, &trans->out.data, ofs + 94);
-               data = trans->out.data.data + ofs;
-               SIVAL(data,          4, file->both_directory_info.file_index);
-               push_nttime(data,    8, file->both_directory_info.create_time);
-               push_nttime(data,   16, file->both_directory_info.access_time);
-               push_nttime(data,   24, file->both_directory_info.write_time);
-               push_nttime(data,   32, file->both_directory_info.change_time);
-               SBVAL(data,         40, file->both_directory_info.size);
-               SBVAL(data,         48, file->both_directory_info.alloc_size);
-               SIVAL(data,         56, file->both_directory_info.attrib);
-               SIVAL(data,         64, file->both_directory_info.ea_size);
-               SCVAL(data,         69, 0); /* reserved */
-               memset(data+70,0,24);
-               trans2_push_data_string(req, trans, &trans->out.data, 
-                                       68 + ofs, 70 + ofs, 
-                                       &file->both_directory_info.short_name, 
-                                       24, STR_UNICODE | STR_LEN8BIT);
-               trans2_append_data_string(req, trans, &trans->out.data, &file->both_directory_info.name, 
-                                         ofs + 60, STR_TERMINATE_ASCII);
-               trans2_align_data(trans);
-               data = trans->out.data.data + ofs;
-               SIVAL(data,          0, trans->out.data.length - ofs);
+               TRANS2_CHECK(smbsrv_blob_append_string(trans, &trans->out.data, file->ea_list.name.s, 
+                                                      ofs + 22 + ea_size, SMBSRV_REQ_DEFAULT_STR_FLAGS(req),
+                                                      STR_LEN8BIT | STR_NOALIGN));
+               TRANS2_CHECK(smbsrv_blob_fill_data(trans, &trans->out.data, trans->out.data.length + 1));
                break;
 
-       case RAW_SEARCH_ID_FULL_DIRECTORY_INFO:
-               trans2_grow_data(trans, &trans->out.data, ofs + 80);
-               data = trans->out.data.data + ofs;
-               SIVAL(data,          4, file->id_full_directory_info.file_index);
-               push_nttime(data,    8, file->id_full_directory_info.create_time);
-               push_nttime(data,   16, file->id_full_directory_info.access_time);
-               push_nttime(data,   24, file->id_full_directory_info.write_time);
-               push_nttime(data,   32, file->id_full_directory_info.change_time);
-               SBVAL(data,         40, file->id_full_directory_info.size);
-               SBVAL(data,         48, file->id_full_directory_info.alloc_size);
-               SIVAL(data,         56, file->id_full_directory_info.attrib);
-               SIVAL(data,         64, file->id_full_directory_info.ea_size);
-               SIVAL(data,         68, 0); /* padding */
-               SBVAL(data,         72, file->id_full_directory_info.file_id);
-               trans2_append_data_string(req, trans, &trans->out.data, &file->id_full_directory_info.name, 
-                                         ofs + 60, STR_TERMINATE_ASCII);
-               data = trans->out.data.data + ofs;
-               SIVAL(data,          0, trans->out.data.length - ofs);
-               break;
-
-       case RAW_SEARCH_ID_BOTH_DIRECTORY_INFO:
-               trans2_grow_data(trans, &trans->out.data, ofs + 104);
-               data = trans->out.data.data + ofs;
-               SIVAL(data,          4, file->id_both_directory_info.file_index);
-               push_nttime(data,    8, file->id_both_directory_info.create_time);
-               push_nttime(data,   16, file->id_both_directory_info.access_time);
-               push_nttime(data,   24, file->id_both_directory_info.write_time);
-               push_nttime(data,   32, file->id_both_directory_info.change_time);
-               SBVAL(data,         40, file->id_both_directory_info.size);
-               SBVAL(data,         48, file->id_both_directory_info.alloc_size);
-               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,26);
-               trans2_push_data_string(req, trans, &trans->out.data, 
-                                       68 + ofs, 70 + ofs, 
-                                       &file->id_both_directory_info.short_name, 
-                                       24, STR_UNICODE | STR_LEN8BIT);
-               SBVAL(data,         96, file->id_both_directory_info.file_id);
-               trans2_append_data_string(req, trans, &trans->out.data, &file->id_both_directory_info.name, 
-                                         ofs + 60, STR_TERMINATE_ASCII);
-               data = trans->out.data.data + ofs;
-               SIVAL(data,          0, trans->out.data.length - ofs);
-               break;
+       case RAW_SEARCH_DATA_DIRECTORY_INFO:
+       case RAW_SEARCH_DATA_FULL_DIRECTORY_INFO:
+       case RAW_SEARCH_DATA_NAME_INFO:
+       case RAW_SEARCH_DATA_BOTH_DIRECTORY_INFO:
+       case RAW_SEARCH_DATA_ID_FULL_DIRECTORY_INFO:
+       case RAW_SEARCH_DATA_ID_BOTH_DIRECTORY_INFO:
+               return smbsrv_push_passthru_search(trans, &trans->out.data, state->data_level, file,
+                                                  SMBSRV_REQ_DEFAULT_STR_FLAGS(req));
+
+       case RAW_SEARCH_DATA_UNIX_INFO:
+       case RAW_SEARCH_DATA_UNIX_INFO2:
+               return NT_STATUS_INVALID_LEVEL;
        }
 
-       return True;
+       return NT_STATUS_OK;
 }
 
 /* callback function for trans2 findfirst/findnext */
-static BOOL find_callback(void *private, union smb_search_data *file)
+static bool find_callback(void *private_data, const union smb_search_data *file)
 {
-       struct find_state *state = talloc_get_type(private, struct find_state);
+       struct find_state *state = talloc_get_type(private_data, struct find_state);
        struct smb_trans2 *trans = state->op->trans;
-       uint_t old_length;
+       unsigned int old_length;
 
        old_length = trans->out.data.length;
 
-       if (!find_fill_info(state, file) ||
+       if (!NT_STATUS_IS_OK(find_fill_info(state, file)) ||
            trans->out.data.length > trans->in.max_data) {
                /* restore the old length and tell the backend to stop */
-               trans2_grow_data(trans, &trans->out.data, old_length);
-               return False;
+               smbsrv_blob_grow_data(trans, &trans->out.data, old_length);
+               return false;
        }
 
        state->last_entry_offset = old_length;  
-       return True;
+       return true;
 }
 
 /*
@@ -1348,7 +850,6 @@ static NTSTATUS trans2_findfirst(struct smbsrv_request *req, struct trans_op *op
 {
        struct smb_trans2 *trans = op->trans;
        union smb_search_first *search;
-       NTSTATUS status;
        uint16_t level;
        struct find_state *state;
 
@@ -1366,21 +867,21 @@ static NTSTATUS trans2_findfirst(struct smbsrv_request *req, struct trans_op *op
        level                             = SVAL(trans->in.params.data, 6);
        search->t2ffirst.in.storage_type  = IVAL(trans->in.params.data, 8);
 
-       trans2_pull_blob_string(req, &trans->in.params, 12, &search->t2ffirst.in.pattern, 0);
+       smbsrv_blob_pull_string(&req->in.bufinfo, &trans->in.params, 12, &search->t2ffirst.in.pattern, 0);
        if (search->t2ffirst.in.pattern == NULL) {
                return NT_STATUS_FOOBAR;
        }
 
-       search->t2ffirst.level = (enum smb_search_level)level;
-       if (search->t2ffirst.level >= RAW_SEARCH_GENERIC) {
+       search->t2ffirst.level = RAW_SEARCH_TRANS2;
+       search->t2ffirst.data_level = (enum smb_search_data_level)level;
+       if (search->t2ffirst.data_level >= RAW_SEARCH_DATA_GENERIC) {
                return NT_STATUS_INVALID_LEVEL;
        }
 
-       if (search->t2ffirst.level == RAW_SEARCH_EA_LIST) {
-               status = ea_pull_name_list(&trans->in.data, req,
-                                          &search->t2ffirst.in.num_names, 
-                                          &search->t2ffirst.in.ea_names);
-               NT_STATUS_NOT_OK_RETURN(status);
+       if (search->t2ffirst.data_level == RAW_SEARCH_DATA_EA_LIST) {
+               TRANS2_CHECK(ea_pull_name_list(&trans->in.data, req,
+                                              &search->t2ffirst.in.num_names, 
+                                              &search->t2ffirst.in.ea_names));
        }
 
        /* setup the private state structure that the backend will
@@ -1389,12 +890,12 @@ static NTSTATUS trans2_findfirst(struct smbsrv_request *req, struct trans_op *op
        NT_STATUS_HAVE_NO_MEMORY(state);
        state->op               = op;
        state->search           = search;
-       state->level            = search->t2ffirst.level;
+       state->data_level       = search->t2ffirst.data_level;
        state->last_entry_offset= 0;
        state->flags            = search->t2ffirst.in.flags;
 
        /* setup for just a header in the reply */
-       trans2_setup_reply(trans, 10, 0, 0);
+       TRANS2_CHECK(trans2_setup_reply(trans, 10, 0, 0));
 
        op->op_info = state;
        op->send_fn = trans2_findfirst_send;
@@ -1435,7 +936,6 @@ static NTSTATUS trans2_findnext(struct smbsrv_request *req, struct trans_op *op)
 {
        struct smb_trans2 *trans = op->trans;
        union smb_search_next *search;
-       NTSTATUS status;
        uint16_t level;
        struct find_state *state;
 
@@ -1453,21 +953,21 @@ static NTSTATUS trans2_findnext(struct smbsrv_request *req, struct trans_op *op)
        search->t2fnext.in.resume_key    = IVAL(trans->in.params.data, 6);
        search->t2fnext.in.flags         = SVAL(trans->in.params.data, 10);
 
-       trans2_pull_blob_string(req, &trans->in.params, 12, &search->t2fnext.in.last_name, 0);
+       smbsrv_blob_pull_string(&req->in.bufinfo, &trans->in.params, 12, &search->t2fnext.in.last_name, 0);
        if (search->t2fnext.in.last_name == NULL) {
                return NT_STATUS_FOOBAR;
        }
 
-       search->t2fnext.level = (enum smb_search_level)level;
-       if (search->t2fnext.level >= RAW_SEARCH_GENERIC) {
+       search->t2fnext.level = RAW_SEARCH_TRANS2;
+       search->t2fnext.data_level = (enum smb_search_data_level)level;
+       if (search->t2fnext.data_level >= RAW_SEARCH_DATA_GENERIC) {
                return NT_STATUS_INVALID_LEVEL;
        }
 
-       if (search->t2fnext.level == RAW_SEARCH_EA_LIST) {
-               status = ea_pull_name_list(&trans->in.data, req,
-                                          &search->t2fnext.in.num_names, 
-                                          &search->t2fnext.in.ea_names);
-               NT_STATUS_NOT_OK_RETURN(status);
+       if (search->t2fnext.data_level == RAW_SEARCH_DATA_EA_LIST) {
+               TRANS2_CHECK(ea_pull_name_list(&trans->in.data, req,
+                                              &search->t2fnext.in.num_names, 
+                                              &search->t2fnext.in.ea_names));
        }
 
        /* setup the private state structure that the backend will give us in the callback */
@@ -1475,12 +975,12 @@ static NTSTATUS trans2_findnext(struct smbsrv_request *req, struct trans_op *op)
        NT_STATUS_HAVE_NO_MEMORY(state);
        state->op               = op;
        state->search           = search;
-       state->level            = search->t2fnext.level;
+       state->data_level       = search->t2fnext.data_level;
        state->last_entry_offset= 0;
        state->flags            = search->t2fnext.in.flags;
 
        /* setup for just a header in the reply */
-       trans2_setup_reply(trans, 8, 0, 0);
+       TRANS2_CHECK(trans2_setup_reply(trans, 8, 0, 0));
 
        op->op_info = state;
        op->send_fn = trans2_findnext_send;
@@ -1534,6 +1034,12 @@ static NTSTATUS trans2_backend(struct smbsrv_request *req, struct trans_op *op)
        return NT_STATUS_FOOBAR;
 }
 
+int smbsrv_trans_partial_destructor(struct smbsrv_trans_partial *tp)
+{
+       DLIST_REMOVE(tp->req->smb_conn->trans_partial, tp);
+       return 0;
+}
+
 
 /*
   send a continue request
@@ -1541,6 +1047,7 @@ static NTSTATUS trans2_backend(struct smbsrv_request *req, struct trans_op *op)
 static void reply_trans_continue(struct smbsrv_request *req, uint8_t command,
                                 struct smb_trans2 *trans)
 {
+       struct smbsrv_request *req2;
        struct smbsrv_trans_partial *tp;
        int count;
 
@@ -1553,15 +1060,18 @@ static void reply_trans_continue(struct smbsrv_request *req, uint8_t command,
 
        tp = talloc(req, struct smbsrv_trans_partial);
 
-       tp->req = talloc_reference(tp, req);
-       tp->trans = trans;
+       tp->req = req;
+       tp->u.trans = trans;
        tp->command = command;
 
        DLIST_ADD(req->smb_conn->trans_partial, tp);
+       talloc_set_destructor(tp, smbsrv_trans_partial_destructor);
+
+       req2 = smbsrv_setup_secondary_request(req);
 
        /* send a 'please continue' reply */
-       smbsrv_setup_reply(req, 0, 0);
-       smbsrv_send_reply(req);
+       smbsrv_setup_reply(req2, 0, 0);
+       smbsrv_send_reply(req2);
 }
 
 
@@ -1606,7 +1116,7 @@ static void reply_trans_send(struct ntvfs_request *ntvfs)
           the negotiated buffer size */
        do {
                uint16_t this_data, this_param, max_bytes;
-               uint_t align1 = 1, align2 = (params_left ? 2 : 0);
+               unsigned int align1 = 1, align2 = (params_left ? 2 : 0);
                struct smbsrv_request *this_req;
 
                max_bytes = req_max_data(req) - (align1 + align2);
@@ -1645,7 +1155,8 @@ static void reply_trans_send(struct ntvfs_request *ntvfs)
                      PTR_DIFF(this_req->out.data + this_param, this_req->out.hdr));
                SSVAL(this_req->out.vwv, VWV(8), PTR_DIFF(data, trans->out.data.data));
 
-               SSVAL(this_req->out.vwv, VWV(9), trans->out.setup_count);
+               SCVAL(this_req->out.vwv, VWV(9), trans->out.setup_count);
+               SCVAL(this_req->out.vwv, VWV(9)+1, 0); /* reserved */
                for (i=0;i<trans->out.setup_count;i++) {
                        SSVAL(this_req->out.vwv, VWV(10+i), trans->out.setup[i]);
                }
@@ -1748,11 +1259,11 @@ static void reply_trans_generic(struct smbsrv_request *req, uint8_t command)
        }
 
        if (command == SMBtrans) {
-               req_pull_string(req, &trans->in.trans_name, req->in.data, -1, STR_TERMINATE);
+               req_pull_string(&req->in.bufinfo, &trans->in.trans_name, req->in.data, -1, STR_TERMINATE);
        }
 
-       if (!req_pull_blob(req, req->in.hdr + param_ofs, param_count, &trans->in.params) ||
-           !req_pull_blob(req, req->in.hdr + data_ofs, data_count, &trans->in.data)) {
+       if (!req_pull_blob(&req->in.bufinfo, req->in.hdr + param_ofs, param_count, &trans->in.params) ||
+           !req_pull_blob(&req->in.bufinfo, req->in.hdr + data_ofs, data_count, &trans->in.data)) {
                smbsrv_send_error(req, NT_STATUS_FOOBAR);
                return;
        }
@@ -1779,9 +1290,20 @@ static void reply_transs_generic(struct smbsrv_request *req, uint8_t command)
        uint16_t param_disp, data_disp;
        uint16_t param_total, data_total;
        DATA_BLOB params, data;
+       uint8_t wct;
+
+       if (command == SMBtrans2) {
+               wct = 9;
+       } else {
+               wct = 8;
+       }
 
        /* parse request */
-       if (req->in.wct < 8) {
+       if (req->in.wct != wct) {
+               /*
+                * TODO: add some error code tests
+                *       w2k3 returns NT_STATUS_DOS(ERRSRV, ERRerror) here
+                */
                smbsrv_send_error(req, NT_STATUS_INVALID_PARAMETER);
                return;
        }
@@ -1799,7 +1321,7 @@ static void reply_transs_generic(struct smbsrv_request *req, uint8_t command)
                return;
        }
 
-       trans = tp->trans;
+       trans = tp->u.trans;
 
        param_total           = SVAL(req->in.vwv, VWV(0));
        data_total            = SVAL(req->in.vwv, VWV(1));
@@ -1810,8 +1332,8 @@ static void reply_transs_generic(struct smbsrv_request *req, uint8_t command)
        data_ofs              = SVAL(req->in.vwv, VWV(6));
        data_disp             = SVAL(req->in.vwv, VWV(7));
 
-       if (!req_pull_blob(req, req->in.hdr + param_ofs, param_count, &params) ||
-           !req_pull_blob(req, req->in.hdr + data_ofs, data_count, &data)) {
+       if (!req_pull_blob(&req->in.bufinfo, req->in.hdr + param_ofs, param_count, &params) ||
+           !req_pull_blob(&req->in.bufinfo, req->in.hdr + data_ofs, data_count, &data)) {
                smbsrv_send_error(req, NT_STATUS_INVALID_PARAMETER);
                return;
        }
@@ -1832,7 +1354,8 @@ static void reply_transs_generic(struct smbsrv_request *req, uint8_t command)
                                                         uint8_t, 
                                                         param_disp + param_count);
                if (trans->in.params.data == NULL) {
-                       goto failed;
+                       smbsrv_send_error(tp->req, NT_STATUS_NO_MEMORY);
+                       return;
                }
                trans->in.params.length = param_disp + param_count;
        }
@@ -1843,7 +1366,8 @@ static void reply_transs_generic(struct smbsrv_request *req, uint8_t command)
                                                       uint8_t, 
                                                       data_disp + data_count);
                if (trans->in.data.data == NULL) {
-                       goto failed;
+                       smbsrv_send_error(tp->req, NT_STATUS_NO_MEMORY);
+                       return;
                }
                trans->in.data.length = data_disp + data_count;
        }
@@ -1861,16 +1385,11 @@ static void reply_transs_generic(struct smbsrv_request *req, uint8_t command)
        if (trans->in.params.length == param_total &&
            trans->in.data.length == data_total) {
                /* its now complete */
-               DLIST_REMOVE(tp->req->smb_conn->trans_partial, tp);
-               reply_trans_complete(tp->req, command, trans);
+               req = tp->req;
+               talloc_free(tp);
+               reply_trans_complete(req, command, trans);
        }
        return;
-
-failed:        
-       smbsrv_send_error(tp->req, NT_STATUS_NO_MEMORY);
-       DLIST_REMOVE(req->smb_conn->trans_partial, tp);
-       talloc_free(req);
-       talloc_free(tp);
 }