#if SQLSERVER
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.InteropServices;
namespace Sdaleo.Systems.SQLServer
{
///
/// Summary description for SQLInfoEnumerator.
/// This class Enumerates a network for SQL Server instances and returns a list.
/// For a given SQL Server instance a list of all available databases is returned
/// For more information see
///
///
///
internal class SQLInfoEnumerator
{
#region ODBC32 external function definitions
[DllImport("odbc32.dll")]
private static extern short SQLAllocHandle(short handleType, IntPtr inputHandle, out IntPtr outputHandlePtr);
[DllImport("odbc32.dll")]
private static extern short SQLSetEnvAttr(IntPtr environmentHandle, int attribute, IntPtr valuePtr, int stringLength);
[DllImport("odbc32.dll")]
private static extern short SQLFreeHandle(short hType, IntPtr Handle);
[DllImport("odbc32.dll", CharSet = CharSet.Ansi)]
private static extern short SQLBrowseConnect(IntPtr handleConnection, StringBuilder inConnection, short stringLength, StringBuilder outConnection, short bufferLength, out short stringLength2Ptr);
#endregion
#region Constants
private const string SQL_DRIVER_STR = "DRIVER={SQL SERVER};";
private const short SQL_SUCCESS = 0;
private const short SQL_SUCCESS_WITH_INFO = 1;
private const short SQL_HANDLE_ENV = 1;
private const short SQL_HANDLE_DBC = 2;
private const int SQL_ATTR_ODBC_VERSION = 200;
private const int SQL_OV_ODBC3 = 3;
private const short SQL_NEED_DATA = 99;
private const short DEFAULT_RESULT_SIZE = 1024;
private const string START_STR = "{";
private const string END_STR = "}";
#endregion
///
/// Enumerate the SQL Servers returning a list (if any exist)
///
///
internal static string[] EnumerateSQLServers()
{
return RetrieveInformation(SQL_DRIVER_STR);
}
///
/// Enumerate the specified SQL server returning a list of databases (if any exist)
///
///
internal static string[] EnumerateSQLServersDatabases(string SQLServerNInstance)
{
return RetrieveInformation(SQL_DRIVER_STR + "SERVER=" + SQLServerNInstance + ";");
}
///
/// Enumerate the specified SQL server returning a list of databases (if any exist)
///
///
internal static string[] EnumerateSQLServersDatabases(string SQLServerNInstance, string Username, string Password)
{
return RetrieveInformation(SQL_DRIVER_STR + "SERVER=" + SQLServerNInstance + ";" + "UID=" + Username + ";" + "PWD=" + Password + ";");
}
///
/// Enumerate for SQLServer/Databases based on the passed information it the string
/// The more information provided to SQLBrowseConnect the more granular it gets so
/// if only DRIVER=SQL SERVER passed then a list of all SQL Servers is returned
/// If DRIVER=SQL SERVER;Server=ServerName is passed then a list of all Databases on the
/// servers is returned etc
///
/// A valid string to query for
///
private static string[] RetrieveInformation(string InputParam)
{
IntPtr m_environmentHandle = IntPtr.Zero;
IntPtr m_connectionHandle = IntPtr.Zero;
StringBuilder inConnection = new StringBuilder(InputParam);
short stringLength = (short)inConnection.Length;
StringBuilder outConnection = new StringBuilder(DEFAULT_RESULT_SIZE);
short stringLength2Ptr = 0;
bool bConnectSuccessful = false;
try
{
// Prepare the SQL Environment Handles
if ((IsSQLSuccess(SQLAllocHandle(SQL_HANDLE_ENV, m_environmentHandle, out m_environmentHandle))) &&
(IsSQLSuccess(SQLSetEnvAttr(m_environmentHandle, SQL_ATTR_ODBC_VERSION, (IntPtr)SQL_OV_ODBC3, 0))) &&
(IsSQLSuccess(SQLAllocHandle(SQL_HANDLE_DBC, m_environmentHandle, out m_connectionHandle))))
{
// Fetch the Data * First get the size of the buffer, then call it to get the buffer *
if (IsSQLDataSuccess(SQLBrowseConnect(m_connectionHandle, inConnection, stringLength, null, 0, out stringLength2Ptr)) &&
IsSQLDataSuccess(SQLBrowseConnect(m_connectionHandle, inConnection, stringLength, outConnection, stringLength2Ptr, out stringLength2Ptr))
)
{
bConnectSuccessful = true;
}
}
}
catch { /* ignore */ }
finally
{
FreeConnection(m_connectionHandle);
FreeConnection(m_environmentHandle);
}
if (bConnectSuccessful && outConnection.ToString() != "")
{
return ParseSQLOutConnection(outConnection.ToString());
}
else
{
return null;
}
}
#region Helper Functions
///
/// For quick SQL Return value evaluation
///
private static bool IsSQLSuccess(short SQL_VALUE)
{
if (SQL_VALUE == SQL_SUCCESS || SQL_VALUE == SQL_SUCCESS_WITH_INFO)
return true;
else
return false;
}
///
/// For quick SQL Return value evaluation
///
private static bool IsSQLDataSuccess(short SQL_VALUE)
{
if (SQL_VALUE == SQL_SUCCESS || SQL_VALUE == SQL_SUCCESS_WITH_INFO || SQL_VALUE == SQL_NEED_DATA)
return true;
else
return false;
}
///
/// Parse an outConnection string returned from SQLBrowseConnect
///
/// string to parse
/// Parsed Server names, or Empty Array if none found
private static string[] ParseSQLOutConnection(string outConnection)
{
int m_Start = outConnection.IndexOf(START_STR) + 1;
int m_lenString = outConnection.IndexOf(END_STR) - m_Start;
if ((m_Start > 0) && (m_lenString > 0))
{
outConnection = outConnection.Substring(m_Start, m_lenString);
}
else
{
outConnection = string.Empty;
}
return outConnection.Split(",".ToCharArray());
}
///
/// Call this to Free a SQL handle
///
private static void FreeConnection(IntPtr handleToFree)
{
if (handleToFree != IntPtr.Zero)
SQLFreeHandle(SQL_HANDLE_DBC, handleToFree);
}
#endregion
}
}
#endif