进程

概念

进程实际上就是一个容器和管理对象,代表程序的运行实例。 - 一个可执行程序,其中包含用于在进程内执行代码的初始代码和数据。大多数进程都是如此,但某些特殊进程没有可执行映像(由内核直接创建)。 - 一个私有的虚拟地址空间,用于按进程内代码的需求分配内存。 - 一个访问令牌(称为主令牌),这是一个存储进程安全上下文的对象,供在进程内执行的线程使用(除非线程通过模拟使用不同的令牌)。 - 一个私有的句柄表,用于访问执行体对象,如事件、信号量和文件。 - 一个或多个执行线程。正常的用户模式进程在创建时带有一个线程(执行经典的 main/WinMain 函数)。没有线程的用户模式进程基本毫无用处,正常情况下会被内核销毁。

image.png 进程由其进程 ID 唯一标识,只要内核进程对象存在,该 ID 就保持唯一。一旦对象被销毁,同一 ID 可能会被新进程重用。需要明确的是,可执行文件本身并不是进程的唯一标识。

进程在任何一个三环都有一个结构体

虚拟内存

每个进程都拥有自己独立的私有线性地址空间。该地址空间初始为空(或接近空,因为可执行映像和 NtDll.Dll 最先被映射,随后是更多子系统 DLL)。一旦主(第一个)线程开始执行,就可能会分配内存、加载更多 DLL 等。这个地址空间是私有的,意味着其他进程无法直接访问它。地址空间的范围从零开始(从技术上讲,地址空间的首尾 64KB 区域无法提交),一直延伸到最大地址,具体取决于进程的“位数”(32 位或 64 位)以及操作系统的“位数”,规则如下:

  • 对于 32 位 Windows 系统上的 32 位进程,默认进程地址空间大小为 2 GB。
    • 对于启用了“增加用户虚拟地址空间”设置的 32 位 Windows 系统上的 32 位进程,每个进程的地址空间最多可配置为 3 GB。要获得扩展地址空间,创建该进程的可执行文件必须在其 PE 头中设置 LARGEADDRESSAWARE 链接器标志。如果未设置,地址空间仍将限制为 2 GB。
  • 对于 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的意思

常见数据类型

类型用途
WORD16位无符号整型数据
DWORD32位无符号整型数据
DWORD6464位无符号整型数据
INT32位有符号整型数据类型
INT_PTR指向INT数据类型的指针类型
INT3232位符号整型
INT6464位符号整型
UINT无符号INT
LONG32位符号整型
ULONG无符号LONG
LONGLONG64位符号整型
SHORT无符号短整型
LPARAM消息的L参数
WPARAM消息的W参数
HANDLE对象的句柄,最基本的句柄类型
HICON图标的句柄
HINSTANCE程序示例的句柄
HKEY注册表键的句柄
HMODULE模块的句柄
HWND窗口的句柄
BOOL布尔型变量
BYTE字节型变量
CONST常量
FLOAT浮点数据类型
SIZE_T表示内存大小,以字节为单位
VOID无类型
WINAPIWindows API的函数调用方式,常见于SDK头文件中对API函数的声明
LPSTR字符指针,也就是字符串常量
LPCSTR字符串常量
LPCTSTR根据环境配置,如果定义了UNICODE宏,则是LPCWSTR类型,否则为LPCSTR类型
LPCWSTRUNICODE字符串常量
LPDWORD执行DWORD类型数据的指针
CHAR8比特字节
TCHAR
如果定义了UNICODE,则为WCHAR,否则为CHAR
UCHAR无符号CHAR
WCHAR
16位Unicode字符

Windows参数简写

  1. b 布尔
  2. by BYTE
  3. c chr或WCHAR TCHAR
  4. n short
  5. i int
  6. x、y分别表示x坐标,y坐标
  7. cx、cy分别表示x 方向长度和y 方向长度
  8. b或f BOOL(int),f代表”flag”
  9. w WORD(无符号short)
  10. ILONG 长整数
  11. dw DWORD 无符号长整数
  12. fn function函数
  13. s string字符串
  14. sZ 以 0 字节结尾的字符串
  15. h 句柄
  16. p 指针
  17. Ipfn 指向函数的长指针
  18. cb字节数
  19. Ipsz 指向以0结尾的字符串的长指针
  20. g_ 全局变量
  21. c_ 常量
  22. m_ 类数据成员
  23. s_ 静态变量
  24. CS_ 类风格选项
  25. CW_ 创建窗口选项
  26. DT_ 绘制文本选项
  27. IDI_ 图标ID号
  28. IDC_ 光标ID号
  29. MB_ 消息框选项
  30. SND_ 声音选项
  31. WM_ 窗口消息
  32. WS_ 窗口风格
  33. 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:保留字段,必需为0
  • lpfnCB:下载进度状态回调接口,实时监控数据时要用

返回值

  • 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:不希望从设备读取数据或向设备写入数据。如果只想改变设备的配置,可以传0
    • GENERIC_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返回的句柄不能由应用程序可能创建的任何的子进程继承,并且与返回句柄关联的文件或设备将获得默认安全描述符
  • dwCreationDisposition
    • CREATE_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 操作完成。
  • 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();