自從會vb用調(diào)用動態(tài)庫函數(shù)以來,我一直在想:如何動態(tài)的調(diào)用dll里的函數(shù)?網(wǎng)上有一個用CallWindowProc函數(shù)的方法,不過我還是喜歡自己有個
辦法.今天工夫不負有心人,我終于把我心中一直想的辦法給實現(xiàn)了,干脆就往自己的空間上貼吧.錯誤的地方,希望可以得到有這方面的師傅給以
指正,以求進步!對于系統(tǒng)api我沒有嘗試,如果調(diào)用約定相符,應(yīng)該適用于對系統(tǒng)api的調(diào)用. 我自己用c寫個dll,然后在vb里寫了這個類. 以下代碼只是我簡單的實現(xiàn),主要的是看實現(xiàn)的道理. vc代碼: /// '我把dll文件名命名為:dll #include <Windows.h> #include <stdlib.h> #include <string.h> #include 'stdafx.h'
BOOL APIENTRY DllMain( HANDLE hModule, DWORD ul_reason_for_call, LPVOID lpReserved ) { return TRUE; }
extern 'C' BOOL _declspec(dllexport) add(int a) { MessageBoxA(NULL,'運行在dll里!','成功',MB_OK); a=999; return 1; } /// vb代碼: '''''''''''''''''''''''''''''''''''''''''''''''''''''''''' '類代碼: Private 狀態(tài)標志 As Boolean Private 模塊句柄 As Long Private 本地函數(shù)地址備份(0 To 4) As Byte Private 被替換函數(shù)的地址 As Long
Public Function 替換函數(shù)地址(模塊名 As String, 函數(shù)名 As String, 本地函數(shù)地址 As Long) As Boolean If 0 = 本地函數(shù)地址 Then 替換函數(shù)地址 = 0 Exit Function End If 被替換函數(shù)的地址 = 替換函數(shù)地址 Dim 函數(shù)地址 As Long Dim a As Long Dim 跳轉(zhuǎn)指令(0 To 4) As Byte '加載模塊 模塊句柄 = LoadLibrary(模塊名) If 0 <> 模塊句柄 Then '狀態(tài)標志 = 1 Else: 替換函數(shù)地址 = 0 Exit Function End If '檢索函數(shù)地址 函數(shù)地址 = GetProcAddress(ByVal 模塊句柄, ByVal 函數(shù)名) If 0 <> 函數(shù)地址 Then '狀態(tài)標志 = 1 Else 替換函數(shù)地址 = 0 Exit Function End If '計算跳轉(zhuǎn)地址 a = 函數(shù)地址 - (本地函數(shù)地址 + 5) '構(gòu)造跳轉(zhuǎn)地址 跳轉(zhuǎn)指令(0) = 233 a = WriteProcessMemory(-1, ByVal VarPtr(跳轉(zhuǎn)指令(1)), ByVal VarPtr(a), 4, 0) If 0 = a Then 替換函數(shù)地址 = 0 Exit Function End If '先備份本地函數(shù)入口指令 a = WriteProcessMemory(-1, ByVal VarPtr(本地函數(shù)地址備份(0)), ByVal 本地函數(shù)地址, 5, 0) If 0 = a Then 替換函數(shù)地址 = 0 Exit Function End If '寫入跳轉(zhuǎn)指令 a = WriteProcessMemory(-1, ByVal 本地函數(shù)地址, ByVal VarPtr(跳轉(zhuǎn)指令(0)), 5, 0) If 0 = a Then 替換函數(shù)地址 = 0 Exit Function Else: 狀態(tài)標志 = 1 替換函數(shù)地址 = 1 End If End Function
Public Function 還原函數(shù)地址() As Boolean
If 0 = 狀態(tài)標志 Then 還原函數(shù)地址 = 0 Exit Function End If Dim a As Long a = WriteProcessMemory(-1, ByVal 被替換函數(shù)的地址, ByVal VarPtr(本地函數(shù)地址備份(0)), 5, 0) If 0 = a Then 還原函數(shù)地址 = 0 Exit Function Else: 狀態(tài)標志 = 0 還原函數(shù)地址 = 1 End If FreeLibrary 模塊句柄 End Function
Public Function 當(dāng)前狀態(tài)() As Boolean 當(dāng)前狀態(tài) = 狀態(tài)標志 End Function ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' 'vb普通模塊代碼: '讀寫內(nèi)存的api函數(shù) Public Declare Function WriteProcessMemory Lib 'kernel32' (ByVal hProcess As Long, ByVal _ lpBaseAddress As Any, lpBuffer As Any, ByVal nSize As Long, lpNumberOfBytesWritten As Long) As Long
'加載模塊的api函數(shù) Public Declare Function LoadLibrary Lib 'kernel32' Alias 'LoadLibraryA' (ByVal lpLibFileName As String) As Long
'檢索模塊里函數(shù)地址的api函數(shù) Public Declare Function GetProcAddress Lib 'kernel32' (ByVal hModule As Long, ByVal lpProcName As String) As Long
' Public Declare Function FreeLibrary Lib 'kernel32' (ByVal hLibModule As Long) As Long
'模擬一個函數(shù)與dll里,我們想調(diào)用函數(shù)類型和參數(shù)一致, 用類將函數(shù)的地址替換 Public Function 測試函數(shù)(參數(shù) As Long) As Boolean '我們隨便給返回0,因為這個指令將不會被程序執(zhí)行到 測試函數(shù) = 0 End Function ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' 'vb窗口模塊代碼: Private Sub Form_Load() Dim 模塊名 As String, 函數(shù)名 As String 模塊名 = App.Path + '/dll.dll' '模塊名現(xiàn)在可以自己定了,自由了! 函數(shù)名 = 'add' Dim p As Boolean Dim aa As New Class1 p = aa.替換函數(shù)地址(模塊名, 函數(shù)名, AddressOf 測試函數(shù)) If p Then 測試函數(shù) 0 '將會彈出對話筐:運行在dll里! aa.還原函數(shù)地址 End If End Sub '''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
|