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