2 Unix SMB/CIFS implementation.
4 Copyright (C) Andrew Tridgell 2003
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9 (at your option) any later version.
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
21 This file handles the parsing of transact2 requests
25 #include "dlinklist.h"
26 #include "smb_server/smb_server.h"
27 #include "librpc/gen_ndr/ndr_misc.h"
28 #include "ntvfs/ntvfs.h"
29 #include "libcli/raw/libcliraw.h"
31 #define TRANS2_CHECK_ASYNC_STATUS_SIMPLE do { \
32 if (!NT_STATUS_IS_OK(req->ntvfs->async_states->status)) { \
33 trans2_setup_reply(trans, 0, 0, 0);\
34 return req->ntvfs->async_states->status; \
37 #define TRANS2_CHECK_ASYNC_STATUS(ptr, type) do { \
38 TRANS2_CHECK_ASYNC_STATUS_SIMPLE; \
39 ptr = talloc_get_type(op->op_info, type); \
41 #define TRANS2_CHECK(cmd) do { \
44 NT_STATUS_NOT_OK_RETURN(_status); \
48 hold the state of a nttrans op while in progress. Needed to allow for async backend
52 struct smbsrv_request *req;
53 struct smb_trans2 *trans;
55 NTSTATUS (*send_fn)(struct trans_op *);
59 #define CHECK_MIN_BLOB_SIZE(blob, size) do { \
60 if ((blob)->length < (size)) { \
61 return NT_STATUS_INFO_LENGTH_MISMATCH; \
64 /* grow the data size of a trans2 reply */
65 static NTSTATUS trans2_grow_data(TALLOC_CTX *mem_ctx,
69 if (new_size > blob->length) {
71 p = talloc_realloc(mem_ctx, blob->data, uint8_t, new_size);
72 NT_STATUS_HAVE_NO_MEMORY(p);
75 blob->length = new_size;
79 /* grow the data, zero filling any new bytes */
80 static NTSTATUS trans2_grow_data_fill(TALLOC_CTX *mem_ctx,
84 uint32_t old_size = blob->length;
85 TRANS2_CHECK(trans2_grow_data(mem_ctx, blob, new_size));
86 if (new_size > old_size) {
87 memset(blob->data + old_size, 0, new_size - old_size);
93 /* setup a trans2 reply, given the data and params sizes */
94 static NTSTATUS trans2_setup_reply(struct smb_trans2 *trans,
95 uint16_t param_size, uint16_t data_size,
98 trans->out.setup_count = setup_count;
99 if (setup_count > 0) {
100 trans->out.setup = talloc_zero_array(trans, uint16_t, setup_count);
101 NT_STATUS_HAVE_NO_MEMORY(trans->out.setup);
103 trans->out.params = data_blob_talloc(trans, NULL, param_size);
104 if (param_size > 0) NT_STATUS_HAVE_NO_MEMORY(trans->out.params.data);
106 trans->out.data = data_blob_talloc(trans, NULL, data_size);
107 if (data_size > 0) NT_STATUS_HAVE_NO_MEMORY(trans->out.data.data);
114 pull a string from a blob in a trans2 request
116 static size_t trans2_pull_blob_string(struct smbsrv_request *req,
117 const DATA_BLOB *blob,
123 /* we use STR_NO_RANGE_CHECK because the params are allocated
124 separately in a DATA_BLOB, so we need to do our own range
126 if (offset >= blob->length) {
130 return req_pull_string(req, str,
132 blob->length - offset,
133 STR_NO_RANGE_CHECK | flags);
136 #define TRANS2_REQ_DEFAULT_STR_FLAGS(req) (((req)->flags2 & FLAGS2_UNICODE_STRINGS) ? STR_UNICODE : STR_ASCII)
139 push a string into the data section of a trans2 request
140 return the number of bytes consumed in the output
142 static size_t trans2_push_data_string(TALLOC_CTX *mem_ctx,
151 int alignment = 0, ret = 0, pkt_len;
153 /* we use STR_NO_RANGE_CHECK because the params are allocated
154 separately in a DATA_BLOB, so we need to do our own range
156 if (!str || offset >= blob->length) {
157 if (flags & STR_LEN8BIT) {
158 SCVAL(blob->data, len_offset, 0);
160 SIVAL(blob->data, len_offset, 0);
165 flags |= STR_NO_RANGE_CHECK;
167 if (dest_len == -1 || (dest_len > blob->length - offset)) {
168 dest_len = blob->length - offset;
171 if (!(flags & (STR_ASCII|STR_UNICODE))) {
172 flags |= default_flags;
175 if ((offset&1) && (flags & STR_UNICODE) && !(flags & STR_NOALIGN)) {
178 SCVAL(blob->data + offset, 0, 0);
179 ret = push_string(blob->data + offset + 1, str, dest_len-1, flags);
182 ret = push_string(blob->data + offset, str, dest_len, flags);
185 /* sometimes the string needs to be terminated, but the length
186 on the wire must not include the termination! */
189 if ((flags & STR_LEN_NOTERM) && (flags & STR_TERMINATE)) {
190 if ((flags & STR_UNICODE) && ret >= 2) {
193 if ((flags & STR_ASCII) && ret >= 1) {
198 if (flags & STR_LEN8BIT) {
199 SCVAL(blob->data, len_offset, pkt_len);
201 SIVAL(blob->data, len_offset, pkt_len);
204 return ret + alignment;
208 append a string to the data section of a trans2 reply
209 len_offset points to the place in the packet where the length field
212 static NTSTATUS trans2_append_data_string(TALLOC_CTX *mem_ctx,
221 const int max_bytes_per_char = 3;
223 offset = blob->length;
224 TRANS2_CHECK(trans2_grow_data(mem_ctx, blob, offset + (2+strlen_m(str))*max_bytes_per_char));
225 ret = trans2_push_data_string(mem_ctx, blob, len_offset, offset, str, -1, default_flags, flags);
227 return NT_STATUS_FOOBAR;
229 TRANS2_CHECK(trans2_grow_data(mem_ctx, blob, offset + ret));
234 align the end of the data section of a trans reply on an even boundary
236 static NTSTATUS trans2_align_data(struct smb_trans2 *trans)
238 if (trans->out.data.length & 1) {
239 TRANS2_CHECK(trans2_grow_data_fill(trans, &trans->out.data, trans->out.data.length+1));
244 static NTSTATUS trans2_push_fsinfo(struct smbsrv_connection *smb_conn,
247 union smb_fsinfo *fsinfo,
248 int default_str_flags)
253 switch (fsinfo->generic.level) {
254 case SMB_QFS_ALLOCATION:
255 TRANS2_CHECK(trans2_grow_data(mem_ctx, blob, 18));
257 SIVAL(blob->data, 0, fsinfo->allocation.out.fs_id);
258 SIVAL(blob->data, 4, fsinfo->allocation.out.sectors_per_unit);
259 SIVAL(blob->data, 8, fsinfo->allocation.out.total_alloc_units);
260 SIVAL(blob->data, 12, fsinfo->allocation.out.avail_alloc_units);
261 SSVAL(blob->data, 16, fsinfo->allocation.out.bytes_per_sector);
266 TRANS2_CHECK(trans2_grow_data(mem_ctx, blob, 5));
268 SIVAL(blob->data, 0, fsinfo->volume.out.serial_number);
269 /* w2k3 implements this incorrectly for unicode - it
270 * leaves the last byte off the string */
271 TRANS2_CHECK(trans2_append_data_string(mem_ctx, blob,
272 fsinfo->volume.out.volume_name.s,
273 4, default_str_flags,
274 STR_LEN8BIT|STR_NOALIGN));
278 case SMB_QFS_VOLUME_INFO:
279 case SMB_QFS_VOLUME_INFORMATION:
280 TRANS2_CHECK(trans2_grow_data(mem_ctx, blob, 18));
282 push_nttime(blob->data, 0, fsinfo->volume_info.out.create_time);
283 SIVAL(blob->data, 8, fsinfo->volume_info.out.serial_number);
284 SSVAL(blob->data, 16, 0); /* padding */
285 TRANS2_CHECK(trans2_append_data_string(mem_ctx, blob,
286 fsinfo->volume_info.out.volume_name.s,
287 12, default_str_flags,
292 case SMB_QFS_SIZE_INFO:
293 case SMB_QFS_SIZE_INFORMATION:
294 TRANS2_CHECK(trans2_grow_data(mem_ctx, blob, 24));
296 SBVAL(blob->data, 0, fsinfo->size_info.out.total_alloc_units);
297 SBVAL(blob->data, 8, fsinfo->size_info.out.avail_alloc_units);
298 SIVAL(blob->data, 16, fsinfo->size_info.out.sectors_per_unit);
299 SIVAL(blob->data, 20, fsinfo->size_info.out.bytes_per_sector);
303 case SMB_QFS_DEVICE_INFO:
304 case SMB_QFS_DEVICE_INFORMATION:
305 TRANS2_CHECK(trans2_grow_data(mem_ctx, blob, 8));
307 SIVAL(blob->data, 0, fsinfo->device_info.out.device_type);
308 SIVAL(blob->data, 4, fsinfo->device_info.out.characteristics);
312 case SMB_QFS_ATTRIBUTE_INFO:
313 case SMB_QFS_ATTRIBUTE_INFORMATION:
314 TRANS2_CHECK(trans2_grow_data(mem_ctx, blob, 12));
316 SIVAL(blob->data, 0, fsinfo->attribute_info.out.fs_attr);
317 SIVAL(blob->data, 4, fsinfo->attribute_info.out.max_file_component_length);
318 /* this must not be null terminated or win98 gets
319 confused! also note that w2k3 returns this as
320 unicode even when ascii is negotiated */
321 TRANS2_CHECK(trans2_append_data_string(mem_ctx, blob,
322 fsinfo->attribute_info.out.fs_type.s,
323 8, default_str_flags,
328 case SMB_QFS_QUOTA_INFORMATION:
329 TRANS2_CHECK(trans2_grow_data(mem_ctx, blob, 48));
331 SBVAL(blob->data, 0, fsinfo->quota_information.out.unknown[0]);
332 SBVAL(blob->data, 8, fsinfo->quota_information.out.unknown[1]);
333 SBVAL(blob->data, 16, fsinfo->quota_information.out.unknown[2]);
334 SBVAL(blob->data, 24, fsinfo->quota_information.out.quota_soft);
335 SBVAL(blob->data, 32, fsinfo->quota_information.out.quota_hard);
336 SBVAL(blob->data, 40, fsinfo->quota_information.out.quota_flags);
341 case SMB_QFS_FULL_SIZE_INFORMATION:
342 TRANS2_CHECK(trans2_grow_data(mem_ctx, blob, 32));
344 SBVAL(blob->data, 0, fsinfo->full_size_information.out.total_alloc_units);
345 SBVAL(blob->data, 8, fsinfo->full_size_information.out.call_avail_alloc_units);
346 SBVAL(blob->data, 16, fsinfo->full_size_information.out.actual_avail_alloc_units);
347 SIVAL(blob->data, 24, fsinfo->full_size_information.out.sectors_per_unit);
348 SIVAL(blob->data, 28, fsinfo->full_size_information.out.bytes_per_sector);
352 case SMB_QFS_OBJECTID_INFORMATION:
353 TRANS2_CHECK(trans2_grow_data(mem_ctx, blob, 64));
355 TRANS2_CHECK(ndr_push_struct_blob(&guid_blob, mem_ctx,
356 &fsinfo->objectid_information.out.guid,
357 (ndr_push_flags_fn_t)ndr_push_GUID));
358 memcpy(blob->data, guid_blob.data, guid_blob.length);
361 SBVAL(blob->data, 16 + 8*i, fsinfo->objectid_information.out.unknown[i]);
367 return NT_STATUS_INVALID_LEVEL;
371 trans2 qfsinfo implementation send
373 static NTSTATUS trans2_qfsinfo_send(struct trans_op *op)
375 struct smbsrv_request *req = op->req;
376 struct smb_trans2 *trans = op->trans;
377 union smb_fsinfo *fsinfo;
379 TRANS2_CHECK_ASYNC_STATUS(fsinfo, union smb_fsinfo);
381 TRANS2_CHECK(trans2_setup_reply(trans, 0, 0, 0));
383 TRANS2_CHECK(trans2_push_fsinfo(req->smb_conn, trans,
384 &trans->out.data, fsinfo,
385 TRANS2_REQ_DEFAULT_STR_FLAGS(req)));
391 trans2 qfsinfo implementation
393 static NTSTATUS trans2_qfsinfo(struct smbsrv_request *req, struct trans_op *op)
395 struct smb_trans2 *trans = op->trans;
396 union smb_fsinfo *fsinfo;
399 /* make sure we got enough parameters */
400 if (trans->in.params.length != 2) {
401 return NT_STATUS_FOOBAR;
404 fsinfo = talloc(op, union smb_fsinfo);
405 NT_STATUS_HAVE_NO_MEMORY(fsinfo);
407 op->op_info = fsinfo;
408 op->send_fn = trans2_qfsinfo_send;
410 level = SVAL(trans->in.params.data, 0);
413 case SMB_QFS_ALLOCATION:
414 fsinfo->allocation.level = RAW_QFS_ALLOCATION;
415 return ntvfs_fsinfo(req->ntvfs, fsinfo);
418 fsinfo->volume.level = RAW_QFS_VOLUME;
419 return ntvfs_fsinfo(req->ntvfs, fsinfo);
421 case SMB_QFS_VOLUME_INFO:
422 case SMB_QFS_VOLUME_INFORMATION:
423 fsinfo->volume_info.level = RAW_QFS_VOLUME_INFO;
424 return ntvfs_fsinfo(req->ntvfs, fsinfo);
426 case SMB_QFS_SIZE_INFO:
427 case SMB_QFS_SIZE_INFORMATION:
428 fsinfo->size_info.level = RAW_QFS_SIZE_INFO;
429 return ntvfs_fsinfo(req->ntvfs, fsinfo);
431 case SMB_QFS_DEVICE_INFO:
432 case SMB_QFS_DEVICE_INFORMATION:
433 fsinfo->device_info.level = RAW_QFS_DEVICE_INFO;
434 return ntvfs_fsinfo(req->ntvfs, fsinfo);
436 case SMB_QFS_ATTRIBUTE_INFO:
437 case SMB_QFS_ATTRIBUTE_INFORMATION:
438 fsinfo->attribute_info.level = RAW_QFS_ATTRIBUTE_INFO;
439 return ntvfs_fsinfo(req->ntvfs, fsinfo);
441 case SMB_QFS_QUOTA_INFORMATION:
442 fsinfo->quota_information.level = RAW_QFS_QUOTA_INFORMATION;
443 return ntvfs_fsinfo(req->ntvfs, fsinfo);
445 case SMB_QFS_FULL_SIZE_INFORMATION:
446 fsinfo->full_size_information.level = RAW_QFS_FULL_SIZE_INFORMATION;
447 return ntvfs_fsinfo(req->ntvfs, fsinfo);
449 case SMB_QFS_OBJECTID_INFORMATION:
450 fsinfo->objectid_information.level = RAW_QFS_OBJECTID_INFORMATION;
451 return ntvfs_fsinfo(req->ntvfs, fsinfo);
454 return NT_STATUS_INVALID_LEVEL;
459 trans2 open implementation send
461 static NTSTATUS trans2_open_send(struct trans_op *op)
463 struct smbsrv_request *req = op->req;
464 struct smb_trans2 *trans = op->trans;
467 TRANS2_CHECK_ASYNC_STATUS(io, union smb_open);
469 TRANS2_CHECK(trans2_setup_reply(trans, 30, 0, 0));
471 smbsrv_push_fnum(trans->out.params.data, VWV(0), io->t2open.out.file.ntvfs);
472 SSVAL(trans->out.params.data, VWV(1), io->t2open.out.attrib);
473 srv_push_dos_date3(req->smb_conn, trans->out.params.data,
474 VWV(2), io->t2open.out.write_time);
475 SIVAL(trans->out.params.data, VWV(4), io->t2open.out.size);
476 SSVAL(trans->out.params.data, VWV(6), io->t2open.out.access);
477 SSVAL(trans->out.params.data, VWV(7), io->t2open.out.ftype);
478 SSVAL(trans->out.params.data, VWV(8), io->t2open.out.devstate);
479 SSVAL(trans->out.params.data, VWV(9), io->t2open.out.action);
480 SIVAL(trans->out.params.data, VWV(10), 0); /* reserved */
481 SSVAL(trans->out.params.data, VWV(12), 0); /* EaErrorOffset */
482 SIVAL(trans->out.params.data, VWV(13), 0); /* EaLength */
488 trans2 open implementation
490 static NTSTATUS trans2_open(struct smbsrv_request *req, struct trans_op *op)
492 struct smb_trans2 *trans = op->trans;
495 /* make sure we got enough parameters */
496 if (trans->in.params.length < 29) {
497 return NT_STATUS_FOOBAR;
500 io = talloc(op, union smb_open);
501 NT_STATUS_HAVE_NO_MEMORY(io);
503 io->t2open.level = RAW_OPEN_T2OPEN;
504 io->t2open.in.flags = SVAL(trans->in.params.data, VWV(0));
505 io->t2open.in.open_mode = SVAL(trans->in.params.data, VWV(1));
506 io->t2open.in.search_attrs = SVAL(trans->in.params.data, VWV(2));
507 io->t2open.in.file_attrs = SVAL(trans->in.params.data, VWV(3));
508 io->t2open.in.write_time = srv_pull_dos_date(req->smb_conn,
509 trans->in.params.data + VWV(4));;
510 io->t2open.in.open_func = SVAL(trans->in.params.data, VWV(6));
511 io->t2open.in.size = IVAL(trans->in.params.data, VWV(7));
512 io->t2open.in.timeout = IVAL(trans->in.params.data, VWV(9));
513 io->t2open.in.num_eas = 0;
514 io->t2open.in.eas = NULL;
516 trans2_pull_blob_string(req, &trans->in.params, 28, &io->t2open.in.fname, 0);
517 if (io->t2open.in.fname == NULL) {
518 return NT_STATUS_FOOBAR;
521 TRANS2_CHECK(ea_pull_list(&trans->in.data, io, &io->t2open.in.num_eas, &io->t2open.in.eas));
524 op->send_fn = trans2_open_send;
526 return ntvfs_open(req->ntvfs, io);
533 static NTSTATUS trans2_simple_send(struct trans_op *op)
535 struct smbsrv_request *req = op->req;
536 struct smb_trans2 *trans = op->trans;
538 TRANS2_CHECK_ASYNC_STATUS_SIMPLE;
540 TRANS2_CHECK(trans2_setup_reply(trans, 2, 0, 0));
542 SSVAL(trans->out.params.data, VWV(0), 0);
548 trans2 mkdir implementation
550 static NTSTATUS trans2_mkdir(struct smbsrv_request *req, struct trans_op *op)
552 struct smb_trans2 *trans = op->trans;
555 /* make sure we got enough parameters */
556 if (trans->in.params.length < 5) {
557 return NT_STATUS_FOOBAR;
560 io = talloc(op, union smb_mkdir);
561 NT_STATUS_HAVE_NO_MEMORY(io);
563 io->t2mkdir.level = RAW_MKDIR_T2MKDIR;
564 trans2_pull_blob_string(req, &trans->in.params, 4, &io->t2mkdir.in.path, 0);
565 if (io->t2mkdir.in.path == NULL) {
566 return NT_STATUS_FOOBAR;
569 TRANS2_CHECK(ea_pull_list(&trans->in.data, io,
570 &io->t2mkdir.in.num_eas,
571 &io->t2mkdir.in.eas));
574 op->send_fn = trans2_simple_send;
576 return ntvfs_mkdir(req->ntvfs, io);
579 static NTSTATUS trans2_push_passthru_fileinfo(TALLOC_CTX *mem_ctx,
581 enum smb_fileinfo_level level,
582 union smb_fileinfo *st,
583 int default_str_flags)
589 case RAW_FILEINFO_BASIC_INFORMATION:
590 TRANS2_CHECK(trans2_grow_data(mem_ctx, blob, 40));
592 push_nttime(blob->data, 0, st->basic_info.out.create_time);
593 push_nttime(blob->data, 8, st->basic_info.out.access_time);
594 push_nttime(blob->data, 16, st->basic_info.out.write_time);
595 push_nttime(blob->data, 24, st->basic_info.out.change_time);
596 SIVAL(blob->data, 32, st->basic_info.out.attrib);
597 SIVAL(blob->data, 36, 0); /* padding */
600 case RAW_FILEINFO_NETWORK_OPEN_INFORMATION:
601 TRANS2_CHECK(trans2_grow_data(mem_ctx, blob, 56));
603 push_nttime(blob->data, 0, st->network_open_information.out.create_time);
604 push_nttime(blob->data, 8, st->network_open_information.out.access_time);
605 push_nttime(blob->data, 16, st->network_open_information.out.write_time);
606 push_nttime(blob->data, 24, st->network_open_information.out.change_time);
607 SBVAL(blob->data, 32, st->network_open_information.out.alloc_size);
608 SBVAL(blob->data, 40, st->network_open_information.out.size);
609 SIVAL(blob->data, 48, st->network_open_information.out.attrib);
610 SIVAL(blob->data, 52, 0); /* padding */
613 case RAW_FILEINFO_STANDARD_INFORMATION:
614 TRANS2_CHECK(trans2_grow_data(mem_ctx, blob, 24));
616 SBVAL(blob->data, 0, st->standard_info.out.alloc_size);
617 SBVAL(blob->data, 8, st->standard_info.out.size);
618 SIVAL(blob->data, 16, st->standard_info.out.nlink);
619 SCVAL(blob->data, 20, st->standard_info.out.delete_pending);
620 SCVAL(blob->data, 21, st->standard_info.out.directory);
621 SSVAL(blob->data, 22, 0); /* padding */
624 case RAW_FILEINFO_ATTRIBUTE_TAG_INFORMATION:
625 TRANS2_CHECK(trans2_grow_data(mem_ctx, blob, 8));
627 SIVAL(blob->data, 0, st->attribute_tag_information.out.attrib);
628 SIVAL(blob->data, 4, st->attribute_tag_information.out.reparse_tag);
631 case RAW_FILEINFO_EA_INFORMATION:
632 TRANS2_CHECK(trans2_grow_data(mem_ctx, blob, 4));
634 SIVAL(blob->data, 0, st->ea_info.out.ea_size);
637 case RAW_FILEINFO_MODE_INFORMATION:
638 TRANS2_CHECK(trans2_grow_data(mem_ctx, blob, 4));
640 SIVAL(blob->data, 0, st->mode_information.out.mode);
643 case RAW_FILEINFO_ALIGNMENT_INFORMATION:
644 TRANS2_CHECK(trans2_grow_data(mem_ctx, blob, 4));
647 st->alignment_information.out.alignment_requirement);
650 case RAW_FILEINFO_ACCESS_INFORMATION:
651 TRANS2_CHECK(trans2_grow_data(mem_ctx, blob, 4));
653 SIVAL(blob->data, 0, st->access_information.out.access_flags);
656 case RAW_FILEINFO_POSITION_INFORMATION:
657 TRANS2_CHECK(trans2_grow_data(mem_ctx, blob, 8));
659 SBVAL(blob->data, 0, st->position_information.out.position);
662 case RAW_FILEINFO_COMPRESSION_INFORMATION:
663 TRANS2_CHECK(trans2_grow_data(mem_ctx, blob, 16));
665 SBVAL(blob->data, 0, st->compression_info.out.compressed_size);
666 SSVAL(blob->data, 8, st->compression_info.out.format);
667 SCVAL(blob->data, 10, st->compression_info.out.unit_shift);
668 SCVAL(blob->data, 11, st->compression_info.out.chunk_shift);
669 SCVAL(blob->data, 12, st->compression_info.out.cluster_shift);
670 SSVAL(blob->data, 13, 0); /* 3 bytes padding */
671 SCVAL(blob->data, 15, 0);
674 case RAW_FILEINFO_INTERNAL_INFORMATION:
675 TRANS2_CHECK(trans2_grow_data(mem_ctx, blob, 8));
677 SBVAL(blob->data, 0, st->internal_information.out.file_id);
680 case RAW_FILEINFO_ALL_INFORMATION:
681 TRANS2_CHECK(trans2_grow_data(mem_ctx, blob, 72));
683 push_nttime(blob->data, 0, st->all_info.out.create_time);
684 push_nttime(blob->data, 8, st->all_info.out.access_time);
685 push_nttime(blob->data, 16, st->all_info.out.write_time);
686 push_nttime(blob->data, 24, st->all_info.out.change_time);
687 SIVAL(blob->data, 32, st->all_info.out.attrib);
688 SIVAL(blob->data, 36, 0); /* padding */
689 SBVAL(blob->data, 40, st->all_info.out.alloc_size);
690 SBVAL(blob->data, 48, st->all_info.out.size);
691 SIVAL(blob->data, 56, st->all_info.out.nlink);
692 SCVAL(blob->data, 60, st->all_info.out.delete_pending);
693 SCVAL(blob->data, 61, st->all_info.out.directory);
694 SSVAL(blob->data, 62, 0); /* padding */
695 SIVAL(blob->data, 64, st->all_info.out.ea_size);
696 TRANS2_CHECK(trans2_append_data_string(mem_ctx, blob,
697 st->all_info.out.fname.s,
698 68, default_str_flags,
702 case RAW_FILEINFO_NAME_INFORMATION:
703 TRANS2_CHECK(trans2_grow_data(mem_ctx, blob, 4));
705 TRANS2_CHECK(trans2_append_data_string(mem_ctx, blob,
706 st->name_info.out.fname.s,
707 0, default_str_flags,
711 case RAW_FILEINFO_ALT_NAME_INFORMATION:
712 TRANS2_CHECK(trans2_grow_data(mem_ctx, blob, 4));
714 TRANS2_CHECK(trans2_append_data_string(mem_ctx, blob,
715 st->alt_name_info.out.fname.s,
716 0, default_str_flags,
720 case RAW_FILEINFO_STREAM_INFORMATION:
721 for (i=0;i<st->stream_info.out.num_streams;i++) {
722 uint32_t data_size = blob->length;
725 TRANS2_CHECK(trans2_grow_data(mem_ctx, blob, data_size + 24));
726 data = blob->data + data_size;
727 SBVAL(data, 8, st->stream_info.out.streams[i].size);
728 SBVAL(data, 16, st->stream_info.out.streams[i].alloc_size);
729 TRANS2_CHECK(trans2_append_data_string(mem_ctx, blob,
730 st->stream_info.out.streams[i].stream_name.s,
731 data_size + 4, default_str_flags,
733 if (i == st->stream_info.out.num_streams - 1) {
734 SIVAL(blob->data, data_size, 0);
736 TRANS2_CHECK(trans2_grow_data_fill(mem_ctx, blob, (blob->length+7)&~7));
737 SIVAL(blob->data, data_size,
738 blob->length - data_size);
743 case RAW_FILEINFO_SMB2_ALL_EAS:
744 list_size = ea_list_size_chained(st->all_eas.out.num_eas,
745 st->all_eas.out.eas);
746 TRANS2_CHECK(trans2_grow_data(mem_ctx, blob, list_size));
748 ea_put_list_chained(blob->data,
749 st->all_eas.out.num_eas,
750 st->all_eas.out.eas);
753 case RAW_FILEINFO_SMB2_ALL_INFORMATION:
754 TRANS2_CHECK(trans2_grow_data(mem_ctx, blob, 0x64));
756 push_nttime(blob->data, 0x00, st->all_info2.out.create_time);
757 push_nttime(blob->data, 0x08, st->all_info2.out.access_time);
758 push_nttime(blob->data, 0x10, st->all_info2.out.write_time);
759 push_nttime(blob->data, 0x18, st->all_info2.out.change_time);
760 SIVAL(blob->data, 0x20, st->all_info2.out.attrib);
761 SIVAL(blob->data, 0x24, st->all_info2.out.unknown1);
762 SBVAL(blob->data, 0x28, st->all_info2.out.alloc_size);
763 SBVAL(blob->data, 0x30, st->all_info2.out.size);
764 SIVAL(blob->data, 0x38, st->all_info2.out.nlink);
765 SCVAL(blob->data, 0x3C, st->all_info2.out.delete_pending);
766 SCVAL(blob->data, 0x3D, st->all_info2.out.directory);
767 SBVAL(blob->data, 0x40, st->all_info2.out.file_id);
768 SIVAL(blob->data, 0x48, st->all_info2.out.ea_size);
769 SIVAL(blob->data, 0x4C, st->all_info2.out.access_mask);
770 SBVAL(blob->data, 0x50, st->all_info2.out.position);
771 SBVAL(blob->data, 0x58, st->all_info2.out.mode);
772 TRANS2_CHECK(trans2_append_data_string(mem_ctx, blob,
773 st->all_info.out.fname.s,
774 0x60, default_str_flags,
779 return NT_STATUS_INVALID_LEVEL;
782 return NT_STATUS_INVALID_LEVEL;
785 static NTSTATUS trans2_push_fileinfo(struct smbsrv_connection *smb_conn,
788 union smb_fileinfo *st,
789 int default_str_flags)
792 enum smb_fileinfo_level passthru_level;
794 switch (st->generic.level) {
795 case RAW_FILEINFO_GENERIC:
796 case RAW_FILEINFO_GETATTR:
797 case RAW_FILEINFO_GETATTRE:
798 case RAW_FILEINFO_SEC_DESC:
799 case RAW_FILEINFO_SMB2_ALL_EAS:
800 case RAW_FILEINFO_SMB2_ALL_INFORMATION:
801 /* handled elsewhere */
802 return NT_STATUS_INVALID_LEVEL;
804 case RAW_FILEINFO_UNIX_BASIC:
805 case RAW_FILEINFO_UNIX_LINK:
806 /* not implemented yet */
807 return NT_STATUS_INVALID_LEVEL;
809 case RAW_FILEINFO_STANDARD:
810 TRANS2_CHECK(trans2_grow_data(mem_ctx, blob, 22));
812 srv_push_dos_date2(smb_conn, blob->data, 0, st->standard.out.create_time);
813 srv_push_dos_date2(smb_conn, blob->data, 4, st->standard.out.access_time);
814 srv_push_dos_date2(smb_conn, blob->data, 8, st->standard.out.write_time);
815 SIVAL(blob->data, 12, st->standard.out.size);
816 SIVAL(blob->data, 16, st->standard.out.alloc_size);
817 SSVAL(blob->data, 20, st->standard.out.attrib);
820 case RAW_FILEINFO_EA_SIZE:
821 TRANS2_CHECK(trans2_grow_data(mem_ctx, blob, 26));
823 srv_push_dos_date2(smb_conn, blob->data, 0, st->ea_size.out.create_time);
824 srv_push_dos_date2(smb_conn, blob->data, 4, st->ea_size.out.access_time);
825 srv_push_dos_date2(smb_conn, blob->data, 8, st->ea_size.out.write_time);
826 SIVAL(blob->data, 12, st->ea_size.out.size);
827 SIVAL(blob->data, 16, st->ea_size.out.alloc_size);
828 SSVAL(blob->data, 20, st->ea_size.out.attrib);
829 SIVAL(blob->data, 22, st->ea_size.out.ea_size);
832 case RAW_FILEINFO_EA_LIST:
833 list_size = ea_list_size(st->ea_list.out.num_eas,
834 st->ea_list.out.eas);
835 TRANS2_CHECK(trans2_grow_data(mem_ctx, blob, list_size));
837 ea_put_list(blob->data,
838 st->ea_list.out.num_eas, st->ea_list.out.eas);
841 case RAW_FILEINFO_ALL_EAS:
842 list_size = ea_list_size(st->all_eas.out.num_eas,
843 st->all_eas.out.eas);
844 TRANS2_CHECK(trans2_grow_data(mem_ctx, blob, list_size));
846 ea_put_list(blob->data,
847 st->all_eas.out.num_eas, st->all_eas.out.eas);
850 case RAW_FILEINFO_IS_NAME_VALID:
853 case RAW_FILEINFO_BASIC_INFO:
854 passthru_level = RAW_FILEINFO_BASIC_INFORMATION;
857 case RAW_FILEINFO_STANDARD_INFO:
858 passthru_level = RAW_FILEINFO_STANDARD_INFORMATION;
861 case RAW_FILEINFO_EA_INFO:
862 passthru_level = RAW_FILEINFO_EA_INFORMATION;
865 case RAW_FILEINFO_COMPRESSION_INFO:
866 passthru_level = RAW_FILEINFO_COMPRESSION_INFORMATION;
869 case RAW_FILEINFO_ALL_INFO:
870 passthru_level = RAW_FILEINFO_ALL_INFORMATION;
873 case RAW_FILEINFO_NAME_INFO:
874 passthru_level = RAW_FILEINFO_NAME_INFORMATION;
877 case RAW_FILEINFO_ALT_NAME_INFO:
878 passthru_level = RAW_FILEINFO_ALT_NAME_INFORMATION;
881 case RAW_FILEINFO_STREAM_INFO:
882 passthru_level = RAW_FILEINFO_STREAM_INFORMATION;
886 passthru_level = st->generic.level;
890 return trans2_push_passthru_fileinfo(mem_ctx, blob,
896 fill in the reply from a qpathinfo or qfileinfo call
898 static NTSTATUS trans2_fileinfo_send(struct trans_op *op)
900 struct smbsrv_request *req = op->req;
901 struct smb_trans2 *trans = op->trans;
902 union smb_fileinfo *st;
904 TRANS2_CHECK_ASYNC_STATUS(st, union smb_fileinfo);
906 TRANS2_CHECK(trans2_setup_reply(trans, 2, 0, 0));
907 SSVAL(trans->out.params.data, 0, 0);
909 TRANS2_CHECK(trans2_push_fileinfo(req->smb_conn, trans,
910 &trans->out.data, st,
911 TRANS2_REQ_DEFAULT_STR_FLAGS(req)));
917 trans2 qpathinfo implementation
919 static NTSTATUS trans2_qpathinfo(struct smbsrv_request *req, struct trans_op *op)
921 struct smb_trans2 *trans = op->trans;
922 union smb_fileinfo *st;
925 /* make sure we got enough parameters */
926 if (trans->in.params.length < 2) {
927 return NT_STATUS_FOOBAR;
930 st = talloc(op, union smb_fileinfo);
931 NT_STATUS_HAVE_NO_MEMORY(st);
933 level = SVAL(trans->in.params.data, 0);
935 trans2_pull_blob_string(req, &trans->in.params, 6, &st->generic.in.file.path, 0);
936 if (st->generic.in.file.path == NULL) {
937 return NT_STATUS_FOOBAR;
940 /* work out the backend level - we make it 1-1 in the header */
941 st->generic.level = (enum smb_fileinfo_level)level;
942 if (st->generic.level >= RAW_FILEINFO_GENERIC) {
943 return NT_STATUS_INVALID_LEVEL;
946 if (st->generic.level == RAW_FILEINFO_EA_LIST) {
947 TRANS2_CHECK(ea_pull_name_list(&trans->in.data, req,
948 &st->ea_list.in.num_names,
949 &st->ea_list.in.ea_names));
953 op->send_fn = trans2_fileinfo_send;
955 return ntvfs_qpathinfo(req->ntvfs, st);
960 trans2 qpathinfo implementation
962 static NTSTATUS trans2_qfileinfo(struct smbsrv_request *req, struct trans_op *op)
964 struct smb_trans2 *trans = op->trans;
965 union smb_fileinfo *st;
967 struct ntvfs_handle *h;
969 /* make sure we got enough parameters */
970 if (trans->in.params.length < 4) {
971 return NT_STATUS_FOOBAR;
974 st = talloc(op, union smb_fileinfo);
975 NT_STATUS_HAVE_NO_MEMORY(st);
977 h = smbsrv_pull_fnum(req, trans->in.params.data, 0);
978 level = SVAL(trans->in.params.data, 2);
980 st->generic.in.file.ntvfs = h;
981 /* work out the backend level - we make it 1-1 in the header */
982 st->generic.level = (enum smb_fileinfo_level)level;
983 if (st->generic.level >= RAW_FILEINFO_GENERIC) {
984 return NT_STATUS_INVALID_LEVEL;
987 if (st->generic.level == RAW_FILEINFO_EA_LIST) {
988 TRANS2_CHECK(ea_pull_name_list(&trans->in.data, req,
989 &st->ea_list.in.num_names,
990 &st->ea_list.in.ea_names));
994 op->send_fn = trans2_fileinfo_send;
996 SMBSRV_CHECK_FILE_HANDLE_NTSTATUS(st->generic.in.file.ntvfs);
997 return ntvfs_qfileinfo(req->ntvfs, st);
1002 parse a trans2 setfileinfo/setpathinfo data blob
1004 static NTSTATUS trans2_parse_sfileinfo(struct smbsrv_request *req,
1005 union smb_setfileinfo *st,
1006 const DATA_BLOB *blob)
1011 switch (st->generic.level) {
1012 case RAW_SFILEINFO_GENERIC:
1013 case RAW_SFILEINFO_SETATTR:
1014 case RAW_SFILEINFO_SETATTRE:
1015 case RAW_SFILEINFO_SEC_DESC:
1016 /* handled elsewhere */
1017 return NT_STATUS_INVALID_LEVEL;
1019 case RAW_SFILEINFO_STANDARD:
1020 CHECK_MIN_BLOB_SIZE(blob, 12);
1022 st->standard.in.create_time = srv_pull_dos_date2(req->smb_conn, blob->data + 0);
1023 st->standard.in.access_time = srv_pull_dos_date2(req->smb_conn, blob->data + 4);
1024 st->standard.in.write_time = srv_pull_dos_date2(req->smb_conn, blob->data + 8);
1026 return NT_STATUS_OK;
1028 case RAW_SFILEINFO_EA_SET:
1029 return ea_pull_list(blob, req,
1030 &st->ea_set.in.num_eas,
1031 &st->ea_set.in.eas);
1033 case SMB_SFILEINFO_BASIC_INFO:
1034 case SMB_SFILEINFO_BASIC_INFORMATION:
1035 CHECK_MIN_BLOB_SIZE(blob, 36);
1037 st->basic_info.in.create_time = pull_nttime(blob->data, 0);
1038 st->basic_info.in.access_time = pull_nttime(blob->data, 8);
1039 st->basic_info.in.write_time = pull_nttime(blob->data, 16);
1040 st->basic_info.in.change_time = pull_nttime(blob->data, 24);
1041 st->basic_info.in.attrib = IVAL(blob->data, 32);
1043 return NT_STATUS_OK;
1045 case SMB_SFILEINFO_DISPOSITION_INFO:
1046 case SMB_SFILEINFO_DISPOSITION_INFORMATION:
1047 CHECK_MIN_BLOB_SIZE(blob, 1);
1049 st->disposition_info.in.delete_on_close = CVAL(blob->data, 0);
1051 return NT_STATUS_OK;
1053 case SMB_SFILEINFO_ALLOCATION_INFO:
1054 case SMB_SFILEINFO_ALLOCATION_INFORMATION:
1055 CHECK_MIN_BLOB_SIZE(blob, 8);
1057 st->allocation_info.in.alloc_size = BVAL(blob->data, 0);
1059 return NT_STATUS_OK;
1061 case RAW_SFILEINFO_END_OF_FILE_INFO:
1062 case RAW_SFILEINFO_END_OF_FILE_INFORMATION:
1063 CHECK_MIN_BLOB_SIZE(blob, 8);
1065 st->end_of_file_info.in.size = BVAL(blob->data, 0);
1067 return NT_STATUS_OK;
1069 case RAW_SFILEINFO_RENAME_INFORMATION:
1070 CHECK_MIN_BLOB_SIZE(blob, 12);
1072 st->rename_information.in.overwrite = CVAL(blob->data, 0);
1073 st->rename_information.in.root_fid = IVAL(blob->data, 4);
1074 len = IVAL(blob->data, 8);
1075 str_blob.data = blob->data+12;
1076 str_blob.length = MIN(blob->length, len);
1077 trans2_pull_blob_string(req, &str_blob, 0,
1078 &st->rename_information.in.new_name,
1080 if (st->rename_information.in.new_name == NULL) {
1081 return NT_STATUS_FOOBAR;
1084 return NT_STATUS_OK;
1086 case RAW_SFILEINFO_POSITION_INFORMATION:
1087 CHECK_MIN_BLOB_SIZE(blob, 8);
1089 st->position_information.in.position = BVAL(blob->data, 0);
1091 return NT_STATUS_OK;
1093 case RAW_SFILEINFO_MODE_INFORMATION:
1094 CHECK_MIN_BLOB_SIZE(blob, 4);
1096 st->mode_information.in.mode = IVAL(blob->data, 0);
1098 return NT_STATUS_OK;
1100 case RAW_SFILEINFO_UNIX_BASIC:
1101 case RAW_SFILEINFO_UNIX_LINK:
1102 case RAW_SFILEINFO_UNIX_HLINK:
1103 case RAW_SFILEINFO_1023:
1104 case RAW_SFILEINFO_1025:
1105 case RAW_SFILEINFO_1029:
1106 case RAW_SFILEINFO_1032:
1107 case RAW_SFILEINFO_1039:
1108 case RAW_SFILEINFO_1040:
1109 return NT_STATUS_INVALID_LEVEL;
1112 return NT_STATUS_INVALID_LEVEL;
1116 trans2 setfileinfo implementation
1118 static NTSTATUS trans2_setfileinfo(struct smbsrv_request *req, struct trans_op *op)
1120 struct smb_trans2 *trans = op->trans;
1121 union smb_setfileinfo *st;
1123 struct ntvfs_handle *h;
1125 /* make sure we got enough parameters */
1126 if (trans->in.params.length < 4) {
1127 return NT_STATUS_FOOBAR;
1130 st = talloc(op, union smb_setfileinfo);
1131 NT_STATUS_HAVE_NO_MEMORY(st);
1133 h = smbsrv_pull_fnum(req, trans->in.params.data, 0);
1134 level = SVAL(trans->in.params.data, 2);
1136 st->generic.in.file.ntvfs = h;
1137 /* work out the backend level - we make it 1-1 in the header */
1138 st->generic.level = (enum smb_setfileinfo_level)level;
1139 if (st->generic.level >= RAW_SFILEINFO_GENERIC) {
1140 return NT_STATUS_INVALID_LEVEL;
1143 TRANS2_CHECK(trans2_parse_sfileinfo(req, st, &trans->in.data));
1146 op->send_fn = trans2_simple_send;
1148 SMBSRV_CHECK_FILE_HANDLE_NTSTATUS(st->generic.in.file.ntvfs);
1149 return ntvfs_setfileinfo(req->ntvfs, st);
1153 trans2 setpathinfo implementation
1155 static NTSTATUS trans2_setpathinfo(struct smbsrv_request *req, struct trans_op *op)
1157 struct smb_trans2 *trans = op->trans;
1158 union smb_setfileinfo *st;
1161 /* make sure we got enough parameters */
1162 if (trans->in.params.length < 4) {
1163 return NT_STATUS_FOOBAR;
1166 st = talloc(op, union smb_setfileinfo);
1167 NT_STATUS_HAVE_NO_MEMORY(st);
1169 level = SVAL(trans->in.params.data, 0);
1171 trans2_pull_blob_string(req, &trans->in.params, 6, &st->generic.in.file.path, 0);
1172 if (st->generic.in.file.path == NULL) {
1173 return NT_STATUS_FOOBAR;
1176 /* work out the backend level - we make it 1-1 in the header */
1177 st->generic.level = (enum smb_setfileinfo_level)level;
1178 if (st->generic.level >= RAW_SFILEINFO_GENERIC) {
1179 return NT_STATUS_INVALID_LEVEL;
1182 TRANS2_CHECK(trans2_parse_sfileinfo(req, st, &trans->in.data));
1185 op->send_fn = trans2_simple_send;
1187 return ntvfs_setpathinfo(req->ntvfs, st);
1191 /* a structure to encapsulate the state information about an in-progress ffirst/fnext operation */
1193 struct trans_op *op;
1195 enum smb_search_level level;
1196 uint16_t last_entry_offset;
1201 fill a single entry in a trans2 find reply
1203 static BOOL find_fill_info(struct find_state *state,
1204 union smb_search_data *file)
1206 struct smbsrv_request *req = state->op->req;
1207 struct smb_trans2 *trans = state->op->trans;
1209 uint_t ofs = trans->out.data.length;
1212 switch (state->level) {
1213 case RAW_SEARCH_SEARCH:
1214 case RAW_SEARCH_FFIRST:
1215 case RAW_SEARCH_FUNIQUE:
1216 case RAW_SEARCH_GENERIC:
1217 case RAW_SEARCH_SMB2:
1218 /* handled elsewhere */
1221 case RAW_SEARCH_STANDARD:
1222 if (state->flags & FLAG_TRANS2_FIND_REQUIRE_RESUME) {
1223 trans2_grow_data(trans, &trans->out.data, ofs + 27);
1224 SIVAL(trans->out.data.data, ofs, file->standard.resume_key);
1227 trans2_grow_data(trans, &trans->out.data, ofs + 23);
1229 data = trans->out.data.data + ofs;
1230 srv_push_dos_date2(req->smb_conn, data, 0, file->standard.create_time);
1231 srv_push_dos_date2(req->smb_conn, data, 4, file->standard.access_time);
1232 srv_push_dos_date2(req->smb_conn, data, 8, file->standard.write_time);
1233 SIVAL(data, 12, file->standard.size);
1234 SIVAL(data, 16, file->standard.alloc_size);
1235 SSVAL(data, 20, file->standard.attrib);
1236 trans2_append_data_string(trans, &trans->out.data, file->standard.name.s,
1237 ofs + 22, TRANS2_REQ_DEFAULT_STR_FLAGS(req),
1238 STR_LEN8BIT | STR_TERMINATE | STR_LEN_NOTERM);
1241 case RAW_SEARCH_EA_SIZE:
1242 if (state->flags & FLAG_TRANS2_FIND_REQUIRE_RESUME) {
1243 trans2_grow_data(trans, &trans->out.data, ofs + 31);
1244 SIVAL(trans->out.data.data, ofs, file->ea_size.resume_key);
1247 trans2_grow_data(trans, &trans->out.data, ofs + 27);
1249 data = trans->out.data.data + ofs;
1250 srv_push_dos_date2(req->smb_conn, data, 0, file->ea_size.create_time);
1251 srv_push_dos_date2(req->smb_conn, data, 4, file->ea_size.access_time);
1252 srv_push_dos_date2(req->smb_conn, data, 8, file->ea_size.write_time);
1253 SIVAL(data, 12, file->ea_size.size);
1254 SIVAL(data, 16, file->ea_size.alloc_size);
1255 SSVAL(data, 20, file->ea_size.attrib);
1256 SIVAL(data, 22, file->ea_size.ea_size);
1257 trans2_append_data_string(trans, &trans->out.data, file->ea_size.name.s,
1258 ofs + 26, TRANS2_REQ_DEFAULT_STR_FLAGS(req),
1259 STR_LEN8BIT | STR_NOALIGN);
1260 trans2_grow_data(trans, &trans->out.data, trans->out.data.length + 1);
1261 trans->out.data.data[trans->out.data.length-1] = 0;
1264 case RAW_SEARCH_EA_LIST:
1265 ea_size = ea_list_size(file->ea_list.eas.num_eas, file->ea_list.eas.eas);
1266 if (state->flags & FLAG_TRANS2_FIND_REQUIRE_RESUME) {
1267 if (!NT_STATUS_IS_OK(trans2_grow_data(trans, &trans->out.data, ofs + 27 + ea_size))) {
1270 SIVAL(trans->out.data.data, ofs, file->ea_list.resume_key);
1273 if (!NT_STATUS_IS_OK(trans2_grow_data(trans, &trans->out.data, ofs + 23 + ea_size))) {
1277 data = trans->out.data.data + ofs;
1278 srv_push_dos_date2(req->smb_conn, data, 0, file->ea_list.create_time);
1279 srv_push_dos_date2(req->smb_conn, data, 4, file->ea_list.access_time);
1280 srv_push_dos_date2(req->smb_conn, data, 8, file->ea_list.write_time);
1281 SIVAL(data, 12, file->ea_list.size);
1282 SIVAL(data, 16, file->ea_list.alloc_size);
1283 SSVAL(data, 20, file->ea_list.attrib);
1284 ea_put_list(data+22, file->ea_list.eas.num_eas, file->ea_list.eas.eas);
1285 trans2_append_data_string(trans, &trans->out.data, file->ea_list.name.s,
1286 ofs + 22 + ea_size, TRANS2_REQ_DEFAULT_STR_FLAGS(req),
1287 STR_LEN8BIT | STR_NOALIGN);
1288 trans2_grow_data(trans, &trans->out.data, trans->out.data.length + 1);
1289 trans->out.data.data[trans->out.data.length-1] = 0;
1292 case RAW_SEARCH_DIRECTORY_INFO:
1293 trans2_grow_data(trans, &trans->out.data, ofs + 64);
1294 data = trans->out.data.data + ofs;
1295 SIVAL(data, 4, file->directory_info.file_index);
1296 push_nttime(data, 8, file->directory_info.create_time);
1297 push_nttime(data, 16, file->directory_info.access_time);
1298 push_nttime(data, 24, file->directory_info.write_time);
1299 push_nttime(data, 32, file->directory_info.change_time);
1300 SBVAL(data, 40, file->directory_info.size);
1301 SBVAL(data, 48, file->directory_info.alloc_size);
1302 SIVAL(data, 56, file->directory_info.attrib);
1303 trans2_append_data_string(trans, &trans->out.data, file->directory_info.name.s,
1304 ofs + 60, TRANS2_REQ_DEFAULT_STR_FLAGS(req),
1305 STR_TERMINATE_ASCII);
1306 data = trans->out.data.data + ofs;
1307 SIVAL(data, 0, trans->out.data.length - ofs);
1310 case RAW_SEARCH_FULL_DIRECTORY_INFO:
1311 trans2_grow_data(trans, &trans->out.data, ofs + 68);
1312 data = trans->out.data.data + ofs;
1313 SIVAL(data, 4, file->full_directory_info.file_index);
1314 push_nttime(data, 8, file->full_directory_info.create_time);
1315 push_nttime(data, 16, file->full_directory_info.access_time);
1316 push_nttime(data, 24, file->full_directory_info.write_time);
1317 push_nttime(data, 32, file->full_directory_info.change_time);
1318 SBVAL(data, 40, file->full_directory_info.size);
1319 SBVAL(data, 48, file->full_directory_info.alloc_size);
1320 SIVAL(data, 56, file->full_directory_info.attrib);
1321 SIVAL(data, 64, file->full_directory_info.ea_size);
1322 trans2_append_data_string(trans, &trans->out.data, file->full_directory_info.name.s,
1323 ofs + 60, TRANS2_REQ_DEFAULT_STR_FLAGS(req),
1324 STR_TERMINATE_ASCII);
1325 data = trans->out.data.data + ofs;
1326 SIVAL(data, 0, trans->out.data.length - ofs);
1329 case RAW_SEARCH_NAME_INFO:
1330 trans2_grow_data(trans, &trans->out.data, ofs + 12);
1331 data = trans->out.data.data + ofs;
1332 SIVAL(data, 4, file->name_info.file_index);
1333 trans2_append_data_string(trans, &trans->out.data, file->name_info.name.s,
1334 ofs + 8, TRANS2_REQ_DEFAULT_STR_FLAGS(req),
1335 STR_TERMINATE_ASCII);
1336 data = trans->out.data.data + ofs;
1337 SIVAL(data, 0, trans->out.data.length - ofs);
1340 case RAW_SEARCH_BOTH_DIRECTORY_INFO:
1341 trans2_grow_data(trans, &trans->out.data, ofs + 94);
1342 data = trans->out.data.data + ofs;
1343 SIVAL(data, 4, file->both_directory_info.file_index);
1344 push_nttime(data, 8, file->both_directory_info.create_time);
1345 push_nttime(data, 16, file->both_directory_info.access_time);
1346 push_nttime(data, 24, file->both_directory_info.write_time);
1347 push_nttime(data, 32, file->both_directory_info.change_time);
1348 SBVAL(data, 40, file->both_directory_info.size);
1349 SBVAL(data, 48, file->both_directory_info.alloc_size);
1350 SIVAL(data, 56, file->both_directory_info.attrib);
1351 SIVAL(data, 64, file->both_directory_info.ea_size);
1352 SCVAL(data, 69, 0); /* reserved */
1353 memset(data+70,0,24);
1354 trans2_push_data_string(trans, &trans->out.data,
1356 file->both_directory_info.short_name.s,
1357 24, TRANS2_REQ_DEFAULT_STR_FLAGS(req),
1358 STR_UNICODE | STR_LEN8BIT);
1359 trans2_append_data_string(trans, &trans->out.data, file->both_directory_info.name.s,
1360 ofs + 60, TRANS2_REQ_DEFAULT_STR_FLAGS(req),
1361 STR_TERMINATE_ASCII);
1362 trans2_align_data(trans);
1363 data = trans->out.data.data + ofs;
1364 SIVAL(data, 0, trans->out.data.length - ofs);
1367 case RAW_SEARCH_ID_FULL_DIRECTORY_INFO:
1368 trans2_grow_data(trans, &trans->out.data, ofs + 80);
1369 data = trans->out.data.data + ofs;
1370 SIVAL(data, 4, file->id_full_directory_info.file_index);
1371 push_nttime(data, 8, file->id_full_directory_info.create_time);
1372 push_nttime(data, 16, file->id_full_directory_info.access_time);
1373 push_nttime(data, 24, file->id_full_directory_info.write_time);
1374 push_nttime(data, 32, file->id_full_directory_info.change_time);
1375 SBVAL(data, 40, file->id_full_directory_info.size);
1376 SBVAL(data, 48, file->id_full_directory_info.alloc_size);
1377 SIVAL(data, 56, file->id_full_directory_info.attrib);
1378 SIVAL(data, 64, file->id_full_directory_info.ea_size);
1379 SIVAL(data, 68, 0); /* padding */
1380 SBVAL(data, 72, file->id_full_directory_info.file_id);
1381 trans2_append_data_string(trans, &trans->out.data, file->id_full_directory_info.name.s,
1382 ofs + 60, TRANS2_REQ_DEFAULT_STR_FLAGS(req),
1383 STR_TERMINATE_ASCII);
1384 data = trans->out.data.data + ofs;
1385 SIVAL(data, 0, trans->out.data.length - ofs);
1388 case RAW_SEARCH_ID_BOTH_DIRECTORY_INFO:
1389 trans2_grow_data(trans, &trans->out.data, ofs + 104);
1390 data = trans->out.data.data + ofs;
1391 SIVAL(data, 4, file->id_both_directory_info.file_index);
1392 push_nttime(data, 8, file->id_both_directory_info.create_time);
1393 push_nttime(data, 16, file->id_both_directory_info.access_time);
1394 push_nttime(data, 24, file->id_both_directory_info.write_time);
1395 push_nttime(data, 32, file->id_both_directory_info.change_time);
1396 SBVAL(data, 40, file->id_both_directory_info.size);
1397 SBVAL(data, 48, file->id_both_directory_info.alloc_size);
1398 SIVAL(data, 56, file->id_both_directory_info.attrib);
1399 SIVAL(data, 64, file->id_both_directory_info.ea_size);
1400 SCVAL(data, 69, 0); /* reserved */
1401 memset(data+70,0,26);
1402 trans2_push_data_string(trans, &trans->out.data,
1404 file->id_both_directory_info.short_name.s,
1405 24, TRANS2_REQ_DEFAULT_STR_FLAGS(req),
1406 STR_UNICODE | STR_LEN8BIT);
1407 SBVAL(data, 96, file->id_both_directory_info.file_id);
1408 trans2_append_data_string(trans, &trans->out.data, file->id_both_directory_info.name.s,
1409 ofs + 60, TRANS2_REQ_DEFAULT_STR_FLAGS(req),
1410 STR_TERMINATE_ASCII);
1411 data = trans->out.data.data + ofs;
1412 SIVAL(data, 0, trans->out.data.length - ofs);
1419 /* callback function for trans2 findfirst/findnext */
1420 static BOOL find_callback(void *private, union smb_search_data *file)
1422 struct find_state *state = talloc_get_type(private, struct find_state);
1423 struct smb_trans2 *trans = state->op->trans;
1426 old_length = trans->out.data.length;
1428 if (!find_fill_info(state, file) ||
1429 trans->out.data.length > trans->in.max_data) {
1430 /* restore the old length and tell the backend to stop */
1431 trans2_grow_data(trans, &trans->out.data, old_length);
1435 state->last_entry_offset = old_length;
1440 trans2 findfirst send
1442 static NTSTATUS trans2_findfirst_send(struct trans_op *op)
1444 struct smbsrv_request *req = op->req;
1445 struct smb_trans2 *trans = op->trans;
1446 union smb_search_first *search;
1447 struct find_state *state;
1450 TRANS2_CHECK_ASYNC_STATUS(state, struct find_state);
1451 search = talloc_get_type(state->search, union smb_search_first);
1453 /* fill in the findfirst reply header */
1454 param = trans->out.params.data;
1455 SSVAL(param, VWV(0), search->t2ffirst.out.handle);
1456 SSVAL(param, VWV(1), search->t2ffirst.out.count);
1457 SSVAL(param, VWV(2), search->t2ffirst.out.end_of_search);
1458 SSVAL(param, VWV(3), 0);
1459 SSVAL(param, VWV(4), state->last_entry_offset);
1461 return NT_STATUS_OK;
1466 trans2 findfirst implementation
1468 static NTSTATUS trans2_findfirst(struct smbsrv_request *req, struct trans_op *op)
1470 struct smb_trans2 *trans = op->trans;
1471 union smb_search_first *search;
1473 struct find_state *state;
1475 /* make sure we got all the parameters */
1476 if (trans->in.params.length < 14) {
1477 return NT_STATUS_FOOBAR;
1480 search = talloc(op, union smb_search_first);
1481 NT_STATUS_HAVE_NO_MEMORY(search);
1483 search->t2ffirst.in.search_attrib = SVAL(trans->in.params.data, 0);
1484 search->t2ffirst.in.max_count = SVAL(trans->in.params.data, 2);
1485 search->t2ffirst.in.flags = SVAL(trans->in.params.data, 4);
1486 level = SVAL(trans->in.params.data, 6);
1487 search->t2ffirst.in.storage_type = IVAL(trans->in.params.data, 8);
1489 trans2_pull_blob_string(req, &trans->in.params, 12, &search->t2ffirst.in.pattern, 0);
1490 if (search->t2ffirst.in.pattern == NULL) {
1491 return NT_STATUS_FOOBAR;
1494 search->t2ffirst.level = (enum smb_search_level)level;
1495 if (search->t2ffirst.level >= RAW_SEARCH_GENERIC) {
1496 return NT_STATUS_INVALID_LEVEL;
1499 if (search->t2ffirst.level == RAW_SEARCH_EA_LIST) {
1500 TRANS2_CHECK(ea_pull_name_list(&trans->in.data, req,
1501 &search->t2ffirst.in.num_names,
1502 &search->t2ffirst.in.ea_names));
1505 /* setup the private state structure that the backend will
1506 give us in the callback */
1507 state = talloc(op, struct find_state);
1508 NT_STATUS_HAVE_NO_MEMORY(state);
1510 state->search = search;
1511 state->level = search->t2ffirst.level;
1512 state->last_entry_offset= 0;
1513 state->flags = search->t2ffirst.in.flags;
1515 /* setup for just a header in the reply */
1516 TRANS2_CHECK(trans2_setup_reply(trans, 10, 0, 0));
1518 op->op_info = state;
1519 op->send_fn = trans2_findfirst_send;
1521 return ntvfs_search_first(req->ntvfs, search, state, find_callback);
1526 trans2 findnext send
1528 static NTSTATUS trans2_findnext_send(struct trans_op *op)
1530 struct smbsrv_request *req = op->req;
1531 struct smb_trans2 *trans = op->trans;
1532 union smb_search_next *search;
1533 struct find_state *state;
1536 TRANS2_CHECK_ASYNC_STATUS(state, struct find_state);
1537 search = talloc_get_type(state->search, union smb_search_next);
1539 /* fill in the findfirst reply header */
1540 param = trans->out.params.data;
1541 SSVAL(param, VWV(0), search->t2fnext.out.count);
1542 SSVAL(param, VWV(1), search->t2fnext.out.end_of_search);
1543 SSVAL(param, VWV(2), 0);
1544 SSVAL(param, VWV(3), state->last_entry_offset);
1546 return NT_STATUS_OK;
1551 trans2 findnext implementation
1553 static NTSTATUS trans2_findnext(struct smbsrv_request *req, struct trans_op *op)
1555 struct smb_trans2 *trans = op->trans;
1556 union smb_search_next *search;
1558 struct find_state *state;
1560 /* make sure we got all the parameters */
1561 if (trans->in.params.length < 12) {
1562 return NT_STATUS_FOOBAR;
1565 search = talloc(op, union smb_search_next);
1566 NT_STATUS_HAVE_NO_MEMORY(search);
1568 search->t2fnext.in.handle = SVAL(trans->in.params.data, 0);
1569 search->t2fnext.in.max_count = SVAL(trans->in.params.data, 2);
1570 level = SVAL(trans->in.params.data, 4);
1571 search->t2fnext.in.resume_key = IVAL(trans->in.params.data, 6);
1572 search->t2fnext.in.flags = SVAL(trans->in.params.data, 10);
1574 trans2_pull_blob_string(req, &trans->in.params, 12, &search->t2fnext.in.last_name, 0);
1575 if (search->t2fnext.in.last_name == NULL) {
1576 return NT_STATUS_FOOBAR;
1579 search->t2fnext.level = (enum smb_search_level)level;
1580 if (search->t2fnext.level >= RAW_SEARCH_GENERIC) {
1581 return NT_STATUS_INVALID_LEVEL;
1584 if (search->t2fnext.level == RAW_SEARCH_EA_LIST) {
1585 TRANS2_CHECK(ea_pull_name_list(&trans->in.data, req,
1586 &search->t2fnext.in.num_names,
1587 &search->t2fnext.in.ea_names));
1590 /* setup the private state structure that the backend will give us in the callback */
1591 state = talloc(op, struct find_state);
1592 NT_STATUS_HAVE_NO_MEMORY(state);
1594 state->search = search;
1595 state->level = search->t2fnext.level;
1596 state->last_entry_offset= 0;
1597 state->flags = search->t2fnext.in.flags;
1599 /* setup for just a header in the reply */
1600 TRANS2_CHECK(trans2_setup_reply(trans, 8, 0, 0));
1602 op->op_info = state;
1603 op->send_fn = trans2_findnext_send;
1605 return ntvfs_search_next(req->ntvfs, search, state, find_callback);
1610 backend for trans2 requests
1612 static NTSTATUS trans2_backend(struct smbsrv_request *req, struct trans_op *op)
1614 struct smb_trans2 *trans = op->trans;
1617 /* direct trans2 pass thru */
1618 status = ntvfs_trans2(req->ntvfs, trans);
1619 if (!NT_STATUS_EQUAL(NT_STATUS_NOT_IMPLEMENTED, status)) {
1623 /* must have at least one setup word */
1624 if (trans->in.setup_count < 1) {
1625 return NT_STATUS_FOOBAR;
1628 /* the trans2 command is in setup[0] */
1629 switch (trans->in.setup[0]) {
1630 case TRANSACT2_FINDFIRST:
1631 return trans2_findfirst(req, op);
1632 case TRANSACT2_FINDNEXT:
1633 return trans2_findnext(req, op);
1634 case TRANSACT2_QPATHINFO:
1635 return trans2_qpathinfo(req, op);
1636 case TRANSACT2_QFILEINFO:
1637 return trans2_qfileinfo(req, op);
1638 case TRANSACT2_SETFILEINFO:
1639 return trans2_setfileinfo(req, op);
1640 case TRANSACT2_SETPATHINFO:
1641 return trans2_setpathinfo(req, op);
1642 case TRANSACT2_QFSINFO:
1643 return trans2_qfsinfo(req, op);
1644 case TRANSACT2_OPEN:
1645 return trans2_open(req, op);
1646 case TRANSACT2_MKDIR:
1647 return trans2_mkdir(req, op);
1650 /* an unknown trans2 command */
1651 return NT_STATUS_FOOBAR;
1656 send a continue request
1658 static void reply_trans_continue(struct smbsrv_request *req, uint8_t command,
1659 struct smb_trans2 *trans)
1661 struct smbsrv_trans_partial *tp;
1664 /* make sure they don't flood us */
1665 for (count=0,tp=req->smb_conn->trans_partial;tp;tp=tp->next) count++;
1667 smbsrv_send_error(req, NT_STATUS_INSUFFICIENT_RESOURCES);
1671 tp = talloc(req, struct smbsrv_trans_partial);
1673 tp->req = talloc_reference(tp, req);
1675 tp->command = command;
1677 DLIST_ADD(req->smb_conn->trans_partial, tp);
1679 /* send a 'please continue' reply */
1680 smbsrv_setup_reply(req, 0, 0);
1681 smbsrv_send_reply(req);
1686 answer a reconstructed trans request
1688 static void reply_trans_send(struct ntvfs_request *ntvfs)
1690 struct smbsrv_request *req;
1691 struct trans_op *op;
1692 struct smb_trans2 *trans;
1693 uint16_t params_left, data_left;
1694 uint8_t *params, *data;
1697 SMBSRV_CHECK_ASYNC_STATUS_ERR(op, struct trans_op);
1700 /* if this function needs work to form the nttrans reply buffer, then
1702 if (op->send_fn != NULL) {
1704 status = op->send_fn(op);
1705 if (!NT_STATUS_IS_OK(status)) {
1706 smbsrv_send_error(req, status);
1711 params_left = trans->out.params.length;
1712 data_left = trans->out.data.length;
1713 params = trans->out.params.data;
1714 data = trans->out.data.data;
1716 smbsrv_setup_reply(req, 10 + trans->out.setup_count, 0);
1718 if (!NT_STATUS_IS_OK(req->ntvfs->async_states->status)) {
1719 smbsrv_setup_error(req, req->ntvfs->async_states->status);
1722 /* we need to divide up the reply into chunks that fit into
1723 the negotiated buffer size */
1725 uint16_t this_data, this_param, max_bytes;
1726 uint_t align1 = 1, align2 = (params_left ? 2 : 0);
1727 struct smbsrv_request *this_req;
1729 max_bytes = req_max_data(req) - (align1 + align2);
1731 this_param = params_left;
1732 if (this_param > max_bytes) {
1733 this_param = max_bytes;
1735 max_bytes -= this_param;
1737 this_data = data_left;
1738 if (this_data > max_bytes) {
1739 this_data = max_bytes;
1742 /* don't destroy unless this is the last chunk */
1743 if (params_left - this_param != 0 ||
1744 data_left - this_data != 0) {
1745 this_req = smbsrv_setup_secondary_request(req);
1750 req_grow_data(this_req, this_param + this_data + (align1 + align2));
1752 SSVAL(this_req->out.vwv, VWV(0), trans->out.params.length);
1753 SSVAL(this_req->out.vwv, VWV(1), trans->out.data.length);
1754 SSVAL(this_req->out.vwv, VWV(2), 0);
1756 SSVAL(this_req->out.vwv, VWV(3), this_param);
1757 SSVAL(this_req->out.vwv, VWV(4), align1 + PTR_DIFF(this_req->out.data, this_req->out.hdr));
1758 SSVAL(this_req->out.vwv, VWV(5), PTR_DIFF(params, trans->out.params.data));
1760 SSVAL(this_req->out.vwv, VWV(6), this_data);
1761 SSVAL(this_req->out.vwv, VWV(7), align1 + align2 +
1762 PTR_DIFF(this_req->out.data + this_param, this_req->out.hdr));
1763 SSVAL(this_req->out.vwv, VWV(8), PTR_DIFF(data, trans->out.data.data));
1765 SSVAL(this_req->out.vwv, VWV(9), trans->out.setup_count);
1766 for (i=0;i<trans->out.setup_count;i++) {
1767 SSVAL(this_req->out.vwv, VWV(10+i), trans->out.setup[i]);
1770 memset(this_req->out.data, 0, align1);
1771 if (this_param != 0) {
1772 memcpy(this_req->out.data + align1, params, this_param);
1774 memset(this_req->out.data+this_param+align1, 0, align2);
1775 if (this_data != 0) {
1776 memcpy(this_req->out.data+this_param+align1+align2, data, this_data);
1779 params_left -= this_param;
1780 data_left -= this_data;
1781 params += this_param;
1784 smbsrv_send_reply(this_req);
1785 } while (params_left != 0 || data_left != 0);
1790 answer a reconstructed trans request
1792 static void reply_trans_complete(struct smbsrv_request *req, uint8_t command,
1793 struct smb_trans2 *trans)
1795 struct trans_op *op;
1797 SMBSRV_TALLOC_IO_PTR(op, struct trans_op);
1798 SMBSRV_SETUP_NTVFS_REQUEST(reply_trans_send, NTVFS_ASYNC_STATE_MAY_ASYNC);
1802 op->command = command;
1806 /* its a full request, give it to the backend */
1807 if (command == SMBtrans) {
1808 SMBSRV_CALL_NTVFS_BACKEND(ntvfs_trans(req->ntvfs, trans));
1811 SMBSRV_CALL_NTVFS_BACKEND(trans2_backend(req, op));
1817 Reply to an SMBtrans or SMBtrans2 request
1819 static void reply_trans_generic(struct smbsrv_request *req, uint8_t command)
1821 struct smb_trans2 *trans;
1823 uint16_t param_ofs, data_ofs;
1824 uint16_t param_count, data_count;
1825 uint16_t param_total, data_total;
1828 if (req->in.wct < 14) {
1829 smbsrv_send_error(req, NT_STATUS_INVALID_PARAMETER);
1833 trans = talloc(req, struct smb_trans2);
1834 if (trans == NULL) {
1835 smbsrv_send_error(req, NT_STATUS_NO_MEMORY);
1839 param_total = SVAL(req->in.vwv, VWV(0));
1840 data_total = SVAL(req->in.vwv, VWV(1));
1841 trans->in.max_param = SVAL(req->in.vwv, VWV(2));
1842 trans->in.max_data = SVAL(req->in.vwv, VWV(3));
1843 trans->in.max_setup = CVAL(req->in.vwv, VWV(4));
1844 trans->in.flags = SVAL(req->in.vwv, VWV(5));
1845 trans->in.timeout = IVAL(req->in.vwv, VWV(6));
1846 param_count = SVAL(req->in.vwv, VWV(9));
1847 param_ofs = SVAL(req->in.vwv, VWV(10));
1848 data_count = SVAL(req->in.vwv, VWV(11));
1849 data_ofs = SVAL(req->in.vwv, VWV(12));
1850 trans->in.setup_count = CVAL(req->in.vwv, VWV(13));
1852 if (req->in.wct != 14 + trans->in.setup_count) {
1853 smbsrv_send_error(req, NT_STATUS_DOS(ERRSRV, ERRerror));
1857 /* parse out the setup words */
1858 trans->in.setup = talloc_array(trans, uint16_t, trans->in.setup_count);
1859 if (trans->in.setup_count && !trans->in.setup) {
1860 smbsrv_send_error(req, NT_STATUS_NO_MEMORY);
1863 for (i=0;i<trans->in.setup_count;i++) {
1864 trans->in.setup[i] = SVAL(req->in.vwv, VWV(14+i));
1867 if (command == SMBtrans) {
1868 req_pull_string(req, &trans->in.trans_name, req->in.data, -1, STR_TERMINATE);
1871 if (!req_pull_blob(req, req->in.hdr + param_ofs, param_count, &trans->in.params) ||
1872 !req_pull_blob(req, req->in.hdr + data_ofs, data_count, &trans->in.data)) {
1873 smbsrv_send_error(req, NT_STATUS_FOOBAR);
1877 /* is it a partial request? if so, then send a 'send more' message */
1878 if (param_total > param_count || data_total > data_count) {
1879 reply_trans_continue(req, command, trans);
1883 reply_trans_complete(req, command, trans);
1888 Reply to an SMBtranss2 request
1890 static void reply_transs_generic(struct smbsrv_request *req, uint8_t command)
1892 struct smbsrv_trans_partial *tp;
1893 struct smb_trans2 *trans = NULL;
1894 uint16_t param_ofs, data_ofs;
1895 uint16_t param_count, data_count;
1896 uint16_t param_disp, data_disp;
1897 uint16_t param_total, data_total;
1898 DATA_BLOB params, data;
1901 if (req->in.wct < 8) {
1902 smbsrv_send_error(req, NT_STATUS_INVALID_PARAMETER);
1906 for (tp=req->smb_conn->trans_partial;tp;tp=tp->next) {
1907 if (tp->command == command &&
1908 SVAL(tp->req->in.hdr, HDR_MID) == SVAL(req->in.hdr, HDR_MID)) {
1909 /* TODO: check the VUID, PID and TID too? */
1915 smbsrv_send_error(req, NT_STATUS_INVALID_PARAMETER);
1921 param_total = SVAL(req->in.vwv, VWV(0));
1922 data_total = SVAL(req->in.vwv, VWV(1));
1923 param_count = SVAL(req->in.vwv, VWV(2));
1924 param_ofs = SVAL(req->in.vwv, VWV(3));
1925 param_disp = SVAL(req->in.vwv, VWV(4));
1926 data_count = SVAL(req->in.vwv, VWV(5));
1927 data_ofs = SVAL(req->in.vwv, VWV(6));
1928 data_disp = SVAL(req->in.vwv, VWV(7));
1930 if (!req_pull_blob(req, req->in.hdr + param_ofs, param_count, ¶ms) ||
1931 !req_pull_blob(req, req->in.hdr + data_ofs, data_count, &data)) {
1932 smbsrv_send_error(req, NT_STATUS_INVALID_PARAMETER);
1936 /* only allow contiguous requests */
1937 if ((param_count != 0 &&
1938 param_disp != trans->in.params.length) ||
1940 data_disp != trans->in.data.length)) {
1941 smbsrv_send_error(req, NT_STATUS_INVALID_PARAMETER);
1945 /* add to the existing request */
1946 if (param_count != 0) {
1947 trans->in.params.data = talloc_realloc(trans,
1948 trans->in.params.data,
1950 param_disp + param_count);
1951 if (trans->in.params.data == NULL) {
1954 trans->in.params.length = param_disp + param_count;
1957 if (data_count != 0) {
1958 trans->in.data.data = talloc_realloc(trans,
1959 trans->in.data.data,
1961 data_disp + data_count);
1962 if (trans->in.data.data == NULL) {
1965 trans->in.data.length = data_disp + data_count;
1968 memcpy(trans->in.params.data + param_disp, params.data, params.length);
1969 memcpy(trans->in.data.data + data_disp, data.data, data.length);
1971 /* the sequence number of the reply is taken from the last secondary
1973 tp->req->seq_num = req->seq_num;
1975 /* we don't reply to Transs2 requests */
1978 if (trans->in.params.length == param_total &&
1979 trans->in.data.length == data_total) {
1980 /* its now complete */
1981 DLIST_REMOVE(tp->req->smb_conn->trans_partial, tp);
1982 reply_trans_complete(tp->req, command, trans);
1987 smbsrv_send_error(tp->req, NT_STATUS_NO_MEMORY);
1988 DLIST_REMOVE(req->smb_conn->trans_partial, tp);
1995 Reply to an SMBtrans2
1997 void smbsrv_reply_trans2(struct smbsrv_request *req)
1999 reply_trans_generic(req, SMBtrans2);
2003 Reply to an SMBtrans
2005 void smbsrv_reply_trans(struct smbsrv_request *req)
2007 reply_trans_generic(req, SMBtrans);
2011 Reply to an SMBtranss request
2013 void smbsrv_reply_transs(struct smbsrv_request *req)
2015 reply_transs_generic(req, SMBtrans);
2019 Reply to an SMBtranss2 request
2021 void smbsrv_reply_transs2(struct smbsrv_request *req)
2023 reply_transs_generic(req, SMBtrans2);