Archive: Detect if Dll is wrong version


Detect if Dll is wrong version
Hi,

I have a software that depends on dbghelp.dll to work properly.

I've found out that on previous operating system, that dll wasn't available (Win98). So I've written a routine that see if the dll is available and if it's not, it download it from my server and put it in the installation direction.

The problem I have run into is that on Windows 2000, the debghelp.com is there but do not support the MiniDumpWriteDump function.

How can I verify if that function is supported so that I can download the dll if it's not?

Here's how I detect if the dll is available:

System::Call 'kernel32::LoadLibrary(t "dbghelp.dll") i .r1'
IntCmp $1 0 NoFoundIt NoFoundIt FoundIt

Can anyone help me?

Thanks,

Karl



; ################################################################
; output on stack (get with pop):
; "0": WFP not available, error calling WFP, file not existing or file not protected
; "1": WFP enabled and protecting the file and file exists
; example: !insertmacro FileProtectedByWfp "c:\windows\system32\kernel32.dll" DetailPrint
; Pop $0 ; get result
; attention: LOGLINE must not be an Rx register, you can use ";" to disable logging
!macro FileProtectedByWfp FILENAME LOGLINE
!define Index_FileProtectedByWfp 'FileProtectedByWfp_Line${__LINE__}'
Push $R0
Push $R1
Push $R2
Push $R3
; we must copy ${FILENAME} to register first (think about calling this macro with argument $R0)
StrCpy $R1 "${FILENAME}" ; copy file name to $R1
StrCpy $R0 "0" ; init return value
IfFileExists "$R1" 0 ${Index_FileProtectedByWfp}-missing
System::Call `sfc::SfcIsFileProtected(i, w) i(0,R1).R2 ? e`
Pop $R3 ; dll error code
StrCmp $R2 "error" ${Index_FileProtectedByWfp}-callerror
; sfc is running (windows 2000 and newer)
StrCmp $R2 "0" 0 ${Index_FileProtectedByWfp}-fileprotected
; check getlasterror
StrCmp $R3 "2" ${Index_FileProtectedByWfp}-notprotected
; function could be called but unknown dll error occured (failed)
${LOGLINE} "FileProtectedByWFP: unknown error $R3 calling SfcIsFileProtected for $R1"
; debug MessageBox MB_OK "FileProtectedByWFP: unknown error $R3 calling SfcIsFileProtected for $R1"
goto ${Index_FileProtectedByWfp}-finish
${Index_FileProtectedByWfp}-notprotected:
${LOGLINE} "FileProtectedByWFP: file $R1 is not protected"
; debug MessageBox MB_OK "FileProtectedByWFP: file $R1 is not protected"
goto ${Index_FileProtectedByWfp}-finish
${Index_FileProtectedByWfp}-fileprotected:
${LOGLINE} "FileProtectedByWFP: file $R1 is protected"
; debug MessageBox MB_OK "FileProtectedByWFP: file $R1 is protected"
StrCpy $R0 "1" ; file $R1 is protected!
goto ${Index_FileProtectedByWfp}-finish
${Index_FileProtectedByWfp}-missing:
${LOGLINE} "FileProtectedByWFP: file $R1 not found"
; debug MessageBox MB_OK "FileProtectedByWFP: file $R1 not found"
StrCpy $R0 "0"
goto ${Index_FileProtectedByWfp}-finish
${Index_FileProtectedByWfp}-callerror:
${LOGLINE} "FileProtectedByWFP: error $R3 calling SfcIsFileProtected for $R1"
; debug MessageBox MB_OK "FileProtectedByWFP: error $R3 calling SfcIsFileProtected for $R1"
StrCpy $R0 "0"
goto ${Index_FileProtectedByWfp}-finish
${Index_FileProtectedByWfp}-finish:
Pop $R3
Pop $R2
Pop $R1
Exch $R0
!undef Index_FileProtectedByWfp
!macroend

; ################################################################
; example: !insertmacro CheckFileVersionUpToDate "local\mydll.dll" "$SYSDIR\mydll.dll" ";"
; Pop $0 ; getresult
; returns 2 if the file is up to date (or a even newer version is already installed)
; returns 1 if the file is not up to date but cannot be updated due to Windows File Protection
; returns 0 if the file is missing or not up to date and can/should be updated
;
; you can use ";" for LOGLINE for no logging or some other command displaying or logging details
!macro CheckFileVersionUpToDate LOCALFILE TARGETFILE LOGLINE
!define Index_CheckFileVersionUpToDate 'CheckFileVersionUpToDate_Line${__LINE__}'
Push $R0 ; result
Push $R1
Push $R2
Push $R3
Push $R4

StrCpy $R0 "0"
GetDLLVersionLocal "${LOCALFILE}" $R1 $R2
${LOGLINE} "${LOCALFILE} version $R1 $R2"
IfFileExists "${TARGETFILE}" 0 ${Index_CheckFileVersionUpToDate}-finish
ClearErrors
${LOGLINE} "check ${TARGETFILE}..."
GetDllVersion "${TARGETFILE}" $R3 $R4
IfErrors ${Index_CheckFileVersionUpToDate}-finish
${LOGLINE} "${TARGETFILE} version $R3 $R4"
IntCmpU $R1 $R3 0 +2 ${Index_CheckFileVersionUpToDate}-checkWFP
IntCmpU $R2 $R4 0 0 ${Index_CheckFileVersionUpToDate}-checkWFP

; obviously installed version is up to date (or even newer)
StrCpy $R0 "2"
Goto ${Index_CheckFileVersionUpToDate}-finish
${Index_CheckFileVersionUpToDate}-checkWFP:
!insertmacro FileProtectedByWfp "${TARGETFILE}" "${LOGLINE}"
Pop $R0
; 0 => file is not protected or does not exist
; 1 => file is protected
StrCmp $R0 "1" 0 ${Index_CheckFileVersionUpToDate}-finish
${LOGLINE} "${TARGETFILE} wfp"
${Index_CheckFileVersionUpToDate}-finish:
; MessageBox MB_OK "$R0 # ${TARGETFILE} $R3 $R4 ${LOCALFILE} $R1 $R2 "
ClearErrors
Pop $R4
Pop $R3
Pop $R2
Pop $R1
Exch $R0 ; result zurückgeben
!undef Index_CheckFileVersionUpToDate
!macroend

CheckFileVersionUpToDate is the main macro

If you do not know where the DLL is located you could search PATH directories, but I would not recommend this.

But if this is a legacy DLL (no COM) then I would perhaps check if it is installed in the default location (probably SYSDIR) and install your DLL in INSTALLDIR.


Thanks for your suggestion,

Here's how I ended solving my problem...

After calling LoadLibrary, I call:

System::Call "kernel32::GetModuleHandle(t 'dbghelp.dll') i .s"
System::Call "kernel32::GetProcAddress(i s, t 'MiniDumpWriteDump') i .r2"

The I do
IntCmp $2 0 NoFoundIt NoFoundIt DbgDone

If the ProcAddress is not found, I know this is the wrong version of DbgHelp that is on that operating system.

Regard,

Karl