Dll代码里没有DllMain函数,为什么也能生成DLL啊??我正在看王艳平《windows程序》我看的是他的第一版,第九章《动态链接库和钩子》,9.3.5 Hook实例---进程保护器,这个例子是创建了 一个dll,dll包含了Jeffrey Richter写的CAPIHook类了(这个不是重点)王艳平的dll的代码里面,没有DllMain函数,我尝试过了,他的代码是可以生成dll的,VC 6没有报错。书上不是说,每个dll里面要有DllMain吗??为什么能通过啊?? 希望大家能解决我的疑问啊。
//////////////////////////////////////////////////
// HookTermProLib.cpp文件
#include <windows.h>
#include "APIHook.h" //CAPIHook类的头文件extern CAPIHook g_TerminateProcess;// 自定义TerminateProcess函数
BOOL WINAPI Hook_TerminateProcess(HANDLE hProcess, UINT uExitCode)
{
typedef BOOL (WINAPI *PFNTERMINATEPROCESS)(HANDLE, UINT); // 取得主模块的文件名称
char szPathName[MAX_PATH];
::GetModuleFileName(NULL, szPathName, MAX_PATH); // 构建发送给主窗口的字符串
char sz[2048];
wsprintf(sz, "\r\n 进程:(%d)%s\r\n\r\n 进程句柄:%X\r\n 退出代码:%d",
::GetCurrentProcessId(), szPathName, hProcess, uExitCode); // 发送这个字符串到主对话框
COPYDATASTRUCT cds = { ::GetCurrentProcessId(), strlen(sz) + 1, sz };
if(::SendMessage(::FindWindow(NULL, "进程保护器"), WM_COPYDATA, 0, (LPARAM)&cds) != -1)
{
// 如果函数的返回值不是-1,我们就允许API函数执行
return ((PFNTERMINATEPROCESS)(PROC)g_TerminateProcess)(hProcess, uExitCode);
}
return TRUE;
}// 挂钩TerminateProcess函数
CAPIHook g_TerminateProcess("kernel32.dll", "TerminateProcess",
(PROC)Hook_TerminateProcess);
///////////////////////////////////////////////////////////////////////////#pragma data_seg("YCIShared")
HHOOK g_hHook = NULL;
#pragma data_seg()static HMODULE ModuleFromAddress(PVOID pv)
{
MEMORY_BASIC_INFORMATION mbi;
if(::VirtualQuery(pv, &mbi, sizeof(mbi)) != 0)
{
return (HMODULE)mbi.AllocationBase;
}
else
{
return NULL;
}
}static LRESULT WINAPI GetMsgProc(int code, WPARAM wParam, LPARAM lParam)
{
return ::CallNextHookEx(g_hHook, code, wParam, lParam);
}BOOL WINAPI SetSysHook(BOOL bInstall, DWORD dwThreadId)
{
BOOL bOk;
if(bInstall)
{
g_hHook = ::SetWindowsHookEx(WH_GETMESSAGE, GetMsgProc,
ModuleFromAddress(GetMsgProc), dwThreadId);
bOk = (g_hHook != NULL);
}
else
{
bOk = ::UnhookWindowsHookEx(g_hHook);
g_hHook = NULL;
}
return bOk;
}
//////////////////////////////////////////////////
// HookTermProLib.cpp文件
#include <windows.h>
#include "APIHook.h" //CAPIHook类的头文件extern CAPIHook g_TerminateProcess;// 自定义TerminateProcess函数
BOOL WINAPI Hook_TerminateProcess(HANDLE hProcess, UINT uExitCode)
{
typedef BOOL (WINAPI *PFNTERMINATEPROCESS)(HANDLE, UINT); // 取得主模块的文件名称
char szPathName[MAX_PATH];
::GetModuleFileName(NULL, szPathName, MAX_PATH); // 构建发送给主窗口的字符串
char sz[2048];
wsprintf(sz, "\r\n 进程:(%d)%s\r\n\r\n 进程句柄:%X\r\n 退出代码:%d",
::GetCurrentProcessId(), szPathName, hProcess, uExitCode); // 发送这个字符串到主对话框
COPYDATASTRUCT cds = { ::GetCurrentProcessId(), strlen(sz) + 1, sz };
if(::SendMessage(::FindWindow(NULL, "进程保护器"), WM_COPYDATA, 0, (LPARAM)&cds) != -1)
{
// 如果函数的返回值不是-1,我们就允许API函数执行
return ((PFNTERMINATEPROCESS)(PROC)g_TerminateProcess)(hProcess, uExitCode);
}
return TRUE;
}// 挂钩TerminateProcess函数
CAPIHook g_TerminateProcess("kernel32.dll", "TerminateProcess",
(PROC)Hook_TerminateProcess);
///////////////////////////////////////////////////////////////////////////#pragma data_seg("YCIShared")
HHOOK g_hHook = NULL;
#pragma data_seg()static HMODULE ModuleFromAddress(PVOID pv)
{
MEMORY_BASIC_INFORMATION mbi;
if(::VirtualQuery(pv, &mbi, sizeof(mbi)) != 0)
{
return (HMODULE)mbi.AllocationBase;
}
else
{
return NULL;
}
}static LRESULT WINAPI GetMsgProc(int code, WPARAM wParam, LPARAM lParam)
{
return ::CallNextHookEx(g_hHook, code, wParam, lParam);
}BOOL WINAPI SetSysHook(BOOL bInstall, DWORD dwThreadId)
{
BOOL bOk;
if(bInstall)
{
g_hHook = ::SetWindowsHookEx(WH_GETMESSAGE, GetMsgProc,
ModuleFromAddress(GetMsgProc), dwThreadId);
bOk = (g_hHook != NULL);
}
else
{
bOk = ::UnhookWindowsHookEx(g_hHook);
g_hHook = NULL;
}
return bOk;
}
其实,DllMain和你写的其他DLL暴露的函数一样,只是一个函数入口地址而已。
第一贴里面有详细的代码了CAPIHook是个全局对象,在extern CAPIHook g_TerminateProcess; 这一句已经申明了
后面有个初始化 :// 挂钩TerminateProcess函数
CAPIHook g_TerminateProcess("kernel32.dll", "TerminateProcess",
(PROC)Hook_TerminateProcess);再看他的代理函数,(代理结束进程的函数TerminateProcess),代码如下:
// 自定义TerminateProcess函数
BOOL WINAPI Hook_TerminateProcess(HANDLE hProcess, UINT uExitCode)
{
typedef BOOL (WINAPI *PFNTERMINATEPROCESS)(HANDLE, UINT);// 取得主模块的文件名称
char szPathName[MAX_PATH];
::GetModuleFileName(NULL, szPathName, MAX_PATH);// 构建发送给主窗口的字符串
char sz[2048];
wsprintf(sz, "\r\n 进程:(%d)%s\r\n\r\n 进程句柄:%X\r\n 退出代码:%d",
::GetCurrentProcessId(), szPathName, hProcess, uExitCode);// 发送这个字符串到主对话框
COPYDATASTRUCT cds = { ::GetCurrentProcessId(), strlen(sz) + 1, sz };
if(::SendMessage(::FindWindow(NULL, "进程保护器"), WM_COPYDATA, 0, (LPARAM)&cds) != -1)
{
// 如果函数的返回值不是-1,我们就允许API函数执行
return ((PFNTERMINATEPROCESS)(PROC)g_TerminateProcess)(hProcess, uExitCode);
}return TRUE;
}return ((PFNTERMINATEPROCESS)(PROC)g_TerminateProcess)(hProcess, uExitCode);
这一句代码中有个g_TerminateProcess和我们的全局对象重名了,是怎么回事啊??
按照上下文理解,这句代码应该是调用系统本身的API TerminateProcess 函数啊,是怎么调用的啊??
大牛,希望帮忙解决一下啊。谢谢啊。
如果不显式规定入口点,vc的dll入口点是_DllMainCRTStartup,在这里会执行crt初始化,全局对象的创建等工作
还有那种纯资源DLL,更是没啥可干的。