本書是講解Windows 操作系統(tǒng)內(nèi)部機(jī)制的專著,作者從基本概念入手,全面系統(tǒng)地介紹了Windows的各種基本構(gòu)件,如進(jìn)程、線程、DLL和內(nèi)存管理等,并列舉了大量應(yīng)用程序,精辟地分析了構(gòu)件的使用方法,為掌握Windows 編程技巧提供了一條有效的捷徑。對(duì)于不同水平的Windows 編程人員來說,本書都具有極好的參考價(jià)值。
在開始介紹Microsoft Windows 的特性之前,必須首先了解Windows的各個(gè)函數(shù)是如何進(jìn)行錯(cuò)誤處理的。
當(dāng)調(diào)用一個(gè)Windows函數(shù)時(shí),它首先要檢驗(yàn)傳遞給它的的各個(gè)參數(shù)的有效性,然后再設(shè)法執(zhí)行任務(wù)。如果傳遞了一個(gè)無效參數(shù),或者由于某種原因無法執(zhí)行這項(xiàng)操作,那么操作系統(tǒng)就會(huì)返回一個(gè)值,指明該函數(shù)在某種程度上運(yùn)行失敗了。
目 錄
第一部分 程序員必讀
第1章 對(duì)程序錯(cuò)誤的處理 1
1.1 定義自己的錯(cuò)誤代碼 4
1.2 ErrorShow示例應(yīng)用程序 5
第2章 Unicode 11
2.1 字符集 11
2.1.1 單字節(jié)與雙字節(jié)字符集 11
2.1.2 Unicode:寬字節(jié)字符集 12
2.2 為什么使用Unicode 13
2.3 Windows 2000與Unicode 13
2.4 Windows 98與Unicode 13
2.5 Windows CE與Unicode 14
2.6 需要注意的問題 14
2.7 對(duì)COM的簡單說明 14
2.8 如何編寫Unicode源代碼 15
2.8.1 C運(yùn)行期庫對(duì)Unicode的支持 15
2.8.2 Windows定義的Unicode數(shù)據(jù)類型 17
2.8.3 Windows中的Unicode函數(shù)和ANSI
函數(shù) 17
2.8.4 Windows字符串函數(shù) 19
2.9 成為符合ANSI和Unicode的應(yīng)用程序 19
2.9.1 Windows字符串函數(shù) 19
2.9.2 資源 22
2.9.3 確定文本是ANSI文本還是Unicode
文本 22
2.9.4 在Unicode與ANSI之間轉(zhuǎn)換字符串 23
第3章 內(nèi)核對(duì)象 27
3.1 什么是內(nèi)核對(duì)象 27
3.1.1 內(nèi)核對(duì)象的使用計(jì)數(shù) 27
3.1.2 安全性 28
3.2 進(jìn)程的內(nèi)核對(duì)象句柄表 30
3.2.1 創(chuàng)建內(nèi)核對(duì)象 30
3.2.2 關(guān)閉內(nèi)核對(duì)象 32
3.3 跨越進(jìn)程邊界共享內(nèi)核對(duì)象 32
3.3.1 對(duì)象句柄的繼承性 32
3.3.2 改變句柄的標(biāo)志 35
3.3.3 命名對(duì)象 36
3.3.4 終端服務(wù)器的名字空間 39
3.3.5 復(fù)制對(duì)象句柄 39
第二部分 編程的具體方法
第4章 進(jìn)程 45
4.1 編寫第一個(gè)Windows應(yīng)用程序 46
4.1.1 進(jìn)程的實(shí)例句柄 49
4.1.2 進(jìn)程的前一個(gè)實(shí)例句柄 50
4.1.3 進(jìn)程的命令行 50
4.1.4 進(jìn)程的環(huán)境變量 51
4.1.5 進(jìn)程的親緣性 54
4.1.6 進(jìn)程的錯(cuò)誤模式 54
4.1.7 進(jìn)程的當(dāng)前驅(qū)動(dòng)器和目錄 54
4.1.8 進(jìn)程的當(dāng)前目錄 55
4.1.9 系統(tǒng)版本 56
4.2 CreateProcess函數(shù) 58
4.2.1 pszApplicationName和
pszCommandLine 59
4.2.2 psa Process、psa Thread和
binherit Handles 60
4.2.3 fdwCreate 62
4.2.4 pvEnvironment 64
4.2.5 pszCurDir 64
4.2.6 psiStartInfo 64
4.2.7 ppiProcInfo 67
4.3 終止進(jìn)程的運(yùn)行 69
4.3.1 主線程的進(jìn)入點(diǎn)函數(shù)返回 69
4.3.2 ExitProcess函數(shù) 69
4.3.3 TerminateProcess函數(shù) 70
4.3.4 進(jìn)程終止運(yùn)行時(shí)出現(xiàn)的情況 71
4.4 子進(jìn)程 72
4.5 枚舉系統(tǒng)中運(yùn)行的進(jìn)程 73
第5章 作業(yè) 91
5.1 對(duì)作業(yè)進(jìn)程的限制 93
5.2 將進(jìn)程放入作業(yè) 99
5.3 終止作業(yè)中所有進(jìn)程的運(yùn)行 99
5.4 查詢作業(yè)統(tǒng)計(jì)信息 100
5.5 作業(yè)通知信息 103
5.6 JobLab示例應(yīng)用程序 104
第6章 線程的基礎(chǔ)知識(shí) 121
6.1 何時(shí)創(chuàng)建線程 121
6.2 何時(shí)不能創(chuàng)建線程 122
6.3 編寫第一個(gè)線程函數(shù) 123
6.4 CreateThread函數(shù) 124
6.4.1 psa 124
6.4.2 cbStack 124
6.4.3 pfnStartAddr和pvParam 125
6.4.4 fdwCreate 126
6.4.5 pdwThreadID 126
6.5 終止線程的運(yùn)行 127
6.5.1 線程函數(shù)返回 127
6.5.2 ExitThread函數(shù) 127
6.5.3 TerminateThread函數(shù) 127
6.5.4 在進(jìn)程終止運(yùn)行時(shí)撤消線程 128
6.5.5 線程終止運(yùn)行時(shí)發(fā)生的操作 128
6.6 線程的一些性質(zhì) 129
6.7 C/C++運(yùn)行期庫的考慮 131
6.7.1 Oops—錯(cuò)誤地調(diào)用了Create Thread 138
6.7.2 不應(yīng)該調(diào)用的C/C++運(yùn)行期庫函數(shù) 138
6.8 對(duì)自己的ID概念應(yīng)該有所了解 139
第7章 線程的調(diào)度、優(yōu)先級(jí)和親緣性 142
7.1 暫停和恢復(fù)線程的運(yùn)行 143
7.2 暫停和恢復(fù)進(jìn)程的運(yùn)行 144
7.3 睡眠方式 145
7.4 轉(zhuǎn)換到另一個(gè)線程 145
7.5 線程的運(yùn)行時(shí)間 146
7.6 運(yùn)用環(huán)境結(jié)構(gòu) 148
7.7 線程的優(yōu)先級(jí) 152
7.8 對(duì)優(yōu)先級(jí)的抽象說明 153
7.9 程序的優(yōu)先級(jí) 156
7.9.1 動(dòng)態(tài)提高線程的優(yōu)先級(jí)等級(jí) 158
7.9.2 為前臺(tái)進(jìn)程調(diào)整調(diào)度程序 159
7.9.3 Scheduling Lab示例應(yīng)用程序 160
7.10 親緣性 167
第8章 用戶方式中線程的同步 172
8.1 原子訪問:互鎖的函數(shù)家族 172
8.2 高速緩存行 177
8.3 高級(jí)線程同步 178
8.4 關(guān)鍵代碼段 180
8.4.1 關(guān)鍵代碼段準(zhǔn)確的描述 182
8.4.2 關(guān)鍵代碼段與循環(huán)鎖 185
8.4.3 關(guān)鍵代碼段與錯(cuò)誤處理 185
8.4.4 非常有用的提示和技巧 186
第9章 線程與內(nèi)核對(duì)象的同步 190
9.1 等待函數(shù) 191
9.2 成功等待的副作用 194
9.3 事件內(nèi)核對(duì)象 195
9.4 等待定時(shí)器內(nèi)核對(duì)象 204
9.4.1 讓等待定時(shí)器給APC項(xiàng)排隊(duì) 207
9.4.2 定時(shí)器的松散特性 209
9.5 信標(biāo)內(nèi)核對(duì)象 210
9.6 互斥對(duì)象內(nèi)核對(duì)象 211
9.6.1 釋放問題 213
9.6.2 互斥對(duì)象與關(guān)鍵代碼段的比較 214
9.6.3 Queue示例應(yīng)用程序 214
9.7 線程同步對(duì)象速查表 223
9.8 其他的線程同步函數(shù) 224
9.8.1 異步設(shè)備I/O 224
9.8.2 WaitForInputIdle 224
9.8.3 MsgWaitForMultipleObjects (Ex) 225
9.8.4 WaitForDebugEvent 225
9.8.5 SingleObjectAndWait 226
第10章 線程同步工具包 228
10.1 實(shí)現(xiàn)關(guān)鍵代碼段:Optex 228
10.2 創(chuàng)建線程安全的數(shù)據(jù)類型和反信標(biāo) 239
10.3 單個(gè)寫入程序/多個(gè)閱讀程序的保護(hù) 251
10.4 實(shí)現(xiàn)一個(gè)WaitForMultipleExpressions
函數(shù) 259
第11章 線程池的使用 274
11.1 方案1:異步調(diào)用函數(shù) 275
11.2 方案2:按規(guī)定的時(shí)間間隔調(diào)用函數(shù) 277
11.3 方案3:當(dāng)單個(gè)內(nèi)核對(duì)象變?yōu)橐淹ㄖ獱顟B(tài)
時(shí)調(diào)用函數(shù) 283
11.4 方案4:當(dāng)異步I/O請(qǐng)求完成運(yùn)行時(shí)調(diào)用
函數(shù) 285
第12章 纖程 287
12.1 纖程的操作 287
12.2 Counter示例應(yīng)用程序 289
第三部分 內(nèi) 存 管 理
第13章 Windows的內(nèi)存結(jié)構(gòu) 299
13.1 進(jìn)程的虛擬地址空間 299
13.2 虛擬地址空間如何分區(qū) 300
13.2.1 NuLL 指針分配的分區(qū)—適用于
Windows 2000和Windows 98 300
13.2.2 MS-DOS/16位Windows 應(yīng)用程序兼容
分區(qū)—僅適用于Windows 98 301
13.2.3 用戶方式分區(qū)—適用于Windows 2000
和Windows 98 301
13.2.4 64 KB禁止進(jìn)入的分區(qū)—僅適用
于Windows 2000 302
13.2.5 共享的MMF分區(qū)—僅適用于
Windows 98 303
13.2.6 內(nèi)核方式分區(qū)—適用于Windows
2000和Windows 98 303
13.3 地址空間中的區(qū)域 303
13.4 提交地址空間區(qū)域中的物理存儲(chǔ)器 304
13.5 物理存儲(chǔ)器與頁文件 304
13.6 保護(hù)屬性 307
13.6.1 Copy-On-Write 訪問 308
13.6.2 特殊的訪問保護(hù)屬性的標(biāo)志 309
13.7 綜合使用所有的元素 309
13.7.1 區(qū)域的內(nèi)部情況 312
13.7.2 與Windows 98地址空間的差別 315
13.8 數(shù)據(jù)對(duì)齊的重要性 319
第14章 虛擬內(nèi)存 323
14.1 系統(tǒng)信息 323
14.2 虛擬內(nèi)存的狀態(tài) 330
14.3 確定地址空間的狀態(tài) 336
14.3.1 VMQuery函數(shù) 337
14.3.2 虛擬內(nèi)存表示例應(yīng)用程序 343
第15章 在應(yīng)用程序中使用虛擬內(nèi)存 354
15.1 在地址空間中保留一個(gè)區(qū)域 354
15.2 在保留區(qū)域中的提交存儲(chǔ)器 355
15.3 同時(shí)進(jìn)行區(qū)域的保留和內(nèi)存的提交 356
15.4 何時(shí)提交物理存儲(chǔ)器 357
15.5 回收虛擬內(nèi)存和釋放地址空間區(qū)域 358
15.5.1 何時(shí)回收物理存儲(chǔ)器 359
15.5.2 虛擬內(nèi)存分配的示例應(yīng)用程序 360
15.6 改變保護(hù)屬性 368
15.7 清除物理存儲(chǔ)器的內(nèi)容 369
15.8 地址窗口擴(kuò)展—適用于
Windows 2000 372
第16章 線程的堆棧 385
16.1 Windows 98下的線程堆棧 387
16.2 C/C++運(yùn)行期庫的堆棧檢查函數(shù) 389
16.3 Summation示例應(yīng)用程序 390
第17章 內(nèi)存映射文件 397
17.1 內(nèi)存映射的可執(zhí)行文件和DLL
文件 397
17.1.1 可執(zhí)行文件或DLL的多個(gè)實(shí)例
不能共享靜態(tài)數(shù)據(jù) 398
17.1.2 在可執(zhí)行文件或DLL的多個(gè)實(shí)
例之間共享靜態(tài)數(shù)據(jù) 400
17.1.3 AppInst示例應(yīng)用程序 404
17.2 內(nèi)存映射數(shù)據(jù)文件 409
17.2.1 方法 1:一個(gè)文件,一個(gè)緩存 409
17.2.2 方法 2:兩個(gè)文件,一個(gè)緩存 409
17.2.3 方法 3:一個(gè)文件,兩個(gè)緩存 410
17.2.4 方法 4:一個(gè)文件,零緩存 410
17.3 使用內(nèi)存映射文件 410
17.3.1 步驟 1:創(chuàng)建或打開文件內(nèi)核
對(duì)象 411
17.3.2 步驟 2:創(chuàng)建一個(gè)文件映射內(nèi)核
對(duì)象 412
17.3.3 步驟 3:將文件數(shù)據(jù)映射到進(jìn)程
的地址空間 414
17.3.4 步驟4:從進(jìn)程的地址空間中撤消
文件數(shù)據(jù)的映像 416
17.3.5 步驟 5和步驟 6:關(guān)閉文件映射對(duì)象
和文件對(duì)象 417
17.3.6 文件倒序示例應(yīng)用程序 418
17.4 使用內(nèi)存映射文件來處理大文件 426
17.5 內(nèi)存映射文件與數(shù)據(jù)視圖的相關(guān)性 427
17.6 設(shè)定內(nèi)存映射文件的基地址 428
17.7 實(shí)現(xiàn)內(nèi)存映射文件的具體方法 429
17.8 使用內(nèi)存映射文件在進(jìn)程之間共享
數(shù)據(jù) 431
17.9 頁文件支持的內(nèi)存映射文件 431
17.10 稀疏提交的內(nèi)存映射文件 438
第18章 堆棧 451
18.1 進(jìn)程的默認(rèn)堆棧 451
18.2 為什么要?jiǎng)?chuàng)建輔助堆棧 452
18.2.1 保護(hù)組件 452
18.2.2 更有效的內(nèi)存管理 453
18.2.3 進(jìn)行本地訪問 453
18.2.4 減少線程同步的開銷 453
18.2.5 迅速釋放堆棧 453
18.3 如何創(chuàng)建輔助堆棧 454
18.3.1 從堆棧中分配內(nèi)存塊 455
18.3.2 改變內(nèi)存塊的大小 456
18.3.3 了解內(nèi)存塊的大小 456
18.3.4 釋放內(nèi)存塊 457
18.3.5 撤消堆棧 457
18.3.6 用C++程序來使用堆棧 457
18.4 其他堆棧函數(shù) 460
第四部分 動(dòng)態(tài)鏈接庫
第19章 DLL基礎(chǔ) 463
19.1 DLL與進(jìn)程的地址空間 464
19.2 DLL的總體運(yùn)行情況 465
19.3 創(chuàng)建DLL模塊 467
19.3.1 輸出的真正含義是什么 469
19.3.2 創(chuàng)建用于非Visual C++工具
的DLL 471
19.4 創(chuàng)建可執(zhí)行模塊 472
19.5 運(yùn)行可執(zhí)行模塊 474
第20章 DLL的高級(jí)操作技術(shù) 477
20.1 DLL模塊的顯式加載和
符號(hào)鏈接 477
20.1.1 顯式加載DLL模塊 478
20.1.2 顯式卸載DLL模塊 479
20.1.3 顯式鏈接到一個(gè)輸出符號(hào) 480
20.2 DLL的進(jìn)入點(diǎn)函數(shù) 481
20.2.1 DLL_PROCESS_ATTACH通知 482
20.2.2 DLL_PROCESS_DETACH通知 483
20.2.3 DLL_THREAD_ATTACH通知 485
20.2.4 DLL_THREAD_DETACH通知 485
20.2.5 順序調(diào)用DllMain 486
20.2.6 DllMain與C/C++運(yùn)行期庫 488
20.3 延遲加載DLL 489
20.4 函數(shù)轉(zhuǎn)發(fā)器 499
20.5 已知的DLL 499
20.6 DLL轉(zhuǎn)移 500
20.7 改變模塊的位置 501
20.8 綁定模塊 506
第21章 線程本地存儲(chǔ)器 509
21.1 動(dòng)態(tài)TLS 509
21.2 靜態(tài)TLS 513
第22章 插入DLL和掛接API 515
22.1 插入DLL:一個(gè)例子 515
22.2 使用注冊(cè)表來插入DLL 517
22.3 使用Windows掛鉤來插入DLL 518
22.4 使用遠(yuǎn)程線程來插入DLL 531
22.4.1 Inject Library 示例應(yīng)用程序 534
22.4.2 Image Walk DLL 541
22.5 使用特洛伊DLL來插入DLL 544
22.6 將DLL作為調(diào)試程序來插入 544
22.7 用Windows 98上的內(nèi)存映射文件
插入代碼 544
22.8 用CreateProcess插入代碼 544
22.9 掛接API的一個(gè)示例 545
22.9.1 通過改寫代碼來掛接API 546
22.9.2 通過操作模塊的輸入節(jié)來掛接API 546
22.9.3 LastMsgBoxInfo示例應(yīng)用程序 549
第五部分 結(jié)構(gòu)化異常處理
第23章 結(jié)束處理程序 565
23.1 通過例子理解結(jié)束處理程序 566
23.2 Funcenstein1 566
23.3 Funcenstein2 566
23.4 Funcenstein3 568
23.5 Funcfurter1 568
23.6 突擊測驗(yàn):FuncaDoodleDoo 569
23.7 Funcenstein4 570
23.8 Funcarama1 571
23.9 Funcarama2 572
23.10 Funcarama3 572
23.11 Funcarama4:最終的邊界 573
23.12 關(guān)于finally塊的說明 574
23.13 Funcfurter2 575
23.14 SEH結(jié)束處理示例程序 576
第24章 異常處理程序和軟件異常 578
24.1 通過例子理解異常過濾器和異常處理
程序 578
24.1.1 Funcmeister1 578
24.1.2 Funcmeister2 579
24.2 EXCEPTION_EXECUTE_HANDLER 580
24.2.1 一些有用的例子 581
24.2.2 全局展開 583
24.2.3 暫停全局展開 585
24.3 EXCEPTION_CONTINUE_
EXECUTION 586
24.4 EXCEPTION_CONTINUE_
SEARCH 588
24.5 Get Exception Code 589
24.6 Get Exception Information 592
24.7 軟件異常 595
第25章 未處理異常和C++異常 598
25.1 即時(shí)調(diào)試 600
25.2 關(guān)閉異常消息框 601
25.2.1 強(qiáng)制進(jìn)程終止運(yùn)行 601
25.2.2 包裝一個(gè)線程函數(shù) 601
25.2.3 包裝所有的線程函數(shù) 601
25.2.4 自動(dòng)調(diào)用調(diào)試程序 602
25.3 程序員自己調(diào)用UnhandledException
Filter 602
25.4 UnhandledExceptionFilter函數(shù)的一些
細(xì)節(jié) 603
25.5 異常與調(diào)試程序 604
25.6 C++異常與結(jié)構(gòu)性異常的對(duì)比 618
第六部分 窗 口
第26章 窗口消息 623
26.1 線程的消息隊(duì)列 623
26.2 將消息發(fā)送到線程的消息隊(duì)列中 625
26.3 向窗口發(fā)送消息 626
26.4 喚醒一個(gè)線程 630
26.4.1 隊(duì)列狀態(tài)標(biāo)志 630
26.4.2 從線程的隊(duì)列中提取消息的
算法 631
26.4.3 利用內(nèi)核對(duì)象或隊(duì)列狀態(tài)標(biāo)
志喚醒線程 634
26.5 通過消息發(fā)送數(shù)據(jù) 636
26.6 Windows如何處理ANSI/Unicode
字符和字符串 642
第27章 硬件輸入模型和局部輸入狀態(tài) 645
27.1 原始輸入線程 645
27.2 局部輸入狀態(tài) 646
27.2.1 鍵盤輸入與焦點(diǎn) 647
27.2.2 鼠標(biāo)光標(biāo)管理 649
27.3 將虛擬輸入隊(duì)列同局部輸入狀態(tài)掛接
在一起 651
27.3.1 LISLab 示例程序 652
27.3.2 LISWatch 示例程序 666
第七部分 附 錄
附錄A 建立環(huán)境 675
附錄B 消息分流器、子控件宏和API宏 686