鸣谢 1
目录 1
前言 3
0.1 我对大家的期望 3
0.2 关于示例应用程序 3
0.2.3 有关16位Windows编程的知识 4
0.2.4 在Windows 95下运行示例应用程序 4
0.2.2 Message Cracker Macros(消息拆析宏) 4
0.2.1 用C语言写的程序 4
0.2.5 不相关代码 5
0.2.6 相互独立的应用程序 5
0.2.7 STRICT一致性 5
0.2.8 错误检查 5
0.2.9 没有错误 6
0.2.10 测试平台及环境 6
0.2.11 Unicode 7
0.3 安装示例程序 7
0.3.1 Windows 95 7
0.3.2 Windows NT 8
第1章 WIN32API及支持它的平台 10
1.1 梦想:Win32API 10
1.2 Win32s 11
1.3 Windows NT 11
1.4 Windows 95 12
1.5 现实:Win32 API 13
第2章 进程 15
2.1 核心对象 16
2.2 编写第一个Win32应用程序 17
2.2.1 进程的实例句柄 19
2.2.2 进程的先前实例句柄 21
2.2.3 进程的命令行 22
2.2.4 进程的环境变量 23
2.2.5 进程的错误方式 26
2.2.6 进程的当前驱动器和目录 26
2.2.7 进程继承的核心对象 27
2.2.8 系统版本 29
2.3 CreateProcess函数 30
2.3.1 lpszImageName和lpszCommandLine 31
2.3.2 lpsaProcess,lpsaThread和fInheritHandles 32
2.3.3 fdwCreate 33
2.3.4 lpvEnvironment 35
2.3.5 lpszCurDir 35
2.3.6 lpsiStartInfo 35
2.3.7 lppiProcInfo 39
2.4 终止进程 40
2.4.1 ExitPorcess函数 40
2.4.3 进程的结束 41
2.4.2 TerminateProcess函数 41
2.5 子进程 42
2.5.1 运行分离的子进程 43
第3章 线程 44
3.1 何时创建线程 44
3.2 何时不用创建线程 45
3.3 编写第一个线程函数 47
3.3.1 线程的栈 47
3.3.2 线程的CONTEXT结构 48
3.3.3 线程的执行时间 48
3.4.1 lpsa 50
3.4 CreateThread函数 50
3.4.2 cbStacr 51
3.4.3 lpStartAddr和lpvThreadParm 51
3.4.4 fdwCreate 52
3.4.5 lpIDThead 53
3.5 终止线程 53
3.5.1 ExitThread函数 53
3.5.2 TerminateThread函数 53
3.5.3 线程终止时发生些什么 54
3.6 识别自己的身份 55
3.7 系统如何安排线程 58
3.7.1 如何使用Win32 API分配优先级 59
3.7.2 修改进程优先级类 61
3.7.3 设定线程相对优先级 62
3.7.4 挂起及恢复线程 64
3.8 查看系统内部 64
3.9 进程、线程和C运行时库 69
3.9.1 要避免使用的C运行时函数 72
第4章 Win32存储结构 74
4.1 我所知的CPU 74
4.2 虚拟地址空间 76
4.2.1 Windows 95如何划分进程的地址空间 77
4.2.2 Windows NT如何划分进程的地址空间 78
4.3 地址空间中的区域 80
4.4 在区域内提交物理存储 81
4.5 物理存储 82
4.5.1 不在页面文件中维护的物理存储 83
4.6 保护属性 84
4.6.1 写时拷贝(Copy-On-Write)访问 85
4.6.2 特殊访问保护属性标志 85
4.7 综述 86
4.7.1 区域内部 89
4.7.2 Windows 95地址空间的差别 93
第5章 探索虚存 100
5.1 系统信息 100
5.1.1 系统信息示例应用程序 101
5.2 虚存状态 107
5.2.1 虚存状态示例应用程序 108
5.3 确定地址空间的状态 113
5.3.1 VMQuery函数 114
5.3.2 虚存分配示例应用程序 123
第6章 使用虚存 132
6.1 在地址空间中保留区域 132
6.2 在保留区内提交存储 134
6.3 同时保留区域和提交存储 135
6.4 何时提交物理存储 135
6.5 回收物理存储和释放区域 137
6.5.1 何时回收物理存储 138
6.5.2 虚存分配示例应用程序 138
6.6 改变保护属性 149
6.7 在RAM中锁住物理存储 150
6.8 线程的栈 151
6.8.1 Windows 95下的线程栈 154
6.8.2 C运行时刻的栈检查函数 155
第7章 存储映射文件 158
7.1 存储映射EXE和DLL 158
7.1.1 静态数据不能被一个EXE或一个DLL文件的多个实例共享 159
7.2 存储映射数据文件 161
7.2.1 方法1:一个文件,一个缓冲区 161
7.2.4 方法4:一个文件,零个缓冲区 162
7.2.3 方法3:一个文件,两个缓冲区 162
7.2.2 方法2:两个文件,一个缓冲区 162
7.3 使用存储映射文件 163
7.3.1 步骤1:创建或打开文件核心对象 163
7.3.2 步骤2:创建文件映射核心对象 164
7.3.3 步骤3:映射文件的数据到进程地址空间 166
7.3.4 步骤4:从进程地址空间解除文件数据的映射 169
7.3.5 步骤5和步骤6:关闭文件映射对象和文件对象 170
7.3.6 使用存储映射文件处理大文件 171
7.4 存储映射文件和一致性 173
7.4.1 文件反转示例应用程序 174
7.4.2 指定存储映射文件的基地址 183
7.5 存储映射文件和Win32实现 184
7.5.1 使用存储映射文件在进程间共享数据 186
7.5.2 由页面文件备份的存储映射文件 189
7.5.3 存储映射文件共享示例应用程序 190
7.6 稀疏提交的存储映射文件 197
第8章 堆 199
8.1 什么是Win32堆? 199
8.1.2 创建自己的Win32堆 200
8.1.1 进程的缺省堆 200
8.1.3 创建另外的Win32堆 202
8.1.4 消除Win32堆 205
8.1.5 在C++中使用堆 205
8.1.6 16位的Windows堆函数 209
第9章 线程同步 213
9.1 同步概述 213
9.1.1 最坏的事情之一 213
9.2 临界区 214
9.2.1 创建临界区 216
9.2.2 使用临界区 217
10.1.1 抢占式调度 218
9.2.3 临界区示例应用程序 223
9.3 用核心对象同步线程 235
9.3.1 互斥量 238
9.3.2 互斥量示例应用程序 243
9.3.3 信号量 252
9.3.4 超级市场示例应用程序 253
9.3.5 事件 277
9.3.6 Bucket of Balls示例应用程序 278
9.3.7 SWMRG复合同步对象 280
9.3.8 Bucket示例源代码 285
9.3.9 文档统计示例应用程序 304
9.4 线程挂起 313
9.4.1 Sleep 313
9.4.2 异步文件I/O 313
9.4.3 WaitForInputIdle 313
9.4.4 MsgWaitForMultipleObjects 314
9.4.5 WaitForDebugEvent 315
9.4.6 Interlocked函数族 315
第10章 窗口消息和异步输入 317
10.1 多任务 317
10.2 线程队列和消息处理 320
10.2.1 Win32消息队列结构 320
10.2.2 发送消息给线程的消息队列 320
10.2.3 发送消息给窗口 322
10.2.4 唤醒线程 325
10.3 用消息发送数据 330
10.3.1 拷贝数据示例应用程序 332
10.4 非序列化输入 338
10.4.1 怎样使输入非序列化 339
10.5 局部输入状态 342
10.5.1 键盘输入和焦点 343
10.5.2 鼠标光标管理 346
10.5.3 局部输入状态实验示例应用程序 347
第11章 动态链接库 365
11.1 创建动态链接库 365
11.1.1 映射DLL到进程地址空间 367
11.2 DLL入口和出口函数 371
11.2.1 DLL-PROCESS-ATTACH 373
11.2.2 DLL-PROCESS-DETACH 374
11.2.3 DLL-THREAD-ATTACH 375
11.2.4 DLL-THREAD-DETACH 377
11.2.5 系统如何把对DllMain的调用顺序化 378
11.2.6 DllMain和C运行时库 381
11.3 从DLL中输出函数和变量 382
11.4 从DLL输出函数和变量 384
11.4.1 DLL的头文件 389
11.5.1 EXE或DLL的段 390
11.5 在同一EXE或DLL的多个映射之间共享数据 390
11.5.2 ModUse示例应用程序 393
11.5.3 MultInst示例应用程序 403
第12章 线程局部存储 406
12.1 动态线程局部存储 407
12.1.1 使用动态线程局部存储 408
12.1.2 动态线程局部存储示例应用程序 410
12.2 静态线程局部存储 421
12.2.1 静态局部存储示例应用程序 422
第13章 文件系统和文件输入输出 431
13.1 Win32文件名约定 432
13.2 系统和卷操作 433
13.2.1 获得卷的特定信息 436
13.2.2 磁盘信息查看示例应用程序 441
13.3 目录操作 450
13.3.1 获得当前目录 450
13.3.2 改变当前目录 451
13.3.4 获得窗口目录路径 452
13.3.5 创建和删除目录 452
13.3.3 获得系统目录 452
13.4 拷贝、删除、移动及改名文件 453
13.4.1 拷贝一个文件 453
13.4.2 删除一个文件 453
13.4.3 移动一个文件 453
13.4.4 改名文件 455
13.5 创建、打开和关闭文件 456
13.6 同步读写文件 460
13.6.1 定位文件指针 462
13.6.4 锁定及解锁文件的某区域 463
13.6.2 设置文件尾 463
13.6.3 强制缓冲的数据写入磁盘 463
13.7 异步读写文件 466
13.7.1 同时执行多个异步文件I/O操作 472
13.7.2 告警异步文件I/O 473
13.7.3 告警I/O示例应用程序 475
13.8 操作文件属性 488
13.8.1 文件标志 488
13.8.2 文件大小 489
13.8.3 文件时间戳 489
13.9 搜寻文件 492
13.9.1 目录漫游示例应用程序 495
13.10 文件系统变化通知 504
13.10.1 文件变化示例应用程序 507
第14章 结构化异常处理 521
14.1 终止处理程序 522
14.1.1 通过例子理解终止处理程序 522
14.1.2 关于finally块的几点说明 533
14.1.3 SEH终止示例应用程序 535
14.2 异常过滤程序和异常处理程序 545
14.2.1 通过例子理解异常过滤程序和异常处理程序 546
14.2.2 EXCEPTION-EXECUTE-HANDLER 547
14.2.3 EXCEPTION-CONTINUE-EXECUTION 548
14.2.4 EXCEPTION-CONTINUE-SEARCH 550
14.2.5 全局展开 553
14.2.6 停止全局展开 555
14.2.7 关于异常过滤程序的进一步讨论 556
14.2.8 GetExceptionInformation 560
14.2.9 SEH异常情况示例应用程序 565
14.2.10 SEH SUM示例应用程序 575
14.3 软件异常情况 582
14.3.1 SEH软件异常情况示例应用程序 584
14.3.2 未处理的异常情况 595
14.3.3 没有调试器附属时的未处理异常情况 596
14.3.4 关闭异常情况消息框 598
14.3.5 自己调用UnhandledExceptionFilter 600
14.3.6 未处理的核心态异常情况 600
15.1.1 单字节与双字节字符集 602
15.1 字符集 602
第15章 UNICODE 602
15.1.2 Unicode:宽字节字符集 603
15.2 为什么要使用Unicode 604
15.3 如何编写Unicode源代码 604
15.3.1 Windows NT和Unicode 605
15.3.2 Windows 95和Unicode 605
15.3.3 C运行时库中对Unicode的支持 605
15.3.4 Win32定义的Unicode数据类型 610
15.3.5 Win32中的Unicode和ANSI函数 611
15.4.1 Win32中的字符串函数 613
15.4 使你的应用程序区分ANSI和UNICODE 613
15.4.2 资源 615
15.4.3 文本文件 616
15.4.4 在Unicode与ANSI之间的字符串转换 616
15.4.5 Windows NT:窗口类和过程 620
第16章 闯过进程的边界墙 622
16.1 为什么需要打破进程边界墙:一个例子 622
16.2 使用Registry来注入一个DLL 624
16.3 使用窗口钩子来注入一个DLL 626
16.3.1 Program Manager恢复示例应用程序 627
16.4 使用远程线程来注入一个DLL 642
16.4.1 如何装入一个DLL 642
16.5 影响其它进程的Win32函数 642
16.5.1 CreateRemoteThread 643
16.5.2 GetThreadContext和SetThreadContext 644
16.5.3 VirtualQueryEx和VirtualProtectEx 648
16.5.4 ReadProcessMemory和WriteProcessMemory 648
16.6 创建一个函数来把DLL注入到任意进程的地址空间内 649
16.6.1 版本0:为什么显而易见的方法就是不起作用 649
16.6.2 版本1:手工编码的机器语言 650
16.6.3 版本2:AllocProcessMemory和CreateRemoteThread 652
16.6.4 ProcMem实用函数 656
16.6.5 InjectLib函数 659
16.7 测试Injectlib函数 669
16.7.1 注入库测试示例应用程序 669
16.7.2 Image Walk动态链接库 671
16.8 小结 674
附录A 消息拆析器 676
A.1 消息拆析器 677
A.2 子控制宏 680
A.3 API宏 681
附录B BUILD环境 682
B.1 ADVWIN32.H头文件 682
B.1.1 Warning Leve14(四级警告) 682
B.1.2 STRICT宏 682
B.1.3 Unicode 683
B.1.4 ARRAY-SIZE宏 683
B.1.5 BEGINTHREADEX宏 683
B.1.6 链接器指令 684
B.2 不能在源文件中设置的项目Settings(设置) 687