Recently I have revisited Iczelion's ODBC tutorial in order to write a reader for a legacy code that used a MSAccess file.
I post here for future reference the fully working tutorial in fasm syntax after removing some cruft that had nothing to do with ODBC.
; This is an excerpt of Iczelion's ODBC tutorial
format PE GUI 4.0
entry start
include 'win32a.inc'
SQL_NULL_HANDLE = 0
SQL_HANDLE_ENV = 1
SQL_HANDLE_DBC = 2
SQL_HANDLE_STMT = 3
SQL_ATTR_ODBC_VERSION = 0C8h
SQL_OV_ODBC3 = 3
SQL_DRIVER_COMPLETE = 1
SQL_C_CHAR = 1
section '.text' code readable executable
start:
invoke GetModuleHandle,0
mov [hInstance],eax
call GetProgramPath
ccall ODBCConnect,NULL
ccall RunQuery,NULL
call ODBCDisconnect
exit:
invoke ExitProcess,0
proc GetProgramPath
invoke GetModuleFileName,NULL,ProgPath,sizeof.ProgPath
std
mov edi,ProgPath
add edi,sizeof.ProgPath-1
mov al,"\"
mov ecx,sizeof.ProgPath
repne scasb
cld
mov byte [edi+2],0
ret
endp
proc ODBCConnect hDlg
invoke SQLAllocHandle,SQL_HANDLE_ENV,SQL_NULL_HANDLE,hEnv
or ax,ax
je .alloc_ok
cmp ax,1
jnz .error_alloc
.alloc_ok:
invoke SQLSetEnvAttr,[hEnv],SQL_ATTR_ODBC_VERSION, SQL_OV_ODBC3,0
or ax,ax
je .env_set
cmp ax,1
jnz .error_attr
.env_set:
invoke SQLAllocHandle,SQL_HANDLE_DBC,[hEnv],hConn
or ax,ax
je .open_db
cmp ax,1
jnz .error_handle
.open_db:
invoke lstrcpy,ConnectString,strConnect
invoke lstrcat,ConnectString,ProgPath
invoke lstrcat,ConnectString,DBName
invoke SQLDriverConnect,[hConn],[hDlg],ConnectString,sizeof.ConnectString,\
Conn,sizeof.Conn,StrLen,SQL_DRIVER_COMPLETE
or ax,ax
je .connected
cmp ax,1
jnz .error_conn
.connected:
invoke MessageBox,[hDlg],Conn,ConnectCaption,MB_OK+MB_ICONINFORMATION
jmp .done
.error_conn:
invoke SQLFreeHandle,SQL_HANDLE_DBC,[hConn]
invoke SQLFreeHandle,SQL_HANDLE_ENV,[hEnv]
invoke MessageBox,[hDlg],ConnFail,AppName,MB_OK+MB_ICONERROR
jmp .done
.error_handle:
invoke SQLFreeHandle,SQL_HANDLE_ENV,[hEnv]
invoke MessageBox,[hDlg],AllocConnFail,AppName,MB_OK+MB_ICONERROR
jmp .done
.error_attr:
invoke SQLFreeHandle,SQL_HANDLE_ENV,[hEnv]
invoke MessageBox,[hDlg],SetAttrFail,AppName,MB_OK+MB_ICONERROR
jmp .done
.error_alloc:
invoke MessageBox,[hDlg],AllocEnvFail,AppName,MB_OK+MB_ICONERROR
.done:
ret
endp
proc ODBCDisconnect hDlg
invoke SQLDisconnect,[hConn]
invoke SQLFreeHandle,SQL_HANDLE_DBC,[hConn]
invoke SQLFreeHandle,SQL_HANDLE_ENV,[hEnv]
invoke MessageBox,[hDlg],Disconnect,AppName,MB_OK+MB_ICONINFORMATION
ret
endp
proc RunQuery hDlg
invoke SQLAllocHandle,SQL_HANDLE_STMT,[hConn],hStmt
or ax,ax
je .query
cmp ax,1
jnz .error_alloc
.query:
invoke SQLExecDirect,[hStmt],SQLStatement,sizeof.SQLStatement
or ax,ax
je .fill_data
cmp ax,1
jnz .error_exec
.fill_data:
call FillData
jmp .cleanup
.error_exec:
invoke MessageBox,[hDlg],ExecuteFail,AppName,MB_OK+MB_ICONERROR
.cleanup:
invoke SQLCloseCursor,[hStmt]
invoke SQLFreeHandle,SQL_HANDLE_STMT,[hStmt]
jmp .done
.error_alloc:
invoke MessageBox,[hDlg],AllocStmtFail,AppName,MB_OK+MB_ICONERROR
.done:
ret
endp
proc FillData
invoke SQLBindCol,[hStmt],1,SQL_C_CHAR,TheName,sizeof.TheName,NameLength
invoke SQLBindCol,[hStmt],2,SQL_C_CHAR,TheSurname,sizeof.TheSurname,SurnameLength
.loop:
invoke SQLFetch,[hStmt]
or ax,ax
je .row_available
cmp ax,1
jnz .end_loop
.row_available:
invoke MessageBox,NULL,TheSurname,TheName,MB_OKCANCEL+MB_ICONINFORMATION
cmp eax,IDOK
je .loop
.end_loop:
ret
endp
section '.bss' readable writeable
hInstance dd ? ; instance handle
hConn dd ? ; connection handle
hStmt dd ?
hEnv dd ? ; environment handle
StrLen dd ?
TheName rb 26
sizeof.TheName = $-TheName
TheSurname rb 26
sizeof.TheSurname = $-TheSurname
NameLength dd ?
SurnameLength dd ?
ProgPath rb 256
sizeof.ProgPath = $-ProgPath
Conn rb 256
sizeof.Conn = $-Conn
ConnectString rb 1024
sizeof.ConnectString = $-ConnectString
SQLStatement db "select * from main",0
sizeof.SQLStatement = $-SQLStatement
strConnect db "DRIVER={Microsoft Access Driver (*.mdb)};DBQ=",0
DBName db "test.mdb",0
ConnectCaption db "Complete Connection String",0
Disconnect db "Disconnect successful",0
AppName db "ODBC Test",0
AllocEnvFail db "Environment handle allocation failed",0
AllocConnFail db "Connection handle allocation failed",0
SetAttrFail db "Cannot set desired ODBC version",0
NoData db "You must type the name in the edit box",0
ExecuteFail db "Execution of SQL statement failed",0
ConnFail db "Connection attempt failed",0
AllocStmtFail db "Statement handle allocation failed",0
section '.idata' import data readable writeable
library kernel,'KERNEL32.DLL',\
odbc,'ODBC32.DLL',\
user,'USER32.DLL'
import kernel,\
GetModuleHandle,'GetModuleHandleA',\
GetModuleFileName,'GetModuleFileNameA',\
ExitProcess,'ExitProcess',\
lstrcpy,'lstrcpyA',\
lstrcat,'lstrcatA',\
lstrlen,'lstrlenA'
import odbc,\
SQLAllocHandle,'SQLAllocHandle',\
SQLBindCol,'SQLBindCol',\
SQLBindParameter,'SQLBindParameter',\
SQLCloseCursor,'SQLCloseCursor',\
SQLDisconnect,'SQLDisconnect',\
SQLDriverConnect,'SQLDriverConnectA',\
SQLExecDirect,'SQLExecDirectA',\
SQLExecute,'SQLExecute',\
SQLFetch,'SQLFetch',\
SQLFreeHandle,'SQLFreeHandle',\
SQLPrepare,'SQLPrepareA',\
SQLSetEnvAttr,'SQLSetEnvAttr'
import user,\
MessageBox,'MessageBoxA'