MODULE SambaServer;
IMPORT SYSTEM, Machine, Modules, Streams, KernelLog, Commands, Dates, Strings, Files, TCP, TCPServices;
CONST
PrimaryDomain = "BLUEBOTTLE";
Server = "A2SAMBA";
NativeOS = "A2";
LANManager = "A2 LAN Manager";
FileSystem = "AosFS";
Trace = FALSE;
SMBPort* = 445;
TYPE
Share = POINTER TO RECORD
path, unc : Files.FileName;
next : Share;
END;
Connection = POINTER TO RECORD
error: BOOLEAN;
errorcode: LONGINT;
out: Streams.Writer;
in: Streams.Reader;
msgSize: LONGINT;
cmd: LONGINT;
flags: LONGINT;
flags2: INTEGER;
tid: INTEGER;
pid: INTEGER;
uid: INTEGER;
mid: INTEGER;
fid: INTEGER;
sid: INTEGER;
pattern: ARRAY 256 OF CHAR;
netbios: INTEGER;
filename: ARRAY 256 OF CHAR;
sharename: ARRAY 256 OF CHAR;
client: TCP.Connection;
next: Connection;
END;
Agent = OBJECT(TCPServices.Agent)
VAR
out: Streams.Writer;
in: Streams.Reader;
c: Connection;
BEGIN {ACTIVE}
(* Initialisation *)
Streams.OpenReader(in, client.Receive);
Streams.OpenWriter(out, client.Send);
WHILE (client.state IN TCP.OpenStates) DO
NEW(c);
SetLastConnection(c);
c.out := out;
c.in := in;
c.client := client;
c.error := CheckSMBHeader(c);
IF ~c.error THEN
Dispatch(c);
END;
END;
END Agent;
VAR
service: TCPServices.Service;
lastUID, lastTID, lastFID, lastSID: INTEGER;
firstConn: Connection;
shares : Share;
PROCEDURE GetUID(): INTEGER;
BEGIN {EXCLUSIVE}
INC(lastUID);
RETURN lastUID;
END GetUID;
PROCEDURE GetTID(): INTEGER;
BEGIN {EXCLUSIVE}
INC(lastTID);
RETURN lastTID;
END GetTID;
PROCEDURE GetFID(): INTEGER;
BEGIN {EXCLUSIVE}
INC(lastFID);
RETURN lastFID;
END GetFID;
PROCEDURE GetSID(): INTEGER;
BEGIN {EXCLUSIVE}
INC(lastSID);
RETURN lastSID;
END GetSID;
PROCEDURE SetLastConnection(c: Connection);
VAR
oldConn: Connection;
BEGIN {EXCLUSIVE}
oldConn := GetLastConnection();
oldConn.next := c;
END SetLastConnection;
PROCEDURE GetSharename(VAR c: Connection);
VAR
k: Connection;
BEGIN
k := firstConn;
WHILE (k.next # NIL) DO
IF (k.tid = c.tid) & (Strings.Length(k.sharename) > 0) THEN
COPY(k.sharename, c.sharename);
RETURN;
END;
k := k.next;
END;
END GetSharename;
PROCEDURE GetLastConnection(): Connection;
VAR
c: Connection;
BEGIN
c := firstConn;
WHILE (c.next # NIL) DO
c := c.next;
END;
RETURN c;
END GetLastConnection;
PROCEDURE GetPattern(sid: INTEGER; VAR pattern: ARRAY OF CHAR);
VAR
c: Connection;
BEGIN
c := firstConn;
WHILE (c.sid # sid) DO
c := c.next;
END;
COPY(c.pattern, pattern);
END GetPattern;
PROCEDURE RemoveConnections(tid: INTEGER);
VAR
c, prev: Connection;
BEGIN {EXCLUSIVE}
c := firstConn;
WHILE (c.next # NIL) DO
IF c.tid = tid THEN
prev.next := c.next
END;
prev := c;
c := prev.next;
END;
END RemoveConnections;
PROCEDURE GetFileName(fid: INTEGER; VAR filename: ARRAY OF CHAR);
VAR
c: Connection;
BEGIN
c := firstConn;
WHILE ((c.fid # fid) & (c.next # NIL)) DO
c := c.next;
END;
IF (c.fid = fid) THEN
COPY(c.filename, filename);
ELSE
IF Trace THEN KernelLog.String(" -- FID not found!"); KernelLog.Ln(); END;
c.error := TRUE;
c.errorcode := 393217;
c.netbios := 32 + 3;
WriteSMBHeader(c);
c.out.Net8(0);
c.out.RawInt(0);
c.out.Update();
END;
END GetFileName;
PROCEDURE Dispatch(c: Connection);
BEGIN
IF c.cmd = ORD(72X) THEN
HandleNegotiate(c);
ELSIF c.cmd = ORD(73X) THEN
HandleSessionSetup(c);
ELSIF c.cmd = ORD(75X) THEN
HandleTreeConnect(c);
ELSIF c.cmd = ORD(2DX) THEN
HandleOpen(c);
ELSIF c.cmd = ORD(04X) THEN
HandleClose(c);
ELSIF c.cmd = ORD(32X) THEN
HandleTrans2(c);
ELSIF c.cmd = ORD(71X) THEN
HandleTreeDisconnect(c);
ELSIF c.cmd = ORD(02X) THEN
HandleOpenOld(c);
ELSIF c.cmd = ORD(08X) THEN
HandleQueryInformation(c);
ELSIF c.cmd = ORD(23X) THEN
HandleQueryInfo2(c);
ELSIF c.cmd = ORD(2EX) THEN
HandleRead(c);
ELSIF c.cmd = ORD(0BX) THEN
HandleWrite(c);
ELSIF c.cmd = ORD(2FX) THEN
HandleWriteAndX(c);
ELSIF c.cmd = ORD(0A0X) THEN
HandleTrans(c);
ELSIF c.cmd = ORD(25X) THEN
HandleLMTrans(c);
ELSIF c.cmd = ORD(05X) THEN
HandleFlush(c);
ELSIF c.cmd = ORD(07X) THEN
HandleRename(c);
ELSIF c.cmd = ORD(06X) THEN
HandleDelete(c);
ELSIF c.cmd = ORD(09X) THEN
HandleSetInfo2(c);
ELSIF c.cmd = ORD(22X) THEN
HandleSetInfo2(c);
ELSIF c.cmd = ORD(34X) THEN
HandleFindClose2(c);
ELSIF c.cmd = ORD(2BX) THEN
HandleEcho(c);
ELSIF c.cmd = ORD(00X) THEN
HandleCreateDir(c);
ELSIF c.cmd = ORD(01X) THEN
HandleDeleteDir(c);
ELSIF c.cmd = ORD(0FX) THEN
HandleCreateNew(c);
ELSE
IF Trace THEN KernelLog.String(" -- Unknown packet: "); KernelLog.Int(c.cmd, 0); KernelLog.Ln(); END;
c.in.SkipBytes(1);
c.in.Reset();
END;
END Dispatch;
PROCEDURE HandleCreateNew(c: Connection);
VAR
filename: ARRAY 256 OF CHAR;
f: Files.File;
res: LONGINT;
BEGIN
IF Trace THEN KernelLog.String("Handle Create New: "); KernelLog.Int(c.cmd, 0); KernelLog.Ln(); END;
c.in.SkipBytes(1);
c.in.SkipBytes(2);
c.in.SkipBytes(4);
c.in.SkipBytes(2);
c.in.SkipBytes(1);
c.in.RawString(filename);
ReplaceSlash(filename);
GetSharename(c);
Strings.Concat(c.sharename, filename, filename);
IF Trace THEN KernelLog.String(" -- Filename: "); KernelLog.String(filename); KernelLog.Ln(); END;
f := Files.Old(filename);
IF (f # NIL) THEN
Files.Delete(filename, res);
END;
f := Files.New(filename);
Files.Register(f);
IF res # 0 THEN
c.error := TRUE;
c.errorcode := 327681;
c.netbios := 32 + 3;
WriteSMBHeader(c);
c.out.Net8(0);
c.out.RawInt(0);
c.out.Update();
RETURN;
END;
c.netbios := 32 + 5;
WriteSMBHeader(c);
c.out.Net8(1);
c.fid := GetFID();
c.out.RawInt(c.fid);
c.out.RawInt(0);
c.out.Update();
END HandleCreateNew;
PROCEDURE HandleCreateDir(c: Connection);
VAR
dirname: ARRAY 256 OF CHAR;
res: LONGINT;
BEGIN
IF Trace THEN KernelLog.String("Handle Create Directory: "); KernelLog.Int(c.cmd, 0); KernelLog.Ln(); END;
c.in.SkipBytes(1);
c.in.SkipBytes(2);
c.in.SkipBytes(1);
c.in.RawString(dirname);
IF Trace THEN KernelLog.String(" -- Directory: "); KernelLog.String(dirname); KernelLog.Ln(); END;
Files.CreateDirectory(dirname, res);
IF res # 0 THEN
c.error := TRUE;
END;
c.netbios := 32 + 3;
WriteSMBHeader(c);
c.out.Net8(0);
c.out.RawInt(0);
c.out.Update();
END HandleCreateDir;
PROCEDURE HandleDeleteDir(c: Connection);
VAR
dirname: ARRAY 256 OF CHAR;
res: LONGINT;
BEGIN
IF Trace THEN KernelLog.String("Handle Delete Directory: "); KernelLog.Int(c.cmd, 0); KernelLog.Ln(); END;
c.in.SkipBytes(1);
c.in.SkipBytes(2);
c.in.SkipBytes(1);
c.in.RawString(dirname);
IF Trace THEN KernelLog.String(" -- Directory: "); KernelLog.String(dirname); KernelLog.Ln(); END;
Files.RemoveDirectory(dirname, TRUE, res);
IF res # 0 THEN
c.error := TRUE;
c.errorcode := 327681;
END;
c.netbios := 32 + 3;
WriteSMBHeader(c);
c.out.Net8(0);
c.out.RawInt(0);
c.out.Update();
END HandleDeleteDir;
PROCEDURE HandleEcho(c: Connection);
VAR
i, len: LONGINT;
byteCount, echoCount: INTEGER;
buffer: ARRAY 32 OF CHAR;
BEGIN
IF Trace THEN KernelLog.String("Handle Echo: "); KernelLog.Int(c.cmd, 0); KernelLog.Ln(); END;
c.in.SkipBytes(1);
c.in.RawInt(echoCount);
c.in.RawInt(byteCount);
c.in.Bytes(buffer, 0, byteCount, len);
FOR i := 1 TO echoCount DO
c.netbios := 32 + 5 + SHORT(len);
WriteSMBHeader(c);
c.out.Net8(1);
c.out.RawInt(SHORT(i));
c.out.RawInt(SHORT(len));
c.out.Bytes(buffer, 0, len);
c.out.Update();
END;
END HandleEcho;
PROCEDURE HandleLMTrans(c: Connection);
BEGIN
IF Trace THEN KernelLog.String("Handle LANMAN Trans: "); KernelLog.Int(c.cmd, 0); KernelLog.Ln(); END;
c.error := TRUE;
c.errorcode := 140312577;
c.netbios := 32 + 3;
WriteSMBHeader(c);
c.out.Net8(0);
c.out.RawInt(0);
c.out.Update();
END HandleLMTrans;
PROCEDURE HandleTrans(c: Connection);
BEGIN
IF Trace THEN KernelLog.String("Handle Trans: "); KernelLog.Int(c.cmd, 0); KernelLog.Ln(); END;
c.error := TRUE;
c.errorcode := 65537;
c.netbios := 32 + 3;
WriteSMBHeader(c);
c.out.Net8(0);
c.out.RawInt(0);
c.out.Update();
END HandleTrans;
PROCEDURE HandleRead(c: Connection);
VAR
fidToRead, maxCount: INTEGER;
offset, len: LONGINT;
f: Files.File;
r: Files.Reader;
buffer: ARRAY 65536 OF CHAR;
filename: ARRAY 256 OF CHAR;
BEGIN
IF Trace THEN KernelLog.String("Handle Read File: "); KernelLog.Int(c.cmd, 0); KernelLog.Ln(); END;
c.in.SkipBytes(5);
c.in.RawInt(fidToRead);
GetFileName(fidToRead, filename);
ReplaceSlash(filename);
IF Trace THEN KernelLog.String(" -- File to read: "); KernelLog.String(filename); KernelLog.Ln(); END;
c.in.RawLInt(offset);
c.in.RawInt(maxCount);
f := Files.Old(filename);
IF (f # NIL) THEN
Files.OpenReader(r, f, offset);
r.Bytes(buffer, 0, maxCount, len);
c.netbios := 32 + 27 + SHORT(len);
WriteSMBHeader(c);
c.out.Net8(12);
c.out.Net8(255);
c.out.Net8(0);
c.out.Net16(0);
c.out.RawInt(-1);
c.out.RawInt(0);
c.out.RawInt(0);
c.out.RawInt(SHORT(len));
c.out.RawInt(59);
c.out.RawLInt(0);
c.out.RawInt(0);
c.out.RawLInt(0);
c.out.RawInt(SHORT(len));
c.out.Bytes(buffer, 0, len);
c.out.Update();
ELSE
IF Trace THEN KernelLog.String(" -- FID invalid!"); KernelLog.Ln(); END;
c.error := TRUE;
c.errorcode := 393217;
c.netbios := 32 + 3;
WriteSMBHeader(c);
c.out.Net8(0);
c.out.RawInt(0);
c.out.Update();
END;
END HandleRead;
PROCEDURE HandleWrite(c: Connection);
VAR
fidToWrite, count : INTEGER;
offset, len, res: LONGINT;
buffer: ARRAY 65536 OF CHAR;
filename: ARRAY 256 OF CHAR;
f: Files.File;
w: Files.Writer;
BEGIN
IF Trace THEN KernelLog.String("Handle Write File: "); KernelLog.Int(c.cmd, 0); KernelLog.Ln(); END;
c.in.SkipBytes(1);
c.in.RawInt(fidToWrite);
GetFileName(fidToWrite, filename);
ReplaceSlash(filename);
IF Trace THEN KernelLog.String(" -- File to write: "); KernelLog.String(filename); KernelLog.Ln(); END;
c.in.RawInt(count);
c.in.RawLInt(offset);
c.in.SkipBytes(7);
IF count = 0 THEN
IF Trace THEN KernelLog.String(" -- Count was zero. "); KernelLog.Ln(); END;
IF offset # 0 THEN
Files.Delete(filename, res);
f := Files.New(filename);
Files.Register(f);
END;
c.netbios := 32 + 5;
WriteSMBHeader(c);
c.out.Net8(1);
c.out.RawInt(0);
c.out.Net16(0);
c.out.Update();
RETURN;
END;
f := Files.Old(filename);
IF (f # NIL) THEN
c.in.Bytes(buffer, 0, count, len);
Files.OpenWriter(w, f, offset);
w.Bytes(buffer, 0, len);
w.Update();
c.netbios := 32 + 5;
WriteSMBHeader(c);
c.out.Net8(1);
c.out.RawInt(count);
c.out.Net16(0);
c.out.Update();
ELSE
IF Trace THEN KernelLog.String(" -- FID invalid!"); KernelLog.Ln(); END;
c.error := TRUE;
c.errorcode := 393217;
c.netbios := 32 + 3;
WriteSMBHeader(c);
c.out.Net8(0);
c.out.RawInt(0);
c.out.Update();
END;
END HandleWrite;
PROCEDURE HandleWriteAndX(c: Connection);
VAR
fidToWrite, byteCount, dataOffset: INTEGER;
offset, len: LONGINT;
f: Files.File;
w: Files.Writer;
buffer: ARRAY 65536 OF CHAR;
filename: ARRAY 256 OF CHAR;
BEGIN
IF Trace THEN KernelLog.String("Handle Write File AndX: "); KernelLog.Int(c.cmd, 0); KernelLog.Ln(); END;
c.in.SkipBytes(5);
c.in.RawInt(fidToWrite);
GetFileName(fidToWrite, filename);
ReplaceSlash(filename);
IF Trace THEN KernelLog.String(" -- File to write: "); KernelLog.String(filename); KernelLog.Ln(); END;
c.in.RawLInt(offset);
c.in.SkipBytes(12);
c.in.RawInt(dataOffset);
c.in.RawInt(byteCount);
IF (dataOffset = 0) OR (byteCount = 0) THEN
f := NIL;
len := 0;
ELSE
c.in.SkipBytes(dataOffset - 59);
f := Files.Old(filename);
END;
IF (f # NIL) THEN
Files.OpenWriter(w, f, offset);
c.in.Bytes(buffer, 0, byteCount, len);
w.Bytes(buffer, 0, len);
w.Update();
c.netbios := 32 + 15;
WriteSMBHeader(c);
c.out.Net8(6);
c.out.Net8(255);
c.out.Net8(0);
c.out.Net16(0);
c.out.RawInt(SHORT(len));
c.out.RawInt(-1);
c.out.RawInt(0);
c.out.RawInt(0);
c.out.RawInt(0);
c.out.Update();
ELSE
IF Trace THEN KernelLog.String(" -- FID invalid!"); KernelLog.Ln(); END;
c.error := TRUE;
c.errorcode := 393217;
c.netbios := 32 + 3;
WriteSMBHeader(c);
c.out.Net8(0);
c.out.RawInt(0);
c.out.Update();
END;
END HandleWriteAndX;
PROCEDURE HandleQueryInformation(c: Connection);
VAR
filename: ARRAY 256 OF CHAR;
i: INTEGER;
f: Files.File;
t,d: LONGINT;
dTime: Dates.DateTime;
BEGIN
IF Trace THEN KernelLog.String("Handle Query Information: "); KernelLog.Int(c.cmd, 0); KernelLog.Ln(); END;
c.in.SkipBytes(4);
c.in.RawString(filename);
ReplaceSlash(filename);
GetSharename(c);
Strings.Concat(c.sharename, filename, filename);
IF Trace THEN KernelLog.String(" -- Filename: "); KernelLog.String(filename); KernelLog.Ln(); END;
f := Files.Old(filename);
IF (f # NIL) OR (filename = c.sharename) THEN
c.netbios := 32 + 23;
WriteSMBHeader(c);
c.out.Net8(10);
IF (filename = c.sharename) OR (Files.Directory IN f.flags) THEN
c.out.RawInt(10H);
ELSE
c.out.RawInt(0H);
END;
IF (f # NIL) THEN
f.GetDate(t,d);
dTime := Dates.OberonToDateTime(d,t);
GetUnixTimeStamp(dTime, t);
c.out.RawLInt(t);
c.out.RawLInt(f.Length());
ELSE
c.out.RawLInt(0);
c.out.RawLInt(0);
END;
FOR i := 1 TO 5 DO
c.out.RawInt(0);
END;
c.out.RawInt(0);
c.out.Update();
ELSE
IF Trace THEN KernelLog.String(" -- File not found!"); KernelLog.Ln(); END;
c.error := TRUE;
c.errorcode := 131073;
c.netbios := 32 + 3;
WriteSMBHeader(c);
c.out.Net8(0);
c.out.RawInt(0);
c.out.Update();
END;
END HandleQueryInformation;
PROCEDURE HandleOpenOld(c: Connection);
VAR
filename: ARRAY 256 OF CHAR;
f: Files.File;
d,t : LONGINT;
dTime: Dates.DateTime;
BEGIN
IF Trace THEN KernelLog.String("Handle Open (old) File: "); KernelLog.Int(c.cmd, 0); KernelLog.Ln(); END;
c.in.SkipBytes(8);
c.in.RawString(filename);
ReplaceSlash(filename);
GetSharename(c);
Strings.Concat(c.sharename, filename, filename);
IF Trace THEN KernelLog.String(" -- Filename: "); KernelLog.String(filename); KernelLog.Ln(); END;
f := Files.Old(filename);
IF (f # NIL) THEN
COPY(filename, c.filename);
c.netbios := 32 + 17;
WriteSMBHeader(c);
c.out.Net8(7);
c.fid := GetFID();
c.out.RawInt(c.fid);
IF (Files.Directory IN f.flags) THEN
c.out.RawInt(10H);
ELSE
c.out.RawInt(0H);
END;
f.GetDate(t,d);
dTime := Dates.OberonToDateTime(d,t);
GetUnixTimeStamp(dTime, t);
c.out.RawLInt(t);
c.out.RawLInt(f.Length());
c.out.RawInt(0);
c.out.RawInt(0);
c.out.Update();
ELSE
IF Trace THEN KernelLog.String(" -- File not found!"); KernelLog.Ln(); END;
c.error := TRUE;
c.errorcode := 131073;
c.netbios := 32 + 3;
WriteSMBHeader(c);
c.out.Net8(0);
c.out.RawInt(0);
c.out.Update();
END;
END HandleOpenOld;
PROCEDURE HandleNegotiate(VAR c: Connection);
VAR
variable: LONGINT;
name: ARRAY 64 OF CHAR;
support: BOOLEAN;
size: LONGINT;
dialectIndex: INTEGER;
t: ARRAY 2 OF LONGINT;
BEGIN
support := FALSE;
size := c.msgSize;
dialectIndex := 0;
IF Trace THEN KernelLog.String("Handle Negotiation: "); KernelLog.Int(c.cmd, 0); KernelLog.Ln(); END;
c.in.SkipBytes(3);
WHILE (size - 35 > 0) &( ~support) DO
variable := c.in.Net8();
c.in.RawString(name);
IF (variable = 2) & (name = "NT LM 0.12") THEN
support := TRUE;
IF Trace THEN
KernelLog.String(" -- NTLM 0.12 OK");
KernelLog.Ln();
END;
ELSE
INC(dialectIndex);
END;
size := size - 2 - Strings.Length(name);
END;
IF ~support THEN
c.error := TRUE;
END;
c.netbios := 32 + 37 + 10 + SHORT(Strings.Length(PrimaryDomain) + Strings.Length(Server));
WriteSMBHeader(c);
c.out.Net8(17);
c.out.RawInt(dialectIndex);
c.out.Net8(1);
c.out.RawInt(1);
c.out.RawInt(1);
c.out.RawLInt(32767);
c.out.RawLInt(32767);
c.out.RawLInt(0);
c.out.RawLInt(0);
GetSMBTimeStamp(Dates.Now(), t);
c.out.RawLInt(t[0]);
c.out.RawLInt(t[1]);
c.out.Char(CHR(0));
c.out.Char(CHR(0));
c.out.Net8(8);
c.out.RawInt(SHORT(Strings.Length(PrimaryDomain) + Strings.Length(Server)));
c.out.String("serverpw");
c.out.RawString(PrimaryDomain);
c.out.RawString(Server);
c.out.Update();
END HandleNegotiate;
PROCEDURE HandleSessionSetup(c: Connection);
VAR
ansiPwLen: INTEGER;
ansiPass: ARRAY 256 OF CHAR;
ucPwLen: INTEGER;
uniPass: ARRAY 256 OF CHAR;
username: ARRAY 256 OF CHAR;
i: LONGINT;
BEGIN
IF Trace THEN KernelLog.String("Handle Session setup: "); KernelLog.Int(c.cmd, 0); KernelLog.Ln(); END;
c.in.SkipBytes(15);
c.in.RawInt(ansiPwLen);
c.in.RawInt(ucPwLen);
c.in.SkipBytes(10);
IF ansiPwLen > 0 THEN
c.in.Bytes(ansiPass, 0, ansiPwLen, i);
END;
IF ucPwLen > 0 THEN
c.in.Bytes(uniPass, 0, ucPwLen, i);
END;
c.in.RawString(username);
IF Trace THEN KernelLog.String(" -- Username: "); KernelLog.String(username); KernelLog.Ln(); END;
IF username = "" THEN
c.error := TRUE;
c.errorcode := 262146;
c.netbios := 32 + 3;
WriteSMBHeader(c);
c.out.Net8(0);
c.out.RawInt(0);
c.out.Update();
RETURN;
END;
c.netbios := 32 + 12 + SHORT(Strings.Length(NativeOS) + Strings.Length(PrimaryDomain) + Strings.Length(LANManager));
WriteSMBHeader(c);
c.out.Net8(3);
c.out.Char(CHR(255));
c.out.Net8(0);
c.out.Net16(0);
c.out.RawInt(1);
c.out.RawInt(3 + SHORT(Strings.Length(NativeOS) + Strings.Length(PrimaryDomain) + Strings.Length(LANManager)));
c.out.RawString(NativeOS);
c.out.RawString(LANManager);
c.out.RawString(PrimaryDomain);
c.out.Update();
END HandleSessionSetup;
PROCEDURE HandleTreeConnect(c: Connection);
VAR
i,offset: LONGINT;
pwLen: INTEGER;
byteCount: INTEGER;
password: ARRAY 256 OF CHAR;
path: ARRAY 256 OF CHAR;
service: ARRAY 256 OF CHAR;
string : Strings.String;
share : Share;
BEGIN
IF Trace THEN KernelLog.String("Handle Tree Connect: "); KernelLog.Int(c.cmd, 0); KernelLog.Ln(); END;
c.in.SkipBytes(7);
c.in.RawInt(pwLen);
c.in.RawInt(byteCount);
IF pwLen > 0 THEN
c.in.Bytes(password, 0, pwLen, i);
END;
c.in.RawString(path);
c.in.RawString(service);
IF Trace THEN
KernelLog.String(" -- Service: "); KernelLog.String(service); KernelLog.Ln();
KernelLog.String(" -- Path: "); KernelLog.String(path);
END;
IF Strings.EndsWith("IPC$", path) THEN
IF Trace THEN KernelLog.String(" -- IPC"); KernelLog.Ln; END;
service := "IPC";
ELSE
IF Trace THEN KernelLog.String(" - FILESYSTEM"); KernelLog.Ln; END;
service := "A:";
END;
offset := Strings.Find(path, 3, CHR(5CH));
string := Strings.Substring2(offset, path);
IF (string # NIL) THEN COPY(string^, path); END;
share := FindShare(path);
IF (share # NIL) THEN
COPY(share.path, c.sharename);
KernelLog.String(" -- Sharename: "); KernelLog.String(c.sharename); KernelLog.Ln();
ELSIF (service = "IPC") THEN
KernelLog.String(" -- IPC Connected"); KernelLog.Ln();
ELSE
KernelLog.String(" NO SHARE FOUND"); KernelLog.Ln();
c.error := TRUE;
c.errorcode := 4390913;
c.netbios := 32 + 3;
WriteSMBHeader(c);
c.out.Net8(0);
c.out.RawInt(0);
c.out.Update();
END;
c.netbios := 32 + 19 + SHORT(Strings.Length(FileSystem) + Strings.Length(service));
WriteSMBHeader(c);
c.out.Net8(7);
c.out.Char(CHR(255));
c.out.Net8(0);
c.out.Net16(0);
c.out.RawInt(0);
c.out.RawLInt(268435456);
c.out.RawLInt(268435456);
c.out.RawInt(2 + SHORT(Strings.Length(FileSystem) + Strings.Length(service)));
c.out.RawString(service);
c.out.RawString(FileSystem);
c.out.Update();
END HandleTreeConnect;
PROCEDURE HandleTreeDisconnect(c: Connection);
BEGIN
IF Trace THEN KernelLog.String("Handle Tree Disonnect: "); KernelLog.Int(c.cmd, 0); KernelLog.Ln(); END;
c.netbios := 32 + 3;
WriteSMBHeader(c);
c.out.Net8(0);
c.out.RawInt(0);
c.out.Update();
c.client.Discard();
RemoveConnections(c.tid);
END HandleTreeDisconnect;
PROCEDURE HandleOpen(c: Connection);
VAR
byteCount, openFunc: INTEGER;
filename: ARRAY 256 OF CHAR;
f: Files.File;
t,d: LONGINT;
dTime: Dates.DateTime;
BEGIN
IF Trace THEN KernelLog.String("Handle Open: "); KernelLog.Int(c.cmd, 0); KernelLog.Ln(); END;
c.in.SkipBytes(17);
c.in.RawInt(openFunc);
c.in.SkipBytes(12);
c.in.RawInt(byteCount);
c.in.RawString(filename);
ReplaceSlash(filename);
GetSharename(c);
Strings.Concat(c.sharename, filename, filename);
IF Trace THEN KernelLog.String(" -- Filename: "); KernelLog.String(filename); KernelLog.Ln(); END;
f := Files.Old(filename);
IF ((f # NIL) OR (filename = c.sharename)) & (0 IN SYSTEM.VAL(SET, openFunc)) THEN
IF Trace THEN KernelLog.String(" -- opening file..."); KernelLog.Ln(); END;
COPY(filename, c.filename);
c.netbios := 32 + 33;
WriteSMBHeader(c);
c.out.Net8(15);
c.out.Char(CHR(255));
c.out.Net8(0);
c.out.Net16(0);
c.fid := GetFID();
c.out.RawInt(c.fid);
IF ((f # NIL) & (Files.Directory IN f.flags)) OR (filename = c.sharename) THEN
c.out.RawInt(10H);
ELSE
c.out.RawInt(0H);
END;
IF (f # NIL) THEN
f.GetDate(t,d);
dTime := Dates.OberonToDateTime(d,t);
GetUnixTimeStamp(dTime, t);
c.out.RawLInt(t);
c.out.RawLInt(f.Length());
ELSE
c.out.RawLInt(0);
c.out.RawLInt(0);
END;
c.out.RawInt(0);
c.out.RawInt(0);
c.out.RawInt(0);
c.out.RawInt(1);
c.out.RawLInt(0);
c.out.RawInt(0);
c.out.RawInt(0);
c.out.Update();
ELSIF (f = NIL) & (4 IN SYSTEM.VAL(SET, openFunc)) THEN
IF Trace THEN KernelLog.String(" -- creating file..."); KernelLog.Ln(); END;
f := Files.New(filename);
COPY(filename, c.filename);
Files.Register(f);
c.netbios := 32 + 33;
WriteSMBHeader(c);
c.out.Net8(15);
c.out.Char(CHR(255));
c.out.Net8(0);
c.out.Net16(0);
c.fid := GetFID();
c.out.RawInt(c.fid);
c.out.RawInt(0H);
GetUnixTimeStamp(Dates.Now(), t);
c.out.RawLInt(t);
c.out.RawLInt(f.Length());
c.out.RawInt(0);
c.out.RawInt(0);
c.out.RawInt(0);
c.out.RawInt(2);
c.out.RawLInt(0);
c.out.RawInt(0);
c.out.RawInt(0);
c.out.Update();
ELSIF (f # NIL) & ~(0 IN SYSTEM.VAL(SET, openFunc)) THEN
IF Trace THEN KernelLog.String(" -- Invalid open mode!."); KernelLog.Ln(); END;
c.error := TRUE;
c.errorcode := 786433;
c.netbios := 32 + 3;
WriteSMBHeader(c);
c.out.Net8(0);
c.out.RawInt(0);
c.out.Update();
ELSIF Strings.StartsWith("/PIPE/", 0, filename) THEN
IF Trace THEN KernelLog.String(" -- opening pipe..."); KernelLog.Ln(); END;
COPY(filename, c.filename);
c.netbios := 32 + 33;
WriteSMBHeader(c);
c.out.Net8(15);
c.out.Char(CHR(255));
c.out.Net8(0);
c.out.Net16(0);
c.fid := GetFID();
c.out.RawInt(c.fid);
c.out.RawInt(0H);
c.out.RawLInt(0);
c.out.RawLInt(0);
c.out.RawInt(0);
c.out.RawInt(0);
c.out.RawInt(0);
c.out.RawInt(1);
c.out.RawLInt(0);
c.out.RawInt(0);
c.out.RawInt(0);
c.out.Update();
ELSE
IF Trace THEN KernelLog.String(" -- File not found!"); KernelLog.Ln(); END;
c.error := TRUE;
c.errorcode := 131073;
c.netbios := 32 + 3;
WriteSMBHeader(c);
c.out.Net8(0);
c.out.RawInt(0);
c.out.Update();
END;
END HandleOpen;
PROCEDURE HandleClose(c: Connection);
BEGIN
IF Trace THEN KernelLog.String("Handle File close: "); KernelLog.Int(c.cmd, 0); KernelLog.Ln(); END;
c.netbios := 32 + 3;
WriteSMBHeader(c);
c.out.Net8(0);
c.out.RawInt(0);
c.out.Update();
END HandleClose;
PROCEDURE HandleFindClose2(c: Connection);
BEGIN
IF Trace THEN KernelLog.String("Handle find close 2: "); KernelLog.Int(c.cmd, 0); KernelLog.Ln(); END;
c.netbios := 32 + 3;
WriteSMBHeader(c);
c.out.Net8(0);
c.out.RawInt(0);
c.out.Update();
END HandleFindClose2;
PROCEDURE HandleFlush(c : Connection);
BEGIN
IF Trace THEN KernelLog.String("Handle Flush: "); KernelLog.Int(c.cmd, 0); KernelLog.Ln(); END;
c.netbios := 32 + 3;
WriteSMBHeader(c);
c.out.Net8(0);
c.out.RawInt(0);
c.out.Update();
END HandleFlush;
PROCEDURE HandleRename(c : Connection);
VAR
oldName, newName,
oldPath, newPath: ARRAY 256 OF CHAR;
res: LONGINT;
BEGIN
IF Trace THEN KernelLog.String("Handle Rename: "); KernelLog.Int(c.cmd, 0); KernelLog.Ln(); END;
c.in.SkipBytes(6);
c.in.RawString(oldName);
ReplaceSlash(oldName);
Files.SplitPath(oldName, oldPath, oldName);
c.in.SkipBytes(1);
c.in.RawString(newName);
ReplaceSlash(newName);
Files.SplitPath(newName, newPath, newName);
IF Trace THEN
KernelLog.String(" -- Old: "); KernelLog.String(oldName); KernelLog.Ln();
KernelLog.String(" -- New: "); KernelLog.String(newName); KernelLog.Ln();
END;
IF oldPath = newPath THEN
Files.Rename(oldName, newName, res);
END;
IF res # 0 THEN
c.error := TRUE;
c.errorcode := 327681;
END;
c.netbios := 32 + 3;
WriteSMBHeader(c);
c.out.Net8(0);
c.out.RawInt(0);
c.out.Update();
END HandleRename;
PROCEDURE HandleDelete(c: Connection);
VAR
name, path: ARRAY 256 OF CHAR;
res: LONGINT;
BEGIN
IF Trace THEN KernelLog.String("Handle Delete: "); KernelLog.Int(c.cmd, 0); KernelLog.Ln(); END;
c.in.SkipBytes(6);
c.in.RawString(name);
ReplaceSlash(name);
Files.SplitPath(name, path, name);
IF Trace THEN KernelLog.String(" -- Filename: "); KernelLog.String(name); KernelLog.Ln(); END;
Files.Delete(name, res);
IF res # 0 THEN
c.error := TRUE;
c.errorcode := 327681;
END;
c.netbios := 32 + 3;
WriteSMBHeader(c);
c.out.Net8(0);
c.out.RawInt(0);
c.out.Update();
END HandleDelete;
PROCEDURE HandleQueryInfo2(c: Connection);
VAR
filename: ARRAY 256 OF CHAR;
fid: INTEGER;
f: Files.File;
t,d: LONGINT;
dTime: Dates.DateTime;
BEGIN
IF Trace THEN KernelLog.String("Handle Query Information 2: "); KernelLog.Int(c.cmd, 0); KernelLog.Ln(); END;
c.in.SkipBytes(1);
c.in.RawInt(fid);
GetFileName(fid, filename);
ReplaceSlash(filename);
IF Trace THEN KernelLog.String(" -- Filename: "); KernelLog.String(filename); KernelLog.Ln(); END;
f := Files.Old(filename);
IF (f # NIL) THEN
c.netbios := 32 + 25;
WriteSMBHeader(c);
c.out.Net8(11);
c.out.RawLInt(0);
c.out.RawLInt(0);
f.GetDate(t,d);
dTime := Dates.OberonToDateTime(d,t);
GetDOSTimeStamp(dTime, t);
c.out.RawLInt(t);
c.out.RawLInt(f.Length());
c.out.RawLInt(f.Length());
c.out.RawInt(0);
c.out.RawInt(0);
c.out.Update();
ELSE
IF Trace THEN KernelLog.String(" -- File not found!"); KernelLog.Ln(); END;
c.error := TRUE;
c.errorcode := 131073;
c.netbios := 32 + 3;
WriteSMBHeader(c);
c.out.Net8(0);
c.out.RawInt(0);
c.out.Update();
END;
END HandleQueryInfo2;
PROCEDURE HandleSetInfo2(c: Connection);
BEGIN
IF Trace THEN KernelLog.String("Handle Set Information 2: "); KernelLog.Int(c.cmd, 0); KernelLog.Ln(); END;
c.netbios := 32 + 3;
WriteSMBHeader(c);
c.out.Net8(0);
c.out.RawInt(0);
c.out.Update();
END HandleSetInfo2;
PROCEDURE HandleTrans2(c: Connection);
VAR
offset: INTEGER;
subcommand: INTEGER;
BEGIN
IF Trace THEN KernelLog.String("Handle Trans2 Request..."); KernelLog.Int(c.cmd, 0); KernelLog.Ln(); END;
c.in.SkipBytes(21);
c.in.RawInt(offset);
offset := offset - 63;
c.in.SkipBytes(6);
c.in.RawInt(subcommand);
c.in.SkipBytes(offset);
IF Trace THEN KernelLog.String(" -- Subcommand: "); KernelLog.Int(subcommand, 0); KernelLog.Ln(); END;
Trans2Logic(subcommand, c);
END HandleTrans2;
PROCEDURE Trans2Logic(subcmd: INTEGER; c: Connection);
VAR
enum: Files.Enumerator;
eName, fullName, pathname, prefix, pattern, resumeFn, modPat: ARRAY 256 OF CHAR;
eFlags, flags : SET;
eTime, eDate, eSize : LONGINT;
success, eos: BOOLEAN;
i,j,z, searchCount, totalFileNameLen, lastlen, loi, sidnext: INTEGER;
f: Files.File;
tarray: ARRAY 2 OF LONGINT;
t,d: LONGINT;
dTime: Dates.DateTime;
BEGIN
IF (subcmd = 7) THEN
IF Trace THEN KernelLog.String(" -- QUERY FILE INFO"); KernelLog.Ln(); END;
c.error := TRUE;
c.errorcode := 327681;
c.netbios := 32 + 3;
WriteSMBHeader(c);
c.out.Net8(0);
c.out.RawInt(0);
c.out.Update();
RETURN;
ELSIF (subcmd = 3) THEN
IF Trace THEN KernelLog.String(" -- QUERY FS INFO"); KernelLog.Ln(); END;
c.netbios := 32 + 25 + 10 + SHORT(Strings.Length(FileSystem) + 1);
WriteSMBHeader(c);
c.out.Net8(10);
c.out.RawInt(0);
c.out.RawInt(12 + SHORT(Strings.Length(FileSystem) + 1));
c.out.Net16(0);
c.out.RawInt(0);
c.out.RawInt(55);
c.out.RawInt(0);
c.out.RawInt(12 + SHORT(Strings.Length(FileSystem) + 1));
c.out.RawInt(55);
c.out.RawInt(0);
c.out.Net8(0);
c.out.Net8(0);
c.out.RawInt(12 + SHORT(Strings.Length(FileSystem) + 1));
c.out.RawLInt(32);
c.out.RawLInt(64);
c.out.RawLInt(Strings.Length(FileSystem) + 1);
c.out.RawString(FileSystem);
c.out.Update();
ELSIF (subcmd = 5) THEN
IF Trace THEN KernelLog.String(" -- QUERY PATH INFO"); KernelLog.Ln(); END;
c.in.SkipBytes(6);
c.in.RawString(eName);
IF Trace THEN KernelLog.String(" -- Path name: "); KernelLog.String(eName); KernelLog.Ln(); END;
f := Files.Old(eName);
IF ((f = NIL) & (eName[0] # 0X)) THEN
c.error := TRUE;
c.errorcode := 131073;
c.netbios := 32 + 3;
WriteSMBHeader(c);
c.out.Net8(0);
c.out.RawInt(0);
c.out.Update();
RETURN;
END;
c.netbios := SHORT(32 + 89 + Strings.Length(eName));
WriteSMBHeader(c);
c.out.Net8(10);
c.out.RawInt(2);
c.out.RawInt(82);
c.out.Net16(0);
c.out.RawInt(2);
c.out.RawInt(55);
c.out.RawInt(0);
c.out.RawInt(82);
c.out.RawInt(57);
c.out.RawInt(0);
c.out.Net8(0);
c.out.Net8(0);
c.out.RawInt(84);
c.out.RawInt(0);
c.out.RawLInt(0);
c.out.RawLInt(0);
c.out.RawLInt(0);
c.out.RawLInt(0);
c.out.RawLInt(0);
c.out.RawLInt(0);
c.out.RawLInt(0);
c.out.RawLInt(0);
IF eName[0] = 0X THEN
c.out.RawInt(16);
ELSE
c.out.RawInt(0);
END;
c.out.RawLInt(0);
c.out.RawLInt(0);
c.out.RawLInt(0);
c.out.RawLInt(0);
c.out.RawLInt(1);
c.out.Net8(0);
IF eName[0] = 0X THEN
c.out.Net8(1);
ELSE
c.out.Net8(0);
END;
c.out.RawLInt(0);
c.out.RawLInt(Strings.Length(eName));
c.out.RawString(eName);
c.out.Update();
ELSIF (subcmd = 1) THEN
IF Trace THEN KernelLog.String(" -- FIND FIRST 2"); KernelLog.Ln(); END;
c.in.SkipBytes(2);
c.in.RawInt(searchCount);
c.in.SkipBytes(2);
c.in.RawInt(loi);
c.in.SkipBytes(4);
c.in.RawString(pattern);
IF Trace THEN KernelLog.String(" -- Search Count: "); KernelLog.Int(searchCount, 0); KernelLog.Ln(); END;
RemoveSlash(pattern);
ReplaceSlash(pattern);
RemoveQuotes(pattern);
GetSharename(c);
IF Trace THEN
KernelLog.String(" -- Pattern: "); KernelLog.String(pattern); KernelLog.Ln();
KernelLog.String(" -- Level of Interest: "); KernelLog.Int(loi, 0); KernelLog.Ln();
KernelLog.String(" -- Sharename: "); KernelLog.String(c.sharename); KernelLog.Ln();
END;
COPY(pattern, c.pattern);
Strings.Concat(c.sharename, pattern, modPat);
IF Trace THEN KernelLog.String(" -- Modprefix: "); KernelLog.String(modPat); KernelLog.Ln(); END;
NEW(enum);
enum.Open(modPat, {});
IF searchCount > 100 THEN
searchCount := 100;
END;
i := 0;
totalFileNameLen := 0;
WHILE (enum.HasMoreEntries()) & (i < searchCount) DO
success := enum.GetEntry(fullName, eFlags, eTime, eDate, eSize);
IF success THEN
Files.SplitName(fullName, prefix, eName);
Files.SplitPath(eName, pathname, eName);
totalFileNameLen := totalFileNameLen + SHORT(Strings.Length(eName));
lastlen := SHORT(Strings.Length(eName));
INC(i);
END;
END;
eos := ~enum.HasMoreEntries();
IF Trace THEN KernelLog.String(" -- Files found: "); KernelLog.Int(i, 0); KernelLog.Ln(); END;
IF i = 0 THEN
c.error := TRUE;
c.errorcode := 131073;
c.netbios := 32 + 3;
WriteSMBHeader(c);
c.out.Net8(0);
c.out.RawInt(0);
c.out.Update();
RETURN;
END;
IF loi = 260 THEN
j := 96*i + totalFileNameLen;
lastlen := lastlen + 96;
ELSIF loi = 1 THEN
j := 28*i + totalFileNameLen;
lastlen := lastlen + 28;
ELSE
IF Trace THEN KernelLog.String(" -- LEVEL OF INTEREST NOT SUPPORTED "); KernelLog.Ln(); END;
RETURN;
END;
c.netbios := 32 + 23 + 10 + j;
WriteSMBHeader(c);
c.out.Net8(10);
c.out.RawInt(10);
c.out.RawInt(j);
c.out.Net16(0);
c.out.RawInt(10);
c.out.RawInt(55);
c.out.RawInt(0);
c.out.RawInt(j);
c.out.RawInt(65);
c.out.RawInt(0);
c.out.Net8(0);
c.out.Net8(0);
c.out.RawInt(10 + j);
c.sid := GetSID();
c.out.RawInt(c.sid);
c.out.RawInt(i);
IF eos THEN
c.out.RawInt(1);
ELSE
c.out.RawInt(0);
END;
c.out.RawInt(0);
c.out.RawInt(j - lastlen);
enum.Reset();
WHILE (i > 0) DO
success := enum.GetEntry(fullName, eFlags, eTime, eDate, eSize);
IF success THEN
Files.SplitName(fullName, prefix, eName);
Files.SplitPath(eName, pathname, eName);
f := Files.Old(eName);
IF loi = 260 THEN
c.out.RawLInt(96 + Strings.Length(eName));
c.out.RawLInt(0);
c.out.RawLInt(0);
c.out.RawLInt(0);
c.out.RawLInt(0);
c.out.RawLInt(0);
IF (f # NIL) THEN
f.GetDate(t,d);
dTime := Dates.OberonToDateTime(d,t);
GetSMBTimeStamp(dTime, tarray);
c.out.RawLInt(tarray[0]);
c.out.RawLInt(tarray[1]);
ELSE
c.out.RawLInt(0);
c.out.RawLInt(0);
END;
c.out.RawLInt(0);
c.out.RawLInt(0);
IF (f # NIL) THEN
c.out.RawLInt(f.Length());
c.out.RawLInt(0);
ELSE
c.out.RawLInt(0);
c.out.RawLInt(0);
END;
IF (f # NIL) THEN
c.out.RawLInt(f.Length());
ELSE
c.out.RawLInt(0);
END;
c.out.RawLInt(0);
flags := {};
IF (Files.Directory IN eFlags) THEN INCL(flags, 4); END;
IF (Files.ReadOnly IN eFlags) THEN INCL(flags, 0) END;
c.out.RawLInt(SYSTEM.VAL(LONGINT, flags));
c.out.RawLInt(1 + Strings.Length(eName));
c.out.RawLInt(0);
c.out.RawSInt(0);
c.out.RawSInt(0);
FOR z := 1 TO 24 DO
c.out.Net8(0);
END;
c.out.RawString(eName);
c.out.RawSInt(0);
ELSIF loi = 1 THEN
c.out.RawLInt(0);
c.out.RawLInt(0);
c.out.RawLInt(0);
IF (f # NIL) THEN
f.GetDate(t,d);
dTime := Dates.OberonToDateTime(d,t);
GetUnixTimeStamp(dTime, t);
c.out.RawLInt(t);
c.out.RawLInt(f.Length());
c.out.RawLInt(f.Length());
ELSE
c.out.RawLInt(0);
c.out.RawLInt(0);
c.out.RawLInt(0);
END;
flags := {};
IF (Files.Directory IN eFlags) THEN INCL(flags, 4); END;
IF (Files.ReadOnly IN eFlags) THEN INCL(flags, 0) END;
c.out.RawInt(SYSTEM.VAL(INTEGER, flags));
c.out.RawSInt(SHORT(SHORT(Strings.Length(eName))));
c.out.RawString(eName);
END;
END;
DEC(i);
END;
c.out.Update();
enum.Close();
ELSIF (subcmd = 2) THEN
IF Trace THEN KernelLog.String(" -- FIND Next 2"); KernelLog.Ln(); END;
c.in.RawInt(sidnext);
c.in.RawInt(searchCount);
c.in.RawInt(loi);
c.in.SkipBytes(6);
c.in.RawString(resumeFn);
GetPattern(sidnext, pattern);
ReplaceSlash(pattern);
GetSharename(c);
IF Trace THEN
KernelLog.String(" _- Search Count: "); KernelLog.Int(searchCount, 0); KernelLog.Ln();
KernelLog.String(" _- Resume Filename: "); KernelLog.String(resumeFn); KernelLog.Ln();
KernelLog.String(" -- Pattern: "); KernelLog.String(pattern); KernelLog.Ln();
KernelLog.String(" -- Level of Interest: "); KernelLog.Int(loi, 0); KernelLog.Ln();
KernelLog.String(" -- sharename: "); KernelLog.String(c.sharename); KernelLog.Ln();
END;
Strings.Concat(c.sharename, pattern, modPat);
IF Trace THEN KernelLog.String(" -- Modprefix: "); KernelLog.String(modPat); KernelLog.Ln(); END;
NEW(enum);
enum.Open(modPat, {});
IF searchCount > 100 THEN
searchCount := 100;
END;
i := 0;
totalFileNameLen := 0;
WHILE (eName # resumeFn) & (enum.HasMoreEntries()) DO
success := enum.GetEntry(fullName, eFlags, eTime, eDate, eSize);
IF success THEN
Files.SplitName(fullName, prefix, eName);
Files.SplitPath(eName, pathname, eName);
END;
END;
WHILE (enum.HasMoreEntries()) & (i < searchCount) DO
success := enum.GetEntry(fullName, eFlags, eTime, eDate, eSize);
IF success THEN
Files.SplitName(fullName, prefix, eName);
Files.SplitPath(eName, pathname, eName);
totalFileNameLen := totalFileNameLen + SHORT(Strings.Length(eName));
lastlen := SHORT(Strings.Length(eName));
INC(i);
END;
END;
eos := ~enum.HasMoreEntries();
IF Trace THEN KernelLog.String(" -- Files found: "); KernelLog.Int(i, 0); KernelLog.Ln(); END;
IF loi = 260 THEN
j := 96*i + totalFileNameLen;
lastlen := lastlen + 96;
ELSIF loi = 1 THEN
j := 28*i + totalFileNameLen;
lastlen := lastlen + 28;
ELSE
IF Trace THEN KernelLog.String(" -- LEVEL OF INTEREST NOT SUPPORTED "); KernelLog.Ln(); END;
RETURN;
END;
c.netbios := 32 + 23 + 8 + j;
WriteSMBHeader(c);
c.out.Net8(8);
c.out.RawInt(8);
c.out.RawInt(j);
c.out.Net16(0);
c.out.RawInt(8);
c.out.RawInt(55);
c.out.RawInt(0);
c.out.RawInt(j);
c.out.RawInt(63);
c.out.RawInt(0);
c.out.Net8(0);
c.out.Net8(0);
c.out.RawInt(10 + j);
c.out.RawInt(i);
IF eos THEN
c.out.RawInt(1);
ELSE
c.out.RawInt(0);
END;
c.out.RawInt(0);
c.out.RawInt(j - lastlen);
enum.Reset();
WHILE (eName # resumeFn) & (enum.HasMoreEntries()) DO
success := enum.GetEntry(fullName, eFlags, eTime, eDate, eSize);
IF success THEN
Files.SplitName(fullName, prefix, eName);
Files.SplitPath(eName, pathname, eName);
END;
END;
WHILE (i > 0) DO
success := enum.GetEntry(fullName, eFlags, eTime, eDate, eSize);
IF success THEN
Files.SplitName(fullName, prefix, eName);
Files.SplitPath(eName, pathname, eName);
f := Files.Old(eName);
IF loi = 260 THEN
c.out.RawLInt(96 + Strings.Length(eName));
c.out.RawLInt(0);
c.out.RawLInt(0);
c.out.RawLInt(0);
c.out.RawLInt(0);
c.out.RawLInt(0);
IF (f # NIL) THEN
f.GetDate(t,d);
dTime := Dates.OberonToDateTime(d,t);
GetSMBTimeStamp(dTime, tarray);
c.out.RawLInt(tarray[0]);
c.out.RawLInt(tarray[1]);
ELSE
c.out.RawLInt(0);
c.out.RawLInt(0);
END;
c.out.RawLInt(0);
c.out.RawLInt(0);
IF (f # NIL) THEN
c.out.RawLInt(f.Length());
c.out.RawLInt(0);
c.out.RawLInt(f.Length());
c.out.RawLInt(0);
ELSE
c.out.RawLInt(0);
c.out.RawLInt(0);
c.out.RawLInt(0);
c.out.RawLInt(0);
END;
flags := {};
IF (Files.Directory IN eFlags) THEN INCL(flags, 4); END;
IF (Files.ReadOnly IN eFlags) THEN INCL(flags, 0) END;
c.out.RawLInt(SYSTEM.VAL(LONGINT, flags));
c.out.RawLInt(1 + Strings.Length(eName));
c.out.RawLInt(0);
c.out.RawSInt(0);
c.out.RawSInt(0);
FOR z := 1 TO 24 DO
c.out.Net8(0);
END;
c.out.RawString(eName);
c.out.RawSInt(0);
ELSIF loi = 1 THEN
c.out.RawLInt(0);
c.out.RawLInt(0);
c.out.RawLInt(0);
IF (f # NIL) THEN
f.GetDate(t,d);
dTime := Dates.OberonToDateTime(d,t);
GetUnixTimeStamp(dTime, t);
c.out.RawLInt(t);
c.out.RawLInt(f.Length());
ELSE
c.out.RawLInt(0);
c.out.RawLInt(0);
END;
IF (f # NIL) THEN
c.out.RawLInt(f.Length());
ELSE
c.out.RawLInt(0);
END;
flags := {};
IF (Files.Directory IN eFlags) THEN INCL(flags, 4); END;
IF (Files.ReadOnly IN eFlags) THEN INCL(flags, 0) END;
c.out.RawInt(SYSTEM.VAL(INTEGER, flags));
c.out.RawSInt(SHORT(SHORT(Strings.Length(eName))));
c.out.RawString(eName);
END;
END;
DEC(i);
END;
c.out.Update();
enum.Close();
END;
END Trans2Logic;
PROCEDURE WriteSMBHeader(c: Connection);
BEGIN
c.in.Reset();
c.out.Reset();
c.out.Net16(0);
c.out.Net16(c.netbios);
c.out.Char(CHR(255));
c.out.String("SMB");
c.out.Net8(c.cmd);
IF ~c.error THEN
c.out.Net32(0);
ELSE
c.out.RawLInt(c.errorcode);
END;
c.out.Net8(90H);
c.out.RawInt(1);
c.out.Net32(0);
c.out.Net32(0);
c.out.Net32(0);
IF (c.cmd = ORD(75X)) THEN
c.tid := GetTID();
END;
c.out.RawInt(c.tid);
c.out.RawInt(c.pid);
IF (c.cmd = ORD(73X)) THEN
c.uid := GetUID();
END;
c.out.RawInt(c.uid);
c.out.RawInt(c.mid);
END WriteSMBHeader;
PROCEDURE CheckSMBHeader(VAR c: Connection): BOOLEAN;
VAR
variable: LONGINT;
BEGIN
c.in.SkipBytes(2);
c.msgSize := c.in.Net16();
variable := c.in.Net32();
IF variable # -11317950 THEN
c.error := TRUE;
RETURN TRUE;
END;
c.cmd := c.in.Net8();
variable := c.in.Net32();
IF variable # 0 THEN
c.error := TRUE;
RETURN TRUE;
END;
c.flags := c.in.Net8();
c.in.RawInt(c.flags2);
c.in.SkipBytes(12);
c.in.RawInt(c.tid);
c.in.RawInt(c.pid);
c.in.RawInt(c.uid);
c.in.RawInt(c.mid);
RETURN FALSE;
END CheckSMBHeader;
PROCEDURE ReplaceSlash(VAR name: ARRAY OF CHAR);
VAR
i: LONGINT;
BEGIN
i := 0;
WHILE (i < Strings.Length(name)) DO
IF name[i] = CHR(5CH) THEN
name[i] := CHR(2FH);
END;
INC(i)
END;
END ReplaceSlash;
PROCEDURE RemoveQuotes(VAR name: ARRAY OF CHAR);
VAR
i,j: LONGINT;
newName: ARRAY 256 OF CHAR;
BEGIN
i := 0;
j := 0;
WHILE (i < Strings.Length(name)) DO
IF name[i] # CHR(22H) THEN
newName[j] := name[i];
INC(i);
INC(j);
ELSE
INC(i);
END;
END;
COPY(newName, name);
END RemoveQuotes;
PROCEDURE RemoveSlash(VAR name: ARRAY OF CHAR);
VAR
i: LONGINT;
BEGIN
i := 1;
WHILE (i <= Strings.Length(name)) DO
name[i-1] := name[i];
INC(i)
END;
END RemoveSlash;
PROCEDURE NewAgent(c: TCP.Connection; s: TCPServices.Service): TCPServices.Agent;
VAR
a: Agent;
BEGIN
NEW(a, c, s);
RETURN a;
END NewAgent;
PROCEDURE StartServer*(context: Commands.Context);
VAR
res: LONGINT;
BEGIN {EXCLUSIVE}
IF service = NIL THEN
lastUID := 777;
lastTID := 555;
lastFID := 333;
lastSID := 111;
NEW(firstConn);
NEW(service, SMBPort, NewAgent, res);
context.out.String("Start SambaServer...");
IF res = TCPServices.Ok THEN
context.out.String("started!");
context.out.Ln();
ELSE
context.out.Ln();
context.out.String("Could not start SambaServer. Res: ");
context.out.Int(res, 0);
context.out.Ln();
service := NIL;
END;
ELSE
context.out.String("SambaServer already running...");
context.out.Ln();
END;
END StartServer;
PROCEDURE StopServer*(context: Commands.Context);
BEGIN {EXCLUSIVE}
IF service # NIL THEN
service.Stop();
service := NIL;
context.out.String("SambaServer stopped!");
context.out.Ln();
ELSE
context.out.String("SambaServer was already stopped!");
context.out.Ln();
END;
END StopServer;
PROCEDURE FindShare(CONST unc : ARRAY OF CHAR) : Share;
VAR share : Share;
BEGIN {EXCLUSIVE}
share := shares;
WHILE (share # NIL) & (share.unc # unc) DO share := share.next; END;
RETURN share;
END FindShare;
PROCEDURE AddShare*(context : Commands.Context);
VAR share : Share; prefix : Files.Prefix; path : Files.FileName;
BEGIN
NEW(share);
context.arg.SkipWhitespace; context.arg.String(share.unc);
context.arg.SkipWhitespace; context.arg.String(share.path);
Files.SplitName(share.path, prefix, path);
IF (prefix # "") THEN
IF FindShare(share.unc) = NIL THEN
BEGIN {EXCLUSIVE}
share.next := shares;
shares := share;
END;
context.out.String("Added share "); context.out.String(share.unc);
context.out.String(" ("); context.out.String(share.path);
context.out.String(")"); context.out.Ln;
ELSE
context.error.String("UNC "); context.error.String(share.unc);
context.error.String(" is already used."); context.error.Ln;
END;
ELSE
context.error.String("Prefix required"); context.error.Ln;
END;
END AddShare;
PROCEDURE ListShares*(context : Commands.Context);
VAR share : Share;
BEGIN {EXCLUSIVE}
context.out.String("SambaServer share list: "); context.out.Ln;
IF (shares # NIL) THEN
share := shares;
WHILE (share # NIL) DO
context.out.String(share.unc); context.out.String(" -> ");
context.out.String(share.path); context.out.Ln;
share := share.next;
END;
ELSE
context.out.String("No shares"); context.out.Ln;
END;
END ListShares;
PROCEDURE GetSMBTimeStamp(dtNow:Dates.DateTime; VAR t: ARRAY OF LONGINT);
VAR
dtOld : Dates.DateTime;
diffDay, diffHour, diffMinute, diffSecond: LONGINT;
tsNow : HUGEINT;
BEGIN
dtOld.year := 1601;
dtOld.month := 1;
dtOld.day := 1;
dtOld.hour := 0;
dtOld.minute := 0;
dtOld.second := 0;
Dates.TimeDifference(dtOld, dtNow, diffDay, diffHour, diffMinute, diffSecond);
tsNow := Machine.MulH(diffDay, 86400) + diffHour * 3600 + diffMinute * 60 + diffSecond;
tsNow := Machine.MulH(tsNow,10000000);
t[0] := SHORT(tsNow);
t[1] := SHORT(Machine.DivH(tsNow, 100000000H));
END GetSMBTimeStamp;
PROCEDURE GetUnixTimeStamp(dtNow: Dates.DateTime; VAR t: LONGINT);
VAR
dtOld : Dates.DateTime;
diffDay, diffHour, diffMinute, diffSecond: LONGINT;
BEGIN
dtOld.year := 1970;
dtOld.month := 1;
dtOld.day := 1;
dtOld.hour := 0;
dtOld.minute := 0;
dtOld.second := 0;
Dates.TimeDifference(dtOld, dtNow, diffDay, diffHour, diffMinute, diffSecond);
t := diffDay * 86400 + diffHour * 3600 + diffMinute * 60 + diffSecond;
END GetUnixTimeStamp;
PROCEDURE GetDOSTimeStamp(dtNow: Dates.DateTime; VAR t: LONGINT);
VAR
hour, minute, second, year, month, day: LONGINT;
BEGIN
hour := ASH(dtNow.hour, 27);
minute := ASH(dtNow.minute, 21);
second := ASH(dtNow.second DIV 2, 16);
year := ASH(dtNow.year - 1980, 9);
month := ASH(dtNow.month, 5);
day := dtNow.day;
t := hour + minute + second + year + month + day;
END GetDOSTimeStamp;
PROCEDURE Cleanup;
BEGIN {EXCLUSIVE}
IF service # NIL THEN
service.Stop();
service := NIL;
END;
END Cleanup;
BEGIN
shares := NIL;
Modules.InstallTermHandler(Cleanup);
END SambaServer.
SambaServer.StartServer ~
SambaServer.StopServer ~
SystemTools.Free SambaServer ~
SambaServer.ListShares ~
SambaServer.AddShare \AOS AOS: ~
SambaServer.AddShare \FAT FAT:Test/ ~
SambaServer.AddShare \Test ../Legal/ ~