92d31b30ef108aa2b77a36b9b4efa57887d2d7ae
[gd/samba-autobuild/.git] / source4 / libcli / raw / rawfileinfo.c
1 /* 
2    Unix SMB/CIFS implementation.
3    client trans2 operations
4    Copyright (C) James Myers 2003
5    Copyright (C) Andrew Tridgell 2003
6    
7    This program is free software; you can redistribute it and/or modify
8    it under the terms of the GNU General Public License as published by
9    the Free Software Foundation; either version 2 of the License, or
10    (at your option) any later version.
11    
12    This program is distributed in the hope that it will be useful,
13    but WITHOUT ANY WARRANTY; without even the implied warranty of
14    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15    GNU General Public License for more details.
16    
17    You should have received a copy of the GNU General Public License
18    along with this program; if not, write to the Free Software
19    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20 */
21
22 #include "includes.h"
23 #include "libcli/raw/libcliraw.h"
24
25 /* local macros to make the code more readable */
26 #define FINFO_CHECK_MIN_SIZE(size) if (blob->length < (size)) { \
27       DEBUG(1,("Unexpected FILEINFO reply size %d for level %u - expected min of %d\n", \
28                (int)blob->length, parms->generic.level, (size))); \
29       return NT_STATUS_INFO_LENGTH_MISMATCH; \
30 }
31 #define FINFO_CHECK_SIZE(size) if (blob->length != (size)) { \
32       DEBUG(1,("Unexpected FILEINFO reply size %d for level %u - expected %d\n", \
33                (int)blob->length, parms->generic.level, (size))); \
34       return NT_STATUS_INFO_LENGTH_MISMATCH; \
35 }
36
37 /*
38   parse a stream information structure
39 */
40 NTSTATUS smbcli_parse_stream_info(DATA_BLOB blob, TALLOC_CTX *mem_ctx,
41                                   struct stream_information *io)
42 {
43         uint32_t ofs = 0;
44         io->num_streams = 0;
45         io->streams = NULL;
46
47         while (blob.length - ofs >= 24) {
48                 uint_t n = io->num_streams;
49                 uint32_t nlen, len;
50                 ssize_t size;
51                 void *vstr;
52                 io->streams = 
53                         talloc_realloc(mem_ctx, io->streams, struct stream_struct, n+1);
54                 if (!io->streams) {
55                         return NT_STATUS_NO_MEMORY;
56                 }
57                 nlen                      = IVAL(blob.data, ofs + 0x04);
58                 io->streams[n].size       = BVAL(blob.data, ofs + 0x08);
59                 io->streams[n].alloc_size = BVAL(blob.data, ofs + 0x10);
60                 if (nlen > blob.length - (ofs + 24)) {
61                         return NT_STATUS_INFO_LENGTH_MISMATCH;
62                 }
63                 size = convert_string_talloc(io->streams, CH_UTF16, CH_UNIX,
64                                              blob.data+ofs+24, nlen, &vstr);
65                 if (size == -1) {
66                         return NT_STATUS_ILLEGAL_CHARACTER;
67                 }
68                 io->streams[n].stream_name.s = vstr;
69                 io->streams[n].stream_name.private_length = nlen;
70                 io->num_streams++;
71                 len = IVAL(blob.data, ofs);
72                 if (len > blob.length - ofs) {
73                         return NT_STATUS_INFO_LENGTH_MISMATCH;
74                 }
75                 if (len == 0) break;
76                 ofs += len;
77         }
78
79         return NT_STATUS_OK;
80 }
81
82 /*
83   parse the fsinfo 'passthru' level replies
84 */
85 NTSTATUS smb_raw_fileinfo_passthru_parse(const DATA_BLOB *blob, TALLOC_CTX *mem_ctx, 
86                                          enum smb_fileinfo_level level,
87                                          union smb_fileinfo *parms)
88 {       
89         switch (level) {
90         case RAW_FILEINFO_BASIC_INFORMATION:
91                 /* some servers return 40 bytes and some 36. w2k3 return 40, so thats
92                    what we should do, but we need to accept 36 */
93                 if (blob->length != 36) {
94                         FINFO_CHECK_SIZE(40);
95                 }
96                 parms->basic_info.out.create_time = smbcli_pull_nttime(blob->data, 0);
97                 parms->basic_info.out.access_time = smbcli_pull_nttime(blob->data, 8);
98                 parms->basic_info.out.write_time  = smbcli_pull_nttime(blob->data, 16);
99                 parms->basic_info.out.change_time = smbcli_pull_nttime(blob->data, 24);
100                 parms->basic_info.out.attrib      = IVAL(blob->data, 32);
101                 return NT_STATUS_OK;
102
103         case RAW_FILEINFO_STANDARD_INFORMATION:
104                 FINFO_CHECK_SIZE(24);
105                 parms->standard_info.out.alloc_size =     BVAL(blob->data, 0);
106                 parms->standard_info.out.size =           BVAL(blob->data, 8);
107                 parms->standard_info.out.nlink =          IVAL(blob->data, 16);
108                 parms->standard_info.out.delete_pending = CVAL(blob->data, 20);
109                 parms->standard_info.out.directory =      CVAL(blob->data, 21);
110                 return NT_STATUS_OK;
111
112         case RAW_FILEINFO_EA_INFORMATION:
113                 FINFO_CHECK_SIZE(4);
114                 parms->ea_info.out.ea_size = IVAL(blob->data, 0);
115                 return NT_STATUS_OK;
116
117         case RAW_FILEINFO_NAME_INFORMATION:
118                 FINFO_CHECK_MIN_SIZE(4);
119                 smbcli_blob_pull_string(NULL, mem_ctx, blob, 
120                                         &parms->name_info.out.fname, 0, 4, STR_UNICODE);
121                 return NT_STATUS_OK;
122
123         case RAW_FILEINFO_ALL_INFORMATION:
124                 FINFO_CHECK_MIN_SIZE(72);
125                 parms->all_info.out.create_time =           smbcli_pull_nttime(blob->data, 0);
126                 parms->all_info.out.access_time =           smbcli_pull_nttime(blob->data, 8);
127                 parms->all_info.out.write_time =            smbcli_pull_nttime(blob->data, 16);
128                 parms->all_info.out.change_time =           smbcli_pull_nttime(blob->data, 24);
129                 parms->all_info.out.attrib =                IVAL(blob->data, 32);
130                 parms->all_info.out.alloc_size =            BVAL(blob->data, 40);
131                 parms->all_info.out.size =                  BVAL(blob->data, 48);
132                 parms->all_info.out.nlink =                 IVAL(blob->data, 56);
133                 parms->all_info.out.delete_pending =        CVAL(blob->data, 60);
134                 parms->all_info.out.directory =             CVAL(blob->data, 61);
135 #if 1
136                 parms->all_info.out.ea_size =               IVAL(blob->data, 64);
137                 smbcli_blob_pull_string(NULL, mem_ctx, blob,
138                                         &parms->all_info.out.fname, 68, 72, STR_UNICODE);
139 #else
140                 /* this is what the CIFS spec says - and its totally
141                    wrong, but its useful having it here so we can
142                    quickly adapt to broken servers when running
143                    tests */
144                 parms->all_info.out.ea_size =               IVAL(blob->data, 72);
145                 /* access flags 4 bytes at 76
146                    current_position 8 bytes at 80
147                    mode 4 bytes at 88
148                    alignment 4 bytes at 92
149                 */
150                 smbcli_blob_pull_string(NULL, mem_ctx, blob,
151                                         &parms->all_info.out.fname, 96, 100, STR_UNICODE);
152 #endif
153                 return NT_STATUS_OK;
154
155         case RAW_FILEINFO_ALT_NAME_INFORMATION:
156                 FINFO_CHECK_MIN_SIZE(4);
157                 smbcli_blob_pull_string(NULL, mem_ctx, blob, 
158                                         &parms->alt_name_info.out.fname, 0, 4, STR_UNICODE);
159                 return NT_STATUS_OK;
160
161         case RAW_FILEINFO_STREAM_INFORMATION:
162                 return smbcli_parse_stream_info(*blob, mem_ctx, &parms->stream_info.out);
163
164         case RAW_FILEINFO_INTERNAL_INFORMATION:
165                 FINFO_CHECK_SIZE(8);
166                 parms->internal_information.out.file_id = BVAL(blob->data, 0);
167                 return NT_STATUS_OK;
168
169         case RAW_FILEINFO_ACCESS_INFORMATION:
170                 FINFO_CHECK_SIZE(4);
171                 parms->access_information.out.access_flags = IVAL(blob->data, 0);
172                 return NT_STATUS_OK;
173
174         case RAW_FILEINFO_POSITION_INFORMATION:
175                 FINFO_CHECK_SIZE(8);
176                 parms->position_information.out.position = BVAL(blob->data, 0);
177                 return NT_STATUS_OK;
178
179         case RAW_FILEINFO_MODE_INFORMATION:
180                 FINFO_CHECK_SIZE(4);
181                 parms->mode_information.out.mode = IVAL(blob->data, 0);
182                 return NT_STATUS_OK;
183
184         case RAW_FILEINFO_ALIGNMENT_INFORMATION:
185                 FINFO_CHECK_SIZE(4);
186                 parms->alignment_information.out.alignment_requirement 
187                         = IVAL(blob->data, 0);
188                 return NT_STATUS_OK;
189
190         case RAW_FILEINFO_COMPRESSION_INFORMATION:
191                 FINFO_CHECK_SIZE(16);
192                 parms->compression_info.out.compressed_size = BVAL(blob->data,  0);
193                 parms->compression_info.out.format          = SVAL(blob->data,  8);
194                 parms->compression_info.out.unit_shift      = CVAL(blob->data, 10);
195                 parms->compression_info.out.chunk_shift     = CVAL(blob->data, 11);
196                 parms->compression_info.out.cluster_shift   = CVAL(blob->data, 12);
197                 /* 3 bytes of padding */
198                 return NT_STATUS_OK;
199
200         case RAW_FILEINFO_NETWORK_OPEN_INFORMATION:             
201                 FINFO_CHECK_SIZE(56);
202                 parms->network_open_information.out.create_time = smbcli_pull_nttime(blob->data,  0);
203                 parms->network_open_information.out.access_time = smbcli_pull_nttime(blob->data,  8);
204                 parms->network_open_information.out.write_time =  smbcli_pull_nttime(blob->data, 16);
205                 parms->network_open_information.out.change_time = smbcli_pull_nttime(blob->data, 24);
206                 parms->network_open_information.out.alloc_size =             BVAL(blob->data, 32);
207                 parms->network_open_information.out.size =                   BVAL(blob->data, 40);
208                 parms->network_open_information.out.attrib =                 IVAL(blob->data, 48);
209                 return NT_STATUS_OK;
210
211         case RAW_FILEINFO_ATTRIBUTE_TAG_INFORMATION:
212                 FINFO_CHECK_SIZE(8);
213                 parms->attribute_tag_information.out.attrib =      IVAL(blob->data, 0);
214                 parms->attribute_tag_information.out.reparse_tag = IVAL(blob->data, 4);
215                 return NT_STATUS_OK;
216
217         case RAW_FILEINFO_SMB2_ALL_EAS:
218                 FINFO_CHECK_MIN_SIZE(4);
219                 return ea_pull_list_chained(blob, mem_ctx, 
220                                             &parms->all_eas.out.num_eas,
221                                             &parms->all_eas.out.eas);
222
223         case RAW_FILEINFO_SMB2_ALL_INFORMATION:
224                 FINFO_CHECK_MIN_SIZE(0x64);
225                 parms->all_info2.out.create_time    = smbcli_pull_nttime(blob->data, 0x00);
226                 parms->all_info2.out.access_time    = smbcli_pull_nttime(blob->data, 0x08);
227                 parms->all_info2.out.write_time     = smbcli_pull_nttime(blob->data, 0x10);
228                 parms->all_info2.out.change_time    = smbcli_pull_nttime(blob->data, 0x18);
229                 parms->all_info2.out.attrib         = IVAL(blob->data, 0x20);
230                 parms->all_info2.out.unknown1       = IVAL(blob->data, 0x24);
231                 parms->all_info2.out.alloc_size     = BVAL(blob->data, 0x28);
232                 parms->all_info2.out.size           = BVAL(blob->data, 0x30);
233                 parms->all_info2.out.nlink          = IVAL(blob->data, 0x38);
234                 parms->all_info2.out.delete_pending = CVAL(blob->data, 0x3C);
235                 parms->all_info2.out.directory      = CVAL(blob->data, 0x3D);
236                 parms->all_info2.out.file_id        = BVAL(blob->data, 0x40);
237                 parms->all_info2.out.ea_size        = IVAL(blob->data, 0x48);
238                 parms->all_info2.out.access_mask    = IVAL(blob->data, 0x4C);
239                 parms->all_info2.out.position       = BVAL(blob->data, 0x50);
240                 parms->all_info2.out.mode           = BVAL(blob->data, 0x58);
241                 smbcli_blob_pull_string(NULL, mem_ctx, blob,
242                                         &parms->all_info2.out.fname, 0x60, 0x64, STR_UNICODE);
243                 return NT_STATUS_OK;
244
245         case RAW_FILEINFO_SEC_DESC: {
246                 struct ndr_pull *ndr;
247                 NTSTATUS status;
248                 ndr = ndr_pull_init_blob(blob, mem_ctx);
249                 if (!ndr) {
250                         return NT_STATUS_NO_MEMORY;
251                 }
252                 parms->query_secdesc.out.sd = talloc(mem_ctx, struct security_descriptor);
253                 if (parms->query_secdesc.out.sd == NULL) {
254                         return NT_STATUS_NO_MEMORY;
255                 }
256                 status = ndr_pull_security_descriptor(ndr, NDR_SCALARS|NDR_BUFFERS, 
257                                                       parms->query_secdesc.out.sd);
258                 talloc_free(ndr);
259                 return status;
260         }
261
262         default:
263                 break;
264         }
265
266         return NT_STATUS_INVALID_LEVEL;
267 }
268
269
270 /****************************************************************************
271  Handle qfileinfo/qpathinfo trans2 backend.
272 ****************************************************************************/
273 static NTSTATUS smb_raw_info_backend(struct smbcli_session *session,
274                                      TALLOC_CTX *mem_ctx,
275                                      union smb_fileinfo *parms, 
276                                      DATA_BLOB *blob)
277 {       
278         switch (parms->generic.level) {
279         case RAW_FILEINFO_GENERIC:
280         case RAW_FILEINFO_GETATTR:
281         case RAW_FILEINFO_GETATTRE:
282         case RAW_FILEINFO_SEC_DESC:
283                 /* not handled here */
284                 return NT_STATUS_INVALID_LEVEL;
285
286         case RAW_FILEINFO_STANDARD:
287                 FINFO_CHECK_SIZE(22);
288                 parms->standard.out.create_time = raw_pull_dos_date2(session->transport,
289                                                                      blob->data +  0);
290                 parms->standard.out.access_time = raw_pull_dos_date2(session->transport,
291                                                                      blob->data +  4);
292                 parms->standard.out.write_time =  raw_pull_dos_date2(session->transport,
293                                                                      blob->data +  8);
294                 parms->standard.out.size =        IVAL(blob->data,             12);
295                 parms->standard.out.alloc_size =  IVAL(blob->data,             16);
296                 parms->standard.out.attrib =      SVAL(blob->data,             20);
297                 return NT_STATUS_OK;
298
299         case RAW_FILEINFO_EA_SIZE:
300                 FINFO_CHECK_SIZE(26);
301                 parms->ea_size.out.create_time = raw_pull_dos_date2(session->transport,
302                                                                     blob->data +  0);
303                 parms->ea_size.out.access_time = raw_pull_dos_date2(session->transport,
304                                                                     blob->data +  4);
305                 parms->ea_size.out.write_time =  raw_pull_dos_date2(session->transport,
306                                                                     blob->data +  8);
307                 parms->ea_size.out.size =        IVAL(blob->data,             12);
308                 parms->ea_size.out.alloc_size =  IVAL(blob->data,             16);
309                 parms->ea_size.out.attrib =      SVAL(blob->data,             20);
310                 parms->ea_size.out.ea_size =     IVAL(blob->data,             22);
311                 return NT_STATUS_OK;
312
313         case RAW_FILEINFO_EA_LIST:
314                 FINFO_CHECK_MIN_SIZE(4);
315                 return ea_pull_list(blob, mem_ctx, 
316                                     &parms->ea_list.out.num_eas,
317                                     &parms->ea_list.out.eas);
318
319         case RAW_FILEINFO_ALL_EAS:
320                 FINFO_CHECK_MIN_SIZE(4);
321                 return ea_pull_list(blob, mem_ctx, 
322                                     &parms->all_eas.out.num_eas,
323                                     &parms->all_eas.out.eas);
324
325         case RAW_FILEINFO_IS_NAME_VALID:
326                 /* no data! */
327                 FINFO_CHECK_SIZE(0);
328                 return NT_STATUS_OK;
329
330         case RAW_FILEINFO_BASIC_INFO:
331         case RAW_FILEINFO_BASIC_INFORMATION:
332                 return smb_raw_fileinfo_passthru_parse(blob, mem_ctx, 
333                                                        RAW_FILEINFO_BASIC_INFORMATION, parms);
334
335         case RAW_FILEINFO_STANDARD_INFO:
336         case RAW_FILEINFO_STANDARD_INFORMATION:
337                 return smb_raw_fileinfo_passthru_parse(blob, mem_ctx, 
338                                                        RAW_FILEINFO_STANDARD_INFORMATION, parms);
339
340         case RAW_FILEINFO_EA_INFO:
341         case RAW_FILEINFO_EA_INFORMATION:
342                 return smb_raw_fileinfo_passthru_parse(blob, mem_ctx, 
343                                                        RAW_FILEINFO_EA_INFORMATION, parms);
344
345         case RAW_FILEINFO_NAME_INFO:
346         case RAW_FILEINFO_NAME_INFORMATION:
347                 return smb_raw_fileinfo_passthru_parse(blob, mem_ctx, 
348                                                        RAW_FILEINFO_NAME_INFORMATION, parms);
349
350         case RAW_FILEINFO_ALL_INFO:
351         case RAW_FILEINFO_ALL_INFORMATION:
352                 return smb_raw_fileinfo_passthru_parse(blob, mem_ctx, 
353                                                        RAW_FILEINFO_ALL_INFORMATION, parms);
354
355         case RAW_FILEINFO_ALT_NAME_INFO:
356         case RAW_FILEINFO_ALT_NAME_INFORMATION:
357                 return smb_raw_fileinfo_passthru_parse(blob, mem_ctx, 
358                                                        RAW_FILEINFO_ALT_NAME_INFORMATION, parms);
359
360         case RAW_FILEINFO_STREAM_INFO:
361         case RAW_FILEINFO_STREAM_INFORMATION:
362                 return smb_raw_fileinfo_passthru_parse(blob, mem_ctx, 
363                                                        RAW_FILEINFO_STREAM_INFORMATION, parms);
364
365         case RAW_FILEINFO_INTERNAL_INFORMATION:
366                 return smb_raw_fileinfo_passthru_parse(blob, mem_ctx, 
367                                                        RAW_FILEINFO_INTERNAL_INFORMATION, parms);
368
369         case RAW_FILEINFO_ACCESS_INFORMATION:
370                 return smb_raw_fileinfo_passthru_parse(blob, mem_ctx, 
371                                                        RAW_FILEINFO_ACCESS_INFORMATION, parms);
372
373         case RAW_FILEINFO_POSITION_INFORMATION:
374                 return smb_raw_fileinfo_passthru_parse(blob, mem_ctx, 
375                                                        RAW_FILEINFO_POSITION_INFORMATION, parms);
376
377         case RAW_FILEINFO_MODE_INFORMATION:
378                 return smb_raw_fileinfo_passthru_parse(blob, mem_ctx, 
379                                                        RAW_FILEINFO_MODE_INFORMATION, parms);
380
381         case RAW_FILEINFO_ALIGNMENT_INFORMATION:
382                 return smb_raw_fileinfo_passthru_parse(blob, mem_ctx, 
383                                                        RAW_FILEINFO_ALIGNMENT_INFORMATION, parms);
384
385         case RAW_FILEINFO_COMPRESSION_INFO:
386         case RAW_FILEINFO_COMPRESSION_INFORMATION:
387                 return smb_raw_fileinfo_passthru_parse(blob, mem_ctx, 
388                                                        RAW_FILEINFO_COMPRESSION_INFORMATION, parms);
389
390         case RAW_FILEINFO_UNIX_BASIC:
391                 FINFO_CHECK_SIZE(100);
392                 parms->unix_basic_info.out.end_of_file        =            BVAL(blob->data,  0);
393                 parms->unix_basic_info.out.num_bytes          =            BVAL(blob->data,  8);
394                 parms->unix_basic_info.out.status_change_time = smbcli_pull_nttime(blob->data, 16);
395                 parms->unix_basic_info.out.access_time        = smbcli_pull_nttime(blob->data, 24);
396                 parms->unix_basic_info.out.change_time        = smbcli_pull_nttime(blob->data, 32);
397                 parms->unix_basic_info.out.uid                =            BVAL(blob->data, 40);
398                 parms->unix_basic_info.out.gid                =            BVAL(blob->data, 48);
399                 parms->unix_basic_info.out.file_type          =            IVAL(blob->data, 52);
400                 parms->unix_basic_info.out.dev_major          =            BVAL(blob->data, 60);
401                 parms->unix_basic_info.out.dev_minor          =            BVAL(blob->data, 68);
402                 parms->unix_basic_info.out.unique_id          =            BVAL(blob->data, 76);
403                 parms->unix_basic_info.out.permissions        =            BVAL(blob->data, 84);
404                 parms->unix_basic_info.out.nlink              =            BVAL(blob->data, 92);
405                 return NT_STATUS_OK;
406
407         case RAW_FILEINFO_UNIX_LINK:
408                 smbcli_blob_pull_string(session, mem_ctx, blob, 
409                                      &parms->unix_link_info.out.link_dest, 0, 4, STR_UNICODE);
410                 return NT_STATUS_OK;
411                 
412         case RAW_FILEINFO_NETWORK_OPEN_INFORMATION:             
413                 return smb_raw_fileinfo_passthru_parse(blob, mem_ctx, 
414                                                        RAW_FILEINFO_NETWORK_OPEN_INFORMATION, parms);
415
416         case RAW_FILEINFO_ATTRIBUTE_TAG_INFORMATION:
417                 return smb_raw_fileinfo_passthru_parse(blob, mem_ctx, 
418                                                        RAW_FILEINFO_ATTRIBUTE_TAG_INFORMATION, parms);
419
420         case RAW_FILEINFO_SMB2_ALL_INFORMATION:
421                 return smb_raw_fileinfo_passthru_parse(blob, mem_ctx, 
422                                                        RAW_FILEINFO_SMB2_ALL_INFORMATION, parms);
423
424         case RAW_FILEINFO_SMB2_ALL_EAS:
425                 return smb_raw_fileinfo_passthru_parse(blob, mem_ctx, 
426                                                        RAW_FILEINFO_SMB2_ALL_EAS, parms);
427
428         }
429
430         return NT_STATUS_INVALID_LEVEL;
431 }
432
433
434 /****************************************************************************
435  Very raw query file info - returns param/data blobs - (async send)
436 ****************************************************************************/
437 static struct smbcli_request *smb_raw_fileinfo_blob_send(struct smbcli_tree *tree,
438                                                          uint16_t fnum, 
439                                                          uint16_t info_level,
440                                                          DATA_BLOB data)
441 {
442         struct smb_trans2 tp;
443         uint16_t setup = TRANSACT2_QFILEINFO;
444         struct smbcli_request *req;
445         TALLOC_CTX *mem_ctx = talloc_init("raw_fileinfo");
446         
447         tp.in.max_setup = 0;
448         tp.in.flags = 0; 
449         tp.in.timeout = 0;
450         tp.in.setup_count = 1;
451         tp.in.data = data;
452         tp.in.max_param = 2;
453         tp.in.max_data = 0xFFFF;
454         tp.in.setup = &setup;
455         
456         tp.in.params = data_blob_talloc(mem_ctx, NULL, 4);
457         if (!tp.in.params.data) {
458                 talloc_free(mem_ctx);
459                 return NULL;
460         }
461
462         SSVAL(tp.in.params.data, 0, fnum);
463         SSVAL(tp.in.params.data, 2, info_level);
464
465         req = smb_raw_trans2_send(tree, &tp);
466
467         talloc_free(mem_ctx);
468
469         return req;
470 }
471
472
473 /****************************************************************************
474  Very raw query file info - returns param/data blobs - (async recv)
475 ****************************************************************************/
476 static NTSTATUS smb_raw_fileinfo_blob_recv(struct smbcli_request *req,
477                                            TALLOC_CTX *mem_ctx,
478                                            DATA_BLOB *blob)
479 {
480         struct smb_trans2 tp;
481         NTSTATUS status = smb_raw_trans2_recv(req, mem_ctx, &tp);
482         if (NT_STATUS_IS_OK(status)) {
483                 *blob = tp.out.data;
484         }
485         return status;
486 }
487
488 /****************************************************************************
489  Very raw query path info - returns param/data blobs (async send)
490 ****************************************************************************/
491 static struct smbcli_request *smb_raw_pathinfo_blob_send(struct smbcli_tree *tree,
492                                                          const char *fname,
493                                                          uint16_t info_level,
494                                                          DATA_BLOB data)
495 {
496         struct smb_trans2 tp;
497         uint16_t setup = TRANSACT2_QPATHINFO;
498         struct smbcli_request *req;
499         TALLOC_CTX *mem_ctx = talloc_init("raw_pathinfo");
500
501         tp.in.max_setup = 0;
502         tp.in.flags = 0; 
503         tp.in.timeout = 0;
504         tp.in.setup_count = 1;
505         tp.in.data = data;
506         tp.in.max_param = 2;
507         tp.in.max_data = 0xFFFF;
508         tp.in.setup = &setup;
509         
510         tp.in.params = data_blob_talloc(mem_ctx, NULL, 6);
511         if (!tp.in.params.data) {
512                 talloc_free(mem_ctx);
513                 return NULL;
514         }
515
516         SSVAL(tp.in.params.data, 0, info_level);
517         SIVAL(tp.in.params.data, 2, 0);
518         smbcli_blob_append_string(tree->session, mem_ctx, &tp.in.params,
519                                fname, STR_TERMINATE);
520         
521         req = smb_raw_trans2_send(tree, &tp);
522
523         talloc_free(mem_ctx);
524
525         return req;
526 }
527
528 /****************************************************************************
529  send a SMBgetatr (async send)
530 ****************************************************************************/
531 static struct smbcli_request *smb_raw_getattr_send(struct smbcli_tree *tree,
532                                                 union smb_fileinfo *parms)
533 {
534         struct smbcli_request *req;
535         
536         req = smbcli_request_setup(tree, SMBgetatr, 0, 0);
537         if (!req) return NULL;
538
539         smbcli_req_append_ascii4(req, parms->getattr.in.fname, STR_TERMINATE);
540         
541         if (!smbcli_request_send(req)) {
542                 smbcli_request_destroy(req);
543                 return NULL;
544         }
545
546         return req;
547 }
548
549 /****************************************************************************
550  send a SMBgetatr (async recv)
551 ****************************************************************************/
552 static NTSTATUS smb_raw_getattr_recv(struct smbcli_request *req,
553                                      union smb_fileinfo *parms)
554 {
555         if (!smbcli_request_receive(req) ||
556             smbcli_request_is_error(req)) {
557                 return smbcli_request_destroy(req);
558         }
559
560         SMBCLI_CHECK_WCT(req, 10);
561         parms->getattr.out.attrib =     SVAL(req->in.vwv, VWV(0));
562         parms->getattr.out.write_time = raw_pull_dos_date3(req->transport,
563                                                            req->in.vwv + VWV(1));
564         parms->getattr.out.size =       IVAL(req->in.vwv, VWV(3));
565
566 failed:
567         return smbcli_request_destroy(req);
568 }
569
570
571 /****************************************************************************
572  Handle SMBgetattrE (async send)
573 ****************************************************************************/
574 static struct smbcli_request *smb_raw_getattrE_send(struct smbcli_tree *tree,
575                                                  union smb_fileinfo *parms)
576 {
577         struct smbcli_request *req;
578         
579         req = smbcli_request_setup(tree, SMBgetattrE, 1, 0);
580         if (!req) return NULL;
581         
582         SSVAL(req->out.vwv, VWV(0), parms->getattre.in.fnum);
583         if (!smbcli_request_send(req)) {
584                 smbcli_request_destroy(req);
585                 return NULL;
586         }
587
588         return req;
589 }
590
591 /****************************************************************************
592  Handle SMBgetattrE (async send)
593 ****************************************************************************/
594 static NTSTATUS smb_raw_getattrE_recv(struct smbcli_request *req,
595                                       union smb_fileinfo *parms)
596 {
597         if (!smbcli_request_receive(req) ||
598             smbcli_request_is_error(req)) {
599                 return smbcli_request_destroy(req);
600         }
601         
602         SMBCLI_CHECK_WCT(req, 11);
603         parms->getattre.out.create_time =   raw_pull_dos_date2(req->transport,
604                                                                req->in.vwv + VWV(0));
605         parms->getattre.out.access_time =   raw_pull_dos_date2(req->transport,
606                                                                req->in.vwv + VWV(2));
607         parms->getattre.out.write_time  =   raw_pull_dos_date2(req->transport,
608                                                                req->in.vwv + VWV(4));
609         parms->getattre.out.size =          IVAL(req->in.vwv,             VWV(6));
610         parms->getattre.out.alloc_size =    IVAL(req->in.vwv,             VWV(8));
611         parms->getattre.out.attrib =        SVAL(req->in.vwv,             VWV(10));
612
613 failed:
614         return smbcli_request_destroy(req);
615 }
616
617
618 /****************************************************************************
619  Query file info (async send)
620 ****************************************************************************/
621 struct smbcli_request *smb_raw_fileinfo_send(struct smbcli_tree *tree,
622                                              union smb_fileinfo *parms)
623 {
624         DATA_BLOB data;
625         struct smbcli_request *req;
626
627         /* pass off the non-trans2 level to specialised functions */
628         if (parms->generic.level == RAW_FILEINFO_GETATTRE) {
629                 return smb_raw_getattrE_send(tree, parms);
630         }
631         if (parms->generic.level == RAW_FILEINFO_SEC_DESC) {
632                 return smb_raw_query_secdesc_send(tree, parms);
633         }
634         if (parms->generic.level >= RAW_FILEINFO_GENERIC) {
635                 return NULL;
636         }
637
638         data = data_blob(NULL, 0);
639
640         if (parms->generic.level == RAW_FILEINFO_EA_LIST) {
641                 if (!ea_push_name_list(tree, 
642                                        &data,
643                                        parms->ea_list.in.num_names,
644                                        parms->ea_list.in.ea_names)) {
645                         return NULL;
646                 }
647         }
648
649         req = smb_raw_fileinfo_blob_send(tree, 
650                                          parms->generic.in.fnum,
651                                          parms->generic.level, data);
652
653         data_blob_free(&data);
654
655         return req;
656 }
657
658 /****************************************************************************
659  Query file info (async recv)
660 ****************************************************************************/
661 NTSTATUS smb_raw_fileinfo_recv(struct smbcli_request *req,
662                                TALLOC_CTX *mem_ctx,
663                                union smb_fileinfo *parms)
664 {
665         DATA_BLOB blob;
666         NTSTATUS status;
667         struct smbcli_session *session = req?req->session:NULL;
668
669         if (parms->generic.level == RAW_FILEINFO_GETATTRE) {
670                 return smb_raw_getattrE_recv(req, parms);
671         }
672         if (parms->generic.level == RAW_FILEINFO_SEC_DESC) {
673                 return smb_raw_query_secdesc_recv(req, mem_ctx, parms);
674         }
675         if (parms->generic.level == RAW_FILEINFO_GETATTR) {
676                 return smb_raw_getattr_recv(req, parms);
677         }
678
679         status = smb_raw_fileinfo_blob_recv(req, mem_ctx, &blob);
680         if (!NT_STATUS_IS_OK(status)) {
681                 return status;
682         }
683
684         return smb_raw_info_backend(session, mem_ctx, parms, &blob);
685 }
686
687 /****************************************************************************
688  Query file info (sync interface)
689 ****************************************************************************/
690 NTSTATUS smb_raw_fileinfo(struct smbcli_tree *tree,
691                           TALLOC_CTX *mem_ctx,
692                           union smb_fileinfo *parms)
693 {
694         struct smbcli_request *req = smb_raw_fileinfo_send(tree, parms);
695         return smb_raw_fileinfo_recv(req, mem_ctx, parms);
696 }
697
698 /****************************************************************************
699  Query path info (async send)
700 ****************************************************************************/
701 struct smbcli_request *smb_raw_pathinfo_send(struct smbcli_tree *tree,
702                                              union smb_fileinfo *parms)
703 {
704         DATA_BLOB data;
705         struct smbcli_request *req;
706
707         if (parms->generic.level == RAW_FILEINFO_GETATTR) {
708                 return smb_raw_getattr_send(tree, parms);
709         }
710         if (parms->generic.level >= RAW_FILEINFO_GENERIC) {
711                 return NULL;
712         }
713         
714         data = data_blob(NULL, 0);
715
716         if (parms->generic.level == RAW_FILEINFO_EA_LIST) {
717                 if (!ea_push_name_list(tree, 
718                                        &data,
719                                        parms->ea_list.in.num_names,
720                                        parms->ea_list.in.ea_names)) {
721                         return NULL;
722                 }
723         }
724
725         req = smb_raw_pathinfo_blob_send(tree, parms->generic.in.fname,
726                                          parms->generic.level, data);
727         data_blob_free(&data);
728
729         return req;
730 }
731
732 /****************************************************************************
733  Query path info (async recv)
734 ****************************************************************************/
735 NTSTATUS smb_raw_pathinfo_recv(struct smbcli_request *req,
736                                TALLOC_CTX *mem_ctx,
737                                union smb_fileinfo *parms)
738 {
739         /* recv is idential to fileinfo */
740         return smb_raw_fileinfo_recv(req, mem_ctx, parms);
741 }
742
743 /****************************************************************************
744  Query path info (sync interface)
745 ****************************************************************************/
746 NTSTATUS smb_raw_pathinfo(struct smbcli_tree *tree,
747                           TALLOC_CTX *mem_ctx,
748                           union smb_fileinfo *parms)
749 {
750         struct smbcli_request *req = smb_raw_pathinfo_send(tree, parms);
751         return smb_raw_pathinfo_recv(req, mem_ctx, parms);
752 }