You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
251 lines
6.3 KiB
251 lines
6.3 KiB
8 years ago
|
// This code is derived from jcifs smb client library <jcifs at samba dot org>
|
||
|
// Ported by J. Arturo <webmaster at komodosoft dot net>
|
||
|
//
|
||
|
// This library is free software; you can redistribute it and/or
|
||
|
// modify it under the terms of the GNU Lesser General Public
|
||
|
// License as published by the Free Software Foundation; either
|
||
|
// version 2.1 of the License, or (at your option) any later version.
|
||
|
//
|
||
|
// This library is distributed in the hope that it will be useful,
|
||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||
|
// Lesser General Public License for more details.
|
||
|
//
|
||
|
// You should have received a copy of the GNU Lesser General Public
|
||
|
// License along with this library; if not, write to the Free Software
|
||
|
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||
|
using System;
|
||
|
using SharpCifs.Util.Sharpen;
|
||
|
|
||
|
namespace SharpCifs.Smb
|
||
|
{
|
||
|
class SmbTree
|
||
|
{
|
||
|
private static int _treeConnCounter;
|
||
|
|
||
|
internal int ConnectionState;
|
||
|
|
||
|
internal int Tid;
|
||
|
|
||
|
internal string Share;
|
||
|
|
||
|
internal string Service = "?????";
|
||
|
|
||
|
internal string Service0;
|
||
|
|
||
|
internal SmbSession Session;
|
||
|
|
||
|
internal bool InDfs;
|
||
|
|
||
|
internal bool InDomainDfs;
|
||
|
|
||
|
internal int TreeNum;
|
||
|
|
||
|
internal SmbTree(SmbSession session, string share, string service)
|
||
|
{
|
||
|
// used by SmbFile.isOpen
|
||
|
this.Session = session;
|
||
|
this.Share = share.ToUpper();
|
||
|
if (service != null && service.StartsWith("??") == false)
|
||
|
{
|
||
|
this.Service = service;
|
||
|
}
|
||
|
Service0 = this.Service;
|
||
|
ConnectionState = 0;
|
||
|
}
|
||
|
|
||
|
internal virtual bool Matches(string share, string service)
|
||
|
{
|
||
|
return Runtime.EqualsIgnoreCase(this.Share, share) && (service == null ||
|
||
|
service.StartsWith("??") || Runtime.EqualsIgnoreCase(this.Service, service
|
||
|
));
|
||
|
}
|
||
|
|
||
|
public override bool Equals(object obj)
|
||
|
{
|
||
|
if (obj is SmbTree)
|
||
|
{
|
||
|
SmbTree tree = (SmbTree)obj;
|
||
|
return Matches(tree.Share, tree.Service);
|
||
|
}
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
/// <exception cref="SharpCifs.Smb.SmbException"></exception>
|
||
|
internal virtual void Send(ServerMessageBlock request, ServerMessageBlock response
|
||
|
)
|
||
|
{
|
||
|
lock (Session.Transport())
|
||
|
{
|
||
|
if (response != null)
|
||
|
{
|
||
|
response.Received = false;
|
||
|
}
|
||
|
TreeConnect(request, response);
|
||
|
if (request == null || (response != null && response.Received))
|
||
|
{
|
||
|
return;
|
||
|
}
|
||
|
if (Service.Equals("A:") == false)
|
||
|
{
|
||
|
switch (request.Command)
|
||
|
{
|
||
|
case ServerMessageBlock.SmbComOpenAndx:
|
||
|
case ServerMessageBlock.SmbComNtCreateAndx:
|
||
|
case ServerMessageBlock.SmbComReadAndx:
|
||
|
case ServerMessageBlock.SmbComWriteAndx:
|
||
|
case ServerMessageBlock.SmbComClose:
|
||
|
case ServerMessageBlock.SmbComTreeDisconnect:
|
||
|
{
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
case ServerMessageBlock.SmbComTransaction:
|
||
|
case ServerMessageBlock.SmbComTransaction2:
|
||
|
{
|
||
|
switch (((SmbComTransaction)request).SubCommand & unchecked(0xFF))
|
||
|
{
|
||
|
case SmbComTransaction.NetShareEnum:
|
||
|
case SmbComTransaction.NetServerEnum2:
|
||
|
case SmbComTransaction.NetServerEnum3:
|
||
|
case SmbComTransaction.TransPeekNamedPipe:
|
||
|
case SmbComTransaction.TransWaitNamedPipe:
|
||
|
case SmbComTransaction.TransCallNamedPipe:
|
||
|
case SmbComTransaction.TransTransactNamedPipe:
|
||
|
case SmbComTransaction.Trans2GetDfsReferral:
|
||
|
{
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
default:
|
||
|
{
|
||
|
throw new SmbException("Invalid operation for " + Service + " service");
|
||
|
}
|
||
|
}
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
default:
|
||
|
{
|
||
|
throw new SmbException("Invalid operation for " + Service + " service" + request);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
request.Tid = Tid;
|
||
|
if (InDfs && !Service.Equals("IPC") && !string.IsNullOrEmpty(request.Path))
|
||
|
{
|
||
|
request.Flags2 = SmbConstants.Flags2ResolvePathsInDfs;
|
||
|
request.Path = '\\' + Session.Transport().TconHostName + '\\' + Share + request.Path;
|
||
|
}
|
||
|
try
|
||
|
{
|
||
|
Session.Send(request, response);
|
||
|
}
|
||
|
catch (SmbException se)
|
||
|
{
|
||
|
if (se.GetNtStatus() == NtStatus.NtStatusNetworkNameDeleted)
|
||
|
{
|
||
|
TreeDisconnect(true);
|
||
|
}
|
||
|
throw;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/// <exception cref="SharpCifs.Smb.SmbException"></exception>
|
||
|
internal virtual void TreeConnect(ServerMessageBlock andx, ServerMessageBlock andxResponse
|
||
|
)
|
||
|
{
|
||
|
lock (Session.Transport())
|
||
|
{
|
||
|
string unc;
|
||
|
while (ConnectionState != 0)
|
||
|
{
|
||
|
if (ConnectionState == 2 || ConnectionState == 3)
|
||
|
{
|
||
|
// connected or disconnecting
|
||
|
return;
|
||
|
}
|
||
|
try
|
||
|
{
|
||
|
Runtime.Wait(Session.transport);
|
||
|
}
|
||
|
catch (Exception ie)
|
||
|
{
|
||
|
throw new SmbException(ie.Message, ie);
|
||
|
}
|
||
|
}
|
||
|
ConnectionState = 1;
|
||
|
// trying ...
|
||
|
try
|
||
|
{
|
||
|
Session.transport.Connect();
|
||
|
unc = "\\\\" + Session.transport.TconHostName + '\\' + Share;
|
||
|
Service = Service0;
|
||
|
if (Session.transport.Log.Level >= 4)
|
||
|
{
|
||
|
Session.transport.Log.WriteLine("treeConnect: unc=" + unc + ",service=" + Service
|
||
|
);
|
||
|
}
|
||
|
SmbComTreeConnectAndXResponse response = new SmbComTreeConnectAndXResponse(andxResponse
|
||
|
);
|
||
|
SmbComTreeConnectAndX request = new SmbComTreeConnectAndX(Session, unc, Service,
|
||
|
andx);
|
||
|
Session.Send(request, response);
|
||
|
Tid = response.Tid;
|
||
|
Service = response.Service;
|
||
|
InDfs = response.ShareIsInDfs;
|
||
|
TreeNum = _treeConnCounter++;
|
||
|
ConnectionState = 2;
|
||
|
}
|
||
|
catch (SmbException se)
|
||
|
{
|
||
|
// connected
|
||
|
TreeDisconnect(true);
|
||
|
ConnectionState = 0;
|
||
|
throw;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
internal virtual void TreeDisconnect(bool inError)
|
||
|
{
|
||
|
lock (Session.Transport())
|
||
|
{
|
||
|
if (ConnectionState != 2)
|
||
|
{
|
||
|
// not-connected
|
||
|
return;
|
||
|
}
|
||
|
ConnectionState = 3;
|
||
|
// disconnecting
|
||
|
if (!inError && Tid != 0)
|
||
|
{
|
||
|
try
|
||
|
{
|
||
|
Send(new SmbComTreeDisconnect(), null);
|
||
|
}
|
||
|
catch (SmbException se)
|
||
|
{
|
||
|
if (Session.transport.Log.Level > 1)
|
||
|
{
|
||
|
Runtime.PrintStackTrace(se, Session.transport.Log);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
InDfs = false;
|
||
|
InDomainDfs = false;
|
||
|
ConnectionState = 0;
|
||
|
Runtime.NotifyAll(Session.transport);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
public override string ToString()
|
||
|
{
|
||
|
return "SmbTree[share=" + Share + ",service=" + Service + ",tid=" + Tid + ",inDfs="
|
||
|
+ InDfs + ",inDomainDfs=" + InDomainDfs + ",connectionState=" + ConnectionState
|
||
|
+ "]";
|
||
|
}
|
||
|
}
|
||
|
}
|