[freetds] Using freetds in Windows

Frediano Ziglio freddy77 at gmail.com
Sun Jan 10 08:27:53 EST 2010

2010/1/9 James K. Lowden <jklowden at freetds.org>:
> James K. Lowden wrote:
>> It's not
>> a complete answer because (among other reasons) the db-lib error handler
>> won't get the correct error string.
> Hi Freddy,
> A question for you on this topic.
> tdserror() assumes errnum can be converted to a string with strerror(3).
> On Windows that's not true; for winsock errors strerror(3) returns
> "Unknown error".  Somehow, we need to pass the Win32 error string
> (returned from tds_prwsaerror()) to the client libraries.  But how?

The problem is that in Windows C errors (from errno) and system errors
(from GetLastError/WSAGetLastError or returned from APIs depending on
API set!) are not compatible! Errors we detect are from errno and
sockets. However there is no way to distinguish. In dblib structure we
have a simply oserr (and also in TDSSOCKET but currently is used only
for socket error that is systems errors). strerror works for C errors
but not for sockets. System errors messages can be read using
FormatMessage API (not that straight but I have example codes).
Currently I added a macro for sock_strerror so it's easier to
distinguish between strerror and sock_strerror.

> The db-lib call stack is:
> connect(2) (e.g.)
> tdserror(TDSCONTEXT, TDSSOCKET, msgno, oserr)
> _dblib_handle_err_message(TDSCONTEXT, TDSSOCKET, TDSMESSAGE)
> dbperror (DBPROCESS, msgno, oserr)
> I don't want to change the interface to dbperror() or tdserror() just for
> Win32.
> My suggestion: add
>        char * winsock_errstr

I don't like this... perhaps would be better to understand if is a
socket error from tds error code.

> to TDSSOCKET.  Normally it's NULL.  If libtds detects a win32 socket
> error, it looks up the const static string with tds_prwsaerror() and
> stores the pointer in winsock_errstr.  When dbperror() calls the client
> handler, it examines that pointer.  If not NULL, it passes it to the
> client handler instead of calling strerror(3).  To avoid confusion,
> dbperror() sets the pointer to NULL after the handler returns.
> I think this would work with the other client libraries, too.  What do you
> think?

Looking at windows constants I would use a trick and an unique error
number. C errors in windows are very few (the higher constant is 80
but is not used by FreeTDS) while socket errors are usually higher
than 10000. Perhaps we could define a tds_strerror that take this
constants and output a string. (see
http://msdn.microsoft.com/en-us/library/t3ayayh1%28VS.80%29.aspx and

Another problem is thread safety. strerror is not thread safe, it
would be better to use strerror_r if available. Under Windows for C
errors there is _sys_nerrs and _sys_errlist.

> BTW, I'm working on updates to the UG for 0.92.

Good! I saw you committed patch for defncopy and Windows, it was one
of patches I had on my list (you sent me defncopy.c many time ago but
got no time to check it). I saw some strange include in defncopy like
replacements.win32.hacked.h, win32.microsoft directory. Also there is
a strange types.h inclusion in src/tds/token.c... quite strange,
tds_get_varint_size should be defined in data.c (which include
types.h), this breaks my cross Windows compile. Also I got a double
definition cause you added a strncasecmp in include/replacements.h.
Perhaps should be placed in defncopy.c (like strcasecmp define?).

Did you see my initial patch for forbid instance and port
specification on freetds.conf?? I attach it.

> Regards,
> --jkl

-------------- next part --------------
A non-text attachment was scrubbed...
Name: 03-both_deny.diff
Type: text/x-patch
Size: 3895 bytes
Desc: not available
Url : http://lists.ibiblio.org/pipermail/freetds/attachments/20100110/218b1e09/attachment.bin 

More information about the FreeTDS mailing list