When your MS Access 97 application consists of several library MDE files you soon meet with the following problem:
- you have realeased v.1.00 to your client ;
- your client has found a bug in your release ;
- you check your sources and fix the bug - you only edit one line of code, don't change any functions'/subs' definitions etc.;
- you're lucky enough - the bug was located only in one of the library/component MDE files which you delivered to your client in v.1.00 ;
- your client cannot wait, he wants your fix immediately and you e-mail him just a fixed MDE;
- several hours later your client calls you and says that when he starts the app he gets an error message: "The expression you entered has a function name that Microsoft Access can't find"
What is the problem ?
As I've found, the problem is in that MS Access 97 stores GUID of library MDE file in an MDE file which has reference to this library MDE. When you recompile library/component MDE file you have to recompile all the MDE files which have references to these library/component MDEs. If you don't do that you get "The expression you entered has a function name that Microsoft Access can't find" error message or (in the case you changed function definitions, quantity or sequence of functions in modules, added a new module, i.e. you somehow changed interfaces of library mde files) you get GPF :(
But maybe it is possible to "fool" MS Access to solve the problem described in legend of this topic? Yes, it is possible and the code presented here does the trick but I don't recommend to use it in mission-critical real-life projects:
Option Compare Database
Option Explicit
Private Const BYTE_SIZE = 32568
Private Const PATCH_STR_OFFSET = 32 ' starts from 0
Private Const PATCH_STR_LEN = 16 '
Private Const SHOULDBEZERO_OFFSET = 27
Private Const SHOULDNTBE_FF_OFFSET = 75
Public Function TestOfTrick()
Dim strBaseMDEPath As String
Dim strMdeToPatchPath As String
strBaseMDEPath = "c:\tst\lib_old.mde"
strMdeToPatchPath = "c:\tst\lib.mde"
MsgBox smsMDELibPatch(strBaseMDEPath, strMdeToPatchPath)
End Function
Public Function smsMDELibPatch(ByVal vstrBaseMdePath As String, _
ByVal vstrMdeToPatchPath As String, _
Optional ByVal vlngStartOffset As Long = 1) As Boolean
Dim lngBaseSignatureOffset As Long
Dim strBaseSignature As String
Dim lngMdeToPatchSignatureOffset As Long
Dim strMdeToPatchSignature As String
smsMDELibPatch = False
lngBaseSignatureOffset = smsSignatureFind(vstrBaseMdePath, strBaseSignature)
If lngBaseSignatureOffset = 0 Then
MsgBox "Base signature not found in " & vstrBaseMdePath
Else
lngMdeToPatchSignatureOffset = smsSignatureFind(vstrMdeToPatchPath, strMdeToPatchSignature, vlngStartOffset)
If lngMdeToPatchSignatureOffset = 0 Then
MsgBox "Target signature not found in " & vstrMdeToPatchPath
Else
Dim i As Integer
For i = 1 To PATCH_STR_LEN
PatchByte vstrMdeToPatchPath, _
PATCH_STR_OFFSET + lngMdeToPatchSignatureOffset + i, _
CByte(Asc(Mid(strBaseSignature, i, 1)))
Next i
smsMDELibPatch = True
End If
End If
End Function
Public Function smsSignatureDebugPrint(ByVal vstrMdePath As String, _
Optional ByVal vlngStartPos As Long = 1) As Long
Dim intFn As Integer
Dim strbuf As String * BYTE_SIZE
Dim strSignature As String
Dim lngPos As Long
Dim lngBlocksRead As Long
Dim lngOffset As Long
Dim iii As Integer
Dim jjj As Integer
smsSignatureDebugPrint = 0
strSignature = smsSignatureSet()
intFn = FreeFile
Open vstrMdePath For Binary Access Read Shared As #intFn Len = BYTE_SIZE
lngOffset = vlngStartPos - 1
If lngOffset <> 0 Then
Seek intFn, lngOffset + 1
End If
lngBlocksRead = 1
While Not EOF(intFn)
Get intFn, , strbuf
lngPos = InStr(1, strbuf, strSignature)
If lngPos <> 0 Then
'If Asc(Mid(strbuf, lngPos + SHOULDBEZERO_OFFSET, 1)) = 0 Then
'If Asc(Mid(strbuf, lngPos + SHOULDNTBE_FF_OFFSET, 1)) <> &HFF Then
'If Asc(Mid(strbuf, lngPos + SHOULDNTBE_FF_OFFSET, 1)) = &HFF Then
Debug.Print "Filepath = " & vstrMdePath
Debug.Print "BlocksRead = " & lngBlocksRead
Debug.Print "FileOffset = " & lngOffset + lngPos - 1 & "(10), " & smsHex(lngOffset + lngPos - 1) & "(16)"
For iii = 0 To 79 + 16 + 16 + 16 + 16 + 16 + 16
If iii Mod 16 = 0 Then
Debug.Print smsHex(iii, 8) & ": ";
For jjj = 0 To 15
Debug.Print smsHex(Asc(Mid(strbuf, lngPos + iii + jjj, 1))) & " ";
Next jjj
Debug.Print
End If
Next iii
'End If
'End If
smsSignatureDebugPrint = lngOffset + lngPos - 1
GoTo smsSignatureDebugPrint_exit
End If
lngOffset = lngOffset + BYTE_SIZE
lngBlocksRead = lngBlocksRead + 1
Wend
smsSignatureDebugPrint_exit:
Close #intFn
End Function
Public Function smsSignatureFind(ByVal vstrMdePath As String, _
ByRef vstrSignature As String, _
Optional ByVal vlngStartOffset As Long = 1) As Long
Dim intFn As Integer
Dim strbuf As String * BYTE_SIZE
Dim strSignature As String
Dim lngPos As Long
Dim lngBlocksRead As Long
Dim lngOffset As Long
smsSignatureFind = 0
vstrSignature = ""
strSignature = smsSignatureSet()
intFn = FreeFile
Open vstrMdePath For Binary Access Read Shared As #intFn Len = BYTE_SIZE
lngOffset = vlngStartOffset - 1
lngBlocksRead = 1
If lngOffset <> 0 Then
Seek #intFn, lngOffset + 1
End If
While Not EOF(intFn)
Get intFn, , strbuf
lngPos = InStr(1, strbuf, strSignature)
If lngPos <> 0 Then
'If Asc(Mid(strbuf, lngPos + SHOULDBEZERO_OFFSET, 1)) = 0 Then
If Asc(Mid(strbuf, lngPos + SHOULDNTBE_FF_OFFSET, 1)) <> &HFF Then
vstrSignature = Mid(strbuf, lngPos + PATCH_STR_OFFSET, PATCH_STR_LEN)
smsSignatureFind = lngOffset + lngPos - 1
GoTo smsSignatureFind_Exit
End If
'End If
End If
lngOffset = lngOffset + BYTE_SIZE
lngBlocksRead = lngBlocksRead + 1
Wend
smsSignatureFind_Exit:
Close #intFn
End Function
Public Function PatchByte(ByVal vstrFilePath As String, _
ByVal vlngOffset As Long, _
ByVal vbytValue As Byte)
Dim intFn As Integer
intFn = FreeFile
Open vstrFilePath For Binary Access Write As #intFn
Put #intFn, vlngOffset, vbytValue
Close intFn
End Function
Private Function smsHex(ByVal vvar As Variant, Optional ByVal intOutputLen As Integer = 2)
Dim strRet As String
strRet = Hex(vvar)
If Len(strRet) = 0 Then
smsHex = "??"
ElseIf Len(strRet) < intOutputLen Then
smsHex = String(intOutputLen - Len(strRet), "0") & strRet
Else
smsHex = strRet
End If
End Function
Private Function smsSignatureSet() As String
Dim strSignature As String
'00 - 7f
''''strSignature = strSignature & Chr(&H7F) - isn't present sometimes !!!
'01 - 00 - four times
strSignature = strSignature & Chr(&H0)
strSignature = strSignature & Chr(&H0)
strSignature = strSignature & Chr(&H0)
strSignature = strSignature & Chr(&H0)
'05 - 13, Acc2000 0E
strSignature = strSignature & Chr(&H13)
'06 - 00 - three times
strSignature = strSignature & Chr(&H0)
strSignature = strSignature & Chr(&H0)
strSignature = strSignature & Chr(&H0)
'09 - 09
strSignature = strSignature & Chr(&H9)
'10 - 00 - five times
strSignature = strSignature & Chr(&H0)
strSignature = strSignature & Chr(&H0)
strSignature = strSignature & Chr(&H0)
strSignature = strSignature & Chr(&H0)
strSignature = strSignature & Chr(&H0)
'15 - 01
strSignature = strSignature & Chr(&H1)
'16 - 00
strSignature = strSignature & Chr(&H0)
'17 - 08
strSignature = strSignature & Chr(&H8)
'18 - 00 - seven times
strSignature = strSignature & Chr(&H0)
strSignature = strSignature & Chr(&H0)
strSignature = strSignature & Chr(&H0)
strSignature = strSignature & Chr(&H0)
strSignature = strSignature & Chr(&H0)
strSignature = strSignature & Chr(&H0)
strSignature = strSignature & Chr(&H0)
'25 - B9 02
'27 - (00)(6 times)
'
'33 - 5 bytes to patch
'
'38 - Another five bytes
'
'43 - And Another six bytes
'
' Tail of signature ???
'49 - 00 00
'51 - 09 04
'53 - 00 00
'55 - 19 04
'57 - 00 00
'59 - E3 04
'61 - 00 00 00 00 00 00
'67 - <byte> 00 <byte1 = byte> ...
smsSignatureSet = strSignature
End Function
| HOME TOPICS |
Copyright © 19981999 by Shamil Salakhetdinov.
|
| Last updated: June 7, 1999
Published also here at 4TOPS: Patching GUID of MDE files |
|