SmbTree.cs 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250
  1. // This code is derived from jcifs smb client library <jcifs at samba dot org>
  2. // Ported by J. Arturo <webmaster at komodosoft dot net>
  3. //
  4. // This library is free software; you can redistribute it and/or
  5. // modify it under the terms of the GNU Lesser General Public
  6. // License as published by the Free Software Foundation; either
  7. // version 2.1 of the License, or (at your option) any later version.
  8. //
  9. // This library is distributed in the hope that it will be useful,
  10. // but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  12. // Lesser General Public License for more details.
  13. //
  14. // You should have received a copy of the GNU Lesser General Public
  15. // License along with this library; if not, write to the Free Software
  16. // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  17. using System;
  18. using SharpCifs.Util.Sharpen;
  19. namespace SharpCifs.Smb
  20. {
  21. class SmbTree
  22. {
  23. private static int _treeConnCounter;
  24. internal int ConnectionState;
  25. internal int Tid;
  26. internal string Share;
  27. internal string Service = "?????";
  28. internal string Service0;
  29. internal SmbSession Session;
  30. internal bool InDfs;
  31. internal bool InDomainDfs;
  32. internal int TreeNum;
  33. internal SmbTree(SmbSession session, string share, string service)
  34. {
  35. // used by SmbFile.isOpen
  36. this.Session = session;
  37. this.Share = share.ToUpper();
  38. if (service != null && service.StartsWith("??") == false)
  39. {
  40. this.Service = service;
  41. }
  42. Service0 = this.Service;
  43. ConnectionState = 0;
  44. }
  45. internal virtual bool Matches(string share, string service)
  46. {
  47. return Runtime.EqualsIgnoreCase(this.Share, share) && (service == null ||
  48. service.StartsWith("??") || Runtime.EqualsIgnoreCase(this.Service, service
  49. ));
  50. }
  51. public override bool Equals(object obj)
  52. {
  53. if (obj is SmbTree)
  54. {
  55. SmbTree tree = (SmbTree)obj;
  56. return Matches(tree.Share, tree.Service);
  57. }
  58. return false;
  59. }
  60. /// <exception cref="SharpCifs.Smb.SmbException"></exception>
  61. internal virtual void Send(ServerMessageBlock request, ServerMessageBlock response
  62. )
  63. {
  64. lock (Session.Transport())
  65. {
  66. if (response != null)
  67. {
  68. response.Received = false;
  69. }
  70. TreeConnect(request, response);
  71. if (request == null || (response != null && response.Received))
  72. {
  73. return;
  74. }
  75. if (Service.Equals("A:") == false)
  76. {
  77. switch (request.Command)
  78. {
  79. case ServerMessageBlock.SmbComOpenAndx:
  80. case ServerMessageBlock.SmbComNtCreateAndx:
  81. case ServerMessageBlock.SmbComReadAndx:
  82. case ServerMessageBlock.SmbComWriteAndx:
  83. case ServerMessageBlock.SmbComClose:
  84. case ServerMessageBlock.SmbComTreeDisconnect:
  85. {
  86. break;
  87. }
  88. case ServerMessageBlock.SmbComTransaction:
  89. case ServerMessageBlock.SmbComTransaction2:
  90. {
  91. switch (((SmbComTransaction)request).SubCommand & unchecked(0xFF))
  92. {
  93. case SmbComTransaction.NetShareEnum:
  94. case SmbComTransaction.NetServerEnum2:
  95. case SmbComTransaction.NetServerEnum3:
  96. case SmbComTransaction.TransPeekNamedPipe:
  97. case SmbComTransaction.TransWaitNamedPipe:
  98. case SmbComTransaction.TransCallNamedPipe:
  99. case SmbComTransaction.TransTransactNamedPipe:
  100. case SmbComTransaction.Trans2GetDfsReferral:
  101. {
  102. break;
  103. }
  104. default:
  105. {
  106. throw new SmbException("Invalid operation for " + Service + " service");
  107. }
  108. }
  109. break;
  110. }
  111. default:
  112. {
  113. throw new SmbException("Invalid operation for " + Service + " service" + request);
  114. }
  115. }
  116. }
  117. request.Tid = Tid;
  118. if (InDfs && !Service.Equals("IPC") && !string.IsNullOrEmpty(request.Path))
  119. {
  120. request.Flags2 = SmbConstants.Flags2ResolvePathsInDfs;
  121. request.Path = '\\' + Session.Transport().TconHostName + '\\' + Share + request.Path;
  122. }
  123. try
  124. {
  125. Session.Send(request, response);
  126. }
  127. catch (SmbException se)
  128. {
  129. if (se.GetNtStatus() == NtStatus.NtStatusNetworkNameDeleted)
  130. {
  131. TreeDisconnect(true);
  132. }
  133. throw;
  134. }
  135. }
  136. }
  137. /// <exception cref="SharpCifs.Smb.SmbException"></exception>
  138. internal virtual void TreeConnect(ServerMessageBlock andx, ServerMessageBlock andxResponse
  139. )
  140. {
  141. lock (Session.Transport())
  142. {
  143. string unc;
  144. while (ConnectionState != 0)
  145. {
  146. if (ConnectionState == 2 || ConnectionState == 3)
  147. {
  148. // connected or disconnecting
  149. return;
  150. }
  151. try
  152. {
  153. Runtime.Wait(Session.transport);
  154. }
  155. catch (Exception ie)
  156. {
  157. throw new SmbException(ie.Message, ie);
  158. }
  159. }
  160. ConnectionState = 1;
  161. // trying ...
  162. try
  163. {
  164. Session.transport.Connect();
  165. unc = "\\\\" + Session.transport.TconHostName + '\\' + Share;
  166. Service = Service0;
  167. if (Session.transport.Log.Level >= 4)
  168. {
  169. Session.transport.Log.WriteLine("treeConnect: unc=" + unc + ",service=" + Service
  170. );
  171. }
  172. SmbComTreeConnectAndXResponse response = new SmbComTreeConnectAndXResponse(andxResponse
  173. );
  174. SmbComTreeConnectAndX request = new SmbComTreeConnectAndX(Session, unc, Service,
  175. andx);
  176. Session.Send(request, response);
  177. Tid = response.Tid;
  178. Service = response.Service;
  179. InDfs = response.ShareIsInDfs;
  180. TreeNum = _treeConnCounter++;
  181. ConnectionState = 2;
  182. }
  183. catch (SmbException se)
  184. {
  185. // connected
  186. TreeDisconnect(true);
  187. ConnectionState = 0;
  188. throw;
  189. }
  190. }
  191. }
  192. internal virtual void TreeDisconnect(bool inError)
  193. {
  194. lock (Session.Transport())
  195. {
  196. if (ConnectionState != 2)
  197. {
  198. // not-connected
  199. return;
  200. }
  201. ConnectionState = 3;
  202. // disconnecting
  203. if (!inError && Tid != 0)
  204. {
  205. try
  206. {
  207. Send(new SmbComTreeDisconnect(), null);
  208. }
  209. catch (SmbException se)
  210. {
  211. if (Session.transport.Log.Level > 1)
  212. {
  213. Runtime.PrintStackTrace(se, Session.transport.Log);
  214. }
  215. }
  216. }
  217. InDfs = false;
  218. InDomainDfs = false;
  219. ConnectionState = 0;
  220. Runtime.NotifyAll(Session.transport);
  221. }
  222. }
  223. public override string ToString()
  224. {
  225. return "SmbTree[share=" + Share + ",service=" + Service + ",tid=" + Tid + ",inDfs="
  226. + InDfs + ",inDomainDfs=" + InDomainDfs + ",connectionState=" + ConnectionState
  227. + "]";
  228. }
  229. }
  230. }