LCOV - code coverage report
Current view: top level - src/server - server.c (source / functions) Hit Total Coverage
Test: FreeTDS coverage Lines: 61 235 26.0 %
Date: 2017-09-19 14:19:50 Functions: 5 16 31.2 %

          Line data    Source code
       1             : /* FreeTDS - Library of routines accessing Sybase and Microsoft databases
       2             :  * Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004  Brian Bruns
       3             :  * Copyright (C) 2010  Frediano Ziglio
       4             :  *
       5             :  * This library is free software; you can redistribute it and/or
       6             :  * modify it under the terms of the GNU Library General Public
       7             :  * License as published by the Free Software Foundation; either
       8             :  * version 2 of the License, or (at your option) any later version.
       9             :  *
      10             :  * This library is distributed in the hope that it will be useful,
      11             :  * but WITHOUT ANY WARRANTY; without even the implied warranty of
      12             :  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
      13             :  * Library General Public License for more details.
      14             :  *
      15             :  * You should have received a copy of the GNU Library General Public
      16             :  * License along with this library; if not, write to the
      17             :  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
      18             :  * Boston, MA 02111-1307, USA.
      19             :  */
      20             : 
      21             : #include <config.h>
      22             : 
      23             : #if HAVE_STRING_H
      24             : #include <string.h>
      25             : #endif /* HAVE_STRING_H */
      26             : 
      27             : #include <assert.h>
      28             : 
      29             : #include <freetds/tds.h>
      30             : #include <freetds/server.h>
      31             : #include <freetds/string.h>
      32             : #include <freetds/data.h>
      33             : #include <freetds/bytes.h>
      34             : 
      35             : void
      36        1932 : tds_env_change(TDSSOCKET * tds, int type, const char *oldvalue, const char *newvalue)
      37             : {
      38             :         TDS_SMALLINT totsize;
      39             : 
      40             :         /* If oldvalue is NULL, treat it like "" */
      41        1932 :         if (oldvalue == NULL)
      42         644 :                 oldvalue = "";
      43             : 
      44             :         /*
      45             :          * NOTE: I don't know why each type of environment value has a different
      46             :          * format.  According to the TDS5 specifications, they should all use
      47             :          * the same format.   The code for the TDS_ENV_CHARSET case *should*
      48             :          * work for all environment values.  -- Steve Kirkendall
      49             :          */
      50             : 
      51        1932 :         switch (type) {
      52             :         case TDS_ENV_DATABASE:
      53             :         case TDS_ENV_LANG:
      54             :         case TDS_ENV_PACKSIZE:
      55             :         case TDS_ENV_CHARSET:
      56        1932 :                 tds_put_byte(tds, TDS_ENVCHANGE_TOKEN);
      57             :                 /* totsize = type + newlen + newvalue + oldlen + oldvalue  */
      58             :                 /* FIXME ucs2 */
      59        1932 :                 totsize = (IS_TDS7_PLUS(tds->conn) ? 2 : 1) * (strlen(oldvalue) + strlen(newvalue)) + 3;
      60        1932 :                 tds_put_smallint(tds, totsize);
      61        1932 :                 tds_put_byte(tds, type);
      62        1932 :                 tds_put_byte(tds, strlen(newvalue));
      63             :                 /* FIXME this assume singlebyte -> ucs2 for mssql */
      64        1932 :                 tds_put_string(tds, newvalue, strlen(newvalue));
      65        1932 :                 tds_put_byte(tds, strlen(oldvalue));
      66             :                 /* FIXME this assume singlebyte -> ucs2 for mssql */
      67        1932 :                 tds_put_string(tds, oldvalue, strlen(oldvalue));
      68        1932 :                 break;
      69             :         case TDS_ENV_LCID:
      70             :         case TDS_ENV_SQLCOLLATION:
      71             : #if 1
      72           0 :                 tds_put_byte(tds, TDS_ENVCHANGE_TOKEN);
      73             :                 /* totsize = type + len + oldvalue + len + newvalue */
      74           0 :                 totsize = 3 + strlen(newvalue) + strlen(oldvalue);
      75           0 :                 tds_put_smallint(tds, totsize);
      76           0 :                 tds_put_byte(tds, type);
      77           0 :                 tds_put_byte(tds, strlen(newvalue));
      78           0 :                 tds_put_n(tds, newvalue, strlen(newvalue));
      79           0 :                 tds_put_byte(tds, strlen(oldvalue));
      80           0 :                 tds_put_n(tds, oldvalue, strlen(oldvalue));
      81           0 :                 break;
      82             : #endif
      83             :         default:
      84           0 :                 tdsdump_log(TDS_DBG_WARN, "tds_env_change() ignoring unsupported environment code #%d", type);
      85             :         }
      86        1932 : }
      87             : 
      88             : void
      89           0 : tds_send_eed(TDSSOCKET * tds, int msgno, int msgstate, int severity, char *msgtext, char *srvname, char *procname, int line)
      90             : {
      91             :         int totsize;
      92             : 
      93           0 :         tds_put_byte(tds, TDS_EED_TOKEN);
      94           0 :         totsize = 7 + strlen(procname) + 5 + strlen(msgtext) + 2 + strlen(srvname) + 3;
      95           0 :         tds_put_smallint(tds, totsize);
      96           0 :         tds_put_smallint(tds, msgno);
      97           0 :         tds_put_smallint(tds, 0);       /* unknown */
      98           0 :         tds_put_byte(tds, msgstate);
      99           0 :         tds_put_byte(tds, severity);
     100           0 :         tds_put_byte(tds, strlen(procname));
     101           0 :         tds_put_n(tds, procname, strlen(procname));
     102           0 :         tds_put_byte(tds, 0);   /* unknown */
     103           0 :         tds_put_byte(tds, 1);   /* unknown */
     104           0 :         tds_put_byte(tds, 0);   /* unknown */
     105           0 :         tds_put_smallint(tds, strlen(msgtext) + 1);
     106           0 :         tds_put_n(tds, msgtext, strlen(msgtext));
     107           0 :         tds_put_byte(tds, severity);
     108           0 :         tds_put_byte(tds, strlen(srvname));
     109           0 :         tds_put_n(tds, srvname, strlen(srvname));
     110           0 :         tds_put_byte(tds, 0);   /* unknown */
     111           0 :         tds_put_byte(tds, 1);   /* unknown */
     112           0 :         tds_put_byte(tds, 0);   /* unknown */
     113           0 : }
     114             : 
     115             : void
     116        1288 : tds_send_msg(TDSSOCKET * tds, int msgno, int msgstate, int severity,
     117             :              const char *msgtext, const char *srvname, const char *procname, int line)
     118             : {
     119             :         int msgsz;
     120             :         size_t len;
     121             : 
     122        1288 :         tds_put_byte(tds, TDS_INFO_TOKEN);
     123        1288 :         if (!procname)
     124        1288 :                 procname = "";
     125        1288 :         len = strlen(procname);
     126        1288 :         msgsz = 4               /* msg no    */
     127             :                 + 1             /* msg state */
     128             :                 + 1             /* severity  */
     129             :                 /* FIXME ucs2 */
     130        2576 :                 + 4 + (IS_TDS7_PLUS(tds->conn) ? 2 : 1) * (strlen(msgtext) + strlen(srvname) + len)
     131        2576 :                 + (IS_TDS72_PLUS(tds->conn) ? 4 : 2);        /* line number */
     132        1288 :         tds_put_smallint(tds, msgsz);
     133        1288 :         tds_put_int(tds, msgno);
     134        1288 :         tds_put_byte(tds, msgstate);
     135        1288 :         tds_put_byte(tds, severity);
     136        1288 :         tds_put_smallint(tds, strlen(msgtext));
     137             :         /* FIXME ucs2 */
     138        1288 :         tds_put_string(tds, msgtext, strlen(msgtext));
     139        1288 :         tds_put_byte(tds, strlen(srvname));
     140             :         /* FIXME ucs2 */
     141        1288 :         tds_put_string(tds, srvname, strlen(srvname));
     142        1288 :         if (len) {
     143           0 :                 tds_put_byte(tds, len);
     144             :                 /* FIXME ucs2 */
     145           0 :                 tds_put_string(tds, procname, len);
     146             :         } else {
     147        1288 :                 tds_put_byte(tds, 0);
     148             :         }
     149        1288 :         if (IS_TDS72_PLUS(tds->conn))
     150           0 :                 tds_put_int(tds, line);
     151             :         else
     152        1288 :                 tds_put_smallint(tds, line);
     153        1288 : }
     154             : 
     155             : void
     156           0 : tds_send_err(TDSSOCKET * tds, int severity, int dberr, int oserr, char *dberrstr, char *oserrstr)
     157             : {
     158           0 :         tds_put_byte(tds, TDS_ERROR_TOKEN);
     159           0 : }
     160             : 
     161             : void
     162         644 : tds_send_login_ack(TDSSOCKET * tds, const char *progname)
     163             : {
     164             :         TDS_UINT ui, version;
     165             : 
     166         644 :         tds_put_byte(tds, TDS_LOGINACK_TOKEN);
     167         644 :         tds_put_smallint(tds, 10 + (IS_TDS7_PLUS(tds->conn)? 2 : 1) * strlen(progname));     /* length of message */
     168         644 :         if (IS_TDS50(tds->conn)) {
     169           0 :                 tds_put_byte(tds, 5);
     170           0 :                 version = 0x05000000u;
     171             :         } else {
     172         644 :                 tds_put_byte(tds, 1);
     173             :                 /* see src/tds/token.c */
     174         644 :                 if (IS_TDS73_PLUS(tds->conn)) {
     175             :                         version = 0x730B0003u;
     176         644 :                 } else if (IS_TDS72_PLUS(tds->conn)) {
     177             :                         version = 0x72090002u;
     178         644 :                 } else if (IS_TDS71_PLUS(tds->conn)) {
     179         644 :                         version = tds->conn->tds71rev1 ? 0x07010000u : 0x71000001u;
     180             :                 } else {
     181           0 :                         version = (TDS_MAJOR(tds->conn) << 24) | (TDS_MINOR(tds->conn) << 16);
     182             :                 }
     183             :         }
     184         644 :         TDS_PUT_A4BE(&ui, version);
     185         644 :         tds_put_n(tds, &ui, 4);
     186             : 
     187         644 :         tds_put_byte(tds, strlen(progname));
     188             :         /* FIXME ucs2 */
     189         644 :         tds_put_string(tds, progname, strlen(progname));
     190             : 
     191             :         /* server version, always big endian */
     192        1288 :         TDS_PUT_A4BE(&ui, tds->conn->product_version & 0x7fffffffu);
     193         644 :         tds_put_n(tds, &ui, 4);
     194         644 : }
     195             : 
     196             : void
     197           0 : tds_send_capabilities_token(TDSSOCKET * tds)
     198             : {
     199           0 :         tds_put_byte(tds, TDS_CAPABILITY_TOKEN);
     200           0 :         tds_put_smallint(tds, 18);
     201           0 :         tds_put_byte(tds, 1);
     202           0 :         tds_put_byte(tds, 7);
     203           0 :         tds_put_byte(tds, 7);
     204           0 :         tds_put_byte(tds, 97);
     205           0 :         tds_put_byte(tds, 65);
     206           0 :         tds_put_byte(tds, 207);
     207           0 :         tds_put_byte(tds, 255);
     208           0 :         tds_put_byte(tds, 255);
     209           0 :         tds_put_byte(tds, 230);
     210           0 :         tds_put_byte(tds, 2);
     211           0 :         tds_put_byte(tds, 7);
     212           0 :         tds_put_byte(tds, 0);
     213           0 :         tds_put_byte(tds, 0);
     214           0 :         tds_put_byte(tds, 2);
     215           0 :         tds_put_byte(tds, 0);
     216           0 :         tds_put_byte(tds, 0);
     217           0 :         tds_put_byte(tds, 0);
     218           0 :         tds_put_byte(tds, 0);
     219           0 : }
     220             : 
     221             : /**
     222             :  * Send a "done" token, marking the end of a table, stored procedure, or query.
     223             :  * \param tds           Where the token will be written to.
     224             :  * \param token         The appropriate type of "done" token for this context:
     225             :  *                      TDS_DONE_TOKEN outside a stored procedure,
     226             :  *                      TDS_DONEINPROC_TOKEN inside a stored procedure, or
     227             :  *                      TDS_DONEPROC_TOKEN at the end of a stored procedure.
     228             :  * \param flags         Bitwise-OR of flags in the "enum tds_end" data type.
     229             :  *                      TDS_DONE_FINAL for the last statement in a query,
     230             :  *                      TDS_DONE_MORE_RESULTS if not the last statement,
     231             :  *                      TDS_DONE_ERROR if the statement had an error,
     232             :  *                      TDS_DONE_INXACT if a transaction is  pending,
     233             :  *                      TDS_DONE_PROC inside a stored procedure,
     234             :  *                      TDS_DONE_COUNT if a table was sent (and rows counted)
     235             :  *                      TDS_DONE_CANCELLED if the query was canceled, and
     236             :  *                      TDS_DONE_EVENT if the token marks an event.
     237             :  * \param numrows       Number of rows, if flags has TDS_DONE_COUNT.
     238             :  */
     239             : void
     240         644 : tds_send_done(TDSSOCKET * tds, int token, TDS_SMALLINT flags, TDS_INT numrows)
     241             : {
     242         644 :         tds_put_byte(tds, token);
     243         644 :         tds_put_smallint(tds, flags);
     244         644 :         tds_put_smallint(tds, 2); /* are these two bytes the transaction status? */
     245         644 :         if (IS_TDS72_PLUS(tds->conn))
     246           0 :                 tds_put_int8(tds, numrows);
     247             :         else
     248         644 :                 tds_put_int(tds, numrows);
     249         644 : }
     250             : 
     251             : void
     252         644 : tds_send_done_token(TDSSOCKET * tds, TDS_SMALLINT flags, TDS_INT numrows)
     253             : {
     254         644 :         tds_send_done(tds, TDS_DONE_TOKEN, flags, numrows);
     255         644 : }
     256             : 
     257             : void
     258           0 : tds_send_control_token(TDSSOCKET * tds, TDS_SMALLINT numcols)
     259             : {
     260             :         int i;
     261             : 
     262           0 :         tds_put_byte(tds, TDS_CONTROL_FEATUREEXTACK_TOKEN);
     263           0 :         tds_put_smallint(tds, numcols);
     264           0 :         for (i = 0; i < numcols; i++) {
     265           0 :                 tds_put_byte(tds, 0);
     266             :         }
     267           0 : }
     268             : void
     269           0 : tds_send_col_name(TDSSOCKET * tds, TDSRESULTINFO * resinfo)
     270             : {
     271           0 :         int col, hdrsize = 0;
     272             :         TDSCOLUMN *curcol;
     273             : 
     274           0 :         tds_put_byte(tds, TDS_COLNAME_TOKEN);
     275           0 :         for (col = 0; col < resinfo->num_cols; col++) {
     276           0 :                 curcol = resinfo->columns[col];
     277           0 :                 hdrsize += tds_dstr_len(&curcol->column_name) + 1;
     278             :         }
     279             : 
     280           0 :         tds_put_smallint(tds, hdrsize);
     281           0 :         for (col = 0; col < resinfo->num_cols; col++) {
     282           0 :                 curcol = resinfo->columns[col];
     283           0 :                 tds_put_byte(tds, tds_dstr_len(&curcol->column_name));
     284             :                 /* exclude the null */
     285           0 :                 tds_put_n(tds, tds_dstr_cstr(&curcol->column_name), tds_dstr_len(&curcol->column_name));
     286             :         }
     287           0 : }
     288             : void
     289           0 : tds_send_col_info(TDSSOCKET * tds, TDSRESULTINFO * resinfo)
     290             : {
     291           0 :         int col, hdrsize = 0;
     292             :         TDSCOLUMN *curcol;
     293             : 
     294           0 :         tds_put_byte(tds, TDS_COLFMT_TOKEN);
     295             : 
     296           0 :         for (col = 0; col < resinfo->num_cols; col++) {
     297           0 :                 curcol = resinfo->columns[col];
     298           0 :                 hdrsize += 5;
     299           0 :                 if (!is_fixed_type(curcol->column_type)) {
     300           0 :                         hdrsize++;
     301             :                 }
     302             :         }
     303           0 :         tds_put_smallint(tds, hdrsize);
     304             : 
     305           0 :         for (col = 0; col < resinfo->num_cols; col++) {
     306           0 :                 curcol = resinfo->columns[col];
     307           0 :                 tds_put_n(tds, "\0\0\0\0", 4);
     308           0 :                 tds_put_byte(tds, curcol->column_type);
     309           0 :                 if (!is_fixed_type(curcol->column_type)) {
     310           0 :                         tds_put_byte(tds, curcol->column_size);
     311             :                 }
     312             :         }
     313           0 : }
     314             : 
     315             : void
     316           0 : tds_send_result(TDSSOCKET * tds, TDSRESULTINFO * resinfo)
     317             : {
     318             :         TDSCOLUMN *curcol;
     319             :         int i, totlen;
     320             :         size_t len;
     321             : 
     322           0 :         tds_put_byte(tds, TDS_RESULT_TOKEN);
     323           0 :         totlen = 2;
     324           0 :         for (i = 0; i < resinfo->num_cols; i++) {
     325           0 :                 curcol = resinfo->columns[i];
     326           0 :                 len = tds_dstr_len(&curcol->column_name);
     327           0 :                 totlen += 8;
     328           0 :                 totlen += len;
     329           0 :                 curcol = resinfo->columns[i];
     330           0 :                 if (!is_fixed_type(curcol->column_type)) {
     331           0 :                         totlen++;
     332             :                 }
     333             :         }
     334           0 :         tds_put_smallint(tds, totlen);
     335           0 :         tds_put_smallint(tds, resinfo->num_cols);
     336           0 :         for (i = 0; i < resinfo->num_cols; i++) {
     337           0 :                 curcol = resinfo->columns[i];
     338           0 :                 len = tds_dstr_len(&curcol->column_name);
     339           0 :                 tds_put_byte(tds, tds_dstr_len(&curcol->column_name));
     340           0 :                 tds_put_n(tds, tds_dstr_cstr(&curcol->column_name), len);
     341           0 :                 tds_put_byte(tds, '0');
     342           0 :                 tds_put_int(tds, curcol->column_usertype);
     343           0 :                 tds_put_byte(tds, curcol->column_type);
     344           0 :                 if (!is_fixed_type(curcol->column_type)) {
     345           0 :                         tds_put_byte(tds, curcol->column_size);
     346             :                 }
     347           0 :                 tds_put_byte(tds, 0);
     348             :         }
     349           0 : }
     350             : 
     351             : void
     352           0 : tds7_send_result(TDSSOCKET * tds, TDSRESULTINFO * resinfo)
     353             : {
     354             :         int i, j;
     355             :         TDSCOLUMN *curcol;
     356             : 
     357             :         /* TDS7+ uses TDS7_RESULT_TOKEN to send column names and info */
     358           0 :         tds_put_byte(tds, TDS7_RESULT_TOKEN);
     359             : 
     360             :         /* send the number of columns */
     361           0 :         tds_put_smallint(tds, resinfo->num_cols);
     362             : 
     363             :         /* send info about each column */
     364           0 :         for (i = 0; i < resinfo->num_cols; i++) {
     365             : 
     366             :                 /* usertype, flags, and type */
     367           0 :                 curcol = resinfo->columns[i];
     368           0 :                 tds_put_smallint(tds, curcol->column_usertype);
     369           0 :                 tds_put_smallint(tds, curcol->column_flags);
     370           0 :                 tds_put_byte(tds, curcol->column_type); /* smallint? */
     371             : 
     372             :                 /* bytes in "size" field varies */
     373           0 :                 if (is_blob_type(curcol->column_type)) {
     374           0 :                         tds_put_int(tds, curcol->column_size);
     375           0 :                 } else if (curcol->column_type>=128) { /*is_large_type*/
     376           0 :                         tds_put_smallint(tds, curcol->column_size);
     377             :                 } else {
     378           0 :                         tds_put_tinyint(tds, curcol->column_size);
     379             :                 }
     380             : 
     381             :                 /* some types have extra info */
     382           0 :                 if (is_numeric_type(curcol->column_type)) {
     383           0 :                         tds_put_tinyint(tds, curcol->column_prec);
     384           0 :                         tds_put_tinyint(tds, curcol->column_scale);
     385           0 :                 } else if (is_blob_type(curcol->column_type)) {
     386           0 :                         size_t len = tds_dstr_len(&curcol->table_name);
     387           0 :                         const char *name = tds_dstr_cstr(&curcol->table_name);
     388             : 
     389           0 :                         tds_put_smallint(tds, 2 * len);
     390           0 :                         for (j = 0; name[j] != '\0'; j++){
     391           0 :                                 tds_put_byte(tds, name[j]);
     392           0 :                                 tds_put_byte(tds, 0);
     393             :                         }
     394             :                 }
     395             : 
     396             :                 /* finally the name, in UCS16 format */
     397           0 :                 tds_put_byte(tds, tds_dstr_len(&curcol->column_name));
     398           0 :                 for (j = 0; j < tds_dstr_len(&curcol->column_name); j++) {
     399           0 :                         tds_put_byte(tds, tds_dstr_cstr(&curcol->column_name)[j]);
     400           0 :                         tds_put_byte(tds, 0);
     401             :                 }
     402             :         }
     403           0 : }
     404             : 
     405             : /**
     406             :  * Send any tokens that mark the start of a table.  This automatically chooses
     407             :  * the right tokens for this client's version of the TDS protocol.  In other
     408             :  * words, it is a wrapper around tds_send_col_name(), tds_send_col_info(),
     409             :  * tds_send_result(), and tds7_send_result().
     410             :  * \param tds           The socket to which the tokens will be written.  Also,
     411             :  *                      it contains the TDS protocol version number.
     412             :  * \param resinfo       Describes the table to be send, especially the number
     413             :  *                      of columns and the names & data types of each column.
     414             :  */
     415           0 : void tds_send_table_header(TDSSOCKET * tds, TDSRESULTINFO * resinfo)
     416             : {
     417           0 :         switch (TDS_MAJOR(tds->conn)) {
     418             :         case 4:
     419             :                 /*
     420             :                  * TDS4 uses TDS_COLNAME_TOKEN to send column names, and
     421             :                  * TDS_COLFMT_TOKEN to send column info.  The number of columns
     422             :                  * is implied by the number of column names.
     423             :                  */
     424           0 :                 tds_send_col_name(tds, resinfo);
     425           0 :                 tds_send_col_info(tds, resinfo);
     426           0 :                 break;
     427             : 
     428             :         case 5:
     429             :                 /* TDS5 uses a TDS_RESULT_TOKEN to send all column information */
     430           0 :                 tds_send_result(tds, resinfo);
     431           0 :                 break;
     432             : 
     433             :         case 7:
     434             :                 /*
     435             :                  * TDS7+ uses a TDS7_RESULT_TOKEN to send all column
     436             :                  * information.
     437             :                  */
     438           0 :                 tds7_send_result(tds, resinfo);
     439           0 :                 break;
     440             :         }
     441           0 : }
     442             : 
     443             : void
     444           0 : tds_send_row(TDSSOCKET * tds, TDSRESULTINFO * resinfo)
     445             : {
     446             :         TDSCOLUMN *curcol;
     447             :         int colsize, i;
     448             : 
     449           0 :         tds_put_byte(tds, TDS_ROW_TOKEN);
     450           0 :         for (i = 0; i < resinfo->num_cols; i++) {
     451           0 :                 curcol = resinfo->columns[i];
     452           0 :                 if (!is_fixed_type(curcol->column_type)) {
     453             :                         /* FIX ME -- I have no way of knowing the actual length of non character variable data (eg nullable int) */
     454           0 :                         colsize = strlen((char *) curcol->column_data);
     455           0 :                         tds_put_byte(tds, colsize);
     456           0 :                         tds_put_n(tds, curcol->column_data, colsize);
     457             :                 } else {
     458           0 :                         tds_put_n(tds, curcol->column_data, tds_get_size_by_type(curcol->column_type));
     459             :                 }
     460             :         }
     461           0 : }
     462             : 
     463             : void
     464           0 : tds71_send_prelogin(TDSSOCKET * tds)
     465             : {
     466             :         static const unsigned char prelogin[] = {
     467             :                 0x00, 0x00, 0x15, 0x00, 0x06, 0x01, 0x00, 0x1b,
     468             :                 0x00, 0x01, 0x02, 0x00, 0x1c, 0x00, 0x01, 0x03,
     469             :                 0x00, 0x1d, 0x00, 0x00, 0xff, 0x08, 0x00, 0x01,
     470             :                 0x55, 0x00, 0x00, 0x02, 0x00 
     471             :         };
     472             : 
     473           0 :         tds_put_n(tds, prelogin, sizeof(prelogin));
     474           0 : }
     475             : 

Generated by: LCOV version 1.13