#include "headers.h"
SmbProcessResult
smbcomreadandx(SmbSession *s, SmbHeader *h, uchar *pdata, SmbBuffer *b)
{
uchar andxcommand;
ushort andxoffset;
ulong andxoffsetfixup;
ulong datafixup;
ulong bytecountfixup;
ushort fid;
SmbTree *t;
SmbFile *f;
vlong offset;
ushort maxcount;
long toread;
long nb;
if (h->wordcount != 10 && h->wordcount != 12)
return SmbProcessResultFormat;
andxcommand = *pdata++;
pdata++;
andxoffset = smbnhgets(pdata); pdata += 2;
fid = smbnhgets(pdata); pdata += 2;
offset = smbnhgetl(pdata); pdata += 4;
maxcount = smbnhgets(pdata); pdata += 2;
pdata += 2; // mincount
pdata += 4; // timeout ?
pdata += 2; // remaining
if (h->wordcount == 12)
offset |= (vlong)smbnhgetl(pdata) << 32;
t = smbidmapfind(s->tidmap, h->tid);
if (t == nil) {
smbseterror(s, ERRSRV, ERRinvtid);
return SmbProcessResultError;
}
f = smbidmapfind(s->fidmap, fid);
if (f == nil) {
smbseterror(s, ERRDOS, ERRbadfid);
return SmbProcessResultError;
}
if (!f->ioallowed) {
smbseterror(s, ERRDOS, ERRbadaccess);
return SmbProcessResultError;
}
h->wordcount = 12;
if (!smbbufferputandxheader(s->response, h, &s->peerinfo, andxcommand, &andxoffsetfixup))
return SmbProcessResultMisc;
if (!smbbufferputs(s->response, -1) // remaining
|| !smbbufferputs(s->response, 0) // datacompactionmode
|| !smbbufferputs(s->response, 0)) // reserved
return SmbProcessResultMisc;
datafixup = smbbufferwriteoffset(s->response);
if (!smbbufferputbytes(s->response, nil, 6)
|| !smbbufferfill(s->response, 0, 8)) // reserved
return SmbProcessResultMisc;
bytecountfixup = smbbufferwriteoffset(s->response);
if (!smbbufferputs(s->response, 0)
|| !smbbufferputb(s->response, 0))
return SmbProcessResultMisc;
smbbufferwritelimit(s->response, smbbufferwriteoffset(s->response) + 65535);
smbbufferoffsetputs(s->response, datafixup + 2, smbbufferwriteoffset(s->response));
seek(f->fd, offset, 0);
toread = smbbufferwritespace(s->response);
if (toread > maxcount)
toread = maxcount;
nb = readn(f->fd, smbbufferwritepointer(s->response), toread);
if (nb < 0) {
smbseterror(s, ERRDOS, ERRbadaccess);
return SmbProcessResultError;
}
if (!smbbufferputbytes(s->response, nil, nb)
|| !smbbufferfixuprelatives(s->response, bytecountfixup)
|| !smbbufferoffsetputs(s->response, datafixup, nb)
|| !smbbufferoffsetputs(s->response, datafixup + 4, nb >> 16))
return SmbProcessResultMisc;
if (andxcommand != SMB_COM_NO_ANDX_COMMAND)
return smbchaincommand(s, h, andxoffsetfixup, andxcommand, andxoffset, b);
return SmbProcessResultReply;
}
|