diff -dPNur freetds/include/tds.h freetds-ds/include/tds.h
--- freetds/include/tds.h	2008-06-18 11:06:26.000000000 +0200
+++ freetds-ds/include/tds.h	2008-07-02 22:10:03.000000000 +0200
@@ -1009,6 +1009,7 @@
 	TDS_INT *column_lenbind;
 	TDS_INT column_textpos;
 	TDS_INT column_text_sqlgetdatapos;
+	TDS_CHAR column_text_sqlputdatainfo;
 
 	BCPCOLDATA *bcp_column_data;
 	/**
diff -dPNur freetds/src/odbc/odbc.c freetds-ds/src/odbc/odbc.c
--- freetds/src/odbc/odbc.c	2008-06-18 11:06:26.000000000 +0200
+++ freetds-ds/src/odbc/odbc.c	2008-07-02 22:10:03.000000000 +0200
@@ -4652,6 +4652,7 @@
 	SQLLEN dummy_cb;
 	int nSybType;
 
+	TDS_INT converted_column_cur_size;
 	int extra_bytes = 0;
 
 	INIT_HSTMT;
@@ -4690,6 +4691,7 @@
 		ODBC_RETURN(stmt, SQL_ERROR);
 	}
 	colinfo = tds->current_results->columns[icol - 1];
+	converted_column_cur_size = colinfo->column_cur_size;
 
 	if (colinfo->column_cur_size < 0) {
 		*pcbValue = SQL_NULL_DATA;
@@ -4715,7 +4717,7 @@
 			if (is_blob_type(colinfo->column_type))
 				src = ((TDSBLOB *) src)->textvalue;
 
-			if (fCType == SQL_C_CHAR && colinfo->column_text_sqlgetdatapos) {
+			if (fCType == SQL_C_CHAR) {
 				TDS_CHAR buf[3];
 				SQLLEN len;
 
@@ -4758,40 +4760,15 @@
 						}
 					} else {
 						nread = colinfo->column_text_sqlgetdatapos / 2;
-						if (nread >= colinfo->column_cur_size)
+						
+						if (colinfo->column_text_sqlgetdatapos > 0
+						    && nread >= colinfo->column_cur_size)
 							ODBC_RETURN(stmt, SQL_NO_DATA);
 					}
 					
 					src += nread;
 					srclen = colinfo->column_cur_size - nread;
-					break;
-				default:
-					if (colinfo->column_text_sqlgetdatapos >= colinfo->column_cur_size)
-						ODBC_RETURN(stmt, SQL_NO_DATA);
-						
-					src += colinfo->column_text_sqlgetdatapos;
-					srclen = colinfo->column_cur_size - colinfo->column_text_sqlgetdatapos;
-
-				}
-			} else if (fCType == SQL_C_BINARY) {
-				switch (nSybType) {
-				case SYBCHAR:
-				case SYBVARCHAR:
-				case SYBTEXT:
-				case XSYBCHAR:
-				case XSYBVARCHAR:
-					nread = (src[0] == '0' && toupper(src[1]) == 'X')? 2 : 0;
-						
-					while ((nread < colinfo->column_cur_size) && (src[nread] == ' ' || src[nread] == '\0')) 
-						nread++;
-
-					nread += colinfo->column_text_sqlgetdatapos * 2;
-					
-					if (nread && nread >= colinfo->column_cur_size)
-						ODBC_RETURN(stmt, SQL_NO_DATA);
-
-					src += nread;
-					srclen = colinfo->column_cur_size - nread;
+					converted_column_cur_size *= 2;
 					break;
 				default:
 					if (colinfo->column_text_sqlgetdatapos > 0
@@ -4842,7 +4819,7 @@
 			if (colinfo->column_text_sqlgetdatapos == 0 && cbValueMax > 0)
 				++colinfo->column_text_sqlgetdatapos;
 			
-			if (colinfo->column_text_sqlgetdatapos < colinfo->column_cur_size) {	/* not all read ?? */
+			if (colinfo->column_text_sqlgetdatapos < converted_column_cur_size) {	/* not all read ?? */
 				odbc_errs_add(&stmt->errs, "01004", "String data, right truncated");
 				ODBC_RETURN(stmt, SQL_SUCCESS_WITH_INFO);
 			}
