///<summary> /// Lists all computers of the specified type or types that are visible /// in the specified domain. It may also enumerate domains. ///</summary> ///<param name = "domain">The name of the workgroup in which to enumerate computers /// of the specified type or types. If domain is null, servers /// are enumerated for the current domain of the computer</param> ///<param name = "types">The type or types o fcoimputer to enumerate. Computers that match /// at least one of the specified types are returned (SV_*)</param> ///<returns><code>System.String</code> (sorted)</returns> public string[] ListServersNames(string domain, uint types) { lock (this) { if (Debug.DebugOn) { Debug.WriteLine(Debug.Info, "listServersNames"); } var param = new MarshalBuffer(100); var data = new MarshalBuffer(1000); // Level 0 DoNetServerEnum2(domain, types, 0, param, data); int pos = 0; pos += 2; // converter int converter = param.GetShortAt(pos); pos += 2; // number of entries int counter = param.GetShortAt(pos); pos += 2; int maxcounter = param.GetShortAt(pos); pos += 2; if (maxcounter > counter) { if (Debug.DebugOn) { Debug.WriteLine(Debug.Warning, "The buffer for NetServerEnum2 was too small."); } } /* * struct SERVER_INFO_0 { * char sv0_name[16]; * }; */ var names = new string[counter]; for (int i = 0; i < counter; i++) { names[i] = data.GetZtAsciiStringAt(pos, i * 16); } Util.Util.SortStrings(names); return(names); } // lock }
/// <summary> /// Changes password on the server /// </summary> /// <param name = "user">user name</param> /// <param name = "oldpwd">old password</param> /// <param name = "newpwd">new password</param> public void ChangePassword(string user, string oldpwd, string newpwd) { lock (this) { if (Debug.DebugOn) { Debug.WriteLine(Debug.Info, "SamOEMChangePassword"); } var param = new MarshalBuffer(100); int pos = 0; pos += param.SetShortAt(pos, SamOEMChangePassword); // parameter descriptor string pos += param.SetZtAsciiStringAt(pos, "zsT"); // the data descriptor string for the (returned) data which = null string pos += param.SetZtAsciiStringAt(pos, "B516B16"); // user pos += param.SetZtAsciiStringAt(pos, user); // data size pos += param.SetShortAt(pos, 532); param.Size = pos; byte[] data = CifsLogin.GetChangePasswordData(oldpwd, newpwd); SendTransaction(null, "\\PIPE\\LANMAN", param, data, data.Length); var rdata = new MarshalBuffer(100); receiveTransaction(param, rdata); pos = 0; int error = param.GetShortAt(pos); // ignore more data if (error != 0 && error != 234) { throw CifsIoException.getLMException(error); } } // lock }
private void DoNetServerEnum2(string domain, uint types, int level, MarshalBuffer param, MarshalBuffer data) { int pos = 0; pos += param.SetShortAt(pos, NetShareEnum2); // parameter descriptor string pos += param.SetZtAsciiStringAt(pos, "WrLehDz"); // the data descriptor string for the (returned) data switch (level) { case 0: pos += param.SetZtAsciiStringAt(pos, "B16"); break; case 1: pos += param.SetZtAsciiStringAt(pos, "B16BBDz"); break; default: Debug.WriteLine(Debug.Error, "Invalid NetServerEnum2 level"); throw new ApplicationException("doNetServerEnum2"); } // corresponding to the "W": Level 1 pos += param.SetShortAt(pos, level); // buffer size pos += param.SetShortAt(pos, fReturnBufferSize); if (domain == null) { types |= CifsServerInfo.SV_TYPE_DOMAIN_ENUM; } // select types pos += param.SetIntAt(pos, (Int32)types); // domain if (domain != null) { pos += param.SetZtAsciiStringAt(pos, domain); } else { pos += param.SetByteAt(pos, 0); } param.Size = pos; SendTransaction(null, "\\PIPE\\LANMAN", param, null, 0); receiveTransaction(param, data); int error = param.GetShortAt(0); // ignore more data if (error != 0 && error != 234) { throw CifsIoException.getLMException(error); } }
// Several functions relating to printing have been ommited for now ///<summary> /// Lists all computers of the specified type or types that are visible /// in the specified domain. It may also enumerate domains. ///</summary> ///<param name = "domain">The name of the workgroup in which to enumerate computers /// of the specified type or types. If domain is nul, servers /// are enumerated for the current domain of the computer</param> ///<param name = "types">The type or types of computer to enumerate. Computers that /// match at least one of the specified types are returned (SV_*)</param> public CifsServerInfo[] ListServersInfo(string domain, uint types) { if (Debug.DebugOn) { Debug.WriteLine(Debug.Info, "listServersInfo"); } var param = new MarshalBuffer(100); var data = new MarshalBuffer(1000); DoNetServerEnum2(domain, types, 1, param, data); int pos = 0; pos += 2; // converter int converter = param.GetShortAt(pos); pos += 2; // number of entries int counter = param.GetShortAt(pos); pos += 2; int maxcounter = param.GetShortAt(pos); pos += 2; if (maxcounter > counter) { if (Debug.DebugOn) { Debug.WriteLine(Debug.Warning, "The buffer for NetServerEnum2 was too small."); } } /* * struct SERVER_INFO_1 { * char sv1_name[16]; * char sv1_version_major; * char sv1_version_minor; * unsigned long sv1_type; * char *sv1_comment_or_master_browser; * }; */ var infolist = new CifsServerInfo[counter]; pos = 0; for (int i = 0; i < counter; i++) { var info = new CifsServerInfo(); info.ComputerName = data.GetZtAsciiStringAt(pos, 16); pos += 16; info.MajorVersion = data.GetByteAt(pos) & 0xff; pos += 1; info.MinorVersion = data.GetByteAt(pos) & 0xff; pos += 1; info.ServerType = (UInt32)(data.GetIntAt(pos)); pos += 4; int rptr = (data.GetIntAt(pos) & 0xffff); pos += 4; if (rptr != 0) { info.Comment = data.GetZtAsciiStringAt(rptr - converter, 255); } infolist[i] = info; } return(infolist); }
/// <summary> /// Returns the list of shares on the computer /// </summary> /// <param name = "sort">if true, the names are sorted</param> /// <returns>list of <code>CifsShareInfo</code> objects</returns> public CifsShareInfo[] ListSharesInfo(bool sort) { lock (this) { if (Debug.DebugOn) { Debug.WriteLine(Debug.Info, "IPC:NetShareEnum"); } var param = new MarshalBuffer(100); int pos = 0; pos += param.SetShortAt(pos, NetShareEnum); // parameter descriptor string pos += param.SetZtAsciiStringAt(pos, "WrLeh"); // The data descriptor string for the (returned) data which is "B13BWz" pos += param.SetZtAsciiStringAt(pos, "B13BWz"); // corresponding to the "W" pos += param.SetShortAt(pos, 1); // buffer size pos += param.SetShortAt(pos, fReturnBufferSize); param.Size = pos; SendTransaction(null, "\\PIPE\\LANMAN", param, null, 0); var data = new MarshalBuffer(1000); receiveTransaction(param, data); pos = 0; int error = param.GetShortAt(pos); // ignore more data if (error != 0 && error != 234) { throw CifsIoException.getLMException(error); } pos += 2; // converter int converter = param.GetShortAt(pos); pos += 2; // number of entries int counter = param.GetShortAt(pos); pos += 2; // number max of entries int maxcounter = param.GetShortAt(pos); /* * The SHARE_INFO_1 structure is defined as: * * struct SHARE_INFO_1 { * char shi1_netname[13] * char shi1_pad; * unsigned short shi1_type * char *shi1_remark; * } * * where: * * shi1_netname contains a null terminated ASCII string that * specifies the share name of the resource. * * shi1_pad aligns the next data strructure element to a word * boundary. * * shi1_type contains an integer that specifies the type of the * shared resource. * * * shi1_remark points to a null terminated ASCII string that contains * a comment abthe shared resource. The value for shi1_remark is null * for ADMIN$ and IPC$ share names. The shi1_remark pointer is a 32 * bit pointer. The higher 16 bits need to be ignored. The converter * word returned in the parameters section needs to be subtracted * from the lower 16 bits to calculate an offset into the return * buffer where this ASCII string resides. * * In case there are multiple SHARE_INFO_1 data structures to return, * the server may put all these fixed length structures in the return * buffer, leave some space and then put all the variable length data * (the actual value of the shi1_remark strings) at the end of the * buffer. */ if (Debug.DebugOn) { data.debug("NetShareEnum data"); } var result = new CifsShareInfo[counter]; CifsShareInfo info; pos = 0; for (int i = 0; i < counter; i++) { info = new CifsShareInfo(fShare.HostName); // shil_netname[13] info.ShareName = data.GetZtAsciiStringAt(pos, 13); pos += 13; pos += 1; // pad // shil_type info.ShareType = data.GetShortAt(pos); pos += 2; // shil_remark int rptr = (data.GetIntAt(pos) & 0xffff); pos += 4; info.Remark = data.GetZtAsciiStringAt(rptr - converter, 255); result[i] = info; } if (sort) { Util.Util.Sort(result, GetShareInfoComparator()); } return(result); } // lock }
/// <summary> /// Returns detailed information about a particular user /// </summary> /// <param name = "user">User Name</param> /// <returns>user information</returns> public CifsUserInfo GetUserInfo(string user) { if (Debug.DebugOn) { Debug.WriteLine(Debug.Info, "IPC:NetUserGetInfo"); } var param = new MarshalBuffer(100); int pos = 0; pos += param.SetShortAt(pos, NetUserGetInfo); // parameter descriptor string pos += param.SetZtAsciiStringAt(pos, "zWrLh"); // he data descriptor string for the (returned) data which is "B21BzzzWDDzzDDWWzWzDWb21W" pos += param.SetZtAsciiStringAt(pos, "B21BzzzWDDzzDDWWzWzDWb21W"); // user pos += param.SetZtAsciiStringAt(pos, user); // corresponding to the "W" pos += param.SetShortAt(pos, 11); // buffer size pos += param.SetShortAt(pos, fReturnBufferSize); param.Size = pos; SendTransaction(null, "\\PIPE\\LANMAN", param, null, 0); var data = new MarshalBuffer(1000); receiveTransaction(param, data); pos = 0; int error = param.GetShortAt(pos); // ignore more data if (error != 0 && error != 234) { throw CifsIoException.getLMException(error); } pos += 2; // converter int converter = param.GetShortAt(pos); pos += 2; /* A 16 bit number representing the total number of available bytes. * This has meaning only if the return status is NERR_Success or * ERROR_MORE_DATA. Upon success, this number indicates the number of * useful bytes available. Upon failure, this indicates how big the * receive buffer needs to be. */ int bytes = param.GetShortAt(pos); pos += 2; /* * struct user_info_11 { * char usri11_name[21]; * char usri11_pad; * char *usri11_comment; * char *usri11_usr_comment; * char *usri11_full_name; * unsigned short usri11_priv; * unsigned long usri11_auth_flags; * long usri11_password_age; * char *usri11_homedir; * char *usri11_parms; * long usri11_last_logon; * long usri11_last_logoff; * unsigned short usri11_bad_pw_count; * unsigned short usri11_num_logons; * char *usri11_logon_server; * unsigned short usri11_country_code; * char *usri11_workstations; * unsigned long usri11_max_storage; * unsigned short usri11_units_per_week; * unsigned char *usri11_logon_hours; * unsigned short usri11_code_page; * * }; */ if (Debug.DebugOn) { data.debug("NetUserGetInfo data"); } var info = new CifsUserInfo(); pos = 0; // user name for which information is retireved info.UserName = data.GetZtAsciiStringAt(pos, 21); pos += 21; // pad pos++; //comment int ptr = data.GetIntAt(pos) & 0xffff; pos += 4; info.Comment = data.GetZtAsciiStringAt(ptr - converter, bytes); // comment about user ptr = data.GetIntAt(pos) & 0xffff; pos += 4; info.UserComment = data.GetZtAsciiStringAt(ptr - converter, bytes); // full name of the user ptr = data.GetIntAt(pos) & 0xffff; pos += 4; info.FullUserName = data.GetZtAsciiStringAt(ptr - converter, bytes); // level of the privilege assigned to the user info.UserPrivilege = data.GetShortAt(pos); pos += 2; // account operator privileges. info.OperatorPrivileges = data.GetIntAt(pos); pos += 4; // how many seconds have elapsed since the password was last changed. info.PasswordAge = data.GetIntAt(pos) & 0xffffffff; pos += 4; // path name of the user's home directory. ptr = data.GetIntAt(pos) & 0xffff; pos += 4; info.HomeDir = data.GetZtAsciiStringAt(ptr - converter, bytes); // skip usri11_parms pos += 4; // last logon info.fLastLogon = data.GetIntAt(pos) & 0xffffffff; pos += 4; // last logon info.fLastLogoff = data.GetIntAt(pos) & 0xffffffff; pos += 4; // bad logons info.BadLogons = data.GetShortAt(pos); pos += 2; // num logons info.Logons = data.GetShortAt(pos); pos += 2; // logon server ptr = data.GetIntAt(pos) & 0xffff; pos += 4; info.LogonServer = data.GetZtAsciiStringAt(ptr - converter, bytes); return(info); }
/// <summary> /// Set up the session /// </summary> /// <returns>true if ok, false if bad password</returns> private bool DoSessionSetup() { if (Debug.DebugOn) Debug.WriteLine(Debug.Info, "SMB_COM_SESSION_SETUP_ANDX"); byte[] case_sensitive_passwd = null; byte[] case_insensitive_passwd = null; string string_passwd = fShare.Login.Password; SetupSmbMessage(fMsg, SmbMessage.SMB_COM_SESSION_SETUP_ANDX); if (Debug.DebugOn && Debug.DebugLevel >= Debug.Buffer) { Debug.WriteLine(Debug.Buffer, "New SMB Msg:"); Debug.WriteLine(Debug.Buffer, fMsg.getMessageBuffer(), 0, fMsg.getMessageSize()); } if ((fSecurityMode & SM_ENCRYPT_PASSWORDS) != 0) { case_sensitive_passwd = CifsLogin.GetNtAuthData(string_passwd, fEncryptionKey); case_insensitive_passwd = CifsLogin.GetLmAuthData(string_passwd, fEncryptionKey); } else { case_sensitive_passwd = CifsLogin.GetPasswordBytesUnicode(string_passwd); case_insensitive_passwd = CifsLogin.GetPasswordBytesAscii(string_passwd); } /* UCHAR WordCount; Count of parameter words = 13 0: UCHAR AndXCommand; Secondary (X) command; 0xFF = none 1: UCHAR AndXReserved; Reserved (must be 0) 2: USHORT AndXOffset; Offset to next command WordCount 4: USHORT MaxBufferSize; Client's maximum buffer size 6: USHORT MaxMpxCount; Actual maximum multiplexed pending requests 8: USHORT VcNumber; 0 = first (only), nonzero=additional VC number 10:ULONG SessionKey; Session key (valid iff VcNumber != 0) 14:USHORT CaseInsensitivePasswordLength; Account password size, ANSI 16:USHORT CaseSensitivePasswordLength; Account password size, Unicode 18:ULONG Reserved; must be 0 22:ULONG Capabilities; Client capabilities USHORT ByteCount; Count of data bytes; min = 0 UCHAR CaseInsensitivePassword[]; Account Password, ANSI UCHAR CaseSensitivePassword[]; Account Password, Unicode STRING AccountName[]; Account Name, Unicode STRING PrimaryDomain[]; Client's primary domain, Unicode STRING NativeOS[]; Client's native operating system, Unicode STRING NativeLanMan[]; Client's native LAN Manager type, Unicode */ fMsg.setWordCount(13); // AndXCommand fMsg.setByteParameterAt(0, 0xFF); // AndXReserved fMsg.setByteParameterAt(1, 0); // AndXOffset fMsg.setShortParameterAt(2, 0); // MaxBufferSize fMsg.setShortParameterAt(4, CIFS_MAX_BUFFER_SIZE); // MaxMpxCount fMsg.setShortParameterAt(6, 1); // VcNumber fMsg.setShortParameterAt(8, 0); // SessionKey fMsg.setIntParameterAt(10, 0); // CaseInsensitivePasswordLength fMsg.setShortParameterAt(14, case_insensitive_passwd.Length); // CaseSensitivePasswordLength fMsg.setShortParameterAt(16, case_sensitive_passwd.Length); // Reserved fMsg.setIntParameterAt(18, 0); // Capabilities fMsg.setIntParameterAt(22, CAP_UNICODE | CAP_NT_SMBS); var data = new MarshalBuffer(200); int pos = 0; Debug.WriteLine(Debug.Buffer, "Before Ins Pass:"******"After Ins Pass:"******"After Sens Pass:"******"After Acct Name:"); Debug.WriteLine(Debug.Buffer, data.GetBytes(), 0, data.Size); // Primary domain //string pdomain = Environment.GetEnvironmentVariable("CIFSDOMAIN"); // Can this be done better? string pdomain = "?"; // testing -- This works, but the above breaks... why? pos += data.SetZtAsciiStringAt(pos, pdomain); // Native OS pos += data.SetZtAsciiStringAt(pos, ".NET CIFS Client"); data.Size = pos; Debug.WriteLine(Debug.Buffer, "Final data:"); Debug.WriteLine(Debug.Buffer, data.GetBytes(), 0, data.Size); fMsg.setContent(data); if (Debug.DebugOn && Debug.DebugLevel >= Debug.Buffer) { Debug.WriteLine(Debug.Buffer, "Msg to send"); Debug.WriteLine(Debug.Buffer, fMsg.getMessageBuffer(), 0, fMsg.getMessageSize()); } fMsg.SendAndRecieve(fNBTSession, fMsg); if (!fMsg.isResponse()) throw new CifsIoException("PE3"); int errorclass = fMsg.getErrorClass(); if (errorclass != CifsIoException.SUCCESS) { int errorcode = fMsg.getErrorCode(); if ((errorclass == CifsIoException.ERROR_SRV && errorcode == CifsIoException.SRV_BAD_PASSWORD) || (errorclass == CifsIoException.ERROR_DOS && errorcode == CifsIoException.DOS_NO_ACCESS)) return false; throw new CifsIoException(errorclass, errorcode); } fUID = fMsg.getUID(); /* if(Debug.debugOn && Debug.debugLevel >= Debug.INFO) Debug.WriteLine("UID = " + fMsg.getUID()); */ if (fMsg.getWordCount() != 3) return true; /* UCHAR WordCount; Count of parameter words = 3 0: UCHAR AndXCommand; Secondary (X) command; 0xFF = none 1: UCHAR AndXReserved; Reserved (must be 0) 2: USHORT AndXOffset; Offset to next command WordCount 4: USHORT Action; Request mode: bit0 = logged in as GUEST 6: USHORT SecurityBlobLength length of Security Blob that follows in a later field 8: USHORT ByteCount; Count of data bytes UCHAR SecurityBlob[] SecurityBlob of length specified in field SecurityBlobLength STRING NativeOS[]; Server's native operating system STRING NativeLanMan[]; Server's native LAN Manager type STRING PrimaryDomain[]; Server's primary domain */ byte action = fMsg.getByteParameterAt(4); if ((action & 0x01) != 0) fLoggedAsGuest = true; int byte_count = fMsg.getContentSize(); int off = fMsg.getContentOffset(); int max_off = off + byte_count; /* // Skip security blob off += fMsg.getShortParameterAt(6); */ if (off >= max_off) return true; // Read Native OS fServerOS = fMsg.GetZtAsciiStringAt(off, max_off - off); off += fServerOS.Length + 1; if (off >= max_off) return true; // Read NativeLanMan fServerLanMan = fMsg.GetZtAsciiStringAt(off, max_off - off); off += fServerLanMan.Length + 1; if (off >= max_off) return true; // Read Primary Domain fServerPrimaryDomain = fNBTSession.WorkgroupName; return true; }
public void setContent(MarshalBuffer content) { setContent(content.GetBytes(), 0, content.Size); }
/// <summary> /// Ping the server to test the connection to the server and to /// see if the server is still responding. /// </summary> /// <param name = "text">text to send</param> /// <returns>Text returned by server (must be the same as the input text)</returns> public string Echo(string text) { lock (this) { if (Debug.DebugOn) Debug.WriteLine(Debug.Info, "ping (SMB_COM_ECHO)"); // for now we only support 0 or 1 int echos = 1; SetupSmbMessage(fMsg, SmbMessage.SMB_COM_ECHO); /* UCHAR WordCount; Count of parameter words = 1 USHORT EchoCount; Number of times to echo data back USHORT ByteCount; Count of data bytes; min = 1 UCHAR Buffer[1]; Data to echo */ // Set WordCount fMsg.setWordCount(1); // Set echo count fMsg.setShortParameterAt(0, echos); var data = new MarshalBuffer(text.Length + 10); int pos = 0; pos += data.SetAsciiStringAt(pos, text); data.Size = pos; fMsg.setContent(data); fMsg.SendAndRecieve(fNBTSession, fMsg); int errorclass = fMsg.getErrorClass(); if (errorclass != CifsIoException.SUCCESS) throw new CifsIoException(errorclass, fMsg.getErrorCode()); int size = fMsg.getContentSize(); if (size == 0) return ""; pos = fMsg.getContentOffset(); return fMsg.GetAsciiStringAt(pos, size); } }
/// <summary> /// Connects to the tree /// </summary> /// <param name = "password">password</param> /// <returns>true if ok, false if bad password</returns> private bool DoTreeConnect(string password) { if (Debug.DebugOn) Debug.WriteLine(Debug.Info, "SMB_COM_TREE_CONNECT_ANDX"); SetupSmbMessage(fMsg, SmbMessage.SMB_COM_TREE_CONNECT_ANDX); fMsg.setTID(0); /* UCHAR WordCount; Count of parameter words = 4 0: UCHAR AndXCommand; Secondary (X) command; 0xFF = none 1: UCHAR AndXReserved; Reserved (must be 0) 2: USHORT AndXOffset; Offset to next command WordCount 4: USHORT Flags; Additional information bit 0 set = disconnect Tid 6: USHORT PasswordLength; Length of Password[] USHORT ByteCount; Count of data bytes; min = 3 UCHAR Password[]; Password STRING Path[]; Server name and share name STRING Service[]; Service name */ fMsg.setWordCount(4); //AndXCommand fMsg.setByteParameterAt(0, 0xFF); // AndXReserved fMsg.setByteParameterAt(1, 0); // AndXOffset fMsg.setShortParameterAt(2, 0); // Flags fMsg.setShortParameterAt(4, 0); byte[] challenge_response = null; if ((fSecurityMode & SM_ENCRYPT_PASSWORDS) != 0) challenge_response = CifsLogin.GetNtAuthData(password, fEncryptionKey); else challenge_response = Util.Util.GetZtStringBytes(password); //Debug.WriteLine("password="******"A:"; break; case Share.IPC: dev = "IPC"; break; case Share.PRINTER: dev = "LPT1:"; break; default: dev = "A:"; break; } pos += data.SetZtAsciiStringAt(pos, dev); data.Size = pos; fMsg.setContent(data); fMsg.SendAndRecieve(fNBTSession, fMsg); int errorclass = fMsg.getErrorClass(); if (errorclass != CifsIoException.SUCCESS) { int errorcode = fMsg.getErrorCode(); if ((errorclass == CifsIoException.ERROR_SRV && errorcode == CifsIoException.SRV_BAD_PASSWORD) || (errorclass == CifsIoException.ERROR_DOS && errorcode == CifsIoException.DOS_NO_ACCESS)) return false; throw new CifsIoException(errorclass, errorcode); } fUID = fMsg.getUID(); fTID = fMsg.getTID(); return true; }
/// <summary> /// Receives SMB_COM_TRANSACTION /// </summary> /// <param name = "param">param parameters</param> /// <param name = "data">data buffer</param> internal void receiveTransaction(MarshalBuffer param, MarshalBuffer data) { if (Debug.DebugOn) Debug.WriteLine(Debug.Info, "Receive SMB_COM_TRANSACTION"); fMsg.receive(fNBTSession); int errorclass = fMsg.getErrorClass(); if (errorclass != CifsIoException.SUCCESS) throw new CifsIoException(errorclass, fMsg.getErrorCode()); /* UCHAR WordCount; Count of data bytes; value = 10 + SetupCount 0:USHORT TotalParameterCount; Total parameter bytes being sent 2:USHORT TotalDataCount; Total data bytes being sent 4:USHORT Reserved; 6:USHORT ParameterCount; Parameter bytes sent this buffer 8:USHORT ParameterOffset; Offset (from header start) to Parameters 10:USHORT ParameterDisplacement; Displacement of these Parameter bytes 12:USHORT DataCount; Data bytes sent this buffer 14:USHORT DataOffset; Offset (from header start) to data 16:USHORT DataDisplacement; Displacement of these data bytes 18:UCHAR SetupCount; Count of setup words 19:UCHAR Reserved2; Reserved (pad above to word) 20:USHORT Setup[SetupWordCount]; Setup words (# = SetupWordCount) USHORT ByteCount; Count of data bytes UCHAR Pad[]; Pad to SHORT or LONG UCHAR Parameters[ParameterCount]; Parameter bytes (# = ParameterCount) UCHAR Pad1[]; Pad to SHORT or LONG UCHAR Data[DataCount]; Data bytes (# = DataCount) */ int lparam = 0; int ldata = 0; // TotalParameterCount int tot_lparam = fMsg.getShortParameterAt(0); int tot_ldata = fMsg.getShortParameterAt(2); // alloca buffer param.Capacity = tot_lparam; data.Capacity = tot_ldata; while (true) { int rcv_lparam = fMsg.getShortParameterAt(6); int rcv_ldata = fMsg.getShortParameterAt(12); if (rcv_lparam + lparam > tot_lparam || rcv_ldata + ldata > tot_ldata) throw new SystemException("Invalid Data"); if (rcv_lparam > 0) { int off_param = fMsg.getShortParameterAt(8); int dsp_param = fMsg.getShortParameterAt(10); param.SetBytesAt(dsp_param, fMsg, off_param, rcv_lparam); } if (rcv_ldata > 0) { int off_data = fMsg.getShortParameterAt(14); int dsp_data = fMsg.getShortParameterAt(16); data.SetBytesAt(dsp_data, fMsg, off_data, rcv_ldata); } lparam += rcv_lparam; ldata += rcv_ldata; // get Total (they can shrink!) tot_lparam = fMsg.getShortParameterAt(0); tot_ldata = fMsg.getShortParameterAt(2); if (tot_lparam <= lparam && tot_ldata <= ldata) break; fMsg.receive(fNBTSession); errorclass = fMsg.getErrorClass(); if (errorclass != CifsIoException.SUCCESS) throw new CifsIoException(errorclass, fMsg.getErrorCode()); } // while loop param.Size = lparam; data.Size = ldata; }
// end of sentTransaction /// <summary> /// Sends SMB_COM_TRANSACTION2 message /// </summary> /// <param name = "setup">setup words</param> /// <param name = "param">name string</param> /// <param name = "data">data to send</param> /// <param name = "ldata">length of data</param> /// <param name = "fid">file id</param> internal void SendTransaction2(short setup, MarshalBuffer param, byte[] data, int ldata, int fid) // should be protected { if (Debug.DebugOn) Debug.WriteLine(Debug.Info, "Send SMB_COM_TRANSACTION2"); int lparam = param.Size; SetupSmbMessage(fMsg, SmbMessage.SMB_COM_TRANSACTION2); /* UCHAR WordCount; Count of parameter words; value = (14 + SetupCount) USHORT TotalParameterCount; Total parameter bytes being sent USHORT TotalDataCount; Total data bytes being sent USHORT MaxParameterCount; Max parameter bytes to return USHORT MaxDataCount; Max data bytes to return UCHAR MaxSetupCount; Max setup words to return UCHAR Reserved; USHORT Flags; Additional information: bit 0 - also disconnect TID in TID ULONG Timeout; USHORT Reserved2; USHORT ParameterCount; Parameter bytes sent this buffer USHORT ParameterOffset; Offset (from header start) to Parameters USHORT DataCount; Data bytes sent this buffer USHORT DataOffset; Offset (from header start) to data UCHAR SetupCount; Count of setup words UCHAR Reserved3; Reserved (pad above to word) USHORT Setup[SetupCount]; Setup words (# = SetupWordCount) USHORT ByteCount; Count of data bytes STRING Name[]; Must be NULL UCHAR Pad[]; Pad to SHORT or LONG UCHAR Parameters[ ParameterCount]; Parameter bytes (# = ParameterCount) UCHAR Pad1[]; Pad to SHORT or LONG UCHAR Data[ DataCount ]; Data bytes (# = DataCount) */ fMsg.setWordCount(14 + 1); // TotalParameterCount !!!! fMsg.setShortParameterAt(0, lparam); // TotalDataCount !!!! fMsg.setShortParameterAt(2, ldata); // MaxParameterCount returned by server fMsg.setShortParameterAt(4, 16); // MaxDataCount returned by server fMsg.setShortParameterAt(6, 3000); // MaxSetupCount returned by server fMsg.setByteParameterAt(8, 20); // Reserved fMsg.setByteParameterAt(9, 0); // Flags fMsg.setShortParameterAt(10, 0); // Timeout fMsg.setIntParameterAt(12, 0); // Reserved 2 fMsg.setShortParameterAt(16, 0); // ParameterCount bytes sent this buffer fMsg.setShortParameterAt(18, 0); // ParameterOffset bytes sent this buffer fMsg.setShortParameterAt(20, 0); // DataCount bytes sent this buffer fMsg.setShortParameterAt(22, 0); // DataOffset bytes sent this buffer fMsg.setShortParameterAt(24, 0); // SetupCount fMsg.setByteParameterAt(26, 1); // Reserved3 fMsg.setByteParameterAt(27, 0); // Setup[0] fMsg.setShortParameterAt(28, setup); // byteCount fMsg.setContentSize(0); int bytes_off, off; bytes_off = off = fMsg.getContentOffset(); // reserve 1 (Name) + 4 (Pad) + 4 (Pad1) // free bytes for Parameters and Data int free = Math.Min(fMsg.Capacity - bytes_off, fMaxBufferSize) - 9; int send_lparam = Math.Min(free, lparam); int send_ldata = Math.Min(free - send_lparam, ldata); // Name of trans (null string) fMsg.SetByteAt(off, 0); off++; /*----------------- set parameters --------------------*/ // Calculate beginning of Parameters (offset from Header) int param_off = off = MarshalBuffer.Align(off, 2); // set parameter bytes fMsg.SetBytesAt(off, param, 0, send_lparam); // ParameterCount bytes sent this buffer fMsg.setShortParameterAt(18, send_lparam); // ParameterOffset bytes sent this buffer fMsg.setShortParameterAt(20, param_off); off += send_lparam; /*---------------------- set data --------------------*/ // Calculate beginning of data (offset from Header) int data_off = off = MarshalBuffer.Align(off, 2); // set data bytes if (send_ldata > 0) fMsg.SetBytesAt(off, data, 0, send_ldata); // DataCount bytes sent this buffer fMsg.setShortParameterAt(22, send_ldata); // DataOffset bytes sent this buffer fMsg.setShortParameterAt(24, data_off); off += send_ldata; // byteCount fMsg.setContentSize(off - bytes_off); fMsg.send(fNBTSession); if (send_lparam < lparam || send_ldata < ldata) { // receive interim response fMsg.receive(fNBTSession); int errorclass = fMsg.getErrorClass(); if (errorclass != CifsIoException.SUCCESS) throw new CifsIoException(errorclass, fMsg.getErrorCode()); int tot_ldata = send_ldata; int tot_lparam = send_lparam; while (tot_ldata < ldata || tot_lparam < lparam) { // Now send the next packet SetupSmbMessageSecondary(fMsg, SmbMessage.SMB_COM_TRANSACTION_SECONDARY); /* Command SMB_COM_TRANSACTION_SECONDARY UCHAR WordCount; Count of parameter words = 9 (! FID) 0: USHORT TotalParameterCount; Total parameter bytes being sent 2: USHORT TotalDataCount; Total data bytes being sent 4: USHORT ParameterCount; Parameter bytes sent this buffer 6: USHORT ParameterOffset; Offset (from header start) to Parameters 8: USHORT ParameterDisplacement; Displacement of these Parameter bytes 10:USHORT DataCount; Data bytes sent this buffer 12:USHORT DataOffset; Offset (from header start) to data 14:USHORT DataDisplacement; Displacement of these data bytes 16:USHORT Fid; FID for handle based requests, else 0xFFFF. This field is present only if this is an SMB_COM_TRANSACTION2 request. USHORT ByteCount; Count of data bytes UCHAR Pad[]; Pad to SHORT or LONG UCHAR Parameters[ParameterCount]; Parameter bytes (# = ParameterCount) UCHAR Pad1[]; Pad to SHORT or LONG UCHAR Data[DataCount]; Data bytes (# = DataCount) */ fMsg.setWordCount(9); bytes_off = off = fMsg.getContentOffset(); free = Math.Min(fMsg.Capacity - bytes_off, fMaxBufferSize) - 9; send_lparam = Math.Min(lparam - tot_lparam, free); send_ldata = Math.Min(ldata - tot_ldata, free - send_lparam); // TotalParameterCount fMsg.setShortParameterAt(0, lparam); // TotalDataCount fMsg.setShortParameterAt(2, ldata); // ParameterCount fMsg.setShortParameterAt(4, send_lparam); // ParameterDisplacement fMsg.setShortParameterAt(8, tot_lparam); // DataCount fMsg.setShortParameterAt(10, send_ldata); // DataDisplacement fMsg.setShortParameterAt(14, tot_ldata); // FID fMsg.setShortParameterAt(16, fid); /*----------------- set parameters --------------------*/ // Calculate beginning of Parameters (offset from Header) param_off = off = MarshalBuffer.Align(off, 4); // set parameter bytes fMsg.SetBytesAt(off, param, tot_lparam, send_lparam); // ParameterOffset bytes sent this buffer fMsg.setShortParameterAt(6, param_off); off += send_lparam; /*---------------------- set data --------------------*/ // Calculate beginning of data (offset from Header) data_off = off = MarshalBuffer.Align(off, 4); // set data bytes if (send_ldata > 0) fMsg.SetBytesAt(off, data, tot_ldata, send_ldata); // DataOffset bytes sent this buffer fMsg.setShortParameterAt(12, data_off); off += send_ldata; // byteCount fMsg.setContentSize(off - bytes_off); fMsg.send(fNBTSession); tot_lparam += send_lparam; tot_ldata += send_ldata; } // while loop } // if recieving }
public void SetBytesAt(int pos, MarshalBuffer bytes, int from, int len) { Array.Copy(bytes.fBuffer, from, fBuffer, pos, len); }