title: C++ [Microsoft][ODBC SQL Server Driver]String data, right truncation
body: <p><br>
  I need help with ODBC prepared queries. I working on Windows 10(x64). My VPS server is Windows Server 2012(x64). My compiled aplication is 32 bit. I need prepared queries to make SQL Injection not possible. But have one big problem.<br>
  <br><br>
  Error:</p>
  
  <pre><code>[QueryManager] State (22001), Diagnostic: [Microsoft][ODBC SQL Server Driver]String data, right truncation
  </code></pre>
  
  <p>Code:</p>
  
  <pre><code>gQueryManager.BindParameterAsString(1,Name,sizeof(Name)); 
  gQueryManager.ExecQuery("SELECT Value FROM Table WHERE Name=?");
  gQueryManager.Fetch();
  ...
  gQueryManager.Close();
  </code></pre>
  
  <p>This is source code of Query Manager I using:</p>
  
  <pre><code>// QueryManager.cpp: implementation of the CQueryManager class.
  //
  //////////////////////////////////////////////////////////////////////
  
  #include "stdafx.h"
  #include "QueryManager.h"
  #include "Util.h"
  
  CQueryManager gQueryManager;
  //////////////////////////////////////////////////////////////////////
  // Construction/Destruction
  //////////////////////////////////////////////////////////////////////
  
  CQueryManager::CQueryManager() // OK
  {
      this-&gt;m_SQLEnvironment = SQL_NULL_HANDLE;
      this-&gt;m_SQLConnection = SQL_NULL_HANDLE;
      this-&gt;m_STMT = SQL_NULL_HANDLE;
      this-&gt;m_RowCount = -1;
      this-&gt;m_ColCount = -1;
  
      memset(this-&gt;m_SQLColName,0,sizeof(this-&gt;m_SQLColName));
      memset(this-&gt;m_SQLData,0,sizeof(this-&gt;m_SQLData));
  
      SQLAllocHandle(SQL_HANDLE_ENV,SQL_NULL_HANDLE,&amp;this-&gt;m_SQLEnvironment);
      SQLSetEnvAttr(this-&gt;m_SQLEnvironment,SQL_ATTR_ODBC_VERSION,(SQLPOINTER)SQL_OV_ODBC3,SQL_IS_INTEGER);
  }
  
  CQueryManager::~CQueryManager() // OK
  {
      this-&gt;Disconnect();
  }
  
  bool CQueryManager::Connect(char* odbc,char* user,char* pass) // OK
  {
      strcpy_s(this-&gt;m_odbc,odbc);
  
      strcpy_s(this-&gt;m_user,user);
  
      strcpy_s(this-&gt;m_pass,pass);
  
      if(SQL_SUCCEEDED(SQLAllocHandle(SQL_HANDLE_DBC,this-&gt;m_SQLEnvironment,&amp;this-&gt;m_SQLConnection)) == 0)
      {
          return 0;
      }
  
      if(SQL_SUCCEEDED(SQLConnect(this-&gt;m_SQLConnection,(SQLCHAR*)this-&gt;m_odbc,SQL_NTS,(SQLCHAR*)this-&gt;m_user,SQL_NTS,(SQLCHAR*)this-&gt;m_pass,SQL_NTS)) == 0)
      {
          return 0;
      }
  
      if(SQL_SUCCEEDED(SQLAllocHandle(SQL_HANDLE_STMT,this-&gt;m_SQLConnection,&amp;this-&gt;m_STMT)) == 0)
      {
          return 0;
      }
      else
      {
          return 1;
      }
  }
  
  void CQueryManager::Disconnect() // OK
  {
      if(this-&gt;m_STMT != SQL_NULL_HANDLE)
      {
          SQLFreeHandle(SQL_HANDLE_STMT,this-&gt;m_STMT);
          this-&gt;m_STMT = SQL_NULL_HANDLE;
      }
  
      if(this-&gt;m_SQLConnection != SQL_NULL_HANDLE)
      {
          SQLFreeHandle(SQL_HANDLE_DBC,this-&gt;m_SQLConnection);
          this-&gt;m_SQLConnection = SQL_NULL_HANDLE;
      }
  
      if(this-&gt;m_SQLEnvironment != SQL_NULL_HANDLE)
      {
          SQLFreeHandle(SQL_HANDLE_ENV,this-&gt;m_SQLEnvironment);
          this-&gt;m_SQLEnvironment = SQL_NULL_HANDLE;
      }
  }
  
  void CQueryManager::Diagnostic(char* query) // OK
  {
      LogAdd(LOG_BLACK,"%s",query);
  
      SQLINTEGER NativeError;
      SQLSMALLINT RecNumber=1,BufferLength;
      SQLCHAR SqlState[6],MessageText[SQL_MAX_MESSAGE_LENGTH];
  
      while(SQLGetDiagRec(SQL_HANDLE_STMT,this-&gt;m_STMT,(RecNumber++),SqlState,&amp;NativeError,MessageText,sizeof(MessageText),&amp;BufferLength) != SQL_NO_DATA)
      {
          LogAdd(LOG_RED,"[QueryManager] State (%s), Diagnostic: %s",SqlState,MessageText);
      }
  
      if(strcmp((char*)SqlState,"08S01") == 0)
      {
          this-&gt;Connect(this-&gt;m_odbc,this-&gt;m_user,this-&gt;m_pass);
      }
  }
  
  bool CQueryManager::ExecQuery(char* query,...) // OK
  {
      char buff[4096];
  
      va_list arg;
      va_start(arg,query);
      vsprintf_s(buff,query,arg);
      va_end(arg);
  
      SQLRETURN result;
  
      if(SQL_SUCCEEDED((result=SQLExecDirect(this-&gt;m_STMT,(SQLCHAR*)buff,SQL_NTS))) == 0 &amp;&amp; result != SQL_NO_DATA)
      {
          this-&gt;Diagnostic(buff);
          return 0;
      }
  
      SQLRowCount(this-&gt;m_STMT,&amp;this-&gt;m_RowCount);
  
      if(this-&gt;m_RowCount == 0){return 1;}
  
      SQLNumResultCols(this-&gt;m_STMT,&amp;this-&gt;m_ColCount);
  
      if(this-&gt;m_ColCount == 0){return 1;}
  
      if(this-&gt;m_ColCount &gt; MAX_COLUMNS){return 0;}
  
      memset(this-&gt;m_SQLColName,0,sizeof(this-&gt;m_SQLColName));
  
      memset(this-&gt;m_SQLData,0,sizeof(this-&gt;m_SQLData));
  
      for(int n=0;n &lt; this-&gt;m_ColCount;n++)
      {
          SQLDescribeCol(this-&gt;m_STMT,(n+1),this-&gt;m_SQLColName[n],sizeof(this-&gt;m_SQLColName[n]),0,0,0,0,0);
          SQLBindCol(this-&gt;m_STMT,(n+1),SQL_C_CHAR,this-&gt;m_SQLData[n],sizeof(this-&gt;m_SQLData[n]),&amp;this-&gt;m_SQLDataLen[n]);
      }
  
      return 1;
  }
  
  void CQueryManager::Close() // OK
  {
      SQLCloseCursor(this-&gt;m_STMT);
      SQLFreeStmt(this-&gt;m_STMT,SQL_UNBIND);
  }
  
  SQLRETURN CQueryManager::Fetch() // OK
  {
      return SQLFetch(this-&gt;m_STMT);
  }
  
  int CQueryManager::FindIndex(char* ColName) // OK
  {
      for(int n=0;n &lt; this-&gt;m_ColCount;n++)
      {
          if(_stricmp(ColName,(char*)this-&gt;m_SQLColName[n]) == 0)
          {
              return n;
          }
      }
  
      return -1;
  }
  
  int CQueryManager::GetResult(int index) // OK
  {
      return atoi(this-&gt;m_SQLData[index]);
  }
  
  int CQueryManager::GetAsInteger(char* ColName) // OK
  {
      int index = this-&gt;FindIndex(ColName);
  
      if(index == -1)
      {
          return index;
      }
      else
      {
          return atoi(this-&gt;m_SQLData[index]);
      }
  }
  
  float CQueryManager::GetAsFloat(char* ColName) // OK
  {
      int index = this-&gt;FindIndex(ColName);
  
      if(index == -1)
      {
          return (float)index;
      }
      else
      {
          return (float)atof(this-&gt;m_SQLData[index]);
      }
  }
  
  __int64 CQueryManager::GetAsInteger64(char* ColName) // OK
  {
      int index = this-&gt;FindIndex(ColName);
  
      if(index == -1)
      {
          return index;
      }
      else
      {
          return _atoi64(this-&gt;m_SQLData[index]);
      }
  }
  
  void CQueryManager::GetAsString(char* ColName,char* OutBuffer,int OutBufferSize) // OK
  {
      int index = this-&gt;FindIndex(ColName);
  
      if(index == -1)
      {
          memset(OutBuffer,0,OutBufferSize);
      }
      else
      {
          strncpy_s(OutBuffer,OutBufferSize,this-&gt;m_SQLData[index],(OutBufferSize-1));
      }
  }
  
  void CQueryManager::GetAsBinary(char* ColName,BYTE* OutBuffer,int OutBufferSize) // OK
  {
      int index = this-&gt;FindIndex(ColName);
  
      if(index == -1)
      {
          memset(OutBuffer,0,OutBufferSize);
      }
      else
      {
          this-&gt;ConvertStringToBinary(this-&gt;m_SQLData[index],sizeof(this-&gt;m_SQLData[index]),OutBuffer,OutBufferSize);
      }
  }
  
  void CQueryManager::BindParameterAsString(int ParamNumber,void* InBuffer,int ColumnSize) // OK
  {
      this-&gt;m_SQLBindValue[(ParamNumber-1)] = SQL_NTS;
  
      SQLBindParameter(this-&gt;m_STMT,ParamNumber,SQL_PARAM_INPUT,SQL_C_CHAR,SQL_VARCHAR,ColumnSize,0,InBuffer,0,&amp;this-&gt;m_SQLBindValue[(ParamNumber-1)]);
  }
  
  void CQueryManager::BindParameterAsBinary(int ParamNumber,void* InBuffer,int ColumnSize) // OK
  {
      this-&gt;m_SQLBindValue[(ParamNumber-1)] = ColumnSize;
  
      SQLBindParameter(this-&gt;m_STMT,ParamNumber,SQL_PARAM_INPUT,SQL_C_BINARY,SQL_VARBINARY,ColumnSize,0,InBuffer,0,&amp;this-&gt;m_SQLBindValue[(ParamNumber-1)]);
  }
  
  void CQueryManager::ConvertStringToBinary(char* InBuff,int InSize,BYTE* OutBuff,int OutSize) // OK
  {
      int size = 0;
  
      memset(OutBuff,0,OutSize);
  
      for(int n=0;n &lt; InSize,size &lt; OutSize;n++)
      {
          if(InBuff[n] == 0)
          {
              break;
          }
  
          if((n%2) == 0)
          {
              OutBuff[size] = ((InBuff[n]&gt;='A')?((InBuff[n]-'A')+10):(InBuff[n]-'0'))*16;
              size = size+0;
          }
          else
          {
              OutBuff[size] = OutBuff[size] | ((InBuff[n]&gt;='A')?((InBuff[n]-'A')+10):(InBuff[n]-'0'));
              size = size+1;
          }
      }
  }
  
  void CQueryManager::ConvertBinaryToString(BYTE* InBuff,int InSize,char* OutBuff,int OutSize) // OK
  {
      int size = 0;
  
      memset(OutBuff,0,OutSize);
  
      for(int n=0;n &lt; OutSize,size &lt; InSize;n++)
      {
          if((n%2) == 0)
          {
              OutBuff[n] = (((InBuff[size]/16)&gt;=10)?('A'+((InBuff[size]/16)-10)):('0'+(InBuff[size]/16)));
              size = size+0;
          }
          else
          {
              OutBuff[n] = (((InBuff[size]%16)&gt;=10)?('A'+((InBuff[size]%16)-10)):('0'+(InBuff[size]%16)));
              size = size+1;
          }
      }
  }
  </code></pre>