?這個函數(shù)可以創(chuàng)建或打開一個對象的句柄,憑借此句柄就可以控制這些對象:
控制臺對象、通信資源對象、目錄對象(只能打開)、磁盤設備對象、文件對象、郵槽對象、管道對象。
??? 函數(shù)原型:
1?????HANDLE?CreateFile( 2?????????LPCTSTR?lpFileName,?????????????????????????//?文件名 3?????????DWORD?dwDesiredAccess,??????????????????????//?訪問模式 4?????????DWORD?dwShareMode,??????????????????????????//?共享模式 5?????????LPSECURITY_ATTRIBUTES?lpSecurityAttributes,?//?安全屬性(也即銷毀方式) 6?????????DWORD?dwCreationDisposition,????????????????//?how?to?create 7?????????DWORD?dwFlagsAndAttributes,?????????????????//?文件屬性 8?????????HANDLE?hTemplateFile????????????????????????//?模板文件句柄 9?????????);
?
【參數(shù)】
1、lpFileName
??? 一個指向無終結符的字符串的指針,來指明要創(chuàng)建或打開的對象的名字。
??? 在Windows NT/2000/XP平臺上:如果用ANSI版本的函數(shù),字符串長度應限制在MAX_PATH;如果用Unicode版本的函數(shù),這個限制可以擴充到32000個Unicode字符。
??? 在Windows95/98/Me平臺上:只能用ANSI版本的函數(shù),字符串長度限制在MAX_PATH。
2、dwDesiredAccess
??? 指明對象的控制模式。一個應用程序可以包含讀控制、寫控制、讀/寫控制、設備查詢控制。
這個參數(shù)的取值可以是下面這些的組合:
??? 0???????????????????????????????????????????? 指定設備查詢控制:程序可以不訪問設備就查詢到設備屬性。
??? GENERIC_READ??????????????? 指定讀控制,可以從對象中讀取數(shù)據(jù)(指針將可以移動)。
??? GENERIC_WRITE?????????????? 指定寫控制,可以向對象中寫數(shù)據(jù)(指針將可以移動)。
??? ----------------------------------------------------------------------
??? 另外,還可以指定下面的控制標志:
標準控制權限(16-23位掩碼):
??? DELETE???????????????????? 刪除對象的權限。
??? READ_CONTROL??? 從對象的安全描述符中讀取信息的權限,但不包括SACL(系統(tǒng)訪問控制列表)中的信息。
??? WRITE_DAC????????????? 修改對象安全描述符中的DACL(隨機訪問控制列表)的權限
??? WRITE_OWNER????? 修改對象安全描述符中的屬主的權限
??? SYNCHRONIZE???? 同步化使用對象的權限,即可以創(chuàng)建一個線程等待信號量釋放(但有些對象不支持這個權限)。
??? STANDARD_RIGHTS_REQUIRED??? 等價于前面四種權限的總合(通常這四種是必須具有的權限)。
??? STANDARD_RIGHTS_READ??????? 一般等價于READ_CONTROL
??? STANDARD_RIGHTS_WRITE?????? 一般等價于READ_CONTROL
??? STANDARD_RIGHTS_EXECUTE???? 一般等價于READ_CONTROL
??? STANDARD_RIGHTS_ALL???????? 等價于前面五種權限的總合。
特殊控制權限(0-15位掩碼):
??? SPECIFIC_RIGHTS_ALL
??? ACCESS_SYSTEM_SECURITY
??? MAXIMUM_ALLOWED
??? GENERIC_READ
??? GENERIC_WRITE
??? GENERIC_EXECUTE
??? GENERIC_ALL?
注:實質上是通過ACCESS_MASK結構體的一個雙字值來設置標準權限、特殊權限和一般權限的。
3、dwShareMode
??? 指定對象的共享模式。如果dwShareMode==0,表示是互斥使用的。如果CreateFile打開成功,則別的程序只能等到當前程序關閉對象句柄CloseHandle后才能在打開或使用。
??? 使用下面這些值的組合來表示對象的共享模式:
??? FILE_SHARE_DELETE?????? Windows NT/2000/XP:打開操作只有在刪除請求發(fā)生時才能返回成功。
??? FILE_SHARE_READ???????????????? 打開操作只有在讀控制請求發(fā)生時才能返回成功。
??? FILE_SHARE_WRITE??????????????? 打開操作只有在寫控制請求發(fā)生時才能返回成功。
4、lpSecurityAttributes
??? 一個指向SECURITY_ATTRIBUTES結構對象的指針,決定返回的句柄是否被子進程所繼承。如果lpSecurityAttributes參數(shù)為NULL,句柄就不能被子進程繼承。
??? 在Windows NT/2000/XP平臺下:lpSecurityDescriptor這個成員指明了這個對象的安全描述符。如果lpSecurityAttributes參數(shù)為NULL,對象將獲得一個默認的安全描述符。目標文件系統(tǒng)必須為這個參數(shù)的在文件上的有效操作保證安全性。
1?typedef?struct?_SECURITY_ATTRIBUTES?{? 2???????DWORD?nLength;?//結構體的大小(字節(jié)為單位),即siziof(SECURITY_ATTRIBUTES) 3???????LPVOID?lpSecurityDescriptor;?//指向對象的安全描述符的指針,控制對象的共享屬性。在Windows?95/98/Me平臺?????????????????????????????????????????????????????//上這個成員被忽略。 4???????BOOL???bInheritHandle;?//指明當一個新的子進程創(chuàng)建時,是否繼承當前返回的句柄 5?}?SECURITY_ATTRIBUTES,?*PSECURITY_ATTRIBUTES;
?
5、dwCreationDisposition
??? 指明當打開的對象存在或不存在的時候各需怎樣處理。這個參數(shù)必須是一下值的其中之一:
??? CREATE_NEW??????????? 創(chuàng)建新文件/對象(當對象已經存在是將返回失敗)。
??? CREATE_ALWAYS???????? 總是創(chuàng)建(如果對象存在就覆蓋它,清除當前屬性,把文件屬性和dwFlagsAndAttributes指定的標志相結合)。
??? OPEN_EXISTING???????? 打開文件(如果不存在就返回失敗)。
??? OPEN_ALWAYS????? 存在就打開;若不存在,假如dwCreationDisposition==CREATE_NEW就創(chuàng)建一個新文件。
??? TRUNCATE_EXISTING???? 存在就打開,且清空文件內容(至少要有GENERIC_WRITE權限);若文件不存在就返回失敗。
6、dwFlagsAndAttributes
??? 指定文件屬性和標志??梢允且韵轮档娜我饨M合(只有FILE_ATTRIBUTE_NORMAL必須單獨使用,唯一例外):
Attribute:
??? FILE_ATTRIBUTE_ARCHIVE???????????????? 文件存檔(備份或移動時會對文件做標記)。
??? FILE_ATTRIBUTE_ENCRYPTED?????????????? 加密(對文件來說是內容加密,對目錄來說是對將來新建的文件默認為加密屬性),與此同時,如果還設置了FILE_ATTRIBUTE_SYSTEM屬性,當前這個屬性將無效。
??? FILE_ATTRIBUTE_HIDDEN????????????????? 隱藏屬性。
??? FILE_ATTRIBUTE_NORMAL????????????????? 文件沒有其他屬性設置,此屬性只能單獨使用才合法。
??? FILE_ATTRIBUTE_NOT_CONTENT_INDEXED???? 不建立內容索引。
??? FILE_ATTRIBUTE_OFFLINE???????????????? 脫機屬性。文件內容暫時不可用。此屬性被Remote Storage軟件所用,不能任意更改。
??? FILE_ATTRIBUTE_READONLY??????????????? 只讀文件屬性。應用程序不能寫或刪除。
??? FILE_ATTRIBUTE_SYSTEM????????????????? 文件是系統(tǒng)文件或被操作系統(tǒng)互斥地使用。
??? FILE_ATTRIBUTE_TEMPORARY?????????????? 臨時文件,使用過程中盡量留在內存以保證存取速度。
Flag:
??? FILE_FLAG_WRITE_THROUGH??????????? 指示系統(tǒng)立即寫磁盤。這個寫操作允許被cache緩存,但不能被擱置。
??? FILE_FLAG_OVERLAPPED?????????????????? 指示系統(tǒng)初始化對象,如果操作需要大量時間執(zhí)行就先返回一 個 ERROR_IO_PENDING,當操作 完成后再通過事件使能信號量。指定這個標志就必須在read和write函數(shù)里初始化OVERLAPPED 結構體,應用程序必須執(zhí)行重復的讀寫操作。此時,操作系統(tǒng)不維護文件指針,當前的位置?? 需要通過OVERLAPPED的指針傳遞給讀寫函數(shù)。這個標志還允許多個操作的并行(并行讀寫)。
??? FILE_FLAG_NO_BUFFERING???????????????? 指示系統(tǒng)不要緩沖,它如果和FILE_FLAG_OVERLAPPED聯(lián)合使用,將呈現(xiàn)最好的異步性能,因為I/O操作并不依賴于內存管理器的同步性。但是有時I/O操作會慢些,因為沒用cache。有時程序需要做調整,比如文件大小必須是扇區(qū)大小的整數(shù)倍,Buffer地址的按扇區(qū)地址對齊等。按扇區(qū)地址對齊內存邊界可以使用VirtualAlloc來分配內存,GerDiskFreeSpace函數(shù)可以得到磁盤一個扇區(qū)的大小。
??? FILE_FLAG_RANDOM_ACCESS??????????????? 指示文件進行隨即存取,系統(tǒng)可據(jù)此對cache的分配進行優(yōu)化。
??? FILE_FLAG_SEQUENTIAL_SCAN????????????? 指示順序存取,系統(tǒng)也可據(jù)此對cache的分配進行優(yōu)化。即使有隨即存取的操作,也不會出錯,不過cache的優(yōu)化就取消了。在連續(xù)讀取大文件時性能非常好。
??? FILE_FLAG_DELETE_ON_CLOSE????????????? 指示系統(tǒng)在句柄關閉時將響應的文件立即刪除,對當前句柄以外的其他句柄也有效。而且隨后的打開請求也會失敗,直到你使用了FILE_SHARE_DELETE屬性。
??? FILE_FLAG_BACKUP_SEMANTICS???????????? 在Windows NT/2000/XP平臺上:指示文件作為備份或恢復文件打開,這是如果調用進程擁有特殊權限(SE_BACKUP_NAME 或 SE_RESTORE_NAME),就可以不進行安全檢查。也可以在獲得一個目錄的句柄時設置這個flag,目錄句柄可以代替文件句柄傳遞給一些函數(shù)。
??? FILE_FLAG_POSIX_SEMANTICS????????????? 指明按照操作系統(tǒng)接口規(guī)范進行文件存取,這包括允許多文件名的使用。請謹慎使用,因為MS_DOS或16位Windows系統(tǒng)可能不支持。
??? FILE_FLAG_OPEN_REPARSE_POINT?????????? 這個標志指明禁止文件系統(tǒng)的重解析點的動作。文件打開時就返回文件的句柄,而不在乎控制重解析點的過濾器是否可運行。不能和CREATE_ALWAYS同時使用。
??? FILE_FLAG_OPEN_NO_RECALL?????????????? 表明文件數(shù)據(jù)被請求,但仍然駐留在遠程存儲體中,而不會被傳回本地存儲體。這個標志 由遠程存儲系統(tǒng)或分層存儲管理系統(tǒng)使用。
??? 如果CreateFile函數(shù)打開一個命名管道的客戶端,dwFlagsAndAttributes 參數(shù)也會包含服務信息的安全性。當調用程序指定了
SECURITY_PRESENT標志時,dwFlagsAndAttributes 參數(shù)可以取以下一個或多個值:
??? SECURITY_ANONYMOUS????????????????? 指定將客戶端模擬在匿名級別(the Anonymous impersonation level)
??? SECURITY_IDENTIFICATION???????????? 指定將客戶端模擬在身份認證級別(the Identification impersonation level)
??? SECURITY_IMPERSONATION????????????? 指定將客戶端模擬在偽裝級別(the Impersonation impersonation level)
??? SECURITY_DELEGATION???????????????? 指定將客戶端模擬在授權級別(the Delegation impersonation level)
??? SECURITY_CONTEXT_TRACKING?????????? 指定安全跟蹤模式是動態(tài)的,否則(不指定此標志)是靜態(tài)的
??? SECURITY_EFFECTIVE_ONLY???????????? 指定客戶端的安全內容中的有效內容才可以被服務端使用,否則所有內容都可被使用。 這個標志允許客戶端限制服務端在模擬客戶端時所具有的權限。
7、hTemplateFile
??? 把具有GENERIC_READ權限的句柄指定為一個模板文件。這個模板文件提供了文件屬性和擴展屬性,用于創(chuàng)建文件。在Windows95/98/Me平臺上:這個參數(shù)必須為空,否則如果你提供一個句柄,函數(shù)調用將會失敗,用GerLastError函數(shù)獲得的出錯信息為ERROR_NOT_SUPPORTED。
【Return Values】
??? 調用如果成功,返回值時一個打開文件的句柄。
??? 如果調用之前文件已存在,且dwCreationDisposetion 為CREATE_ALWAYS或OPEN_ALWAYS,用GetLastError返回ERROR_ALREADY_EXISTS。
(即使調用成功也會返回這個值)。如果調用之前不存在,GetLastError返回0。
??? 調用如果失敗,返回值是INVALID_HANDLE_VALUE。要進一步了解出錯原因,調用GetLastError。
????
【備注】
??? 在Windows 2000/XP平臺上:
??? 如果你企圖打開一個遠程機器上的文件或目錄,dwDesiredAccess設置為DELETE或者任一其他的控制標志,
而這時遠程文件或目錄還沒有以FILE_SHARE_DELETE的方式打開的話,你的函數(shù)調用就會發(fā)生共享錯誤了。
為了避免共享錯誤,一種辦法是單獨用DELETE方式打開遠程文件或目錄,另一種方法是在打開文件或目錄之前先調用DeleteFile函數(shù)。
??? 如果dwCreationDisposition 參數(shù)指定為CREATE_ALWAYS 并且dwFlagsAndAttributes 參數(shù)指定為FILE_ATTRIBUTE_NORMAL 的話,CreateFile調用將失敗,GetLastError報告的錯誤是ACCESS_DENIED。這時,把dwFlagsAndAttributes 參數(shù)設置為FILE_ATTRIBUTE_HIDDEN和FILE_ATTRIBUTE_NORMAL的聯(lián)合值,將避免這個問題。
二、*****CloseHandle*****
??? 用于關掉一個打開的對象句柄。
??? 函數(shù)原型:
1?BOOL?CloseHandle( 2???????HANDLE?hObject???//?句柄 3?);
?
【返回值】
??? 函數(shù)調用成功返回非零,失敗返回0。獲得更多錯誤信息,需要調用GetLastError函數(shù)。
??? 在Windows NT/2000/XP平臺上:當應用程序在調試器下運行時,關閉一個不合法的句柄將產生一個異常(Exception)。包括兩次關閉同一個句柄,或者試圖關閉一個由FindFirstFile函數(shù)返回的句柄,都會產生異常。
【備注】
??? CloseHandle使指定的句柄無效,減少對象的句柄計數(shù),進行對象保持檢驗。當對象的最后一個句柄關閉時,對象將從系統(tǒng)中刪除。關閉一個線程句柄并不會終止一個線程,要釋放一個線程對象,必須terminate線程,然后關閉所有的線程句柄。用CloseHandle只能關閉由CreateFile函數(shù)返回的句柄。用FindClose來關閉由FindFirstFile返回的句柄。
三、*****ReadFile*****
??? ReadFile函數(shù)從文件指針指定的位置讀取數(shù)據(jù)。讀操作完成后,文件指針將根據(jù)實際讀出的數(shù)據(jù)自動進行調整,除非文件句柄是以OVERLAPPED屬性值打開的。如果是以OVERLAPPED打開的I/O,應用程序就需要自己手動調整文件指針。
??? 這個函數(shù)被設計成兼有同步和異步操作。ReadFileEx函數(shù)則設計成只支持異步操作,異步操作允許應用程序在讀文件期間可以同時進行其他的操作。
??? 函數(shù)原型:
1?BOOL?ReadFile( 2???????HANDLE?hFile,????????????????//?handle?to?file 3???????LPVOID?lpBuffer,?????????????//?data?buffer 4????????DWORD?nNumberOfBytesToRead,?//?number?of?bytes?to?read 5???????LPDWORD?lpNumberOfBytesRead,?//?number?of?bytes?read 6???????LPOVERLAPPED?lpOverlapped????//?overlapped?buffer 7?);
【參數(shù)】
1、hFile
??? 文件句柄(必須具有GENERIC_READ訪問權限)。
??? 在Windows NT/2000/XP平臺上:對于異步讀操作,hFile可以是由CreateFile函數(shù)以FILE_FLAG_OVERLAPPED方式打開的任何句柄,或者一個由socket或accept函數(shù)返回的socket句柄。
??? 在Windows 95/98/Me平臺上:對于郵槽、命名管道和磁盤文件不能使用異步讀操作。?
2、lpBuffer
??? 用來接收從文件中讀出的數(shù)據(jù)的緩沖區(qū)指針。
3、nNumberOfBytesToRead
?指明要讀的字節(jié)總數(shù)。
4、lpNumberOfBytesRead
??? 一個變量指針,用來存儲實際傳輸?shù)淖止?jié)總數(shù)。ReadFile在做所有事情(包括錯誤檢查)之前,先將這個值賦為0。當ReadFile從一個命名管道上返回TRUE時這個參數(shù)為0,說明消息管道另一端調用WriteFile時設置的nNumberOfBytesToWrite 參數(shù)為0。
??? 在Windows NT/2000/XP平臺上:如果lpOverlapped 為NULL,則lpNumberOfBytesRead不能為NULL。如果lpOverlapped 不是NULL,lpNumberOfBytesRead可以設為NULL。如果是一個overlapped形式的讀操作,我們可以動用GetOverlappedResult函數(shù)來獲得傳輸?shù)膶嶋H字節(jié)數(shù)。如果hFile關聯(lián)的是一個完成端口(I/O completion port),那么可以調用GetQueuedCompletionStatus函數(shù)來獲得傳輸?shù)膶嶋H字節(jié)數(shù)。
??? 如果完成端口(I/O completion port)被占用,而你用的是一個用于釋放內存的回調例程,對于lpOverlapped參數(shù)指向的OVERLAPPED結構體來說,為這個參數(shù)指定NULL可以避免重新分配內存時發(fā)生內存泄漏。內存泄漏會導致返回這個參數(shù)值時是一個非法值。
??? Windows 95/98/Me平臺上:這個參數(shù)不允許為NULL。
5、lpOverlapped
??? 一個指向OVERLAPPED結構體的指針。如果hFile是以FILE_FLAG_OVERLAPPED方式獲得的句柄,這個結構是必須的,不能為NULL。(否則函數(shù)會在錯誤的時刻報告讀操作已經完成了)。這時,讀操作在由OVERLAPPED中Offset成員指定的偏移地址開始讀,并且在實際完成讀操作之前就返回了。在這種情況下,ReadFile返回FALSE,GerLastError報告從錯誤類型是ERROR_IO_PENDING。這允許調用進程繼續(xù)其他工作直到讀操作完成。OVERLAPPED結構中的事件將會在讀操作完成時被使能。
??? 如果hFile不是以FILE_FLAG_OVERLAPPED方式獲得的句柄,并且lpOverlapped為NULL,讀操作就從當前文件的開始位置讀起,直到讀操作完成ReadFile函數(shù)才能返回。
??? 在Windows NT/2000/XP平臺上:如果hFile不是以FILE_FLAG_OVERLAPPED方式獲得的句柄,并且lpOverlapped不為NULL,則讀操作在由OVERLAPPED中Offset成員指定的偏移地址開始讀,直到讀操作完成ReadFile函數(shù)才能返回。
??? 在Windows 95/98/Me平臺上:對于文件、磁盤、管道和郵槽的操作,這個參數(shù)必須為NULL。一個不為空的OVERLAPPED結構體指針將導致調用失敗。Windows 95/98/Me平臺只支持串行口和并行口的overlapped 讀寫。
【返回值】
??? 有如下任一種情況發(fā)生都會導致函數(shù)返回:(1)在管道另一端的寫操作完成后(2)請求的字節(jié)數(shù)傳輸完畢(3)發(fā)生錯誤。
??? 如果函數(shù)正確,返回非零。
??? 如果返回值是非零,但接收的字節(jié)數(shù)是0,那么可能是文件指針在讀操作期間超出了文件的end位置。然而,如果文件以FILE_FLAG_OVERLAPPED方式打開,lpOverlapped 參數(shù)不為NULL,文件指針在讀操作期間超出了文件的end位置,那么返回值肯定是FALSE,GetLastError返回的錯誤是ERROR_HANDLE_EOF。
【備注】
??? 如果文件的一部分被另一個進程鎖定,而當前進程試圖重復鎖定,那將會失敗。
??? 一個應用程序在讀以FILE_FLAG_NO_BUFFERING方式打開的文件時要符合一定的條件。
(1)文件讀的開始地址必須是扇區(qū)大小的整數(shù)倍。GetDiskFreeSpace函數(shù)可以取得扇區(qū)的大小。
(2)請求讀的字節(jié)數(shù)也必須是扇區(qū)大小的整數(shù)倍。
(3)用于讀寫操作的Buffer地址必須按照扇區(qū)大小進行邊界對齊??梢酝ㄟ^用VirtualAlloc 函數(shù)申請內存來做到。
??? 在讀操作期間試圖訪問相應的輸入緩沖區(qū),會導致讀入到緩沖區(qū)的數(shù)據(jù)損壞。讀操作完成之前,應用程序不能對這段輸入緩沖區(qū)做任何操作(包括讀、寫、重新分配內存,釋放內存等)。
??? ReadFile可以通過指向控制臺輸入對象的句柄將控制臺的輸入字符讀出來??刂婆_的模式決定了ReadFile的具體行為。
??? 如果一個命名管道正在以消息模式被讀取,并且下一條消息比nNumberOfBytesToRead參數(shù)指定的長度還大,那么ReadFile將返回FALSE并且GetLastError返回錯誤為ERROR_MORE_DATA。剩下沒讀完的消息可能會被隨后的ReadFile或PeckNamedPipe函數(shù)讀出。
??? 讀取一個通信設備時,ReadFile的行為被當前的通信延時所支配,延時屬性的設置和取得使用SetCommTimeouts和GetCommTimeouts函數(shù)。如果你設置延時屬性失敗,就會得到不可預知的結果。
??? 如果ReadFile試圖讀取一個buffer太小的郵槽,將會返回FALSE并且GetLastError返回錯誤為ERROR_INSUFFICIENT_BUFFER 。
??? 如果一個匿名的寫管道句柄已經關閉,而ReadFile試圖用響應的匿名權限讀這個管道句柄,將返回FALSE并且
GetLastError返回錯誤為ERROR_BROKEN_PIPE。
??? 每當有太多的異步I/O請求得不到響應,ReadFile就會失敗,并返回ERROR_INVALID_USER_BUFFER或ERROR_NOT_ENOUGH_MEMORY的錯誤。
??? 在同步和異步兩種情況下,ReadFile中檢測EOF(文件結尾邊界)的代碼是不同的。當一個同步讀操作到達文件結尾時,ReadFile返回TRUE,并設置*lpNumberOfBytesRead 為0 。異步讀操作會在開始調用的讀操作中或者隨后的其他異步操作中突然遇到文件結尾。(1)如果EOF在ReadFile期間被檢測到,將會返回FALSE,且 GetLastError返回錯誤描述 ERROR_HANDLE_EOF。(2)如果EOF在隨后的其他異步操作中被檢測到,則類似GetOverlappedResult 等試圖獲取操作結果的函數(shù)返回FALSE,且 GetLastError返回錯誤描述ERROR_HANDLE_EOF。
??? 為了取消未響應的異步I/O操作,用CancelIo函數(shù)。這個函數(shù)只能取消由調用進程對特定句柄進行的操作。被取消的I/O操作將被描述為ERROR_OPERATION_ABORTED。
??? 如果你正試圖從并不存在的軟驅中讀數(shù)據(jù),系統(tǒng)會彈出消息框提示你重新操作。為了阻止系統(tǒng)的消息框,調用函數(shù)SetErrorMode,參數(shù)設置為SEM_NOOPENFILEERRORBOX。