diff -dPNur freetds/src/odbc/prepare_query.c freetds-ds/src/odbc/prepare_query.c
--- freetds/src/odbc/prepare_query.c	2007-04-18 16:29:24.000000000 +0200
+++ freetds-ds/src/odbc/prepare_query.c	2008-07-02 22:10:03.000000000 +0200
@@ -275,21 +275,110 @@
 	/* copy to destination */
 	if (blob) {
 		TDS_CHAR *p;
+		int dest_type, src_type, sql_src_type, res;
+		CONV_RESULT ores;
+		TDS_DBC * dbc = stmt->dbc;
+		void *free_ptr = NULL;
+		int start = 0;
+		SQLPOINTER extradata = NULL;
+		SQLLEN extralen = 0;
+		
+
+		dest_type = odbc_sql_to_server_type(dbc->tds_socket, drec_ipd->sql_desc_concise_type);
+		if (dest_type == TDS_FAIL)
+			return SQL_ERROR;
+			
+		/* get C type */
+		sql_src_type = drec_apd->sql_desc_concise_type;
+		if (sql_src_type == SQL_C_DEFAULT)
+			sql_src_type = odbc_sql_to_c_type_default(drec_ipd->sql_desc_concise_type);
+
+		/* test source type */
+		/* TODO test intervals */
+		src_type = odbc_c_to_server_type(sql_src_type);
+		if (src_type == TDS_FAIL)
+			return SQL_ERROR;
+		
+		if (sql_src_type == SQL_C_CHAR) {
+			switch (tds_get_conversion_type(curcol->column_type, curcol->column_size)) {
+			case SYBBINARY:
+			case SYBVARBINARY:
+			case XSYBBINARY:
+			case XSYBVARBINARY:
+			case SYBLONGBINARY:
+			case SYBIMAGE:
+				if (!*((char*)DataPtr+len-1))
+					--len;
+					
+				if (!len)
+					return SQL_SUCCESS;
+					
+				if (curcol->column_cur_size > 0
+				&&  curcol->column_text_sqlputdatainfo) {
+					TDS_CHAR data[2];
+					data[0] = curcol->column_text_sqlputdatainfo;
+					data[1] = *(char*)DataPtr;
+				    
+					res = tds_convert(dbc->env->tds_ctx, src_type, data, 2, dest_type, &ores);
+					if (res < 0)
+						return SQL_ERROR;
+				    
+					extradata = ores.ib;
+					extralen = res;
+					
+					start = 1;
+					--len;
+				}
+				
+			        if (len&1) {
+					--len;
+					curcol->column_text_sqlputdatainfo = *((char*)DataPtr+len);
+				}
+
+				res = tds_convert(dbc->env->tds_ctx, src_type, DataPtr+start, len, dest_type, &ores);
+				if (res < 0) {
+					if (extradata)
+						free(extradata);
+						
+					return SQL_ERROR;
+				}
+			    
+				DataPtr = free_ptr = ores.ib;
+				len = res;
+				break;
+			}
+		}
 
 		if (blob->textvalue)
-			p = (TDS_CHAR *) realloc(blob->textvalue, len + curcol->column_cur_size);
+			p = (TDS_CHAR *) realloc(blob->textvalue, len + extralen + curcol->column_cur_size);
 		else {
 			assert(curcol->column_cur_size == 0);
-			p = (TDS_CHAR *) malloc(len);
+			p = (TDS_CHAR *) malloc(len + extralen);
 		}
-		if (!p)
+		if (!p) {
+			if (free_ptr)
+				free(free_ptr);
+			if (extradata)
+				free(extradata);
 			return SQL_ERROR;
+		}
 		blob->textvalue = p;
+		if (extralen) {
+			memcpy(blob->textvalue + curcol->column_cur_size, extradata, extralen);
+			curcol->column_cur_size += extralen;
+		}
 		memcpy(blob->textvalue + curcol->column_cur_size, DataPtr, len);
+		
+		if (extradata)
+			free(extradata);
+		if (free_ptr)
+			free(free_ptr);
 	} else {
 		memcpy(curcol->column_data + curcol->column_cur_size, DataPtr, len);
 	}
+	
 	curcol->column_cur_size += len;
+	
 	if (blob && curcol->column_cur_size > curcol->column_size)
 		curcol->column_size = curcol->column_cur_size;
 
diff -dPNur freetds/src/odbc/unittests/blob1.c freetds-ds/src/odbc/unittests/blob1.c
--- freetds/src/odbc/unittests/blob1.c	2008-01-12 01:14:11.000000000 +0100
+++ freetds-ds/src/odbc/unittests/blob1.c	2008-07-02 22:09:28.000000000 +0200
@@ -47,6 +47,16 @@
 		buf[n] = 'a' + ((start+n) * step % ('z' - 'a' + 1));
 }
 
+static void
+fill_hex(char *buf, size_t len, unsigned int start, unsigned int step)
+{
+	size_t n;
+
+	for (n = 0; n < len; ++n)
+		sprintf(buf + 2*n, "%2x", (unsigned int)('a' + ((start+n) * step % ('z' - 'a' + 1))));
+}
+
+
 static int
 check_chars(const char *buf, size_t len, unsigned int start, unsigned int step)
 {
@@ -60,6 +70,21 @@
 }
 
 static int
