Windows下 DLL Main 函数详解

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
BOOL APIENTRY DllMain( HMODULE hModule,
                       DWORD  ul_reason_for_call,
                       LPVOID lpReserved)
{
	switch (ul_reason_for_call)
	{
	case DLL_PROCESS_ATTACH:
		HookMyAttack();
		break;
	case DLL_THREAD_ATTACH:
	case DLL_THREAD_DETACH:
	case DLL_PROCESS_DETACH:
		break;
	}
	return TRUE;
}

进程映射 - DLL_PROCESS_ATTACH

大家都知道,一个程序要调用Dll里的函数,首先要先把DLL文件映射到进程的地址空间。要把一个DLL文件映射到进程的地址空间,有两种方法:静态链接和动态链接的LoadLibrary或者LoadLibraryEx,另外还可以通过注入方式来进行加载。 当一个DLL文件被映射到进程的地址空间时,系统调用该DLL的DllMain函数,传递的fdwReason参数为DLL_PROCESS_ATTACH,这种调用只会发生在第一次映射时。如果同一个进程后来为已经映射进来的DLL再次调用LoadLibrary或者LoadLibraryEx,操作系统只会增加DLL的使用次数,它不会再用DLL_PROCESS_ATTACH调用DLL的DllMain函数。不同进程用LoadLibrary同一个DLL时,每个进程的第一次映射都会用DLL_PROCESS_ATTACH调用DLL的DllMain函数。 可参考DllMainTest的DLL_PROCESS_ATTACH_Test函数。

C++ Primer 例题不严谨导致的错误

1.该例题出自于6.7节的While的循环的使用(P178页)

1
2
3
4
5
6
7
8
9
int arr1[5]={0,1,2,3,4};
int *source=arr1;
size_t sz = sizeof(arr1)/sizeof(*arry1);
int *dest=new int[sz](0);
while(source != arr1+sz)
{
        *dest++=*source++;
} 
delete []dest; // 错误代码

注意,最后一句调用将会出现运行时错误,因为现在dest指针指向的是dest[5],即第6个不存在的元素,如果现在使用delete删除dest指向的数组的话,将会删除未知的内存位置,解决办法是使用一个临时变量来保存dest指针的初始位置。

函数入栈顺序

约定 入栈顺序 函数类型 _cdecl 右→左 母函数 _fastcall 右→左 子函数 _stdcall 右→左 子函数 如果不指定调用约定的话,默认为_stdcall函数调用函数顺序 参数从右到左依次入栈。 返回地址入栈:将当前代码下一条指令入栈,以确保返回后能够继续执行余下指令。 代码区跳转:CPU将当前代码跳转到函数区域。 栈帧调整。 如: 1 2 3 4 5 6 7 push3;函数参数从右到左依次入栈push2 push 1 call 函数地址; 向当前栈压入当前所在地址;跳转 push ebp;保存旧栈底部 movebp,esp;设置新栈底部 sub ebp,XXX;设置栈顶

sqlite3_exec()函数引发的血案

我们首先来看看sqlite3_exec()函数的原型:

1
2
3
4
5
6
7
SQLITE_API int SQLITE_STDCALL sqlite3_exec(
  sqlite3*,                                  /* An open database */
  const char *sql,                           /* SQL to be evaluated */
  int (*callback)(void*,int,char**,char**),  /* Callback function */
  void *,                                    /* 1st argument to callback */
  char **errmsg                              /* Error msg written here */
);

第一个参数是打开sqlite3数据库句柄,第二个参数是你要执行的sql语句,第三个参数是每次查询所调用的回调函数,第四个参数是我们传入的参数,假如说我们在回调函数中找到了我们需要的数据,那么我们就可以通过这个指针来反馈给我们的调用者,第五个参数是调用sqlite3_exec发生错误时候的描述。

Built with Hugo
主题 StackJimmy 设计