odbc_installer / calldll: infinite loop encountered
Thomas Heller
theller at python.net
Thu Feb 6 15:36:16 EST 2003
"David" <dlashar at sprynet.com> writes:
> > Would it be a good idea to port the odbc stuff from calldll to ctypes?
> > I would try to give all support I can, but I cannot do it alone.
>
> As noted in a separate but related posting, I am brand new to this technique
> of making C calls via Python. But, yes, that's precisely what I'm seeking
> to do... and it's only a few methods on seemingly a single dll that need to
> be called in order to make a DSN entry. I'm not by any means certain (this
> is terra incognita for me!), but it seems that it's odbccp32.dll that
> exposes the necessary methods, which seem to be SQLConfigDataSource,
> SQLInstallDriverEx, and SQLConfigDriver. Details for the genuinely
> knowledgeable are in the ODBC Programmer's Reference:
>
> http://msdn.microsoft.com/library/default.asp?url=/library/en-us/odbc/htm/da
> sdkodbcoverview_whatsnew.asp.
>
> Hope that helps, i.e., clarifies the need. And apologies if this is too
> Win-related. I'm just trying to put as much of my app in Python as I can.
> Thanks,
>
Here is a simple module which wraps the SQLConfigDriver and
SQLConfigDataSource functions:
----- snip -----
from ctypes import windll, c_int, byref, c_string
odbccp32 = windll.odbccp32
user32 = windll.user32
class ODBCError(Exception):
pass
def _ODBCInstallerBool(result):
if result == 0:
# integer to store the error code
err_code = c_int()
# 256 byte buffer for error message
err_message = c_string("\000" * 256)
err_msg_len = c_int()
result = odbccp32.SQLInstallerError(1,
byref(err_code),
err_message,
len(err_message),
byref(err_msg_len))
if result == 0:
raise ODBCError, (err_code.value, err_message.value)
else:
raise ODBCError, "Unknown error"
# use the _ODBCInstallerBool function to check for errors
odbccp32.SQLConfigDataSource.restype = _ODBCInstallerBool
def SQLConfigDataSource(hwnd, request, driver, attributes):
odbccp32.SQLConfigDataSource(hwnd, request, driver, attributes)
msg = c_string("\000" * 256)
msgout = c_int()
# use the _ODBCInstallerBool function to check for errors
odbccp32.SQLConfigDriver.restype = _ODBCInstallerBool
def SQLConfigDriver(hwnd, request, driver, args):
msg = c_string("\000" * 256)
msgout = c_int()
odbccp32.SQLConfigDriver(0, request, driver, args,
msg, len(msg), byref(msgout))
return msg.value
ODBC_ADD_DSN = 1
ODBC_CONFIG_DRIVER = 3
----- EOF -----
You can use it in this way:
>>> from sql_config import * # not good style, but...
>>> SQLConfigDriver(0, ODBC_CONFIG_DRIVER,
... "Silly driver", "CPTimeout=20")
Traceback (most recent call last):
File "<stdin>", line 2, in ?
File "sql_config.py", line 42, in SQLConfigDriver
msg, len(msg), byref(msgout))
File "sql_config.py", line 22, in _ODBCInstallerBool
raise ODBCError, (err_code.value, err_message.value)
sql_config.ODBCError: (6, 'Component not found in the registry')
>>> SQLConfigDriver(0, ODBC_CONFIG_DRIVER,
... "Microsoft Access Driver (*.mdb)", "CPTimeout=20")
''
>>> SQLConfigDataSource(0, ODBC_ADD_DSN,
... "Microsoft Access Driver (*.mdb)", "foo=spam")
Traceback (most recent call last):
File "<stdin>", line 2, in ?
File "sql_config.py", line 30, in SQLConfigDataSource
odbccp32.SQLConfigDataSource(hwnd, request, driver, attributes)
File "sql_config.py", line 22, in _ODBCInstallerBool
raise ODBCError, (err_code.value, err_message.value)
sql_config.ODBCError: (9, 'Invalid DSN')
>>> SQLConfigDataSource(0, ODBC_ADD_DSN,
... "Microsoft Access Driver (*.mdb)",
... "DSN=New Data Source\0Description=Hi\0")
>>>
I wish I had more time to explain this, but hopefully you are
able to figure it out yourself.
Thomas
More information about the Python-list
mailing list