internal SqlError ProcessSNIError(TdsParserStateObject stateObj) { #if DEBUG // There is an exception here for MARS as its possible that another thread has closed the connection just as we see an error Debug.Assert(SniContext.Undefined!=stateObj.DebugOnlyCopyOfSniContext || ((_fMARS) && ((_state == TdsParserState.Closed) || (_state == TdsParserState.Broken))), "SniContext must not be None"); #endif SNINativeMethodWrapper.SNI_Error sniError = new SNINativeMethodWrapper.SNI_Error(); SNINativeMethodWrapper.SNIGetLastError(sniError); if (sniError.sniError != 0) { // handle special SNI error codes that are converted into exception which is not a SqlException. switch (sniError.sniError) { case (int)SNINativeMethodWrapper.SniSpecialErrors.MultiSubnetFailoverWithMoreThan64IPs: // Connecting with the MultiSubnetFailover connection option to a SQL Server instance configured with more than 64 IP addresses is not supported. throw SQL.MultiSubnetFailoverWithMoreThan64IPs(); case (int)SNINativeMethodWrapper.SniSpecialErrors.MultiSubnetFailoverWithInstanceSpecified: // Connecting to a named SQL Server instance using the MultiSubnetFailover connection option is not supported. throw SQL.MultiSubnetFailoverWithInstanceSpecified(); case (int)SNINativeMethodWrapper.SniSpecialErrors.MultiSubnetFailoverWithNonTcpProtocol: // Connecting to a SQL Server instance using the MultiSubnetFailover connection option is only supported when using the TCP protocol. throw SQL.MultiSubnetFailoverWithNonTcpProtocol(); // continue building SqlError instance } } // error.errorMessage is null terminated with garbage beyond that, since fixed length string errorMessage; int MessageLength = Array.IndexOf(sniError.errorMessage, '\0'); if (MessageLength == -1) { errorMessage = String.Empty; // If we don't see the expected null return nothing. } else { errorMessage = new String(sniError.errorMessage, 0, MessageLength); } // Format SNI errors and add Context Information // // General syntax is: // <sqlclient message> // (provider:<SNIx provider>, error: <SNIx error code> - <SNIx error message>) // // errorMessage | sniError | // ------------------------------------------- // ==null | x | must never happen // !=null | != 0 | retrieve corresponding errorMessage from resources // !=null | == 0 | replace text left of errorMessage // Debug.Assert(!ADP.IsEmpty(errorMessage),"Empty error message received from SNI"); string sqlContextInfo = Res.GetString(Enum.GetName(typeof(SniContext), stateObj.SniContext)); string providerRid = String.Format((IFormatProvider)null,"SNI_PN{0}", (int)sniError.provider); string providerName = Res.GetString(providerRid); Debug.Assert(!ADP.IsEmpty(providerName), String.Format((IFormatProvider)null,"invalid providerResourceId '{0}'", providerRid)); uint win32ErrorCode = sniError.nativeError; if (sniError.sniError == 0) { // Provider error. The message from provider is preceeded with non-localizable info from SNI // strip provider info from SNI // int iColon = errorMessage.IndexOf(':'); Debug.Assert(0<=iColon, "':' character missing in sni errorMessage"); Debug.Assert(errorMessage.Length>iColon+1 && errorMessage[iColon+1]==' ', "Expecting a space after the ':' character"); // extract the message excluding the colon and trailing cr/lf chars if (0<=iColon) { int len = errorMessage.Length; len -=2; // exclude "\r\n" sequence iColon+=2; // skip over ": " sequence len-=iColon; /* The error message should come back in the following format: "TCP Provider: MESSAGE TEXT" Fix Bug 370686, if the message is recieved on a Win9x OS, the error message will not contain MESSAGE TEXT per Bug: 269574. If we get a errormessage with no message text, just return the entire message otherwise return just the message text. */ if (len > 0) { errorMessage = errorMessage.Substring(iColon, len); } } } else { // SNI error. Replace the entire message // errorMessage = SQL.GetSNIErrorMessage((int)sniError.sniError); // If its a LocalDB error, then nativeError actually contains a LocalDB-specific error code, not a win32 error code if (sniError.sniError == (int)SNINativeMethodWrapper.SniSpecialErrors.LocalDBErrorCode) { errorMessage += LocalDBAPI.GetLocalDBMessage((int)sniError.nativeError); win32ErrorCode = 0; } } errorMessage = String.Format((IFormatProvider)null, "{0} (provider: {1}, error: {2} - {3})", sqlContextInfo, providerName, (int)sniError.sniError, errorMessage); return new SqlError((int)sniError.nativeError, 0x00, TdsEnums.FATAL_ERROR_CLASS, _server, errorMessage, sniError.function, (int)sniError.lineNumber, win32ErrorCode); }
internal SqlError ProcessSNIError(TdsParserStateObject stateObj) { string sNIErrorMessage; SNINativeMethodWrapper.SNI_Error error = new SNINativeMethodWrapper.SNI_Error(); SNINativeMethodWrapper.SNIGetLastError(error); switch (error.sniError) { case 0x2f: throw SQL.MultiSubnetFailoverWithMoreThan64IPs(); case 0x30: throw SQL.MultiSubnetFailoverWithInstanceSpecified(); case 0x31: throw SQL.MultiSubnetFailoverWithNonTcpProtocol(); } int index = Array.IndexOf<char>(error.errorMessage, '\0'); if (index == -1) { sNIErrorMessage = string.Empty; } else { sNIErrorMessage = new string(error.errorMessage, 0, index); } string str4 = System.Data.Res.GetString(Enum.GetName(typeof(SniContext), stateObj.SniContext)); string str2 = System.Data.Res.GetString(string.Format(null, "SNI_PN{0}", new object[] { (int) error.provider })); if (error.sniError == 0) { int startIndex = sNIErrorMessage.IndexOf(':'); if (0 <= startIndex) { int length = sNIErrorMessage.Length - 2; startIndex += 2; length -= startIndex; if (length > 0) { sNIErrorMessage = sNIErrorMessage.Substring(startIndex, length); } } } else { sNIErrorMessage = SQL.GetSNIErrorMessage((int) error.sniError); if (error.sniError == SNINativeMethodWrapper.SNI_LocalDBErrorCode) { sNIErrorMessage = sNIErrorMessage + LocalDBAPI.GetLocalDBMessage((int) error.nativeError); } } return new SqlError((int) error.nativeError, 0, 20, this._server, string.Format(null, "{0} (provider: {1}, error: {2} - {3})", new object[] { str4, str2, (int) error.sniError, sNIErrorMessage }), error.function, (int) error.lineNumber); }