+check_hex(const char *buf, size_t len, unsigned int start, unsigned int step)
+{
+	size_t n;
+	char symbol[3];
+
+	for (n = 0; n < len; ++n) {
+		sprintf(symbol, "%2x", (unsigned int)('a' + ((start+n) / 2 * step % ('z' - 'a' + 1))));
+		if (buf[n] != symbol[(start+n) % 2])
+			return 0;
+	}
+
+	return 1;
+}
+
+static int
 readBlob(SQLHSTMT * stmth, SQLUSMALLINT pos)
 {
 	SQLRETURN rcode;
@@ -93,6 +118,43 @@
 	return rcode;
 }
 
+static int
+readBlobAsChar(SQLHSTMT * stmth, SQLUSMALLINT pos, int step)
+{
+	SQLRETURN rcode = SQL_SUCCESS_WITH_INFO;
+	char buf[8192];
+	SQLLEN len, total = 0;
+	int i = 0;
+	int check;
+	int bufsize;
+	
+	if (step%2) bufsize = sizeof(buf) - 1;
+	else bufsize = sizeof(buf);
+
+	printf(">> readBlobAsChar field %d\n", pos);
+	while (rcode == SQL_SUCCESS_WITH_INFO) {
+		i++;
+		rcode = SQLGetData(stmth, pos, SQL_C_CHAR, (SQLPOINTER) buf, (SQLINTEGER) bufsize, &len);
+		if (!SQL_SUCCEEDED(rcode) || len <= 0)
+			break;
+		if (len > (SQLLEN) bufsize)
+			len = (SQLLEN) bufsize - 1;
+		printf(">>     step %d: %d bytes readed\n", i, (int) len);
+		
+		check =	check_hex(buf, len, 2*987 + total, 25);
+		if (!check) {
+			fprintf(stderr, "Wrong buffer content\n");
+			failed = 1;
+		}
+		total += len;
+	}
+	printf(">>   total bytes read = %d \n", (int) total);
+	if (total != 20000)
+		failed = 1;
+	return rcode;
+}
+
+
 int
 main(int argc, char **argv)
 {
@@ -106,12 +168,14 @@
 	SQLLEN vind1;
 	char buf2[NBYTES];
 	SQLLEN vind2;
+	char buf3[NBYTES*2 + 1];
+	SQLLEN vind3;
 	int cnt = 2;
 
 	use_odbc_version3 = 1;
 	Connect();
 
-	Command(Statement, "CREATE TABLE #tt ( k INT, t TEXT, b IMAGE, v INT )");
+	Command(Statement, "CREATE TABLE #tt ( k INT, t TEXT, b1 IMAGE, b2 IMAGE, v INT )");
 
 	/* Insert rows ... */
 
@@ -121,7 +185,7 @@
 		rcode = SQLAllocHandle(SQL_HANDLE_STMT, Connection, &m_hstmt);
 		CHECK_RCODE(SQL_HANDLE_DBC, Connection, "SQLAllocHandle StmtH");
 
-		rcode = SQLPrepare(m_hstmt, (SQLCHAR *) "INSERT INTO #tt VALUES ( ?, ?, ?, ? )", SQL_NTS);
+		rcode = SQLPrepare(m_hstmt, (SQLCHAR *) "INSERT INTO #tt VALUES ( ?, ?, ?, ?, ? )", SQL_NTS);
 		CHECK_RCODE(SQL_HANDLE_STMT, m_hstmt, "SQLPrepare");
 
 		SQLBindParameter(m_hstmt, 1, SQL_PARAM_INPUT, SQL_C_LONG, SQL_INTEGER, 0, 0, &key, 0, &vind0);
@@ -133,9 +197,12 @@
 		SQLBindParameter(m_hstmt, 3, SQL_PARAM_INPUT, SQL_C_BINARY, SQL_LONGVARBINARY, 0x10000000, 0, buf2, 0, &vind2);
 		CHECK_RCODE(SQL_HANDLE_STMT, m_hstmt, "SQLBindParameter 3");
 
-		SQLBindParameter(m_hstmt, 4, SQL_PARAM_INPUT, SQL_C_LONG, SQL_INTEGER, 0, 0, &key, 0, &vind0);
+		SQLBindParameter(m_hstmt, 4, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_LONGVARBINARY, 0x10000000, 0, buf3, 0, &vind3);
 		CHECK_RCODE(SQL_HANDLE_STMT, m_hstmt, "SQLBindParameter 4");
 
+		SQLBindParameter(m_hstmt, 5, SQL_PARAM_INPUT, SQL_C_LONG, SQL_INTEGER, 0, 0, &key, 0, &vind0);
+		CHECK_RCODE(SQL_HANDLE_STMT, m_hstmt, "SQLBindParameter 5");
+
 		key = i;
 		vind0 = 0;
 
@@ -144,6 +211,10 @@
 
 		fill_chars(buf2, NBYTES, 987, 25);
 		vind2 = SQL_LEN_DATA_AT_EXEC(NBYTES);
+		
+		memset(buf3, 0, sizeof(buf3));
+		vind3 = SQL_LEN_DATA_AT_EXEC(2*NBYTES+1);
+		
 
 		printf(">> insert... %d\n", i);
 		rcode = SQLExecute(m_hstmt);
@@ -155,10 +226,25 @@
 			CHECK_RCODE(SQL_HANDLE_STMT, m_hstmt, "SQLParamData StmtH");
 			printf(">> SQLParamData: ptr = %p  rcode = %d\n", (void *) p, rcode);
 			if (rcode == SQL_NEED_DATA) {
-				SQLRETURN rcode = SQLPutData(m_hstmt, p, NBYTES);
+				SQLRETURN rcode;
+				if (p == buf3) {
+					fill_hex(buf3, NBYTES, 987, 25);
+					
+					rcode = SQLPutData(m_hstmt, p, NBYTES - (i&1));
 
-				CHECK_RCODE(SQL_HANDLE_STMT, m_hstmt, "SQLPutData StmtH");
-				printf(">> param %p: total bytes written = %d\n", (void *) p, NBYTES);
+					CHECK_RCODE(SQL_HANDLE_STMT, m_hstmt, "SQLPutData StmtH");
+					printf(">> param %p: total bytes written = %d\n", (void *) p, NBYTES - (i&1));
+					
+					rcode = SQLPutData(m_hstmt, p + NBYTES - (i&1), NBYTES + (i&1));
+
+					CHECK_RCODE(SQL_HANDLE_STMT, m_hstmt, "SQLPutData StmtH");
+					printf(">> param %p: total bytes written = %d\n", (void *) p, NBYTES + (i&1));
+				} else {
+					rcode = SQLPutData(m_hstmt, p, NBYTES);
+
+					CHECK_RCODE(SQL_HANDLE_STMT, m_hstmt, "SQLPutData StmtH");
+					printf(">> param %p: total bytes written = %d\n", (void *) p, NBYTES);
+				}
 			}
 		}
 
