第1章 错误处理 1
自定义错误处理的实现 4
错误显示例程 5
第2章Unicode 11
字符集 11
单字节和双字节字符集 11
Unicode:宽字节字符集 12
为何需要Unicode 13
Windows 2000和Unicode 13
Windows 98和Unicode 13
Windows CE和Unicode 14
评论 14
关于COM 15
如何编写Unicode源代码 15
C运行库的Unicode支持 15
Windows定义的Unicode数据类型 17
Windows系统中的Unicode函数和ANSI函数 17
Windows字符串函数 19
让应用程序符合ANSI和Unicode规范 19
Windows字符串函数 20
资源 22
确定文本是ANSI型还是Unicode型 22
在Unicode和ANSI间转换字符串 24
第3章 内核对象 27
内核对象的概念 27
使用计数 27
安全性 28
内核对象句柄表 30
创建内核对象 30
关闭内核对象 32
进程间内核对象的共享 32
对象句柄的继承性 33
改变句柄标志 35
命名对象 36
终端服务器命名空间 40
复制对象句柄 40
第4章 进程 45
编写第一个Windows应用程序 46
进程的实例句柄 49
进程的前一个实例句柄 50
进程的命令行 51
进程的环境变量 52
亲缘性 55
进程的错误模式 55
当前驱动器和目录 55
当前目录 56
系统版本 57
CreateProcess函数 60
pszApplicationName和pszCommandLine 60
psaProcess、 psaThread和 bInheritHandles 62
fdwCreate 64
pvEnvironment 65
pszCurDir 66
psiStartInfo 66
ppiProcInfo 69
进程的终止 70
主线程的入口函数返回 71
ExitProcess函数 71
TerminateProcess函数 72
进程中所有线程的运行终止 73
进程的运行终止 73
子进程 74
枚举系统中运行的进程 76
第5章 作业 94
对作业进程的限制 96
把进程放入作业 102
终止作业中所有进程的运行 103
查询作业统计信息 103
作业通知信息 106
JobLab示例应用程序 108
第6章 线程的基本知识 126
创建线程的时机 126
何时不能创建线程 127
编写第一个线程函数 128
CreateThread函数 129
psa 130
cbStack 130
pfnStartAddr和pvParam 130
fdwCreate 131
pdwThreadID 132
终止线程 132
线程函数返回 132
ExitThread函数 133
TerminateThread函数 133
在进程终止运行时终止线程 134
线程终止运行时发生的操作 134
线程的一些内部细节 134
对于C/C++运行时库的考虑 137
Oops——错误地调用了CreateThread 144
不该调用的C/C++运行时库函数 145
线程的身份标识 145
第7章 线程的调度、优先级和亲缘性 149
挂起和恢复线程的运行 150
进程的挂起和唤醒 151
睡眠 152
线程切换 153
线程的运行时间 153
上下文环境切换 156
线程优先级 160
优先级的抽象说明 161
编程优先级 164
动态提高线程的优先级等级 166
为前台进程调整调度程序 167
SchedulingLab示例应用程序 168
亲缘性 176
第8章 用户模式下的线程同步 181
原子访问:互锁函数族 181
高速缓存行 186
高级线程同步 188
临界区 190
临界区准确的描述 192
临界区与循环锁 195
临界区与错误处理 195
有用的提示和技巧 196
第9章 线程与内核对象的同步 200
等待函数 201
成功等待的副作用 204
事件内核对象 205
等待定时器内核对象 215
用等待定时器给APC项排队 218
定时器的松散特性 220
信号量内核对象 220
互斥内核对象 222
释放问题 223
互斥对象与临界区的比较 224
Queue应用程序示例 225
线程同步对象表 234
其他线程同步函数 235
异步设备I/O 235
waitForInputIdle 235
MsgWaitForMultipleObjects(Ex) 236
WaitForDebugEvent 236
SignalobjectAndWait 237
第10章 线程同步工具包 239
临界区的实现:Optex 239
创建线程安全的数据类型和反信号量 251
单写入多读出程序的保护 263
WaitForMultipleExpressions函数 的实现 272
第11章 线程池 288
场景1:异步调用函数 289
场景2:按规定的时间间隔调用函数 291
场景3:在某个内核对象变为已通知状态时调用函数 297
场景4:异步I/O请求运行完成时调用函数 299
第12章 纤程 301
使用纤程 301
Counter示例应用程序 303
第13章Windows内存结构 313
进程的虚拟地址空间 313
虚拟地址空间分区 313
无效断点分配分区(适于Windows 2000和Windows 98) 314
MS-DOS/16位Windows应用程序兼容分区(仅适于Windows 98) 315
用户模式分区(适用Windows 2000和Windows 98) 315
64KB禁止进入分区(仅适用于Windows 2000) 316
共享的MMF分区(仅适用于Windows 98) 317
内核模式分区(使用于Windows 2000和Windows 98) 317
地址空间区域 317
在地址空间区域中提交物理存储器 318
物理存储器和页面文件 319
保护属性 321
Copy-On-write访问 322
特殊访问保护属性标志 323
综合使用所有元素 323
区域的内部详情 326
Windows 98上地址空间的差异 330
数据对齐的重要性 333
第14章 虚拟内存 338
系统信息 338
虚拟内存的状态 346
确定地址空间状态 352
VMQery函数 353
虚拟内存表应用程序示例 360
第15章 应用程序中虚拟内存的使用 371
地址空间中保留区域 371
在保留区域中提交存储器 373
同时进行保留区域并提交内存 373
何时提交物理存储器 374
物理存储器的回收和地址空间区域的释放 375
何时回收物理存储器 376
虚拟内存分配示例应用程序 377
改变保护属性 386
清除物理存储器内容 387
地址窗口扩展(仅使用于Windows 2000) 390
第16章 线程栈 404
Windows 98下的线程栈 406
C/C++运行时库中的栈检测函数 408
Summation示例应用程序 409
第17章 内存映射文件 416
内存映射的可执行文件和DLL文件 416
可执行文件或DLL的多个实例之间无法共享的静态数据 417
在可执行文件或DLL的多个实例之间共享静态数据 419
AppInst示例应用程序 424
内存映射数据文件 429
方法1:一个文件,一个缓存 429
方法2:两个文件,一个缓存 429
方法3:一个文件,两个缓存 430
方法4:一个文件,零个缓存 430
使用内存映射文件 430
步骤1:创建或打开文件内核对象 431
步骤2:创建文件映射内核对象 432
步骤3:将文件数据映射到进程地址空间 434
步骤4:进程地址空间中撤销文件数据的映像 437
步骤5和步骤6:关闭文件映射对象和文件对象 438
文件倒序示例应用程序 439
使用内存映射文件处理大文件 447
内存映射文件的一致性 448
设定内存映射文件的基地址 449
实现内存映射文件的具体细节 450
使用内存映射文件在进程之间实现数据共享 452
受页面文件支持的内存映射文件 452
稀疏提交的内存映射文件 459
第18章堆 473
进程的默认堆 473
创建辅助堆的原因 474
保护组件 474
更有效地管理内存 475
进行本地访问 475
减少线程同步开销 475
快速释放 475
创建辅助堆的方法 476
分配堆中的内存块 477
改变内存块的大小 478
获取内存块的大小 479
释放内存块 479
销毁堆 479
用C++程序使用堆 479
其他堆函数 482
第19章DLL基础 485
DLL与进程的地址空间 486
DLL的总体运行情况 487
创建DLL模块 490
导出的真正含义 492
使用非Visual C++工具创建DLL 493
创建可执行模块 494
运行可执行模块 497
第20章DLL高级技术 499
显式加载DLL模块和符号链接 499
显式加载DLL模块 499
显式卸载DLL模块 501
显式链接到导出符号 503
DLL的入口函数 504
DLL-PROCESS-ATTACH通知 505
DLL-PROCESS-DETACH通知 506
DLL-THREAD-ATTACH通知 508
DLL-THREAD-DETACH通知 509
顺序调用DllMain 509
D11Main和C/C++运行时库 512
延迟加载DLL 513
函数转发器 523
已知的DLL 523
DLL重定向 525
模块的基址重置 525
绑定模块 531
第21章 线程本地存储 533
动态TLS 533
静态TLS 537
第22章DLL注入以及API挂接 539
DLL注入:一个例子 539
使用注册表注入DLL 541
使用Windows钩子注入DLL 542
使用远程线程注入DLL 555
Inject Library示例应用程序 559
Image Walk DLL 567
使用特洛伊DLL注入DLL 570
将DLL作为调试程序注入 570
在Windows 98平台上使用内存映射文件注入代码 570
使用CreateProcess来注入代码 571
API挂接:一个例子 571
通过覆写代码实现API挂接 572
通过操作模块的导入部分来实现API挂接 573
LastMsgBoxInfo示例应用程序 576
第23章 终止处理例程 593
Funcensteinl 594
Funcenstein2 595
Funcenstein3 596
Funcfurterl 597
小测验:FuncaDoodleDoo 598
Funcenstein4 599
Funcaramal 600
Funcarama2 600
Funcarama3 601
Funcarama4:最终的边界 602
有关finally块的说明 603
Funcfurter2 604
SEH终止示例应用程序 605
第24章 异常处理程序和软件异常 608
通过例子理解异常过滤器和异常处理程序 608
Funcmeisterl 608
Funcmeister2 609
EXCEPTION-EXECUTE-HANDLER 611
一些有用的例子 611
全局展开 614
暂停全局展开 616
EXCEPTION-CONTINUE-EXECUTION 617
EXCEPTION-CONTINUE SEARCH 619
GetExceptionCode 621
与内存相关的异常 621
与异常相关的异常 622
与调试相关的异常 622
与整数相关的异常 622
与浮点数相关的异常 622
GetExceptionInformation 624
软件异常 628
第25章 未处理异常和C++异常 631
即时调试 633
关闭异常消息框 634
强制进程终止运行 634
包装一个线程函数 634
包装所有的线程函数 635
自动调用调试器 635
自己调用UnhandledExceptionFilter 636
UnhandledExceptionFilter函数的 内部细节 636
异常和调试程序 638
C++异常与结构化异常比较 652
第26章 窗口消息 657
线程的消息队列 657
将消息投送到一个线程的消息队列中 658
向窗口发送消息 660
唤醒一个线程 664
队列状态标志 665
从线程队列中提取消息的算法 666
使用内核对象或者队列状态标志来唤醒一个线程 669
使用消息发送数据 671
Windows处理ANSI/Unicode字符和字符串的方法 678
第27章 硬件输入模型与本地输入状态 681
原始输入线程 681
本地输入状态 682
键盘输入和焦点 683
鼠标光标管理 686
将虚拟输入队列和本地输入状态相关联 687
LISLab示例应用程序 689
LISWatch示例应用程序 704
附录A构建环境 713
附录B消息解析器、子控件宏以及API宏 725