进程
概念
进程实际上就是一个容器和管理对象,代表程序的运行实例。 - 一个可执行程序,其中包含用于在进程内执行代码的初始代码和数据。大多数进程都是如此,但某些特殊进程没有可执行映像(由内核直接创建)。 - 一个私有的虚拟地址空间,用于按进程内代码的需求分配内存。 - 一个访问令牌(称为主令牌),这是一个存储进程安全上下文的对象,供在进程内执行的线程使用(除非线程通过模拟使用不同的令牌)。 - 一个私有的句柄表,用于访问执行体对象,如事件、信号量和文件。 - 一个或多个执行线程。正常的用户模式进程在创建时带有一个线程(执行经典的 main/WinMain 函数)。没有线程的用户模式进程基本毫无用处,正常情况下会被内核销毁。
进程由其进程 ID 唯一标识,只要内核进程对象存在,该 ID 就保持唯一。一旦对象被销毁,同一 ID 可能会被新进程重用。需要明确的是,可执行文件本身并不是进程的唯一标识。
进程在任何一个三环都有一个结构体
虚拟内存
每个进程都拥有自己独立的私有线性地址空间。该地址空间初始为空(或接近空,因为可执行映像和 NtDll.Dll 最先被映射,随后是更多子系统 DLL)。一旦主(第一个)线程开始执行,就可能会分配内存、加载更多 DLL 等。这个地址空间是私有的,意味着其他进程无法直接访问它。地址空间的范围从零开始(从技术上讲,地址空间的首尾 64KB 区域无法提交),一直延伸到最大地址,具体取决于进程的“位数”(32 位或 64 位)以及操作系统的“位数”,规则如下:
- 对于 32 位 Windows 系统上的 32 位进程,默认进程地址空间大小为 2 GB。
- 对于启用了“增加用户虚拟地址空间”设置的 32 位 Windows 系统上的 32 位进程,每个进程的地址空间最多可配置为 3 GB。要获得扩展地址空间,创建该进程的可执行文件必须在其 PE 头中设置
LARGEADDRESSAWARE链接器标志。如果未设置,地址空间仍将限制为 2 GB。
- 对于启用了“增加用户虚拟地址空间”设置的 32 位 Windows 系统上的 32 位进程,每个进程的地址空间最多可配置为 3 GB。要获得扩展地址空间,创建该进程的可执行文件必须在其 PE 头中设置
- 对于 64 位进程(自然是在 64 位 Windows 系统上),地址空间大小为 8 TB(Windows 8 及更早版本)或 128 TB(Windows 8.1 及更高版本)。
- 对于 64 位 Windows 系统上的 32 位进程,如果可执行映像的 PE 头中设置了 LARGEADDRESSAWARE 标志,地址空间大小为 4 GB。否则,大小仍为 2 GB。 需要 LARGEADDRESSAWARE 标志的原因在于,2 GB 地址范围只需要 31 位,最高位(MSB)可留给应用程序自由使用。指定此标志表示程序没有将第 31 位用于任何用途,因此该位被置位(对于大于 2 GB 的地址就会发生)不会引发问题。
每个进程都有自己的地址空间,这使得任何进程地址都是相对的,而非绝对的。例如,要确定地址 0x20000 处的内容,仅靠地址本身是不够的;还必须指明该地址属于哪个进程。
内存本身被称为虚拟的(virtual),这意味着地址与其在物理内存(RAM)中的确切位置之间存在间接关系。进程内的缓冲区可能映射到物理内存,也可能临时驻留在文件(如页面文件)中
内存管理的单位称为页(page)。与内存相关的每个属性(如保护或状态)始终以页为粒度。页的大小由 CPU 类型决定(在某些处理器上可能是可配置的),无论如何,内存管理器都必须遵循此规则。在所有 Windows 支持的架构上,普通(有时称为小页)页大小为 4 KB。
成员
KPROCESS
是EPROCESS的第一个成员
句柄表
当一个进程创建或者打开一个内核的时候,,将获得一个句柄,,通过这个句柄可以访问内核对象 如:
HANDLE g_hMutex = ::CreateMutex(NULL, FALSE,"XYZ");
HANDLE g_hMutex = ::OprnMutex(MUTEX_ALL_ACCESS,,FLASE,"XYZ");
HANDLE g_hEvent = ::CreateREvent(NULL,TRUE,,FALSENULL);
HANDLE g_hThread = ::CreateThread(NULL,0,Proc,NULL,0,NULL);
两个进程可以共用同一个内核对象
Windows基础编程
入口点
windows基础编程通过Winmain作为基础入口点
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPreInstance, char* lpCmdLine, int nShowCmd){
return 0;
}
常用的数据类型
查看WIndows数据类型的定义可以看到,所有Windows数据类型都是由C/C++数据类型经过类型重定义得到的
DWORD实质上就是unsigned long数据类型,32位无符号整型
HANDLE实质上是VOID,HANDLED定义为typeod PVOID HANDLE,HANDLE实际上就是一个PVOID,而PVOID就是指向void的指针
原因
- 数据类型与平台相关
- 数据类型过于单一
- 平台差异
命名规律
基本数据类型包括:BYTE、CHAR、WORD、SHORT、INT等
指针类型的命令方式一般是在其指向的数据类型前加”LP”或”P”,字母P就是指针单位 POINTER的简写。
各种句柄类型的命名方式一般都是在对象名前加”H”,比如位图(BITMAP)对应的句柄类型为“HBITMAP”
无符号类型一般是以”U”开头
常量类型一般是类型中带”C”,意为const的意思
常见数据类型
| 类型 | 用途 |
|---|---|
| WORD | 16位无符号整型数据 |
| DWORD | 32位无符号整型数据 |
| DWORD64 | 64位无符号整型数据 |
| INT | 32位有符号整型数据类型 |
| INT_PTR | 指向INT数据类型的指针类型 |
| INT32 | 32位符号整型 |
| INT64 | 64位符号整型 |
| UINT | 无符号INT |
| LONG | 32位符号整型 |
| ULONG | 无符号LONG |
| LONGLONG | 64位符号整型 |
| SHORT | 无符号短整型 |
| LPARAM | 消息的L参数 |
| WPARAM | 消息的W参数 |
| HANDLE | 对象的句柄,最基本的句柄类型 |
| HICON | 图标的句柄 |
| HINSTANCE | 程序示例的句柄 |
| HKEY | 注册表键的句柄 |
| HMODULE | 模块的句柄 |
| HWND | 窗口的句柄 |
| BOOL | 布尔型变量 |
| BYTE | 字节型变量 |
| CONST | 常量 |
| FLOAT | 浮点数据类型 |
| SIZE_T | 表示内存大小,以字节为单位 |
| VOID | 无类型 |
| WINAPI | Windows API的函数调用方式,常见于SDK头文件中对API函数的声明 |
| LPSTR | 字符指针,也就是字符串常量 |
| LPCSTR | 字符串常量 |
| LPCTSTR | 根据环境配置,如果定义了UNICODE宏,则是LPCWSTR类型,否则为LPCSTR类型 |
| LPCWSTR | UNICODE字符串常量 |
| LPDWORD | 执行DWORD类型数据的指针 |
| CHAR | 8比特字节 |
| TCHAR | 如果定义了UNICODE,则为WCHAR,否则为CHAR |
| UCHAR | 无符号CHAR |
| WCHAR | 16位Unicode字符 |
Windows参数简写
- b 布尔
- by BYTE
- c chr或WCHAR TCHAR
- n short
- i int
- x、y分别表示x坐标,y坐标
- cx、cy分别表示x 方向长度和y 方向长度
- b或f BOOL(int),f代表”flag”
- w WORD(无符号short)
- ILONG 长整数
- dw DWORD 无符号长整数
- fn function函数
- s string字符串
- sZ 以 0 字节结尾的字符串
- h 句柄
- p 指针
- Ipfn 指向函数的长指针
- cb字节数
- Ipsz 指向以0结尾的字符串的长指针
- g_ 全局变量
- c_ 常量
- m_ 类数据成员
- s_ 静态变量
- CS_ 类风格选项
- CW_ 创建窗口选项
- DT_ 绘制文本选项
- IDI_ 图标ID号
- IDC_ 光标ID号
- MB_ 消息框选项
- SND_ 声音选项
- WM_ 窗口消息
- WS_ 窗口风格
- rc 矩形
常见API函数
提示框函数MessageBox
MessageBox(HWND hWnd, LPCTSTR lpText, LPCTSTR lpCaption,UINT uType);
hWnd:此参数代表消息框拥有的窗口,如果为NULL,则消息没有拥有窗口IpText:消息框的内容IpCaption:消息框的标题uType:指定一个决定对话框的内容和行为的位行为集。此参数可以为下列标志组的组合
uType标志位
| 按钮参数 | 含义 |
|---|---|
| MB_OK | 默认值,有一个确认按钮在里面 |
| MB_YESNO | 有是和否在里面 |
| MB_ABORTRRETRYINGNORE | 有Abort(放弃)、Retry(重试)和Ignore(跳过) |
| MB_YESNOCANCEL | 消息框内有三个按钮:Yes\NO和Cancel |
| MB_RETERYCANCEL | 有Retry(重试)和Cancel(取消) |
| MB_OKCANCEL | 消息框含有两个按钮:OK和Cancel |
图标:
| 参数 | 含义 |
|---|---|
| MB_ICONEXCLAMATION | 一个感叹号出现在消息框 |
| MB_ICONWARNING | 一个惊叹号出现在消息框 |
| MB_ICONINFORMATION | 一个注意符号出现在消息框 |
| MB_ICONSTERISK | 一个注意符号出现在消息框 |
| MB_ICONQUESTION | 一个问题号出现在消息框 |
| MB_ICONSTOP | 一个停止符出现在消息框 |
| MB_ICONERROR | 一个停止符出现在消息框 |
| MB_ICONHAND | 一个停止符出现在消息框 |
| 按钮: |
| 值 | 含义 |
|---|---|
| MB_DEFBUTTON1 | 第一个按钮是默认按钮。 除非 指定了 MB_DEFBUTTON2、 MB_DEFBUTTON3或MB_DEFBUTTON4,否则 MB_DEFBUTTON1 为默认值。 |
| MB_DEFBUTTON2 | 第二个按钮是默认按钮。 |
| MB_DEFBUTTON3 | 第三个按钮是默认按钮。 |
| MB_DEFBUTTON4 | 第四个按钮是默认按钮。 |
文件操作
文件的下载
概念
指定URL地址读取内容并将读取到的内容保存到特定的文件中
格式
# 要求:使用Urlmon.lib库
#pragma comment(lib,"Urlmon.lib")
HRESULT URLDownloadToFile(
LPUNKNOWN pCaller,
LPCTSTR szURL,
LPCTSTR szFileNale,
DWORD dwReserved,
LPBINDSTATUSCALLBACK lpfnCB
);
参数
pCaller:ActiveX 控件的接口指针,如果当前程序不是 ActiveX 控件写 Null 就可以了szURL:参数为要下载的url地址szFileName:下载文件后白村的文件名dwReserved:保留字段,必需为0lpfnCB:下载进度状态回调接口,实时监控数据时要用
返回值
S_OK:成功下载E_OUTOFMEMORY:缓冲区长度不够,或者没有足够的内存来完成下载的操作INET_E_DOWNLOAD_FAILURE:指定的资源或者回调接口有问题
执行文件
概念
使用代码执行文件
格式
BOOL ShellExecuteEx(
_Inout_SHELLEXECUTEINFO *pExecInfo
)
参数
typedef struct _SHELLEXECUTEINFO {
DWORD cbSize; # 结构大小,以字节为单位
ULONG fMask; # 标志数组,设置其他成员有效性
HWND hwnd; # 可选,窗口句柄,可以设置为NULL
LPCTSTR lpVerb; # 执行的动作,包括:edit、explore、find、open、print、properties
LPCTSTR lpFile; # 以\0 结尾的字符串,指出ipVerb操作对象路径,支持的操作包括open、print等
LPCTSTR lpParameters; # 可选。运行/打开程序的参数,如果打开的是一个文档,则该项无效
LPCTSTR lpDirectory; # 可选。指明工作文档的名字,成员没有说明,则默认为当前目录
int nShow; # 必须。指定打开的程序的显示方式,为SW_值中的一个
HINSTANCE hInstApp; # 如果设置SEE_MASK_NOCLOSEPROCESS S值并且**ShellExecuteEx** 调用成功,则该项的值大于32,如果调用失败,则将设置为SE_ERR_XXX 的错误值。
LPVOID lpIDList; # 一个**ITEMIDLIST**结构的地址,用来存储成员的特别标识符,当fMask不包括`SEE_MASK_IDLIST`或`SEE_MASK_INVOKEIDLIST`时该项被忽略
LPCTSTR lpClass; # 用以指明文件类别的名字或GUID,当fMask不包括`SEE_MASK_CLASSNAME`时该项被忽略
HKEY hkeyClass; # 获得已在系统注册的文件类型的Handle,当fMask不包括`SEE_MASK_HOTKEY`时该项被忽略
DWORD dwHotKey;
union {
HANDLE hIcon; # 取得对应文件类型的图标的Handle,当fMask不包括SEE_MASK_ICON时该项被忽略
HANDLE hMonitor; # 将文档显示在显示器上的Handle,当fMask不包括SEE_MASK_HMONITOR时该项被忽略
} DUMMYUNIONNAME; # 指向新启动的程序的句柄。若fMask不设为`SEE_MASK_NOCLOSEPROCESS`则该项值为NULL。但若程序没有启动,即使fMask设为`SEE_MASK_NOCLOSEPROCESS`,该值也仍为NULL。
HANDLE hProcess;
} SHELLEXECUTEINFO, *LPSHELLEXECUTEINFO
文件的删除、复制与重命名
概念
用于使用语言在系统中删除、复制、重命名文件
格式
文件的删除
BOOL DeleteFile(
[in] LPCTSTR lpFileName
);
文件的复制
BOOL CopyFile(
[in] LPCTSTR lpExistingFileName,
LPCTSTR lpNewFileName,
bool bFailLfExists
);
bFailLexists:传递True;如果目标文件已经存在,不拷贝,CopyFile返回FALSE;传递False,假如存在文件,覆盖文件
文件的移动
BOOL MoveFile(
LPCTSTR lpExstingFileName,
LPCTSTR lpNewFileName
)
文件的创建、打开和删除
文件的创建与打开
CreateFile(
LPCTSTR lpFileName,
DWORD dwDesiredAccess,
DWORD dwShareMode,
LPSECURITY_ATTRIBUTES lpSecurityAttributes,
DWORD dwCreationDisposition,
DWORD dwFlagsAndAttributes,
HANDLE hTemplateFile
)
lpFileName:打开文件或设备的名称dwDesiredAccess:所请求的文件或设备访问权限0:不希望从设备读取数据或向设备写入数据。如果只想改变设备的配置,可以传0GENERIC_READ:允许对设备进行只读访问GENERIC_WRITE:允许对设备进行只写访问,该选项没有隐含GENERIC_READ标志
dwShareMode:文件或者设备的请求共享模式0:要求独占对设备的访问。如果设备已经打开,CreateFile调用会失败;如果成功地打开了设备,后续的CreateFile调用会失败FILE_SHARE_READ:如果有其他对象要使用该设备,则要求不得修改设备的数据;如果该设备已经以写入方式或独占方式打开,那么CreateFile调用会失败FILE_SHARE_WRITE:如果有其他内核对象要使用该设备,则要求不得读取设备的数据FILE_SHARE_DELETE:当对文件进行操作的时候,我们不关心文件是否被逻辑删除或移动。在Windows内部,系统会将文件标记为待删除,然后待文件所有已打开句柄都关闭后,将其真正删除
lpSecutityAttributes:指向SECURITY_ATTRIBUTES结构指针,包含两个独立但相关的数据成员;一个可选的安全描述符以及一个布尔值,该值确定返回的句柄是否可以被子进程继承。该参数可以为null。如果该参数为NULL,则由CreateFile返回的句柄不能由应用程序可能创建的任何的子进程继承,并且与返回句柄关联的文件或设备将获得默认安全描述符dwCreationDispositionCREATE_NEW:创建一个新文件,如果同名文件存在,则调用失败CREATE_ALWAYS:无论同名是否存在都创建新文件OPEN_EXISTING:打开一个已有的文件,如果文件存在,则直接打开文件;如果不存在则会创建一个新文件TRUNCATE_EXISTING:告诉CreateFile打开一个已有的文件并将文件的大小截断为0字节,如果文件不存在,则会创建一个新文件TRUNCATE_EXISTING:打开已有文件并将文件大小截断为0字节;如果不存在,调用失败
dwFlagsAndAttributes:允许我们设置一些标志来微调与设备之间的通信hTemplateFile:指定一个具有GENERIC_READ访问权限的模板文件的句柄,可以为NULL
dwFlagsAndAttributes标志
文件属性
当 CreateFile 创建新文件时,这些属性会被应用到文件上(若打开已存在的文件,多数属性会被忽略)。
FILE_ATTRIBUTE_NORMAL(0x00000080)- 含义:常规文件。该属性不能与其他属性组合使用,只有在单独使用时才有效。
FILE_ATTRIBUTE_READONLY(0x00000001)- 含义:只读文件。应用程序可以读取该文件,但不能写入或删除。
FILE_ATTRIBUTE_HIDDEN(0x00000002)- 含义:隐藏文件。在常规的目录列表中不可见。
FILE_ATTRIBUTE_SYSTEM(0x00000004)- 含义:系统文件。该文件是操作系统的一部分,或由操作系统独占使用。
FILE_ATTRIBUTE_ENCRYPTED(0x00004000)- 含义:加密文件。文件流中的所有数据都将被加密。
行为标志
用于控制内核对文件系统行为的优化或控制 I/O 操作的方式。
FILE_FLAG_WRITE_THROUGH(0x80000000)- 含义:穿透缓存写入。系统会将数据直接写入磁盘,而不经过中间缓存延迟写入,从而降低因掉电导致数据丢失的风险。
FILE_FLAG_OVERLAPPED(0x40000000)- 含义:异步 I/O(重叠 I/O)。指示系统以异步方式执行该文件的读写操作。在此模式下,调用
ReadFile或WriteFile会立即返回,而无需等待 I/O 操作完成。
- 含义:异步 I/O(重叠 I/O)。指示系统以异步方式执行该文件的读写操作。在此模式下,调用
FILE_FLAG_NO_BUFFERING(0x20000000)- 含义:无缓冲 I/O。系统将不使用任何内部缓存来加速文件的读写。使用此标志时,读写请求的数据块大小、内存缓冲区地址以及文件指针偏移量,通常必须与底层磁盘扇区大小(Sector Size)对齐。
FILE_FLAG_RANDOM_ACCESS(0x10000000)- 含义:随机访问优化。提示系统该文件将进行随机访问,系统缓存管理器将优化其预读(Read-ahead)机制,避免无效的顺序预读造成的性能浪费。
FILE_FLAG_SEQUENTIAL_SCAN(0x08000000)- 含义:顺序扫描优化。提示系统该文件将主要从头到尾进行顺序读取,缓存管理器会加大预读量。
FILE_FLAG_DELETE_ON_CLOSE(0x04000000)- 含义关闭时删除。当该文件的所有句柄都被关闭后,系统会自动将文件从磁盘上删除。常用于创建临时文件。
获取错误信息
GetLastError用于获取错误信息
在C当中,是通过函数返回值和全局变量errno
而在Win32中,函数原型:DWORD GetLastError(VOID);
无参数,返回值为DWORD双字的整型,表示错误码的值。针对函数执行遇到不同的错误,GetLastError的返回值是不同的
_Post_equals_last_error_ DWORD GetLastError();