網(wǎng)絡安全編程:文件相關操作API函數(shù)
剛開始接觸編程可能會覺得Windows API是一個很神奇、很萬能的工具,Windows API是Windows下開發(fā)應用程序的基礎知識,不過基礎并不代表簡單,能掌握好Windows API來開發(fā)程序也是非常不容易的。
在Windows下,文件有很多種,比如圖片文件、視頻文件、音頻文件……這些文件都屬于保存在磁盤上的存儲格式不相同的文件。除了常見的磁盤文件格式外,管道、郵槽,甚至是設備對象,在Windows下也都被當作文件來對待。這樣在編程的過程中,操作管道、郵槽、設備對象就如同操作文件一樣。
1. 文件的打開與關閉
要對文件進行操作,首先把要操作的文件打開,文件打開成功后會返回一個可以用于操作文件的句柄,通過這個句柄就可以對文件進行讀寫操作了。
打開文件的API函數(shù)定義如下:
- HANDLE CreateFile(
- LPCTSTR lpFileName,
- DWORD dwDesiredAccess,
- DWORD dwShareMode,
- LPSECURITY_ATTRIBUTES lpSecurityAttributes,
- DWORD dwCreationDisposition,
- DWORD dwFlagsAndAttributes,
- HANDLE hTemplateFile
- );
參數(shù)說明如下:
lpFileName:欲打開或創(chuàng)建的文件名,這里也可以不是文件名,可以是設備對象之類的被視為文件的相關對象。
dwDesiredAccess:對文件的訪問模式,它指定了要對打開的對象進行何種操作。通常是 GENERIC_READ 和 GENERIC_WRITE,分別表示只讀模式和只寫模式;還可以通過按位或運算符同時指定兩種模式,如 GENERIC_READ | GENERIC_WRITE。
dwShareMode:打開文件的共享模式,表示文件被打開后是否允許其他進程進行操作,如果可以進行操作,可以指定其操作的模式。
lpSecurityAttributes:該參數(shù)表示安全屬性,通過這個參數(shù)可以指定返回的文件句柄是否可以被子進程繼承,如果參數(shù)設置為 NULL,表明無法被繼承,否則需要將參數(shù)指向一個 SECURITY_ATTRIBUTES 的結構體。該參數(shù)通常為 NULL。
dwCreationDisposition:在創(chuàng)建或打開的文件存在或不存在時該函數(shù)的處理方式。
dwFlagsAndAttributes:該參數(shù)用來指定新建文件的屬性和對文件操作的方式。
hTemplateFile:文件模板句柄,系統(tǒng)會復制該文件模板的所有屬性到當前創(chuàng)建的文件中。
該函數(shù)若執(zhí)行成功,則返回一個文件句柄;如果執(zhí)行失敗,則返回INVALID_HANDLE_ VALUE。具體失敗的原因可以通過調(diào)用GetLastError()函數(shù)來得到。
文件的打開操作調(diào)用的是CreateFile()函數(shù),該函數(shù)名不像其名字那樣只能用于創(chuàng)建文件。CreateFile()函數(shù)既可以打開文件,也可以創(chuàng)建文件。在Windows下有一個OpenFile()函數(shù)用來打開文件,不過它是Win16的產(chǎn)物,在Win32下必須使用CreateFile()來打開文件。
CreateFile()的參數(shù)很多,不過用習慣后會發(fā)現(xiàn)常用的參數(shù)都很容易記住,甚至有些參數(shù)常用的就是那么一兩個。在對文件操作完成后,需要對打開文件的句柄進行關閉以釋放資源。關閉對象句柄的函數(shù)非常簡單,而且使用也非常廣泛。該函數(shù)的定義如下:
- BOOL CloseHandle(
- HANDLE hObject // handle to object
- );
該函數(shù)的參數(shù)只有一個,這個參數(shù)就是調(diào)用CreateFile()函數(shù)時的返回值,也就是文件句柄。該函數(shù)并不僅僅能夠關閉文件句柄,事件句柄、進程句柄、線程句柄等一系列對象句柄都可以用該函數(shù)進行關閉。
2. 文件的操作
文件的操作有4種,分別是“增、刪、改、查”。接觸過數(shù)據(jù)庫的讀者一定感覺這些操作都是針對數(shù)據(jù)庫的,怎么對文件的操作也是這4種呢?其實,不單單是對文件的操作存在增、刪、改、查,對注冊表、系統(tǒng)服務、進程等的操作也都存在增、刪、改、查。只不過相對應的有不同的Windows API函數(shù),而不是使用數(shù)據(jù)庫的SQL語句而已。
用文件的操作進行舉例說明。文件的“增”操作可以理解為創(chuàng)建文件,文件的“刪”操作可以理解為刪除文件,文件的“改”操作可以理解為對文件的寫操作,文件的“查”操作可以理解為對文件的“讀”操作。
對于文件的讀寫操作可以從狹義和廣義上進行認識,狹義的“讀文件”就是讀取已打開文件的內(nèi)容或數(shù)據(jù),而廣義的“讀文件”則可以是獲取文件的大小、創(chuàng)建時間和修改時間等,因為文件的大小、創(chuàng)建時間、修改時間也屬于文件的屬性,只是這些屬性不保存在本身的文件中。寫操作也是同樣的道理。
下面介紹常用的文件的刪除操作、讀寫操作所涉及的API函數(shù),具體的更多涉及文件操作的函數(shù)無法一一介紹,靠大家自行積累總結。
刪除文件的API函數(shù)定義如下:
- BOOL DeleteFile(
- LPCTSTR lpFileName
- );
該函數(shù)的參數(shù)只有一個,lpFileName表示要刪除的文件的文件名。大部分的文件操作函數(shù)都是通過CreateFile()函數(shù)返回的文件句柄進行操作,而DeleteFile()函數(shù)使用的文件名進行操作的,如果文件被打開以后,又怎么能刪除呢?
讀取文件內(nèi)容的函數(shù)如下:
- HANDLE hFile,
- LPVOID lpBuffer,
- DWORD nNumberOfBytesToRead,
- LPDWORD lpNumberOfBytesRead,
- LPOVERLAPPED lpOverlapped
- ;
參數(shù)說明如下。
hFile:文件句柄,通常是 CreateFile()函數(shù)返回的句柄。
lpBuffer:指向一個緩沖區(qū),函數(shù)會將從文件中讀出的數(shù)據(jù)保存在該緩沖區(qū)中。
nNumberOfBytesToRead:要求讀入的字節(jié)數(shù),通常情況下是緩沖區(qū)的大小。
lpNumberOfBytesRead:指向一個 DWORD 類型的變量,用于返回實際讀入的字節(jié)數(shù)。
lpOverlapped:一般設置為 NULL。
寫入文件內(nèi)容的函數(shù)如下:
- BOOL WriteFile(
- HANDLE hFile,
- LPCVOID lpBuffer,
- DWORD nNumberOfBytesToWrite,
- LPDWORD lpNumberOfBytesWritten,
- LPOVERLAPPED lpOverlapped
- );
WriteFile()函數(shù)的參數(shù)和ReadFile()函數(shù)的參數(shù)意義基本相同,所不同的是第2個參數(shù)。第2個參數(shù)仍然指向一個緩沖區(qū),WriteFile()函數(shù)會將該緩沖區(qū)的內(nèi)容進行寫入。當用WriteFile()函數(shù)寫文件時,寫入的數(shù)據(jù)通常被Windows暫時保存在內(nèi)部的高速緩存中,操作系統(tǒng)會定期進行盤寫入,從而避免頻繁進行I/O操作影響執(zhí)行效率。為了保證數(shù)據(jù)即時寫入可以使用FlushFileBuffers()函數(shù),該函數(shù)的定義如下:
- BOOL FlushFileBuffers(
- HANDLE hFile
- );
該函數(shù)會將指定文件句柄的緩沖區(qū)進行清空,使得Windows將緩沖區(qū)中的文件寫入磁盤。該函數(shù)只有一個參數(shù),即文件句柄。該文件句柄與ReadFile()和WriteFile()所使用的文件句柄相同。
在進行文件讀寫時,往往并不是由前往后順序讀寫,通常是根據(jù)需要讀寫文件的某個部分,這就需要對文件指針進行移動,從而正確對文件進行讀寫操作。移動文件指針的函數(shù)定義如下:
- DWORD SetFilePointer(
- HANDLE hFile,
- LONG lDistanceToMove,
- PLONG lpDistanceToMoveHigh,
- DWORD dwMoveMethod
- );
該函數(shù)的參數(shù)說明如下。
hFile:進行文件操作時的文件句柄,如同 ReadFile()和 WriteFile()。
lDistanceToMove:指定要移動文件指針的距離。
lpDistanceToMoveHigh:一個指向 LONG 型的指針,移動距離的高 32 位,一般為 NULL。
dwMoveMethod:指定移動的起始位置。可以從文件開始位置進行移動(FILE_BEGIN),可以從當前文件位置開始移動(FILE_CURRENT),也可以從文件的末尾開始移動(FILE_END)。
3. 驅(qū)動器及目錄相關操作
下面介紹目錄相關的操作,主要介紹4個相關函數(shù),分別是獲取本地所有邏輯驅(qū)動器、獲取驅(qū)動器類型、創(chuàng)建目錄和移除目錄。下面介紹這4個函數(shù)的定義。
獲取本地所有邏輯驅(qū)動器函數(shù)的定義如下:
- DWORD GetLogicalDriveStrings(
- DWORD nBufferLength,
- LPTSTR lpBuffer
- );
該函數(shù)的參數(shù)說明如下。
nBufferLength:表示 lpBuffer 的長度。
lpBuffer:表示接收本地邏輯驅(qū)動器名的緩沖區(qū)。
該函數(shù)以字符串的形式返回本地所有可用的驅(qū)動器名保存在lpBuffer中。返回字符串的形式如“C:\”,0,“D:\”,0,“E:\”,0,0。
獲取驅(qū)動器類型函數(shù)的定義如下:
- UINT GetDriveType(
- LPCTSTR lpRootPathName
- );
該函數(shù)只有一個參數(shù)lpRootPathName,要獲取邏輯驅(qū)動器類型的驅(qū)動器名,如“C:\”。函數(shù)返回值取以下值之一。
- DRIVE_UNKNOWN:無法識別此驅(qū)動器類型;
- DRIVE_NO_ROOT_DIR:無效的驅(qū)動器路徑;
- DRIVE_REMOVEABLE:可移動驅(qū)動器,如 U 盤、移動硬盤等;
- DRIVE_FIXED:不可移動驅(qū)動器,指硬盤;
- DRIVE_REMOTE:網(wǎng)絡驅(qū)動器;
- DRIVE_CDROM:光盤驅(qū)動器;
- DRIVE_RAMDISK:虛擬驅(qū)動器。
創(chuàng)建目錄的函數(shù)定義如下:
- BOOL CreateDirectory(
- LPCTSTR lpPathName,
- LPSECURITY_ATTRIBUTES lpSecurityAttributes
- );
該函數(shù)的參數(shù)說明如下。
lpPathName:創(chuàng)建目錄的目錄名稱。
lpSecurityAttributes:安全屬性,一般設置為 NULL。
移除目錄的函數(shù)定義如下:
- BOOL RemoveDirectory(
- LPCTSTR lpPathName
- );
該函數(shù)的參數(shù)指定要移除的目錄的目錄名。
以上是關于驅(qū)動器和目錄的幾個常用的API函數(shù)。