《Windows核心编程》学习笔记(3)– 程序入口函数
2011-08-08 16:46
316 查看
1. 进程实例句柄
加载到进程地址空间的每一个可执行文件或者dll文件都被赋予了一个独一无二的实例句柄.
他实际上是一个内存基地址,系统将可执行程序的映像加载到进程地址空间中的这个位置。
Ps :
HMODULE和 HINSTANCE
其实就是一回事.
获得一个可执行文件或者dll文件的句柄/基地址:
(1)GetModuleHandle函数
HMODULE GetModuleHandle( LPCTSTR lpModuleName );
调用这个函数时,参数指定了已在主调进程的地址空间中加载的一个可执行文件或者DLL文件的名称。或者参数为NULL时,会返回主调函数的可执行文件的基地址。
(2)GetModuleHandleEx 函数
BOOL WINAPI GetModuleHandleEx(
__in DWORD dwFlags,
__in LPCTSTR lpModuleName,
__out HMODULE* phModule
);
将GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS作为他的第一个参数,将当前函数的地址作为第二个参数,最后一个参数是一个指向HMODULE的指针,GetModuleHandleEx函数会用传入函数(既第二个参数)所在DLL的基地址来填写该指针.
(3)利用链接器提供的为变量__ImageBase,他指向当前正在运行的模块的基地址.
例如:
#include<windows.h>
#include<tchar.h>
#include<stdio.h>
extern "C" const IMAGE_DOS_HEADER __ImageBase;
void DumpModule()
{
HMODULE hModule =
GetModuleHandle( NULL );
_tprintf( TEXT( "with
GetModuleHandle(NULL) = 0x%x\r\n" ),hModule );
_tprintf( TEXT( "with
__ImageBase = 0x%x\r\n" ),( HINSTANCE )&__ImageBase );
hModule = NULL;
GetModuleHandleEx(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS,
(PCTSTR)DumpModule,
&hModule);
printf("with
GetModuleHandleEx = 0x%x\r\n", hModule);
}
int main( int argc, char* argv[] )
{
DumpModule();
system("pause");
return 0;
}
ps:当调用GetModuleHandle函数,并向其传递NULL值,会返回进程的地址空间中的可执行文件的基地址。所以,即使调用GetModuleHandle(NULL)的代码是一个DLL文件中,返回值仍是可执行文件的基地址,而非DLL文件的基地址。
2.进程前一个实例的句柄
该参数用于16位Windows系统,仍然将其保留为WinMain的一个参数,目的只是方便我们移植到16位Windows应用程序.
3.进程的环境变量
每个进程都有一个与它关联的环境块(environment block),这是在进程地址空间内分配的一个 内存块,其中包含和下面相似的一组字符串: (可以使用GetEnvironmentStrings函数获得)
=::=::\ ...
VarName1=VarValue1\0
VarName2=VarValue2\0
VarName3=VarValue3\0 ...
VarNameX=VarValueX\0
\0
(1)可以使用
GetEnvironmentVariable 函数来判断一个环境变量是否存在;如果存在,它的值是什么。如下
所示:
DWORD GetEnvironmentVariable(
PCTSTR pszName,
PTSTR pszValue,
DWORD cchValue);
调用GetEnvironmentVariable时,pszName指向预期的变量名称,pszValue指向保存变量值的缓冲区,而 cchValue指出缓冲区大小(用字符数来表示)。如果在环境中找到变量名,GetEnvironmentVariable函数将返回复制到缓冲区的字符数;如果在环境中没有找到变量名, 就返回0。然而,由于我们不知道为了保存一个环境变量的值需要多少个字符,所以当0值被当 作cchValue参数的值传入时,GetEnvironmentVariable会返回包括末尾的NULL字符在内的字符的数量。以下代码演示了如何安全地使用这个函数:
void PrintEnvironmentVariable(PCTSTR pszVariableName) {
PTSTR pszValue = NULL;
// 先获得环境变量中的字符数
DWORD dwResult = GetEnvironmentVariable(pszVariableName,
pszValue, 0);
if (dwResult != 0) {
// 为环境变量分配足够的内存,并获得环境变量的值
DWORD size = dwResult * sizeof(TCHAR);
pszValue = (PTSTR)malloc(size);
GetEnvironmentVariable(pszVariableName, pszValue,
size);
_tprintf(TEXT("%s=%s\n"), pszVariableName,
pszValue);
free(pszValue);
} else {
_tprintf(TEXT("'%s'=<unknown
value>\n"), pszVariableName);
}
}
(2)可以使用 ExpandEnvironmentStrings 函数来展开一个环境变量 ,如: %USERPROFILE%\Documents 在我的机器上
USERPROFILE环境变量值为C:\Users\mzf,因此替换后的字符串为:
C:\Users\mzf
\Documents
DWORD ExpandEnvironmentStrings(
PTCSTR pszSrc,
PTSTR pszDst,
DWORD chSize);
调用这个函数时,pszSrc参数是包含“可替换环境变量字符串”的一个字符串的地址。pszDst 参数是用于接收扩展字符串的一个缓冲区的地址,而chSize参数是这个缓冲区的最大大小(用字符数来表示)。返回值是保存扩展字符串所需的缓冲区的大小(用字符数来表示)。如果chSize 参数小于此值,%%变量就不会扩展,而是被空字符串替换。所以,通常要调用两次 ExpandEnvironmentStrings 函数,如下所示:
DWORD chValue =
ExpandEnvironmentStrings(TEXT("PATH='%PATH%'"),
NULL, 0);
PTSTR pszBuffer = new TCHAR[chValue];
chValue = ExpandEnvironmentStrings(TEXT("PATH='%PATH%'"),
pszBuffer, chValue);
_tprintf(TEXT("%s\r\n"), pszBuffer);
delete[] pszBuffer;
(3)使用SetEnvironmentVariable函数添加一个变量,删除一个变量,或者修改一个变
量的值:
BOOL SetEnvironmentVariable(
PCTSTR pszName,
PCTSTR pszValue);
此函数将pszName所标识的一个变量设为pszValue参数所标识的值。如果已经存在具有指定名称的一个变量,SetEnvironmentVariable函数会修改它的值。如果指定的变量不存在,就添加这个变量。如果pszValue为NULL,变量会从环境块中删除.
加载到进程地址空间的每一个可执行文件或者dll文件都被赋予了一个独一无二的实例句柄.
他实际上是一个内存基地址,系统将可执行程序的映像加载到进程地址空间中的这个位置。
Ps :
HMODULE和 HINSTANCE
其实就是一回事.
获得一个可执行文件或者dll文件的句柄/基地址:
(1)GetModuleHandle函数
HMODULE GetModuleHandle( LPCTSTR lpModuleName );
调用这个函数时,参数指定了已在主调进程的地址空间中加载的一个可执行文件或者DLL文件的名称。或者参数为NULL时,会返回主调函数的可执行文件的基地址。
(2)GetModuleHandleEx 函数
BOOL WINAPI GetModuleHandleEx(
__in DWORD dwFlags,
__in LPCTSTR lpModuleName,
__out HMODULE* phModule
);
将GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS作为他的第一个参数,将当前函数的地址作为第二个参数,最后一个参数是一个指向HMODULE的指针,GetModuleHandleEx函数会用传入函数(既第二个参数)所在DLL的基地址来填写该指针.
(3)利用链接器提供的为变量__ImageBase,他指向当前正在运行的模块的基地址.
例如:
#include<windows.h>
#include<tchar.h>
#include<stdio.h>
extern "C" const IMAGE_DOS_HEADER __ImageBase;
void DumpModule()
{
HMODULE hModule =
GetModuleHandle( NULL );
_tprintf( TEXT( "with
GetModuleHandle(NULL) = 0x%x\r\n" ),hModule );
_tprintf( TEXT( "with
__ImageBase = 0x%x\r\n" ),( HINSTANCE )&__ImageBase );
hModule = NULL;
GetModuleHandleEx(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS,
(PCTSTR)DumpModule,
&hModule);
printf("with
GetModuleHandleEx = 0x%x\r\n", hModule);
}
int main( int argc, char* argv[] )
{
DumpModule();
system("pause");
return 0;
}
ps:当调用GetModuleHandle函数,并向其传递NULL值,会返回进程的地址空间中的可执行文件的基地址。所以,即使调用GetModuleHandle(NULL)的代码是一个DLL文件中,返回值仍是可执行文件的基地址,而非DLL文件的基地址。
2.进程前一个实例的句柄
该参数用于16位Windows系统,仍然将其保留为WinMain的一个参数,目的只是方便我们移植到16位Windows应用程序.
3.进程的环境变量
每个进程都有一个与它关联的环境块(environment block),这是在进程地址空间内分配的一个 内存块,其中包含和下面相似的一组字符串: (可以使用GetEnvironmentStrings函数获得)
=::=::\ ...
VarName1=VarValue1\0
VarName2=VarValue2\0
VarName3=VarValue3\0 ...
VarNameX=VarValueX\0
\0
(1)可以使用
GetEnvironmentVariable 函数来判断一个环境变量是否存在;如果存在,它的值是什么。如下
所示:
DWORD GetEnvironmentVariable(
PCTSTR pszName,
PTSTR pszValue,
DWORD cchValue);
调用GetEnvironmentVariable时,pszName指向预期的变量名称,pszValue指向保存变量值的缓冲区,而 cchValue指出缓冲区大小(用字符数来表示)。如果在环境中找到变量名,GetEnvironmentVariable函数将返回复制到缓冲区的字符数;如果在环境中没有找到变量名, 就返回0。然而,由于我们不知道为了保存一个环境变量的值需要多少个字符,所以当0值被当 作cchValue参数的值传入时,GetEnvironmentVariable会返回包括末尾的NULL字符在内的字符的数量。以下代码演示了如何安全地使用这个函数:
void PrintEnvironmentVariable(PCTSTR pszVariableName) {
PTSTR pszValue = NULL;
// 先获得环境变量中的字符数
DWORD dwResult = GetEnvironmentVariable(pszVariableName,
pszValue, 0);
if (dwResult != 0) {
// 为环境变量分配足够的内存,并获得环境变量的值
DWORD size = dwResult * sizeof(TCHAR);
pszValue = (PTSTR)malloc(size);
GetEnvironmentVariable(pszVariableName, pszValue,
size);
_tprintf(TEXT("%s=%s\n"), pszVariableName,
pszValue);
free(pszValue);
} else {
_tprintf(TEXT("'%s'=<unknown
value>\n"), pszVariableName);
}
}
(2)可以使用 ExpandEnvironmentStrings 函数来展开一个环境变量 ,如: %USERPROFILE%\Documents 在我的机器上
USERPROFILE环境变量值为C:\Users\mzf,因此替换后的字符串为:
C:\Users\mzf
\Documents
DWORD ExpandEnvironmentStrings(
PTCSTR pszSrc,
PTSTR pszDst,
DWORD chSize);
调用这个函数时,pszSrc参数是包含“可替换环境变量字符串”的一个字符串的地址。pszDst 参数是用于接收扩展字符串的一个缓冲区的地址,而chSize参数是这个缓冲区的最大大小(用字符数来表示)。返回值是保存扩展字符串所需的缓冲区的大小(用字符数来表示)。如果chSize 参数小于此值,%%变量就不会扩展,而是被空字符串替换。所以,通常要调用两次 ExpandEnvironmentStrings 函数,如下所示:
DWORD chValue =
ExpandEnvironmentStrings(TEXT("PATH='%PATH%'"),
NULL, 0);
PTSTR pszBuffer = new TCHAR[chValue];
chValue = ExpandEnvironmentStrings(TEXT("PATH='%PATH%'"),
pszBuffer, chValue);
_tprintf(TEXT("%s\r\n"), pszBuffer);
delete[] pszBuffer;
(3)使用SetEnvironmentVariable函数添加一个变量,删除一个变量,或者修改一个变
量的值:
BOOL SetEnvironmentVariable(
PCTSTR pszName,
PCTSTR pszValue);
此函数将pszName所标识的一个变量设为pszValue参数所标识的值。如果已经存在具有指定名称的一个变量,SetEnvironmentVariable函数会修改它的值。如果指定的变量不存在,就添加这个变量。如果pszValue为NULL,变量会从环境块中删除.
相关文章推荐
- linux启动分析---C程序入口函数start_kernel
- 裸机程序常识1 _start程序入口标号 -Ttext链接地址作用,如何使用uboot中的函数
- [转载] linux启动分析(5)---C程序入口函数start_kernel
- winform程序不一定要用Main() 函数做入口
- 程序入口函数 main
- Java中static方法、程序入口函数main方法的继承问题
- 如何更改程序入口函数
- 安卓真机调试,程序没有进入到Java_org_cocos2dx_lib_Cocos2dxRenderer_nativeInit入口函数里?
- gcc如何设置程序的入口函数
- 程序入口函数与初始化
- Windows下程序入口函数与_security_init_cookie
- C++ 程序启动入口函数main还是winmain?
- 程序入口函数和glibc及C++全局构造和析构
- C/C++程序入口函数的隐藏方法
- ACE程序入口函数替换机制分析
- 3.1.3、为AutoCAD程序实现入口点函数
- 对WinMain程序入口函数返回值为msg.wParam的几点理解
- 程序员的自我修养 - 入口函数和程序初始化
- DirectX 3D_基础之HLSL(高级着色语言) HLSL着色器程序的编制 HSLS变量 HLSL入口函数 HLSL程序编译 变量常量类型 设置方法 前缀 关键字 类型 语句 类型转换
- 在纯C工程的main函数之前跑代码(手工找到程序入口点, 替换为我们自己的函数)