第一课[编辑器设置-VC++6.0]
用VC++6.0直接生成driver
內容: 
用VC++ 6.0來編輯(不是編譯)Driver的源文件是很不錯的選擇,尤其是搭配用Visual Assist,更方便了。編輯完了,就在VC++里面build,就更方便了。 
我在M$的站點參考了些,DS生成的dsw、和build生成的log文件,都有參考。實際上,M$站點上就是根據build的log文件來改VC的Setting的。Me too 
限于2K DDK,因為XP DDK和2003 DDK不需要VC++6.0了。并且我用VC6來build的時候,會告訴你“Compiler version not supported by Windows DDK”,不過沒有進一步去嘗試。(注:有個bt的方式,照樣添加XP的setting,當然路徑要設置對,然后用UltraEdit修改dsp文件,根據配置把對應的cl、midl、rc、link什么的改為XP DDK的,嘿嘿) 
DDK自己帶了link,98、2K DDK似乎都是VC5的,如果像我這樣做,實際上是用VC6的link了。 
不考慮source、dir、make文件。 
DDK的build,其實算是一個調用nmake工具,而nmake去調相應的文件如cl.exe、link.exe等。 
cl的選項設置,主要注意DDK的include路徑問題,link的選項,就是要讓link去link出一個sys而不是exe,呵呵 
預備工作: 
1、安裝了DDK(呵呵,說句廢話)。目錄名字最好不要帶空格。 
2、建立一個workspace,把自己的c、h、rc等文件加進去。 
3、Configurations,添加Checked、Free,不要Debug、Release(其實這并沒有什么必要,Checked、Debug,看你怎么叫了)。 
剩下的就是改各個設置,讓VC為你build出一個sys文件了。 
我們一個一個的來。所有的改動,都在Project->Setting下面。主要集中在C/C++和Link下。 
1、 General,就一個,Not Using MFC; 
2、 Debug,沒有什么可改的; 
3、 C/C++: 
1.1 General: 
3.1.1 Warning level,用Level3,驅動嘛,穩定壓倒一切,而且DDK sample就是warning 3的,Warnings as errors選上; 
3.1.2 Optimizations,對checked,我是Disable(Debug),省的用SoftIce的時候會有變量說Watch不了,對Free的,我是Customize,后面會講到; 
3.1.3 Debug Info,Free當然是沒有了,你要加上是你的事了,Checked,我用C7;VC默認的Program Database for /"Edit & Continue/",和link的/driver選項沖突; 
3.1.4 Preprocessor definitions,有些我并沒有弄清楚,有些可能是DS用的,大概說說。下面是我某個dsw用的。 
RDRDBG, SRVDBG, FPO=0, WIN32=100, STD_CALL, CONDITION_HANDLING=1, NT_UP=1, NT_INST=0, _NT1X_=100, WINNT=1, _WIN32_WINNT=0x0400, WIN32_LEAN_AND_MEAN=1, DEVL=1, _DLL=1, _X86_=1, $(CPU)=1, NTVERSION=/'WDM/', WINVER=0x500, NTDEBUG=ntsd,DBG=1 
STD_CALL不必說了,driver的函數全部是__stdcall的,其實在其他地方有設置的。 
WINVER=0x500,是因為你是for 2K的。XP的是0x501,不過沒有用,反正不能用VC6了。 
_X86_=1,沒有的話,嘿嘿。Alpha等CPU不是這個值了。 
DBG,free的話,就不要定義,或為0。 
FPO,checked的為0,free的為1。我想應該是指Fram-Pointer Omission吧 
NTDEBUG= checked ? ntsd : ntsdnodebug 
WIN32_LEAN_AND_MEAN, Exclude rarely-used stuff from Windows headers,non-mfc的,用這個能減少build的時間。多些definitions也沒有關系,不影響其他的就好 
NT_UP,為0表示是MP,多處理器的,1表示你在單處理器用的。 
NT_INST, set to turn on instrumentation 
根據driver類型,你可能還要加上別的preprocessor definitions,比如NDIS的IMD,就要NDIS50, NDIS_MINIPORT_DRIVER, NDIS50_MINIPORT。 
3.1.5 Project Options 你只需要最后添加幾個就好了,包括/QIfdiv- /QIf /QI0f,可以在MSDN上查到。值得一提是VC產生的workspace的debug setting,默認有個GZ選項,Catch Release-Build Errors in Debug Build,編譯的時候會說error LNK2001: unresolved external symbol __chkesp,去掉就好了。 
1.2 C++ Language 沒有什么說的,不要RTTI, exception handling看你用沒有用了。 
1.3 Code Generation 把Calling convention用__stdcall,其余不管了(記得STD_CALL嗎); 
1.4 Customize 沒有什么可說的,我一般是function-level linking,因為加了GF選項,Eliminate duplicate strings我也就不選了; 
1.5 Listing Files 就Listing file type可說一下。你要想看匯編代碼的話,可以在這里改改; 
1.6 Optimizations checked自然是disable了,free的,我選是Full optimization和Frame_Popinter Omission,以及Only __inline,其實這看個人了; 
1.7 Precompiled Headers 這個就不說了,看MSDN吧,默認也可以; 
1.8 Preprocessor Preprocessor definitions前面已經說了,重點在Additional include directories上,$(BASEDIR)incddkwdm, $(BASEDIR)incddk, $(BASEDIR)inc, $(BASEDIR)incwin98, ....inc,這是我某個dsw的,所以,BASEDIR的環境變量要設置好,我就順便用DS的工具來start VC,它恰好幫你設置了,當然你也可以直接寫上你的DDK的安裝路徑。找不到include 路徑,會引發一大堆錯誤,比如WDM.H有錯誤等。。。是很多人問的問題; 
4、 好了,輪到Link了 
4.1 General 選Ignore all default libraries,你可以選上generate map file, map文件有時候很有用的;Checked的當然要選上generate debug info, Link incrementally不選;Objects/library modules,添加wdm.lib等,ntoskrnl.lib好像輸出了諸如sprintf、strcat等一些函數(注1),根據driver可能還要其他的,比如ndis.lib;別忘了Output file name改成yourname.sys,可不是yourname.exe啊 
4.2 Debug 就checked要改改,選上Debug info,我是選Both formats的; 
4.3 Input 重點之一,Additional lib path,$(BASEDIR)libchki386,這是我的一個dsw用的,checked填checked lib的路徑,free填freelib的路徑 
4.4 Output 在Entry-point symbol,填DriverEntry,或_DriveEntry@8,一樣; 
根據link的輸出來看,Base address應該填0x10000,Stack,Reserve的應該填0x40000,Commit填0x1000;Version Info,自己填吧; 
4.5 Project Options,重點,很多選項要直接在這里添加。要添加的包括: 
/machine:IX86,CPU相關的 
/debug:full,/debugtype:both 根據M$站點的說法,為了使WinDbg能找到你的symbol,這兩是都要的,而且還要單獨用linker來link一次,VC不認/debug:full,free就沒有這個問題了。根據M$的方法,可以這樣:寫個lnk文件,在Post-build step,再link一次,添加link @yourlnk.lnk,這個lnk文件,可以從log文件提取,如果不用WinDbg,就無所謂了; 
/driver,Use this linker option to build a Windows NT kernel mode driver,MSDN說的 
/IGNORE:4001,4037,4039,4065,4070,4078,4087,4089,4096,4210 查MSDN 
/MERGE:_PAGE=PAGE /MERGE:_TEXT=.text /SECTION:INIT,d,DriverEntry就可以放到INIT section去。 
/FULLBUILD 
/RELEASE,在文件頭添加checksum 
/FORCE:MULTIPLE 
/OPT:REF /OPT:ICF /align:0x20 /osversion:5.00 /subsystem:native 
特別注意/subsystem:native和/driver不要漏了。 
一長串的/ignore可以讓你即使選warning level 4也能通過,warning level 4有點變態的 
其實上面說的大部分是廢話:),大部分選項,你看看build輸出的log文件,就能知道了。這樣你也可以根據你的driver,自己添加一些必要的選項。 
越寫越覺得自己無知 
有什么不對的地方,請指出。 
另外還有用個bat文件在VC下build的方法等,不多說了。 
注1:2003的DDK帶了個ntstrsafe.h,有一些很方便的string函數可以用,而且保證安全,在NT、2K也可以用的,我把它貼上來。用ntoskrnl輸出的如strcpy等函數現在就沒有必要了。 
------------------------------------------------------- 
關于DbgPrint的一個問題: 
我測試驅動的時候碰到藍屏,用si的stack命令一看,居然是KdPrint引起的,很是ft。DbgPrint調用_vsnprintf,它又調用wctomb,就藍了,沒有記錯的話是0xA,IRQL_NOT_LESS_OR_EQUAL。同樣的上下文,其他地方多次用KdPrint都沒有問題。 
我想原因可能在spinlock上。這個DbgPrint在KeAcquireSpinLock和Release之間的。把這個KdPrint注釋掉,就好了。 
因為SpinLock,就提升到dispatch level了,這個時候不能用%wc and %ws的(必須在passive level),而我好像用了,so... 
自己沒有注意看DDK。 
------------------------------------------------------ 
關于優化碰到的一個問題: 
這個問題應該是優化引起的,因為改了就能用了。 
事情是這樣地:一個NDIS5的miniport驅動,在重新搭建的編譯環境下編譯的可以在2K下run的,結果在98下一加載就掛了(他們說以前可以在98下用的),ft,找了半天發現是優化選項的緣故:以前用的是最小代碼優化,而新的用了最快代碼優化,就不行了。這樣也會出問題!?真。。。反正改為最小代碼優化就能用了。 
------------------------------------------------------ 
關于浮點運算: 
用KeSaveFloatingPointState和KeRestoreFloatingPointState 
不過我一直沒有機會用 
直到前幾天,我用上了。我發現直接用這兩函數,會報錯,說不能link 外部的__fltused。 
同事加了個全局的ulong __fltused = 1;錯誤沒有了,可是結果并不正確。sprintf(/"%3f/",x)不對,x是個float。 
后來發現,加上msvcrt.lib就好了,也不用定義全局的變量。 
Walt Oney有更全面的解釋,哪天貼上來 
------------------------------------------------------- 
把Walt Oney關于浮點運算的一個帖子貼上來吧 
From: Walter Oney 
Subject: Re: Using Floating variable in a WDM driver 
Date: 1999/09/22
Message-ID: <37E8B83D.AFA107ED@oneysoft.com>#1/1 
Content-Transfer-Encoding: 7bit 
References: <7sa8kg$elc$1@news.entreprises.cegetel.fr> 
Content-Type: text/plain; charset=us-ascii 
X-Complaints-To: abuse@rcn.com 
X-Trace: GjGUm2k/h6dchDSW3dAtWL+k38GPA70bhhY4oqkqhG8= 
Organization: Walter Oney Software 
Mime-Version: 1.0 
Reply-To: waltoney@oneysoft.com 
NNTP-Posting-Date: 22 Sep 1999 11:08:34 GMT 
Newsgroups: comp.os.ms-windows.programmer.drivers,comp.os.ms-windows.programmer.nt.kernel-mode 
David BOUYEURE wrote: 
> I want to use afloating variable in my driver (98 WDM). 
> I have this error at compile time : 
> /"unresolved external symbol __fltused/" 
> I guess I have to link with a special lib, but I haven/'t found wich one. 
The problem is worse than just finding the right library, unfortunately. The C compiler/'s floating point support assumes that it will be operating in a an application environment where you can initialize the coprocessor, install some exception handlers, and then blast away. It also assumes that the operating system will take care of saving and restoring each thread/'s coprocessor context as required by all the 
thread context switches that occur from then on. 
These assumptions aren/'t usually true in a driver. Furthermore, the runtime library support for coprocessor exceptions can/'t work because there/'s a whole bunch of missing infrastructure. 
What you basically need to do is write your code in such a way that you initialize the coprocessor each time you want to use it (don/'t forget KeSaveFloatingPointState and KeRestoreFloatingPointState). Set things up so that the coprocessor will never generate an exception, too. Then you 
can simply define the symbol __fltused somewhere to satisfy the linker.(All that symbol usually does is drag in the runtime support. You don/'t want that support becuase, as I said, it won/'t work in kernel mode.) You/'ll undoubtedly need some assembly language code for the initialization steps. 
If you have a system thread that will be doing all your floating point math, you can initialize the coprocesor once at the start of the thread. 
The system will save and restore your state as necessary from then on. 
Don/'t forget that you can only do floating point at IRQL < 
DISPATCH_LEVEL. 
-- 
Walter Oney 
[url] http://www.oneysoft.com[/url] 
-------------------------------------------------------- 
關于一些C的字符處理函數 
其實ntoskrnl.exe輸出了不少的諸如atoi、sprintf等函數(2K的,XP的沒有驗證),用dumpbin帶exports參數可以看到。 
那么至少,這些函數在passive level是可以用的。import lib應該就是ntoskrnl.lib了。 
2k ntoskrnl.exe輸出的一些函數copy到下面吧 能用的函數還是不少的 
1155 482 0005DC88 _itoa 
1156 483 0005DD11 _itow 
1159 486 0005DD3F_snprintf 
1160 487 0005DD90 _snwprintf 
1161 488 0005DE00 _stricmp 
1162 489 0005DE8C_strlwr 
1163 48A0005DEB0 _strnicmp 
1164 48B 0005DF60 _strnset 
1165 48C0005DF90 _strrev 
1166 48D 0005DFC0 _strset 
1167 48E 0005DFE0 _strupr 
1168 48F0005E003 _vsnprintf 
1169 490 0005E053 _wcsicmp 
1170 491 0005E09E _wcslwr 
1171 492 0005E0C8 _wcsnicmp 
1172 493 0005E11D _wcsnset 
1173 494 0005E143 _wcsrev 
1174 495 0005E173 _wcsupr 
1175 496 0005E228 atoi 
1176 497 0005E19D atol 
1177 498 0005E2B1 isdigit 
1178 499 0005E289 islower 
1179 49A0005E32E isprint 
1180 49B 0005E306 isspace 
1181 49C0005E261 isupper 
1182 49D 0005E2D9 isxdigit 
1183 49E 0005E35Cmbstowcs 
1184 49F0005E3CF mbtowc 
1185 4A0 0005E410 memchr 
1186 4A1 0005E4C0 memcpy 
1187 4A2 0005E800 memmove 
1188 4A3 0005EB40 memset 
1189 4A4 0005EB98 qsort 
1190 4A5 0005ED64 rand 
1191 4A6 0005ED82 sprintf 
1192 4A7 0005ED5Asrand 
1193 4A8 0005EDF0 strcat 
1194 4A9 0005EEE0 strchr 
1195 4AA 0005EFA0 strcmp 
1196 4AB 0005EDE0 strcpy 
1197 4AC0005F030 strlen 
1198 4AD 0005F0B0 strncat 
1199 4AE 0005F1E0 strncmp 
1200 4AF 0005F220 strncpy 
1201 4B0 0005F320 strrchr 
1202 4B1 0005F350 strspn 
1203 4B2 0005F390 strstr 
1204 4B3 0005F410 swprintf 
1205 4B4 0005F47Ftolower 
1206 4B5 0005F4B3 toupper 
1207 4B6 0005F504 towlower 
1208 4B7 0005F51Ftowupper 
1209 4B8 0005F529 vsprintf 
1210 4B9 0005F57Awcscat 
1211 4BA 0005F5C9 wcschr 
1212 4BB 0005F5F2 wcscmp 
1213 4BC 0005F5A4 wcscpy 
1214 4BD 0005F62B wcscspn 
1215 4BE 0005F66Cwcslen 
1216 4BF 0005F689 wcsncat 
1217 4C0 0005F6C9 wcsncmp 
1218 4C1 0005F701 wcsncpy 
1219 4C2 0005F73E wcsrchr 
1220 4C3 0005F77E wcsspn 
1221 4C4 0005F7C0 wcsstr 
1222 4C5 0005F806 wcstombs 
1223 4C6 0005F879 wctomb 
------------------------------------------------------- 
ntstrsafe.h文件和ntstrsafe.lib文件 
------------------------------------------------------ 
利用DS的插件,可以在VC6和VC.NET下,調用DDK的cl和link,來編譯驅動。 
但是,如果沒有裝DS呢? 
對vc6,你可以這樣啟動你的dsw: 
set BASEDIR=... 
start msdev my.dsw 
或者,比較好的是先進入DDK的build環境,然后 
start msdev my.dsw /useenv 
.NET可以類似處理,就不說了 
[編輯 - 6/30/04 by arthurtu] 
[編輯 - 9/7/04 by arthurtu]
[編輯 - 5/17/05 by arthurtu]
總結
以上是生活随笔為你收集整理的第一课[编辑器设置-VC++6.0]的全部內容,希望文章能夠幫你解決所遇到的問題。
 
                            
                        - 上一篇: 连表查询使用in_SQL 组合查询
- 下一篇: Windows 7 仅是Windows
