1 #include "headers.h"
2
3 SmbProcessResult
smbcomreadandx(SmbSession * s,SmbHeader * h,uchar * pdata,SmbBuffer * b)4 smbcomreadandx(SmbSession *s, SmbHeader *h, uchar *pdata, SmbBuffer *b)
5 {
6 uchar andxcommand;
7 ushort andxoffset;
8 ulong andxoffsetfixup;
9 ulong datafixup;
10 ulong bytecountfixup;
11 ushort fid;
12 SmbTree *t;
13 SmbFile *f;
14 vlong offset;
15 ushort maxcount;
16 long toread;
17 long nb;
18
19 if (h->wordcount != 10 && h->wordcount != 12)
20 return SmbProcessResultFormat;
21
22 andxcommand = *pdata++;
23 pdata++;
24 andxoffset = smbnhgets(pdata); pdata += 2;
25 fid = smbnhgets(pdata); pdata += 2;
26 offset = smbnhgetl(pdata); pdata += 4;
27 maxcount = smbnhgets(pdata); pdata += 2;
28 pdata += 2; // mincount
29 pdata += 4; // timeout ?
30 pdata += 2; // remaining
31 if (h->wordcount == 12)
32 offset |= (vlong)smbnhgetl(pdata) << 32;
33
34 t = smbidmapfind(s->tidmap, h->tid);
35 if (t == nil) {
36 smbseterror(s, ERRSRV, ERRinvtid);
37 return SmbProcessResultError;
38 }
39 f = smbidmapfind(s->fidmap, fid);
40 if (f == nil) {
41 smbseterror(s, ERRDOS, ERRbadfid);
42 return SmbProcessResultError;
43 }
44
45 if (!f->ioallowed) {
46 smbseterror(s, ERRDOS, ERRbadaccess);
47 return SmbProcessResultError;
48 }
49
50 h->wordcount = 12;
51 if (!smbbufferputandxheader(s->response, h, &s->peerinfo, andxcommand, &andxoffsetfixup))
52 return SmbProcessResultMisc;
53 if (!smbbufferputs(s->response, -1) // remaining
54 || !smbbufferputs(s->response, 0) // datacompactionmode
55 || !smbbufferputs(s->response, 0)) // reserved
56 return SmbProcessResultMisc;
57 datafixup = smbbufferwriteoffset(s->response);
58 if (!smbbufferputbytes(s->response, nil, 6)
59 || !smbbufferfill(s->response, 0, 8)) // reserved
60 return SmbProcessResultMisc;
61 bytecountfixup = smbbufferwriteoffset(s->response);
62 if (!smbbufferputs(s->response, 0)
63 || !smbbufferputb(s->response, 0))
64 return SmbProcessResultMisc;
65 smbbufferwritelimit(s->response, smbbufferwriteoffset(s->response) + 65535);
66 smbbufferoffsetputs(s->response, datafixup + 2, smbbufferwriteoffset(s->response));
67 seek(f->fd, offset, 0);
68 toread = smbbufferwritespace(s->response);
69 if (toread > maxcount)
70 toread = maxcount;
71 nb = readn(f->fd, smbbufferwritepointer(s->response), toread);
72 if (nb < 0) {
73 smbseterror(s, ERRDOS, ERRbadaccess);
74 return SmbProcessResultError;
75 }
76 if (!smbbufferputbytes(s->response, nil, nb)
77 || !smbbufferfixuprelatives(s->response, bytecountfixup)
78 || !smbbufferoffsetputs(s->response, datafixup, nb)
79 || !smbbufferoffsetputs(s->response, datafixup + 4, nb >> 16))
80 return SmbProcessResultMisc;
81 if (andxcommand != SMB_COM_NO_ANDX_COMMAND)
82 return smbchaincommand(s, h, andxoffsetfixup, andxcommand, andxoffset, b);
83 return SmbProcessResultReply;
84 }
85