@@ -182,7 +268,7 @@
 			CHECK_RCODE(SQL_HANDLE_STMT, m_hstmt, "SQLSetStmtAttr SQL_ATTR_CURSOR_SENSITIVITY");
 		}
 
-		rcode = SQLPrepare(m_hstmt, (SQLCHAR *) "SELECT t, b, v FROM #tt WHERE k = ?", SQL_NTS);
+		rcode = SQLPrepare(m_hstmt, (SQLCHAR *) "SELECT t, b1, b2, v FROM #tt WHERE k = ?", SQL_NTS);
 		CHECK_RCODE(SQL_HANDLE_STMT, m_hstmt, "SQLPrepare");
 
 		SQLBindParameter(m_hstmt, 1, SQL_PARAM_INPUT, SQL_C_LONG, SQL_INTEGER, 0, 0, &i, 0, &vind0);
@@ -192,7 +278,9 @@
 		CHECK_RCODE(SQL_HANDLE_STMT, m_hstmt, "SQLBindCol 2");
 		SQLBindCol(m_hstmt, 2, SQL_C_BINARY, NULL, 0, &vind2);
 		CHECK_RCODE(SQL_HANDLE_STMT, m_hstmt, "SQLBindCol 3");
-		SQLBindCol(m_hstmt, 3, SQL_C_LONG, &key, 0, &vind0);
+		SQLBindCol(m_hstmt, 3, SQL_C_BINARY, NULL, 0, &vind3);
+		CHECK_RCODE(SQL_HANDLE_STMT, m_hstmt, "SQLBindCol 4");
+		SQLBindCol(m_hstmt, 4, SQL_C_LONG, &key, 0, &vind0);
 		CHECK_RCODE(SQL_HANDLE_STMT, m_hstmt, "SQLBindCol 1");
 
 		vind0 = 0;
@@ -210,6 +298,8 @@
 		CHECK_RCODE(SQL_HANDLE_STMT, m_hstmt, "readBlob 1");
 		rcode = readBlob(m_hstmt, 2);
 		CHECK_RCODE(SQL_HANDLE_STMT, m_hstmt, "readBlob 2");
+		rcode = readBlobAsChar(m_hstmt, 3, i);
+		CHECK_RCODE(SQL_HANDLE_STMT, m_hstmt, "readBlob 3 as SQL_C_CHAR");
 
 		rcode = SQLCloseCursor(m_hstmt);
 		CHECK_RCODE(SQL_HANDLE_STMT, m_hstmt, "SQLCloseCursor StmtH");