Attribute VB_Name = "ModUnloadModule"
Option Explicit
Option Compare Text
'
'卸载进程中指定的模块,需要ModLzOpenProcess.bas与ModGetMod.bas模块配合
'
'由 嗷嗷叫的老马 摘于网络并简单修改
'http://www.m5home.com/
'
Private Const STANDARD_RIGHTS_REQUIRED As Long = &HF0000
Private Const SYNCHRONIZE As Long = &H100000
Private Const PROCESS_ALL_ACCESS As Long = (STANDARD_RIGHTS_REQUIRED Or SYNCHRONIZE Or &HFFF)

Private Declare Function OpenProcess Lib "kernel32.dll" ( _
     ByVal dwDesiredAccess As Long, _
     ByVal bInheritHandle As Long, _
     ByVal dwProcessId As Long) As Long
Private Declare Function NtUnmapViewOfSection Lib "NTDLL.DLL" ( _
     ByVal ProcessHandle As Long, _
     ByVal BaseAddress As Long) As Long
Private Declare Function ZwClose Lib "NTDLL.DLL" ( _
     ByVal ObjectHandle As Long) As Long

Public Function UnloadModule(ByVal hPid As Long, ByRef ModNameOrModHandle As Variant) As Long
    'hPid:                  目标模块所在进程的PID
    'ModNameOrModHandle:    要卸载的模块名称或模块句柄
    '
    '返回值:
    '       成功返回非零,失败返回零.
    '
    Dim hProcess As Long
    Dim hMod As Long
    Dim sMod() As String, tmphMod() As Long
    Dim I As Long
    
    hProcess = OpenProcess(PROCESS_ALL_ACCESS, False, hPid)
    If hProcess = 0 Then
        hProcess = LzOpenProcess(PROCESS_ALL_ACCESS, hPid)
    End If
    If hProcess = 0 Then Exit Function
    
    Select Case VarType(ModNameOrModHandle)     '原流传的代码使用GetModuleHandle来取得目标模块句柄,缺点是不能卸载非系统模块,因为只有系统模块的地址才是每个进程相同的.
        Case vbString                           '传入模块名称的情况下,枚举目标进程的模块,并匹配传入的模块名,得到其模块句柄,需要ModGetMod.bas模块配合
            Call EnumModuleByhProcess(hProcess, sMod(), tmphMod())
            For I = 0 To UBound(tmphMod)
                If sMod(I) = ModNameOrModHandle Then
                    hMod = tmphMod(I)
                    Exit For
                End If
            Next
        Case vbLong                             '传入模块句柄的情况下直接使用
            hMod = ModNameOrModHandle
        Case Else
            GoTo errH
    End Select
    If hMod = 0 Then GoTo errH
    
    NtUnmapViewOfSection hProcess, hMod
    UnloadModule = hProcess
errH:
    ZwClose hProcess
End Function
