Passing Strings by Reference with DllCall using Binary Buffers
Keywords: Passing Strings by Reference DllCall Binary Buffers
Question:
I have several scripts that rely entirely on OLE, with the exception of checking for the availability of a
driver. I realize I can add the ODBC Extender and call qDrivers(), but would rather use a DLLCall,
something like:
cString = StrCat(strfill(" ",4000),Num2Char(0) )
nLen = 4000
nBuffer= BinaryAlloc(8)
BinaryPoke4(nBuffer,1,0)
x = DllCall("ODBCCP32.DLL", long:"SQLGetInstalledDrivers",lpstr:cString,long:nLen,lpbinary:nBuffer)
If x<>0
Message("SQL Driver Call",Strcat("FAILED! ",x))
Else
cString = StrReplace(cString,Num2Char(0),@CRLF )
Message("Installed Drivers",cString)
Endif
exit
Problem is, it doesn't seem to work, though I remember it working back when. Where did I screw up?
Answer:
I did some research at:
http://doc.ddart.net/msdn/header/include/odbcinst.h.html
and with some trial and error ...
and I've got something working ...
BufMax=4000
Buf=BinaryAlloc(BufMax)
BufOut=BinaryAlloc(4)
pBufOut=IntControl(42,BufOut,0,0,0)
bool = DllCall("ODBCCP32.DLL", long:"SQLGetInstalledDrivers",lpbinary:Buf,long:BufMax,long:pBufOut)
BinaryEodSet(Buf,BinaryPeek4(BufOut,0)-1)
BinaryFree(BufOut)
BinaryReplace(Buf,"",@lf,@false)
;BinaryWrite(Buf,"C:\TEMP\TEST.BIN") ; test
list=BinaryPeekStr(Buf,0,BinaryEodGet(Buf))
BinaryFree(Buf)
item = AskItemList("ODBC Installed Drivers",list,@lf,@unsorted,@single)
:cancel
exit
and here is a UDF to do it. This code retrieves driver information.
;----------------------------------------------------------------------------------------------------
; udfGetODBCDriverList(DriverPattern) ; DD.2001:11:13:20:40:06 ;
udfIsODBCDriverInstalled(DriverPattern) ; DD.2001:11:13:20:40:06
;----------------------------------------------------------------------------------------------------
If itemlocate("udfgetodbcdriverlist",IntControl(77,103,0,0,0),@tab) then goto skip_udfgetodbcdriverlist
#DefineFunction udfGetODBCDriverList(DriverPattern)
DriverList=""
BufMax=4000
Buf=BinaryAlloc(BufMax)
BufEod=BinaryAlloc(4)
pBufEod=IntControl(42,BufEod,0,0,0)
If DllCall("ODBCCP32.DLL",long:"SQLGetInstalledDrivers",lpbinary:Buf,long:BufMax,long:pBufEod)
BinaryEodSet(Buf,BinaryPeek4(BufEod,0)-1)
BinaryFree(BufEod)
BinaryReplace(Buf,"",@tab,@false)
DriverList=BinaryPeekStr(Buf,0,BinaryEodGet(Buf)-1)
BinaryFree(Buf)
If (DriverPattern!="")
icount=ItemCount(DriverList,@tab)
i=1
While (i<=icount)
DriverItem=ItemExtract(i,DriverList,@tab)
If !StrIndexWild(DriverItem,DriverPattern,1)
DriverList=ItemRemove(i,DriverList,@tab)
icount=icount-1
else
i=i+1
EndIf
EndWhile
EndIf
EndIf
Return (DriverList)
;udfGetODBCDriverList() returns a tab delimited list of installed ODBC drivers
; DD.20011113, Thanks to Stan Littlefield's request. ;
; this udf replaces WIL's ODBC extender routine: ;
AddExtender("wwodb34i.dll") ;
list=qDriverList() ;
#EndFunction
:skip_udfgetodbcdriverlist
If itemlocate("udfisodbcdriverinstalled", IntControl(77,103,0,0,0), @tab) then goto skip_udfisodbcdriverinstalled
#DefineFunction udfIsODBCDriverInstalled(DriverPattern)
Return(udfGetODBCDriverList(DriverPattern)!="")
#EndFunction
:skip_udfisodbcdriverinstalled
;--- test ---
item = AskItemList("ODBC Installed Drivers",udfGetODBCDriverList(""),@tab,@unsorted,@single)
; all drivers
item = AskItemList("ODBC Installed Drivers",udfGetODBCDriverList("*sql*"),@tab,@unsorted,@single)
;only SQL
item = AskItemList("ODBC Installed Drivers",udfGetODBCDriverList("*soft*"),@tab,@unsorted,@single)
; only Microsoft item = AskItemList("ODBC Installed Drivers",udfGetODBCDriverList("*DBF*"),@tab,@unsorted,@single)
;only DBF DriverPattern = "*foxpro*"
noyes=ItemExtract(udfIsODBCDriverInstalled(DriverPattern)+1,"not","")
message("Demo udfIsODBCDriverInstalled('%DriverPattern%')","Driver is %noyes%installed.")
DriverPattern = "*profox*"
noyes=ItemExtract(udfIsODBCDriverInstalled(DriverPattern)+1,"not","")
message("Demo udfIsODBCDriverInstalled('%DriverPattern%')","Driver is %noyes%installed.")
:cancel
Exit
Article ID: W15136