tags:

views:

70

answers:

1

I'm looking to modify ODBC calls either directly before hitting the ODBC stack or between the ODBC stack and the dll driver for the connection I am using. For instance, if the application does a SELECT, I want to be able to modify it be SELECT_ALL How can I do that?

A: 

The ODBC setup information points to the driver DLL. You could replace that with your own DLL that has the ODBC entrypoints. Simply make all the ones you don't care about be simple calls to the "real" DLL. The execute and prepare entrypoints could modify the given statement before passing it on to the driver DLL.

For example, if using a User DSN, you might replace the value in HKCU\Software\ODBC.ini\datasourcename\Driver with your own shim DLL.

After a bit of googling, I am not finding an obvious empty shell project that would be an ideal starting point. The API reference has details about the API. In general, though, you shouldn't really need information from there. You just need to pass the parameters for each API to the actuall driver DLL. The function prototypes could be extracted from sql.h and sqlext.h.

An alternative method that might be easier than writing a shim DLL would be to hook just the execute and prepare functions (probably just SQLExecDirect and SQLPrepare). This article is the first hit I saw on doing that.

Mark Wilkins
Thanks for the advice, I had thought about that. I tried to do a C++ DLL that forwarded all the exported methods, but didn't have luck getting that to work. Any good keywords to google? Thanks again.
TwoBitsShort
@Christian: Make sure you use `extern "C"` on the exports so that the names are not mangled. You can use `dumpbin /exports` on the DLL to make sure they are not decorated. I'll poke around a bit with Google and see if I can find something. Ideally, it would be nice to get an empty shell that has all the entrypoint functions defined. ... Seems like something of that nature should exist.
Mark Wilkins
@mark: I scanned with dumpbin and then used .def files to declare all the exported functions. Main routine does a loadlibrary of the orig odbc driver and I changed the registry to point to my shim dll. I also tried the pragma approach. Each time I get a notice that the driver does not support the method SQLDirectConnectW. DirectConnectW is not in the export table, and is just a unicode version of DirectConnect. Any ideas?
TwoBitsShort
@Christian: Are you sure it is SQLDirectConnectW? Is it maybe SQLDriverConnectW? I don't think "SQLDirectConnect" is a standard ODBC API.
Mark Wilkins
@mark My mistake, you are correct. I looked into doing a translation DLL, but the documentation is near non-existant and I can't get one to load as per the MS docs. I noticed in a few posts that they may no longer be used or the driver may not support them (even though I thought it was loaded before the driver?)
TwoBitsShort
@mark the exact error is IM001 (Driver does not support this function) which, as per ODBC tracing, is from SQLDriverConnectW, which (obviously) returned a -1.
TwoBitsShort
@mark Success! I had to manually call each one in asm for it to work. Pragma and .DEF redirects did not work whatsoever, but mapping each exported function to an internal function that called the orig function worked. Thanks so much!
TwoBitsShort
@Christian: I'm not quite sure I understand the exact final solution you ended up with, but I'm glad you got it working.
Mark Wilkins
@mark In my cpp file, I have a dummy export for each export on the real DLL, and I call the real DLL function via GetProcAddress and a jmp. The often mentioned Pragma export and .def style DLL redirects didn't work, but jmp'ing to the function does.
TwoBitsShort