Yeah *sigh*, it seems like maybe there is no easy solution for the import stuff.
I'd still like to see some form of improvement on OpenLibrary() though, maybe using some flag or something.
Because I (as I said earlier) certainly test by "feature" rather than OS. (a practice MS recommends)
I try to open a dll, if it's found I check if the function is available, if it is then I use it,
if not then I either use a fallback procedure instead, or I simply do not use that feature on that particular machine.
This way a program that works on XP+ will take advantage of Vista or Win7 features when available.
And it's here that almost all the dll hijack exploits take their opportunity.
Here is a very quick example of what could be done to make OpenLibrary() "safe".
Code: Select all
Procedure.i NewOpenLibrary(library.i,filename$,safe.i=#True)
Protected result.i,path$,len.i
If safe
path$=GetPathPart(ProgramFilename()) ;Why isn't there a ProgramFilepath() ???
Debug path$+filename$
result=OpenLibrary(library,path$+filename$)
If Not result
len=GetSystemDirectory_(@path$,0) ;TCHAR + null term length is returned.
If len
path$=Space(len) ;This could be len-1 but 1 extra byte buffer doesn't hurt.
If GetSystemDirectory_(@path$,len)
Debug path$+"\"+filename$
result=OpenLibrary(library,path$+"\"+filename$)
EndIf
EndIf
If Not result ;Not sure if looking in windows directory has any purpose, it's mostly a holdover from the 16bit windows days.
len=GetWindowsDirectory_(@path$,0)
If len
path$=Space(len)
If GetWindowsDirectory_(@path$,len)
Debug path$+"\"+filename$
result=OpenLibrary(library,path$+"\"+filename$)
EndIf
EndIf
EndIf
EndIf
Else
result=OpenLibrary(library,filename$)
EndIf
ProcedureReturn result
EndProcedure
Debug NewOpenLibrary(#PB_Any,"testing.dll")
Debug ""
Debug NewOpenLibrary(#PB_Any,"dwmapi.dll")
Debug ""
Debug NewOpenLibrary(#PB_Any,"kernel32.dll")
I'm not sure looking in c:\windows\ for a dll makes much sense, on my Win7 I only got twain.dll there and I get an error trying to open it. (16bit?)
But looking in the program exe's path and system32 and failing if not found in either seems safe enough.
In this example I choose to look in the program's path first (to allow overriding support or using older versions of a dll, to avoid "dll hell").
(PS! if a x86 program is run on a 64bit system then system32 is secretly redirected to SysWOW64, it'll still show as system32 though)
To use the old OpenLibrary() behavior just specify #False.
setting the safe flag to False is also of use when using explicit/full paths.
I guess I could have made this more advanced by automatically detecting if you gave, a full path, or a relative path, or no path,
and behaved 3 different ways, but this was just a quick example.
I.e:
If full path is given it should just try the full path, and succeed or fail.
If relative path is given it should just try relative to the programs path, and succeed or fail.
If no path is given it should try the programs path and if fail it will then try the system32 path, and succeed or fail.
You can't get much safer than that if OpenLibrary() behaved like that by default.
Is this reasonable Fred?